feat(brand): AV BEAT 2026 rebrand — blue/navy/white identity

- New AvBeatLogo inline-SVG component (rounded-square emblem with
  forward-leaning AV monogram + horizontal beam detail) at
  src/components/AvBeatLogo.tsx, three variants (full/wordmark/icon).
- Header.tsx now uses the responsive AV BEAT logo lockup in the
  top-left, links to /, full lockup on desktop (emblem+wordmark+tagline),
  emblem+wordmark on tablet, emblem-only on mobile.
- Removed DualSpeedTicker (the 'RECENT FORUM POSTS' ticker strip);
  the news ticker / glow chrome does not match the new aesthetic and the
  forum row was the explicit removal target.
- Tailwind theme + globals.css now expose the AV BEAT 2026 palette as
  semantic tokens: --brand-blue (#1D4ED8), --brand-blue-bright (#38BDF8),
  --brand-navy (#0F172A), --brand-bg (#F8FAFC), --brand-surface, --brand-border,
  --brand-text, --brand-text-muted. Legacy --color-* aliases re-point to the
  new tokens so any inline-styled component re-themes for free.
- Site-wide hex sweep migrates 2,769 hardcoded color literals across 144
  files from the old dark-broadcast palette to the new tokens (orange
  -> blue, dark-brown -> white surface / navy text, cream -> navy).
- Layout body class flipped from 'bb-neon' to 'bg-brand-bg text-brand-text'
  so the dark glow chrome no longer leaks through the new light theme.
This commit is contained in:
2026-06-03 12:07:18 +00:00
parent 39d2bf9073
commit 8042024c4a
146 changed files with 2219 additions and 2081 deletions

View File

@@ -159,7 +159,7 @@ export default async function ManufacturerProfile({
};
return (
<div className="min-h-screen bg-[#1c1815]">
<div className="min-h-screen bg-[#F8FAFC]">
<Header />
<script
type="application/ld+json"
@@ -170,8 +170,8 @@ export default async function ManufacturerProfile({
<BackLink />
</nav>
<header className="flex flex-col sm:flex-row gap-6 mb-8 pb-8 border-b border-[#3a322b]">
<div className="w-24 h-24 rounded-xl bg-[#231d18] flex items-center justify-center overflow-hidden flex-shrink-0">
<header className="flex flex-col sm:flex-row gap-6 mb-8 pb-8 border-b border-[#DCE6F2]">
<div className="w-24 h-24 rounded-xl bg-[#FFFFFF] flex items-center justify-center overflow-hidden flex-shrink-0">
{company.logo_url ? (
/* eslint-disable-next-line @next/next/no-img-element */
<img
@@ -206,7 +206,7 @@ export default async function ManufacturerProfile({
</span>
)}
{company.phone && (
<a href={`tel:${company.phone.replace(/[^\d+]/g, '')}`} className="text-[#888] hover:text-[#F0A623]">
<a href={`tel:${company.phone.replace(/[^\d+]/g, '')}`} className="text-[#888] hover:text-[#1D4ED8]">
{company.phone}
</a>
)}
@@ -217,7 +217,7 @@ export default async function ManufacturerProfile({
href={company.company_website}
target="_blank"
rel="noopener noreferrer"
className="text-[#F0A623] hover:underline"
className="text-[#1D4ED8] hover:underline"
>
Website
</a>
@@ -227,7 +227,7 @@ export default async function ManufacturerProfile({
href={company.press_url}
target="_blank"
rel="noopener noreferrer"
className="text-[#F0A623] hover:underline"
className="text-[#1D4ED8] hover:underline"
>
Newsroom
</a>
@@ -237,7 +237,7 @@ export default async function ManufacturerProfile({
href={company.contact_url}
target="_blank"
rel="noopener noreferrer"
className="text-[#F0A623] hover:underline"
className="text-[#1D4ED8] hover:underline"
>
Contact
</a>
@@ -247,7 +247,7 @@ export default async function ManufacturerProfile({
href={company.linkedin_url}
target="_blank"
rel="noopener noreferrer"
className="text-[#888] hover:text-[#F0A623]"
className="text-[#888] hover:text-[#1D4ED8]"
>
LinkedIn
</a>
@@ -257,7 +257,7 @@ export default async function ManufacturerProfile({
href={`https://twitter.com/${company.twitter_handle}`}
target="_blank"
rel="noopener noreferrer"
className="text-[#888] hover:text-[#F0A623]"
className="text-[#888] hover:text-[#1D4ED8]"
>
X / Twitter
</a>
@@ -283,17 +283,17 @@ export default async function ManufacturerProfile({
<h2 className="text-lg font-display font-bold text-[#e0e0e0] mb-4">Executive leadership</h2>
<div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-4">
{executives.map((e: any) => (
<div key={e.id} className="bg-[#111] border border-[#3a322b] rounded-lg p-4 flex gap-3">
<div key={e.id} className="bg-[#111] border border-[#DCE6F2] rounded-lg p-4 flex gap-3">
{e.photo_url ? (
/* eslint-disable-next-line @next/next/no-img-element */
<img
src={e.photo_url}
alt={e.name}
className="w-16 h-16 rounded-full object-cover bg-[#231d18] flex-shrink-0"
className="w-16 h-16 rounded-full object-cover bg-[#FFFFFF] flex-shrink-0"
loading="lazy"
/>
) : (
<div className="w-16 h-16 rounded-full bg-[#231d18] flex items-center justify-center text-[#666] font-bold flex-shrink-0">
<div className="w-16 h-16 rounded-full bg-[#FFFFFF] flex items-center justify-center text-[#666] font-bold flex-shrink-0">
{(e.name || "?").trim().charAt(0).toUpperCase()}
</div>
)}
@@ -306,7 +306,7 @@ export default async function ManufacturerProfile({
href={e.linkedin_url}
target="_blank"
rel="noopener noreferrer"
className="text-[11px] text-[#F0A623] hover:underline"
className="text-[11px] text-[#1D4ED8] hover:underline"
>
LinkedIn
</a>
@@ -328,14 +328,14 @@ export default async function ManufacturerProfile({
)}
{company.phone && (
<div className="mt-1">
<a href={`tel:${company.phone.replace(/[^\d+]/g, '')}`} className="text-[#F0A623] hover:underline">
<a href={`tel:${company.phone.replace(/[^\d+]/g, '')}`} className="text-[#1D4ED8] hover:underline">
{company.phone}
</a>
</div>
)}
{company.contact_email && (
<div>
<a href={`mailto:${company.contact_email}`} className="text-[#F0A623] hover:underline">
<a href={`mailto:${company.contact_email}`} className="text-[#1D4ED8] hover:underline">
{company.contact_email}
</a>
</div>
@@ -356,7 +356,7 @@ export default async function ManufacturerProfile({
{cleanCategories.map((c: string) => (
<span
key={c}
className="text-xs bg-[#231d18] text-[#aaa] px-2.5 py-1 rounded-full"
className="text-xs bg-[#FFFFFF] text-[#aaa] px-2.5 py-1 rounded-full"
>
{c}
</span>
@@ -382,7 +382,7 @@ export default async function ManufacturerProfile({
return (
<li
key={`${s.show}-${s.show_year}-${s.booth || "?"}`}
className="bg-[#111] border border-[#3a322b] rounded-md px-4 py-3 flex items-center justify-between gap-4"
className="bg-[#111] border border-[#DCE6F2] rounded-md px-4 py-3 flex items-center justify-between gap-4"
>
<div className="min-w-0">
<span className="font-semibold text-[#e0e0e0]">{label}</span>
@@ -401,7 +401,7 @@ export default async function ManufacturerProfile({
<section className="mb-10">
<header className="flex items-baseline justify-between mb-3">
<h2 className="text-lg font-display font-bold text-[#e0e0e0]">Recent coverage</h2>
<Link href={`/news?search=${encodeURIComponent(company.company_name)}`} className="text-xs text-[#F0A623] hover:underline">
<Link href={`/news?search=${encodeURIComponent(company.company_name)}`} className="text-xs text-[#1D4ED8] hover:underline">
All stories
</Link>
</header>
@@ -410,7 +410,7 @@ export default async function ManufacturerProfile({
<Link
key={r.wp_slug}
href={`/news/${r.wp_slug}`}
className="group bg-[#1c1815] border border-[#3a322b] rounded-md p-3 hover:border-[#F0A623] hover:shadow-sm transition-all flex gap-3"
className="group bg-[#F8FAFC] border border-[#DCE6F2] rounded-md p-3 hover:border-[#1D4ED8] hover:shadow-sm transition-all flex gap-3"
>
{/* Image fallback cascade — Ryan rule: never show an empty
gray box on a coverage card. Falls through:
@@ -419,11 +419,11 @@ export default async function ManufacturerProfile({
<img
src={r.featured_image || company.logo_url || '/assets/images/article-placeholder.svg'}
alt=""
className="w-20 h-14 rounded object-cover bg-[#231d18] flex-shrink-0"
className="w-20 h-14 rounded object-cover bg-[#FFFFFF] flex-shrink-0"
loading="lazy"
/>
<div className="min-w-0">
<h3 className="text-xs font-semibold text-[#e0e0e0] leading-snug group-hover:text-[#F0A623] line-clamp-3">
<h3 className="text-xs font-semibold text-[#e0e0e0] leading-snug group-hover:text-[#1D4ED8] line-clamp-3">
{r.title}
</h3>
{r.wp_published_at && (
@@ -447,7 +447,7 @@ export default async function ManufacturerProfile({
{p.slug ? (
<Link
href={`/news/${p.slug}`}
className="text-[#F0A623] hover:underline"
className="text-[#1D4ED8] hover:underline"
>
{p.title}
</Link>
@@ -465,7 +465,7 @@ export default async function ManufacturerProfile({
</section>
)}
<footer className="text-xs text-[#666] mt-12 pt-6 border-t border-[#3a322b]">
<footer className="text-xs text-[#666] mt-12 pt-6 border-t border-[#DCE6F2]">
Listing maintained by AV Beat editorial.
{company.last_mentioned && (
<> Last mentioned in coverage on {new Date(company.last_mentioned).toISOString().slice(0, 10)}.</>