Critical mobile bugs flagged from an iPhone screenshot.
1) Mobile hamburger menu — all main nav items (HOME / SHOW COVERAGE /
DIRECTORY / FORUM / READING LIST) were `text-white` on
`bg-[#F8FAFC]`, i.e. white-on-light. Effectively invisible. Legacy
styling from the dark-theme era that never got updated. Flipped to
`text-[#0F172A]` + `hover:bg-[#FFFFFF]` + `border-[#DCE6F2]` to match
the My Profile / WP Import links right below them that were already
correctly themed.
2) Secondary top nav (social icons / language switcher / Sign In + Join
/ newsletter email input) was a single h-8 flex row that always
rendered — on a phone-width viewport the row spills the email input
off the right edge. Added `hidden md:flex` so the whole bar
disappears on mobile. Affordances stay reachable via the hamburger
menu, in-forum Sign In/Join buttons, and the footer.
3) Forum auth pages (login, register, forgot-password, reset-password)
had `text-white` on every H1 AND on every form input that uses
`bg-[#F8FAFC]`. So users opening any of those four pages saw a blank
white card with invisible labels and couldn't see what they were
typing into the password fields. Same dark-theme regression as #1.
Blanket-replaced `text-white` with `text-[#0F172A]` across all four
files, then restored `text-white` only inside classNames that also
contain `bg-[#1D4ED8]` / `bg-[#1E3A8A]` / `brand-gradient` (the
submit buttons — those WERE correct).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The new A-monogram placeholder shipped in d8ca8ff was correct in the
deployed container, but Cloudflare was serving the previous cached SVG
(cf-cache-status: HIT, last-modified from this morning) because the
account token doesn't carry Zone:Cache Purge scope, so we couldn't
issue an API purge.
Renaming the file to article-placeholder-v2.svg gives CF a fresh URL
to cache, sidestepping the missing-permission entirely. Updated all
6 referencing files (AppImage fallback, legacy-source FALLBACK_IMAGE
constants, FeaturedBento[FromDb], manufacturers/authors pages).
Old file (cached as the old wordmark) just becomes a dangling asset —
not referenced from anywhere, harmless.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Two pointed bugs on the article detail page:
1) Width alignment. The right-rail Related Articles and Related Forum
Posts boxes were free-stretching to the lg:col-span-4 width while the
SidebarAdStack below them rendered ads at their natural 300px (items-
end, right-aligned). The visual result: boxes overhung the ad column
on both edges. Wrapped each sidebar in an inner `w-full lg:w-[300px]
lg:ml-auto` div so every block (ads + boxes + newsletter) shares one
300px column on lg+ and stays full-width on mobile. Applied to both
article templates (/articles/[slug] and /news/[slug]).
2) Placeholder rendered the old "AV BEAT" wordmark when an article had no
featured image. Rebuilt article-placeholder.svg around the new brand
mark — the A-monogram tile with the blue gradient (#2563EB→#1E3A8A)
that matches AnimatedLogo + the rest of the brand-gradient system.
Same 1200×630 dimensions so OG/feed embeds aren't affected.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Two unrelated production bugs called out in the same review pass:
1) AI persona disclosure — strictly removed everywhere readers see it.
- /about/team hero subtitle no longer says "trained AI personas working
under house style"; copy now reads like every other newsroom team page.
- /about "How we work" block drops the line about AI assistants
rewriting press releases + the "Our AI personas are clearly labeled"
sentence. Reworded to just describe the editorial process.
- ArticleComments no longer renders the small "AI" chip beside
is_ai_seeded commenters. The flag stays in the DB for internal
accounting; it just doesn't surface in the UI.
- Stale code comments in articles/[slug] + news/[slug] that referenced
"AI personas participate (tagged)" cleaned up.
The is_ai_seeded / is_ai_response columns are now strictly internal-only.
2) Team page card visibility — the page wrapper got switched from
text-[#e5e7eb] to text-[#0F172A] in the recent restyle, which fixed
white-on-white outside the cards but left the dark-card H3 names
inheriting dark navy on a dark navy bg = invisible. Forced text-white
on both H3s (editorial + ops). Email rows now use min-w-0 + flex-1 +
block truncate so long addresses ellipsis inside the card instead of
pushing the layout past the right edge.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Adds a no-auth star rating system backed by a centralized cross-property
table on supabase01.
Database:
- distribute.article_ratings (id, property, article_slug, rating 1..5,
session_id, ip_hash, user_agent, created_at) with UNIQUE
(property, article_slug, session_id). property column means every RMP
site shares one table; AV Beat writes 'avbeat', BB writes 'bb', etc.
- distribute.article_rating_aggregates view rolls up real_count + real_avg
per (property, slug).
API (/api/articles/rating):
- GET ?slug=X → { avg, count, my_rating } — reads aggregate, plus the
current session's vote if any.
- POST { slug, rating } → inserts the vote; unique_violation on duplicate
is silently swallowed (one vote per session). Returns updated summary.
- Session lives in `av_rate_sid` cookie (uuid, 1y, sameSite=lax). Cookie
is minted by the API on first request, so the client never has to know
about it.
StarRating component:
- Now interactive — hover preview, click to submit, "thanks!" affordance.
- Merges the existing deterministic baseline (slug-hash → 4.0–5.0 + age-
scaled count) with the real aggregate using the baseline as a Bayesian
prior, so a single real rating doesn't crater the displayed average.
- Once the current session has voted, stars show "your rating" and
hover/click are disabled.
- Text colors updated #d0d0d0 → #0F172A so the rating number is readable
on AV Beat's light backgrounds.
Property identifier hardcoded as "avbeat" at the top of the route — when
porting to BB / SNS / BLB / etc., change that constant and keep
everything else identical.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Three coupled rollouts in one shot.
PART A — client highlight matcher (DB migration applied separately):
- promoted-articles.ts: AdvertiserName now carries brand_aliases; matcher
iterates legal name + every alias with word-boundary regex and picks the
longest match across all candidates so "Magewell Launches…" resolves to
"Magewell Electronics Co., Ltd." via its Magewell alias.
- New isStoryAboutClient gate: hard-accept at position 0, accept if any
editorial frame ("Product Spotlight:", "Review:", "First Look", …) appears
in the prefix, hard-reject if the prefix ends with a partner/usage phrase
("with", "using", "powered by", "dealer of", "integration with", "used",
"deploys", "runs on", "leverages", …), otherwise accept within a 32-char
subject window. Validated against 5,000 historical posts: 27 partner
false-positives blocked, 3 editorial-frame stories correctly saved, the
Magewell article now highlights.
PART B — restyling /about, /about/team, /about/contact:
- New .brand-gradient utility: #2563EB→#1E3A8A linear-gradient with a
16%-opacity diagonal sheen that sweeps in the first 30% of a 7s cycle
and rests offscreen-right for the rest. Respects prefers-reduced-motion
(band parked statically at 6% opacity).
- Team page: dark legacy hero (red radial, #ff5a55 eyebrows) replaced with
brand-gradient hero; outer text wrapper #e5e7eb → #0F172A so section
headings stop being white-on-white; all serif H1/H2/H3 → font-display;
red accents (#ff5a55 / #ff6b66 / rgba(214,7,1)) → blue (#93C5FD / #7DD3FC
/ rgba(29,78,216)).
- About page: H1 + Stat values → font-display; Stat cards get a brand-
gradient top stripe.
- Contact page: outer wrapper #e5e7eb → #0F172A (fixes the white-on-white
Contact H1); H1 gets explicit text-[#0F172A] + font-display; dark contact
cards keep dark bg but gain a brand-gradient top stripe + explicit
text-[#e5e7eb] body + brighter cyan eyebrow/link colors.
PART C — richer Industry News client highlight:
- ArticleFeed: client-promoted row swaps the static border-l-4 for an
absolute-positioned .brand-gradient strip on the left edge (sheen pulses
through). Row gets a slightly richer bg tint (from-#1D4ED8/12 via /4).
- HIGHLIGHT pill now uses .brand-gradient instead of the static blue chip.
Also shipping the earlier-staged work:
- AnimatedLogo onDark: white ring around tile + brighter (#E2E8F0) tagline
+ cyan accent rule for the blue header.
- Article-prose: em/strong/code dark colors (em fixes the trailing
copyright/trademark ghost text), hr line color, figcaption readable.
- ArticleComments: "Sign in to join the discussion" bar uses brand-gradient
+ white/outline buttons that read on blue.
- Forum: Discover/Following, Newest/Top Voted/Unanswered, Sign in to post,
Start a thread, Create account — slim pills, brand-gradient active.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The 720px media query had its own ::first-letter override at 52px that
survived the desktop-rule removal — first letter was still rendering
oversized on mobile. Removing this completes the drop-cap rip-out.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Two complaints on /news/[slug]:
- the oversized first-letter drop-cap looked editorial-magazine, not in
spec — first paragraph should start as normal prose
- inline links rendered near-white against the white page because
Tailwind Typography's prose-a variable was overriding the (no-!important)
brand-blue rule, leaving ghost links unreadable
Drop the ::first-letter rule entirely. Force link color to #1e293b body,
font-family to inherit, and decoration color to currentColor so the
underline is the only visual link cue (still WCAG-distinguishable
without relying on color). Hover keeps brand blue.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Header bar is #1D4ED8 but logo was rendering with navy text on the tile's
#2563EB→#1E3A8A gradient — wordmark + tagline were nearly invisible. Flip
all three header breakpoints to variant="onDark" (white wordmark, slate-200
tagline). Also: switch the onDark tagline accent rule from #1D4ED8 (same
blue, invisible) to #7DD3FC cyan, and paint a faint white ring around the
tile so the rounded mark stays distinct from the header background.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- Header: replaces AvBeatLogo across all 3 breakpoints (full / no-tagline / iconOnly).
- Footer: replaces AvBeatLogo full variant.
- AnimatedLogo: new iconOnly prop hides the wordmark+tagline span entirely for the mobile breakpoint.
Existing AvBeatLogo file kept on disk for now (unimported, can be deleted later) so we have a quick rollback target if anyone wants the static A+V monogram back.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Article excerpts sometimes contain raw <p> tags; Next.js HTML-escapes
them into the page <meta>, surfacing as literal '<p>' in view-source
and breaking SEO previews. cleanExcerpt() strips tags + entities for all
plain-text meta surfaces.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Boxes stay sized; tall/odd-ratio images letterbox cleanly against the
existing slate card background instead of being chopped at the edges.
Applied to FeaturedBento, FeaturedBentoFromDb, ArticleFeed, NewsPageClient,
SpotlightCarousel, FeaturedCarousel, AISuggestedArticles, search/page.tsx.
Avatars (rounded-full) unchanged — still object-cover.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Sarah Quinn's author page (and any article missing a featured_image) was
showing the old BB-branded placeholder. New SVG uses the AV Beat navy/cyan
palette and 'PRO AV · DISPLAY · LIVE PRODUCTION' tagline.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Mirror of the BB article-prose change. Font-family swap only; colors were
already dark on AVB. Body smoothing re-enabled per Ryan.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Adverts/contact UI emails on /about/contact + /advertise now point at the
central advertising alias (forwarded to ryan.salazar@). Media-kit hyperlink
on /about/contact corrected to relevantmediaproperties.com/av-beat---media-kit.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Was 11px mono with no background; now a navy outlined pill with uppercase
bold tracking, light-blue fill, and hover state. Same target route.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
src/styles/tailwind.css:195 .article-card:hover background-color was #1c1c1c (near-black, leftover from the dark theme). On the white page that made the card go black on hover and the text disappear into it. Swapped to #e2e8f0 (Tailwind slate-200) so the hover reads as a clean dark-gray distinct from the white surface while keeping the navy article title + slate excerpt fully readable.
src/app/advertise/page.tsx:55 — hero CTA was pointing at the in-page
anchor '#contact'. Swapped to absolute URL
https://relevantmediaproperties.com/av-beat---media-kit (the AV Beat
media-kit landing). target=_blank + rel=noopener so the article tab
isn't replaced.
src/app/home-page/components/ArticleFeed.tsx:597 — the article-card badge
shown when promoted==='client' said '◆ Advertiser' with a title tooltip
'Advertiser coverage: <name>'. Both copies now say 'HIGHLIGHT' / 'Highlight: <name>'.
Visual treatment (diamond glyph, blue token, uppercase tracking) preserved.
The ★ Featured badge for promoted==='premium' is untouched.
Note: BB still has the original 'Advertiser' label; this change is avbeat-only
unless Ryan asks for it mirrored on BB.
Top-of-article block (above the featured image) used Inter (font-heading)
and inconsistent colors (H1 navy, dek light-grey #999, author name
near-white #e0e0e0). With the body section now in Georgia-style serif
on slate-800 (#1e293b), the header read as a separate visual zone.
Unified both detail routes:
src/app/news/[slug]/NewsArticleDetailClient.tsx
- H1 :309 font-heading text-[#0F172A] → font-serif text-[#1e293b]
- Dek :315 font-body text-[#999] → font-serif text-[#1e293b] (this is the lead summary line that was reading as 'white' on the Magewell article — same near-white #999 on white surface)
- Author name link :332 font-heading text-[#e0e0e0] → font-serif text-[#1e293b]
src/app/articles/[slug]/ArticleDetailClient.tsx
- H1 :255 same swap as above
- Author name link :274 same swap as above
Secondary meta (category eyebrow #1D4ED8 blue, read-time/date/author-title #777) intentionally kept at their muted shades — those are subordinate text and read fine on the light surface.
Article detail pages (/news/[slug] and /articles/[slug]) inherited a dark-theme
prose color palette via the .bb-article-prose ruleset + Tailwind's
prose-invert utility. With the new light surface, every text element in
the article body rendered near-white on white, while the H1 (fixed in
the prior commit) was already navy. Bringing the body in line:
src/styles/tailwind.css:
- .bb-article-prose wrapper #d6d4d0 -> #1e293b !important (slate-800 for long-form body)
- .bb-article-prose p:first-of-type #e8e6e0 -> #1e293b
- .bb-article-prose first-letter #f0eee8 -> #0F172A (drop-cap full navy)
- .bb-article-prose h2 #f5f3ee -> #0F172A (in-body subhead matches the page H1)
- .bb-article-prose h3 #ece9e2 -> #0F172A
- .bb-article-prose blockquote #e8e6e0 -> #1e293b
- .bb-article-prose a (BASE) #d6d4d0 -> #1D4ED8 (inline links visibly blue at rest, no longer invisible-until-hover; hover unchanged)
src/app/news/[slug]/NewsArticleDetailClient.tsx
src/app/articles/[slug]/ArticleDetailClient.tsx
- Drop 'prose-invert' from the wrapper className on both routes so any
descendant the bb-article-prose rules don't explicitly color (lists,
strong, em, captions) falls back to Tailwind Typography's default
light-page slate-700 palette.
FeaturedBentoFromDb.tsx:119 — hero excerpt size ramp halved:
text-base md:text-lg (16 / 18 px)
→ text-xs md:text-sm (12 / 14 px)
Restores a clear size gap below the (already-shrunk) hero headline; the
excerpt was visually competing with the title at the same breakpoint.
Typography (approved Phase 1 slice only — utility classes + other reclasses deferred):
- src/styles/tailwind.css body rule: re-add smoothing now that the surface palette is locked in — -webkit-font-smoothing antialiased, -moz-osx-font-smoothing grayscale, text-rendering optimizeLegibility, font-feature-settings 'kern','liga', global letter-spacing -0.005em.
- src/components/FeaturedBentoFromDb.tsx:115 cinematic hero headline: text-2xl md:text-4xl lg:text-5xl leading-tight → text-[40px] md:text-[48px] lg:text-[56px] leading-[1.05] tracking-[-0.02em] font-bold. Confident editorial display per the avinteractive reference.
- src/app/news/[slug]/NewsArticleDetailClient.tsx:309 and src/app/articles/[slug]/ArticleDetailClient.tsx:255 article H1: text-[#f0f0f0] → text-[#0F172A]. Fixes the leftover white-on-white readability bug on article pages.
UI:
- src/app/home-page/components/ArticleFeed.tsx: removed the 'Topics:' chip row from Industry News per current design direction; all stories now show without per-topic filter.
Schema wiring — AV Beat was inheriting a 'bb' default schema from the
original fork. Fixed three call sites so the AV Beat app reads/writes
the av schema unless an explicit NEXT_PUBLIC_SUPABASE_SCHEMA override
is set:
- src/lib/supabase/client.tsx:8 default 'bb' -> 'av'
- src/lib/supabase/server.tsx:11 default 'bb' -> 'av'
- src/app/api/auth/lookup-email/route.ts :31 + :42 hardcoded
.schema('bb') -> .schema('av') so signup lookup hits the
AV-side subscriber tables, not BB's.
Newsletter signup — homepage chips were the BB taxonomy ('Broadcast',
'Post Production', 'Animation', 'AI & Automation', 'Live Production',
'NAB Show'). Swapped for pro-AV verticals that align with the new
forum categories: Conference Rooms & UC, Digital Signage, Live Events
& Staging, Displays & LED, Audio, AV over IP, InfoComm & ISE.
Default selected flipped from 'Broadcast' to 'Conference Rooms & UC'
so the form doesn't pre-select a non-existent value.
-webkit-font-smoothing: antialiased and -moz-osx-font-smoothing: grayscale
were set on body and the Tailwind 'antialiased' utility was applied on
<body>. Both pair correctly with the prior dark theme (light text on
dark surfaces), but on the new white surface they render Inter + Lora
thinner and harsher — strokes lose weight, edges read as jagged.
Removed from src/styles/tailwind.css:59-60 (body rule) and from the
<body className="... antialiased"> utility in src/app/layout.tsx:143.
OS default smoothing (subpixel on Windows / older macOS, 'auto' on modern)
gives Inter + Lora their intended weight and roundness.
dynamic='force-dynamic' + revalidate=0 on the page weren't enough because
FeaturedBentoFromDb -> pickAds() -> fetch in src/lib/ads.ts:98 sets
next:{revalidate:30}. Next.js takes the lowest positive revalidate from
the render tree and opts the whole route into 30-second ISR (visible in
.next/prerender-manifest.json: '/' initialRevalidateSeconds: 30), masking
the page-level force-dynamic directive.
unstable_noStore() called at the top of the HomePage component body
forces an unambiguous, child-tree-overriding opt-out so the Telycam
hero swap (and any future DB-driven hero change) renders on every
request. lib/ads.ts caching is left alone — its revalidate is fine for
ad rotation; we just stop it from poisoning the page-level cache.
(A) src/components/AISuggestedArticles.tsx :186 + :287 — 'AI Suggested Articles' card titles
used text-[#e0e0e0] on now-white card surfaces, making the title invisible until
group-hover flipped it to #1D4ED8. Both occurrences changed to text-[#0F172A].
(ArticleFeed.tsx:627 and NewsPageClient.tsx:276 were already navy from the
prior contrast-fix deploy and cover both pagination + infinite-scroll variants.)
(B) src/components/AvBeatLogo.tsx :99 — header tagline 'Inside the Future of Pro AV'
was rendered in --brand-text-muted (#475569 slate) on a now-blue nav (#1D4ED8),
near-invisible. Changed to rgba(255,255,255,0.85) so it reads against the blue
while sitting visually subordinate to the wordmark above it.
(C) src/lib/articles/excerpt.ts — cleanExcerpt now strips HTML tags (<p>, <br>, <em>, etc.)
and decodes common entities ( , &, <, >, ", ', ') at
render time, then collapses whitespace before the existing trailing-junk/last-word
logic runs. Display-layer only — stored excerpts are not mutated, matching the
'fix at the DISPLAY layer' instruction.
The 2026 rebrand swept surface hexes from dark to light but left near-white text colors baked into components. Three approved fixes:
- FeaturedBento.tsx:255 — 2x2 grid card titles base color #e0e0e0 -> #0F172A (brand-navy). Hover stays #1D4ED8.
- tailwind.css .nav-link-bb — base color #cccccc -> var(--brand-text). Hover unchanged.
- ArticleFeed.tsx :375 + :385 — date input text #888 -> #475569 (brand-text-muted) and dropped [color-scheme:dark] so Chrome stops rendering the dark date-picker chrome on a now-white input.
Findings #2, #3, #6 in the audit were not touched — Ryan flagged them as unverified.
Next.js sets a long s-maxage on prerendered HTML even for routes flagged force-dynamic; Cloudflare then caches that response and ignores subsequent dynamic renders. Explicit Cache-Control + CDN-Cache-Control no-store on / and /news/* keeps the hero swap visible immediately after a DB change.
- Main nav background → brand-blue #1D4ED8 (sampled from logo emblem).
- Nav link text → white with darker-blue hover bg so contrast holds.
- Article card title fixed from #e0e0e0 to navy #0F172A (was unreadable on the new white surface).
- Industry News card date row removed.
- /news Topics filter chip row removed.
- /news article hover from stark #111 to light-blue #EFF6FF tint matching the brand.
- Tagline 'News & Intelligence for Pro AV, Live Production & Display Tech' renamed to 'Pro AV, Display and Live Production Tech' across Header, RSS feed, newsletter welcome template, root layout title, page title, OG/Twitter tags.
- Homepage page.tsx now has `export const dynamic = 'force-dynamic'` + `revalidate = 0` so the hero (FeaturedBentoFromDb) actually re-renders against the live supabase row (previously the page was being statically prerendered which masked DB-driven hero swaps).
- 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.