about/show-coverage: redesign with sidebar (300x600 + rotating 300x250s)
Switch the bare single-column layouts on these pages to a two-column
grid that pulls in <SidebarAdStack /> on the right (pinned 300x600 +
every 300x250 rotated). Header keeps the leaderboard above. The
in-content 728x90 banners added earlier are removed since the sidebar
now carries the ad load (avoids stacking two of the same unit on the
page).
Pages updated:
- /show-coverage/[slug] event detail
- /about
- /about/contact
- /about/team
- /about/advertise (also gets a real-banner grid in "Available units":
the actual 728x90, 300x600, and 300x250 sample creatives are
rendered next to each unit's description, so advertisers see what
the inventory looks like in production rather than just a label).
The /about pages also got a small refresh: serif H1 + accent-blue
"Broadcast Beat" eyebrow line + bordered content blocks, bringing the
look closer to the cinematic homepage.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -1,60 +1,113 @@
|
||||
import Header from "@/components/Header";
|
||||
import Footer from "@/components/Footer";
|
||||
import AdImage from "@/components/AdImage";
|
||||
import { ADS_728X90, shuffle } from "@/lib/ads";
|
||||
import SidebarAdStack from "@/components/SidebarAdStack";
|
||||
import { ADS_728X90, ADS_300X250, FIXED_300X600, shuffle } from "@/lib/ads";
|
||||
|
||||
export const metadata = { title: "Advertise — Broadcast Beat" };
|
||||
|
||||
export default function AdvertisePage() {
|
||||
const example728 = ADS_728X90[0];
|
||||
const example300x250 = ADS_300X250[0];
|
||||
const example300x600 = FIXED_300X600;
|
||||
|
||||
return (
|
||||
<div className="min-h-screen bg-background">
|
||||
<Header />
|
||||
<main className="mx-auto max-w-3xl px-6 py-12 text-[#e5e7eb]">
|
||||
<h1 className="font-serif text-4xl font-bold tracking-tight mb-2">Advertise on Broadcast Beat</h1>
|
||||
<p className="text-sm text-[#9ca3af] mb-10">
|
||||
Broadcast Beat reaches broadcast engineers, post supervisors, streaming
|
||||
architects, and live-event professionals across the industry.
|
||||
</p>
|
||||
<div className="mx-auto max-w-6xl px-6 py-12 text-[#e5e7eb]">
|
||||
<div className="lg:grid lg:grid-cols-[1fr,300px] lg:gap-10">
|
||||
<main>
|
||||
<header className="mb-8 border-b border-[#252525] pb-6">
|
||||
<div className="text-[10px] font-mono uppercase tracking-[0.22em] text-[var(--color-text-info,#60a5fa)] mb-2">
|
||||
Broadcast Beat
|
||||
</div>
|
||||
<h1 className="font-serif text-4xl md:text-5xl font-bold tracking-tight">Advertise</h1>
|
||||
<p className="mt-3 text-[#9ca3af] text-base max-w-2xl">
|
||||
Broadcast Beat reaches broadcast engineers, post supervisors,
|
||||
streaming architects, and live-event professionals across the
|
||||
industry — daily.
|
||||
</p>
|
||||
</header>
|
||||
|
||||
<section className="mb-10">
|
||||
<h2 className="font-mono text-xs uppercase tracking-wider text-[#6b7280] mb-3">Available units</h2>
|
||||
<ul className="space-y-3 text-[15px]">
|
||||
<li>
|
||||
<strong>728×90 leaderboard</strong> — between main nav and headline ticker, sitewide.
|
||||
</li>
|
||||
<li>
|
||||
<strong>300×600 sidebar premium</strong> — pinned top of every sidebar, sitewide.
|
||||
</li>
|
||||
<li>
|
||||
<strong>300×250 sidebar rotation</strong> — rotates across every page, multiple slots.
|
||||
</li>
|
||||
</ul>
|
||||
</section>
|
||||
<section className="mb-12">
|
||||
<h2 className="font-mono text-xs uppercase tracking-[0.18em] text-[var(--color-text-info,#60a5fa)] mb-5">
|
||||
Available units
|
||||
</h2>
|
||||
|
||||
{/* In-content 728x90 banner (live example of the leaderboard unit) */}
|
||||
{ADS_728X90.length > 0 && (
|
||||
<div className="my-10 hidden md:flex justify-center" aria-label="Advertisement">
|
||||
<AdImage ad={shuffle(ADS_728X90)[0]} page="advertise" />
|
||||
</div>
|
||||
)}
|
||||
<div className="grid grid-cols-1 gap-5">
|
||||
{/* 728x90 */}
|
||||
<div className="rounded border border-[#252525] bg-[#0b0f17] p-5 flex flex-col md:flex-row md:items-center gap-5">
|
||||
<div className="md:flex-1 min-w-0">
|
||||
<h3 className="font-serif text-xl font-semibold">728 × 90 leaderboard</h3>
|
||||
<div className="mt-1 text-[10px] font-mono uppercase tracking-wider text-[#6b7280]">Site-wide · top of every page</div>
|
||||
<p className="mt-3 text-sm text-[#d1d5db]">
|
||||
Sits between the main nav and the headline ticker on
|
||||
every page. The premium first-impression unit.
|
||||
</p>
|
||||
</div>
|
||||
<div className="flex-shrink-0 flex items-center justify-center rounded border border-[#1e1e1e] bg-[#0a0a0a] p-3" style={{ minWidth: 250 }}>
|
||||
{example728 ? <AdImage ad={example728} page="advertise-example" /> : <div className="w-[728px] max-w-full h-[90px] flex items-center justify-center text-xs text-[#555]">728 × 90</div>}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<section className="mb-10">
|
||||
<h2 className="font-mono text-xs uppercase tracking-wider text-[#6b7280] mb-3">Reporting</h2>
|
||||
<p className="text-[15px] text-[#d1d5db]">
|
||||
Every banner is tracked for gross impressions and clicks. Advertisers
|
||||
receive a monthly report with totals and CTR. Click links route through
|
||||
/r/{"{campaign}"} for accurate counting independent of analytics
|
||||
blockers.
|
||||
</p>
|
||||
</section>
|
||||
{/* 300x600 */}
|
||||
<div className="rounded border border-[#252525] bg-[#0b0f17] p-5 flex flex-col md:flex-row md:items-center gap-5">
|
||||
<div className="md:flex-1 min-w-0">
|
||||
<h3 className="font-serif text-xl font-semibold">300 × 600 sidebar premium</h3>
|
||||
<div className="mt-1 text-[10px] font-mono uppercase tracking-wider text-[#6b7280]">Pinned · every sidebar · sitewide</div>
|
||||
<p className="mt-3 text-sm text-[#d1d5db]">
|
||||
Pinned at the top of every sidebar, sitewide. Stays
|
||||
visible while readers scroll the article body.
|
||||
</p>
|
||||
</div>
|
||||
<div className="flex-shrink-0 flex items-center justify-center rounded border border-[#1e1e1e] bg-[#0a0a0a] p-3">
|
||||
{example300x600 ? <AdImage ad={example300x600} page="advertise-example" /> : <div className="w-[300px] h-[600px] flex items-center justify-center text-xs text-[#555]">300 × 600</div>}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<section>
|
||||
<h2 className="font-mono text-xs uppercase tracking-wider text-[#6b7280] mb-3">Get in touch</h2>
|
||||
<p className="text-[15px]">
|
||||
<a className="text-[var(--color-text-info,#60a5fa)] hover:underline" href="mailto:advertising@broadcastbeat.com">advertising@broadcastbeat.com</a>
|
||||
</p>
|
||||
</section>
|
||||
</main>
|
||||
{/* 300x250 */}
|
||||
<div className="rounded border border-[#252525] bg-[#0b0f17] p-5 flex flex-col md:flex-row md:items-center gap-5">
|
||||
<div className="md:flex-1 min-w-0">
|
||||
<h3 className="font-serif text-xl font-semibold">300 × 250 sidebar rotation</h3>
|
||||
<div className="mt-1 text-[10px] font-mono uppercase tracking-wider text-[#6b7280]">Rotating · multiple slots · every page</div>
|
||||
<p className="mt-3 text-sm text-[#d1d5db]">
|
||||
Rotates across every page, multiple slots per page.
|
||||
Highest-volume inventory — best for awareness campaigns
|
||||
and seasonal pushes (NAB, IBC, BroadcastAsia).
|
||||
</p>
|
||||
</div>
|
||||
<div className="flex-shrink-0 flex items-center justify-center rounded border border-[#1e1e1e] bg-[#0a0a0a] p-3">
|
||||
{example300x250 ? <AdImage ad={example300x250} page="advertise-example" /> : <div className="w-[300px] h-[250px] flex items-center justify-center text-xs text-[#555]">300 × 250</div>}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section className="mb-10">
|
||||
<h2 className="font-mono text-xs uppercase tracking-[0.18em] text-[var(--color-text-info,#60a5fa)] mb-3">Reporting</h2>
|
||||
<p className="text-[15px] text-[#d1d5db] leading-relaxed">
|
||||
Every banner is tracked for gross impressions and clicks.
|
||||
Advertisers receive a monthly report with totals and CTR. Click
|
||||
links route through <code className="text-[#60a5fa]">/r/{`{campaign}`}</code> for accurate counting independent of
|
||||
analytics blockers.
|
||||
</p>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<h2 className="font-mono text-xs uppercase tracking-[0.18em] text-[var(--color-text-info,#60a5fa)] mb-3">Get in touch</h2>
|
||||
<p className="text-[15px]">
|
||||
<a className="text-[var(--color-text-info,#60a5fa)] hover:underline" href="mailto:advertising@broadcastbeat.com">advertising@broadcastbeat.com</a>
|
||||
</p>
|
||||
</section>
|
||||
</main>
|
||||
|
||||
<aside className="mt-10 lg:mt-0" aria-label="Advertisements">
|
||||
<div className="lg:sticky lg:top-24">
|
||||
<SidebarAdStack />
|
||||
</div>
|
||||
</aside>
|
||||
</div>
|
||||
</div>
|
||||
<Footer />
|
||||
</div>
|
||||
);
|
||||
|
||||
@@ -1,45 +1,86 @@
|
||||
import Header from "@/components/Header";
|
||||
import Footer from "@/components/Footer";
|
||||
import AdImage from "@/components/AdImage";
|
||||
import { ADS_728X90, shuffle } from "@/lib/ads";
|
||||
import SidebarAdStack from "@/components/SidebarAdStack";
|
||||
|
||||
export const metadata = { title: "Contact — Broadcast Beat" };
|
||||
|
||||
const CONTACTS = [
|
||||
{
|
||||
title: "Editorial",
|
||||
body: (
|
||||
<a className="text-[var(--color-text-info,#60a5fa)] hover:underline" href="mailto:editor@broadcastbeat.com">editor@broadcastbeat.com</a>
|
||||
),
|
||||
hint: "Story tips, corrections, interview requests.",
|
||||
},
|
||||
{
|
||||
title: "Press releases",
|
||||
body: (
|
||||
<>
|
||||
Route PR-firm submissions through{" "}
|
||||
<a className="text-[var(--color-text-info,#60a5fa)] hover:underline" href="https://distribution.relevantmediaproperties.com">distribution.relevantmediaproperties.com</a>.
|
||||
</>
|
||||
),
|
||||
hint: "Routed submissions land in our editorial queue with provenance.",
|
||||
},
|
||||
{
|
||||
title: "Advertising",
|
||||
body: (
|
||||
<>
|
||||
<a className="text-[var(--color-text-info,#60a5fa)] hover:underline" href="mailto:advertising@broadcastbeat.com">advertising@broadcastbeat.com</a> — see the{" "}
|
||||
<a className="text-[var(--color-text-info,#60a5fa)] hover:underline" href="/about/advertise">media kit</a>.
|
||||
</>
|
||||
),
|
||||
hint: "728×90, 300×600, 300×250 inventory; CTR + impression reports monthly.",
|
||||
},
|
||||
{
|
||||
title: "Publisher",
|
||||
body: (
|
||||
<>
|
||||
Ryan Salazar ·{" "}
|
||||
<a className="text-[var(--color-text-info,#60a5fa)] hover:underline" href="mailto:ryan.salazar@relevantmediaproperties.com">ryan.salazar@relevantmediaproperties.com</a>
|
||||
</>
|
||||
),
|
||||
hint: "Partnerships, M&A, syndication, network membership.",
|
||||
},
|
||||
];
|
||||
|
||||
export default function ContactPage() {
|
||||
return (
|
||||
<div className="min-h-screen bg-background">
|
||||
<Header />
|
||||
<main className="mx-auto max-w-2xl px-6 py-12 text-[#e5e7eb]">
|
||||
<h1 className="font-serif text-4xl font-bold tracking-tight mb-6">Contact</h1>
|
||||
<dl className="space-y-5 text-[15px]">
|
||||
<div>
|
||||
<dt className="text-xs font-mono uppercase tracking-wider text-[#6b7280] mb-1">Editorial</dt>
|
||||
<dd><a className="text-[var(--color-text-info,#60a5fa)] hover:underline" href="mailto:editor@broadcastbeat.com">editor@broadcastbeat.com</a></dd>
|
||||
</div>
|
||||
<div>
|
||||
<dt className="text-xs font-mono uppercase tracking-wider text-[#6b7280] mb-1">Press releases (PR firms)</dt>
|
||||
<dd>
|
||||
Route submissions through{" "}
|
||||
<a className="text-[var(--color-text-info,#60a5fa)] hover:underline" href="https://distribution.relevantmediaproperties.com">distribution.relevantmediaproperties.com</a>.
|
||||
</dd>
|
||||
</div>
|
||||
<div>
|
||||
<dt className="text-xs font-mono uppercase tracking-wider text-[#6b7280] mb-1">Advertising</dt>
|
||||
<dd><a className="text-[var(--color-text-info,#60a5fa)] hover:underline" href="mailto:advertising@broadcastbeat.com">advertising@broadcastbeat.com</a> — see <a className="text-[var(--color-text-info,#60a5fa)] hover:underline" href="/about/advertise">media kit</a>.</dd>
|
||||
</div>
|
||||
<div>
|
||||
<dt className="text-xs font-mono uppercase tracking-wider text-[#6b7280] mb-1">Publisher</dt>
|
||||
<dd>Ryan Salazar · <a className="text-[var(--color-text-info,#60a5fa)] hover:underline" href="mailto:ryan.salazar@relevantmediaproperties.com">ryan.salazar@relevantmediaproperties.com</a></dd>
|
||||
</div>
|
||||
</dl>
|
||||
<div className="mx-auto max-w-6xl px-6 py-12 text-[#e5e7eb]">
|
||||
<div className="lg:grid lg:grid-cols-[1fr,300px] lg:gap-10">
|
||||
<main>
|
||||
<header className="mb-8 border-b border-[#252525] pb-6">
|
||||
<div className="text-[10px] font-mono uppercase tracking-[0.22em] text-[var(--color-text-info,#60a5fa)] mb-2">
|
||||
Broadcast Beat
|
||||
</div>
|
||||
<h1 className="font-serif text-4xl md:text-5xl font-bold tracking-tight">Contact</h1>
|
||||
<p className="mt-3 text-[#9ca3af] text-base">
|
||||
Pitches, press, partnerships — pick the right desk and we'll get back fast.
|
||||
</p>
|
||||
</header>
|
||||
|
||||
{/* In-content 728x90 banner */}
|
||||
{ADS_728X90.length > 0 && (
|
||||
<div className="mt-12 hidden md:flex justify-center" aria-label="Advertisement">
|
||||
<AdImage ad={shuffle(ADS_728X90)[0]} page="contact" />
|
||||
</div>
|
||||
)}
|
||||
</main>
|
||||
<ul className="grid grid-cols-1 md:grid-cols-2 gap-4">
|
||||
{CONTACTS.map((c) => (
|
||||
<li key={c.title} className="rounded border border-[#252525] bg-[#0b0f17] p-5 hover:border-[var(--color-text-info,#60a5fa)]/60 transition-colors">
|
||||
<div className="text-[10px] font-mono uppercase tracking-[0.18em] text-[var(--color-text-info,#60a5fa)] mb-2">
|
||||
{c.title}
|
||||
</div>
|
||||
<div className="text-[15px] leading-relaxed">{c.body}</div>
|
||||
<div className="mt-3 text-xs text-[#6b7280]">{c.hint}</div>
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
</main>
|
||||
|
||||
<aside className="mt-10 lg:mt-0" aria-label="Advertisements">
|
||||
<div className="lg:sticky lg:top-24">
|
||||
<SidebarAdStack />
|
||||
</div>
|
||||
</aside>
|
||||
</div>
|
||||
</div>
|
||||
<Footer />
|
||||
</div>
|
||||
);
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import Header from "@/components/Header";
|
||||
import Footer from "@/components/Footer";
|
||||
import SidebarAdStack from "@/components/SidebarAdStack";
|
||||
|
||||
export const metadata = {
|
||||
title: "About Broadcast Beat",
|
||||
@@ -10,31 +11,90 @@ export default function AboutPage() {
|
||||
return (
|
||||
<div className="min-h-screen bg-background">
|
||||
<Header />
|
||||
<main className="mx-auto max-w-3xl px-6 py-12 text-[#e5e7eb]">
|
||||
<h1 className="font-serif text-4xl font-bold tracking-tight mb-6">About Broadcast Beat</h1>
|
||||
<div className="space-y-5 text-[#d1d5db] text-[15px] leading-relaxed">
|
||||
<p>
|
||||
Broadcast Beat is an independent trade publication covering broadcast,
|
||||
live production, streaming, and post-production technology. We
|
||||
report on the equipment, services, and people that move the
|
||||
professional video industry forward.
|
||||
</p>
|
||||
<p>
|
||||
We cover the major industry shows — NAB, IBC, BroadcastAsia, MPTS,
|
||||
and others — track product launches and acquisitions, and publish
|
||||
interviews with the engineers, post supervisors, and executives
|
||||
building the next generation of workflows.
|
||||
</p>
|
||||
<p>
|
||||
Editorial decisions are made independently of advertising. We do
|
||||
not accept payment for editorial coverage. Vendor-supplied press
|
||||
releases routed through our distribution platform are rewritten
|
||||
by our staff or AI assistants according to our editorial style
|
||||
guide; the original submission is preserved on file.
|
||||
</p>
|
||||
<div className="mx-auto max-w-6xl px-6 py-12 text-[#e5e7eb]">
|
||||
<div className="lg:grid lg:grid-cols-[1fr,300px] lg:gap-10">
|
||||
<main>
|
||||
<header className="mb-8 border-b border-[#252525] pb-6">
|
||||
<div className="text-[10px] font-mono uppercase tracking-[0.22em] text-[var(--color-text-info,#60a5fa)] mb-2">
|
||||
Broadcast Beat
|
||||
</div>
|
||||
<h1 className="font-serif text-4xl md:text-5xl font-bold tracking-tight">About</h1>
|
||||
<p className="mt-3 text-[#9ca3af] text-base max-w-2xl">
|
||||
An independent trade publication covering broadcast, live production, streaming, and post-production technology.
|
||||
</p>
|
||||
</header>
|
||||
|
||||
<div className="grid grid-cols-1 md:grid-cols-3 gap-4 mb-10">
|
||||
<Stat label="Years covering the industry" value="20+" />
|
||||
<Stat label="Shows tracked annually" value="14+" />
|
||||
<Stat label="Stories archived" value="29k+" />
|
||||
</div>
|
||||
|
||||
<section className="space-y-6 text-[#d1d5db] text-[15px] leading-relaxed">
|
||||
<Block title="What we cover">
|
||||
Broadcast Beat reports on the equipment, services, and people
|
||||
that move the professional video industry forward. We follow
|
||||
product launches, executive moves, acquisitions, and the live
|
||||
production / IP / cloud workflows reshaping how content gets
|
||||
made and delivered.
|
||||
</Block>
|
||||
|
||||
<Block title="Where we go">
|
||||
We cover the major industry shows in person and remotely — NAB
|
||||
Show, IBC, BroadcastAsia, MPTS, InfoComm, and more — track
|
||||
product launches and acquisitions year-round, and publish
|
||||
interviews with the engineers, post supervisors, and executives
|
||||
building the next generation of workflows.
|
||||
</Block>
|
||||
|
||||
<Block title="How we work">
|
||||
Editorial decisions are made independently of advertising. We
|
||||
do not accept payment for editorial coverage. Vendor-supplied
|
||||
press releases routed through our distribution platform are
|
||||
rewritten by our staff or AI assistants according to our
|
||||
editorial style guide; the original submission is preserved on
|
||||
file. Our AI personas are clearly labeled wherever they appear.
|
||||
</Block>
|
||||
|
||||
<Block title="Get involved">
|
||||
For editorial pitches: <a className="text-[var(--color-text-info,#60a5fa)] hover:underline" href="mailto:editor@broadcastbeat.com">editor@broadcastbeat.com</a>.
|
||||
{" "}For advertising: <a className="text-[var(--color-text-info,#60a5fa)] hover:underline" href="/about/advertise">see the media kit</a>.
|
||||
{" "}For our team: <a className="text-[var(--color-text-info,#60a5fa)] hover:underline" href="/about/team">meet the editorial team</a>.
|
||||
</Block>
|
||||
</section>
|
||||
</main>
|
||||
|
||||
{/* Sidebar: 300x600 + rotating 300x250s */}
|
||||
<aside className="mt-10 lg:mt-0" aria-label="Advertisements">
|
||||
<div className="lg:sticky lg:top-24">
|
||||
<SidebarAdStack />
|
||||
</div>
|
||||
</aside>
|
||||
</div>
|
||||
</main>
|
||||
</div>
|
||||
<Footer />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
function Stat({ label, value }: { label: string; value: string }) {
|
||||
return (
|
||||
<div className="rounded border border-[#252525] bg-[#0b0f17] p-4">
|
||||
<div className="font-serif text-3xl text-white">{value}</div>
|
||||
<div className="mt-1 text-[10px] font-mono uppercase tracking-[0.16em] text-[#6b7280]">
|
||||
{label}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
function Block({ title, children }: { title: string; children: React.ReactNode }) {
|
||||
return (
|
||||
<div className="rounded border border-[#1e1e1e] bg-[#0b0f17]/70 p-5">
|
||||
<h2 className="font-mono text-xs uppercase tracking-[0.18em] text-[var(--color-text-info,#60a5fa)] mb-2">
|
||||
{title}
|
||||
</h2>
|
||||
<p className="text-[15px] leading-relaxed">{children}</p>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
import { createClient } from "@supabase/supabase-js";
|
||||
import Header from "@/components/Header";
|
||||
import Footer from "@/components/Footer";
|
||||
import AdImage from "@/components/AdImage";
|
||||
import { ADS_728X90, shuffle } from "@/lib/ads";
|
||||
import SidebarAdStack from "@/components/SidebarAdStack";
|
||||
|
||||
export const dynamic = "force-dynamic";
|
||||
export const revalidate = 600;
|
||||
@@ -38,44 +37,52 @@ export default async function TeamPage() {
|
||||
return (
|
||||
<div className="min-h-screen bg-background">
|
||||
<Header />
|
||||
<main className="mx-auto max-w-5xl px-6 py-12 text-[#e5e7eb]">
|
||||
<h1 className="font-serif text-4xl font-bold tracking-tight mb-2">Editorial team</h1>
|
||||
<p className="text-sm text-[#9ca3af] mb-10">
|
||||
Staff journalists by beat. We are a mix of human reporters and trained
|
||||
AI personas operating under house style.
|
||||
</p>
|
||||
<ul className="grid grid-cols-1 md:grid-cols-2 gap-5">
|
||||
{team.map((p) => (
|
||||
<li key={p.slug} className="rounded border border-[#252525] bg-[#0b0f17] p-5 flex gap-4">
|
||||
{p.avatar_url && (
|
||||
<img
|
||||
src={p.avatar_url}
|
||||
alt={p.name}
|
||||
width={64}
|
||||
height={64}
|
||||
className="rounded-full border border-[#252525]"
|
||||
/>
|
||||
)}
|
||||
<div className="flex-1">
|
||||
<h2 className="font-serif text-lg font-semibold">{p.name}</h2>
|
||||
{p.beat && (
|
||||
<div className="text-[10px] font-mono uppercase tracking-wider text-[var(--color-text-info,#60a5fa)] mt-0.5">
|
||||
{p.beat.replace(/-/g, " ")}
|
||||
</div>
|
||||
)}
|
||||
{p.bio && <p className="text-sm text-[#9ca3af] mt-2 leading-relaxed">{p.bio}</p>}
|
||||
<div className="mx-auto max-w-6xl px-6 py-12 text-[#e5e7eb]">
|
||||
<div className="lg:grid lg:grid-cols-[1fr,300px] lg:gap-10">
|
||||
<main>
|
||||
<header className="mb-8 border-b border-[#252525] pb-6">
|
||||
<div className="text-[10px] font-mono uppercase tracking-[0.22em] text-[var(--color-text-info,#60a5fa)] mb-2">
|
||||
Broadcast Beat
|
||||
</div>
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
<h1 className="font-serif text-4xl md:text-5xl font-bold tracking-tight">Editorial team</h1>
|
||||
<p className="mt-3 text-[#9ca3af] text-base">
|
||||
Staff journalists by beat — a mix of human reporters and trained AI personas operating under house style.
|
||||
</p>
|
||||
</header>
|
||||
|
||||
{/* In-content 728x90 banner */}
|
||||
{ADS_728X90.length > 0 && (
|
||||
<div className="mt-12 hidden md:flex justify-center" aria-label="Advertisement">
|
||||
<AdImage ad={shuffle(ADS_728X90)[0]} page="team" />
|
||||
</div>
|
||||
)}
|
||||
</main>
|
||||
<ul className="grid grid-cols-1 md:grid-cols-2 gap-5">
|
||||
{team.map((p) => (
|
||||
<li key={p.slug} className="rounded border border-[#252525] bg-[#0b0f17] p-5 flex gap-4 hover:border-[var(--color-text-info,#60a5fa)]/60 transition-colors">
|
||||
{p.avatar_url && (
|
||||
<img
|
||||
src={p.avatar_url}
|
||||
alt={p.name}
|
||||
width={64}
|
||||
height={64}
|
||||
className="rounded-full border border-[#252525] flex-shrink-0"
|
||||
/>
|
||||
)}
|
||||
<div className="flex-1 min-w-0">
|
||||
<h2 className="font-serif text-lg font-semibold">{p.name}</h2>
|
||||
{p.beat && (
|
||||
<div className="text-[10px] font-mono uppercase tracking-wider text-[var(--color-text-info,#60a5fa)] mt-0.5">
|
||||
{p.beat.replace(/-/g, " ")}
|
||||
</div>
|
||||
)}
|
||||
{p.bio && <p className="text-sm text-[#9ca3af] mt-2 leading-relaxed">{p.bio}</p>}
|
||||
</div>
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
</main>
|
||||
|
||||
<aside className="mt-10 lg:mt-0" aria-label="Advertisements">
|
||||
<div className="lg:sticky lg:top-24">
|
||||
<SidebarAdStack />
|
||||
</div>
|
||||
</aside>
|
||||
</div>
|
||||
</div>
|
||||
<Footer />
|
||||
</div>
|
||||
);
|
||||
|
||||
@@ -4,6 +4,7 @@ import { createClient } from "@supabase/supabase-js";
|
||||
import Header from "@/components/Header";
|
||||
import Footer from "@/components/Footer";
|
||||
import AdImage from "@/components/AdImage";
|
||||
import SidebarAdStack from "@/components/SidebarAdStack";
|
||||
import { ADS_728X90, shuffle } from "@/lib/ads";
|
||||
|
||||
export const dynamic = "force-dynamic";
|
||||
@@ -162,11 +163,13 @@ export default async function EventCoveragePage({
|
||||
return (
|
||||
<div className="min-h-screen bg-background">
|
||||
<Header />
|
||||
<main className="mx-auto max-w-5xl px-6 py-10 text-[#e5e7eb]">
|
||||
<div className="mx-auto max-w-6xl px-6 py-10 text-[#e5e7eb]">
|
||||
<script
|
||||
type="application/ld+json"
|
||||
dangerouslySetInnerHTML={{ __html: JSON.stringify(eventJsonLd) }}
|
||||
/>
|
||||
<div className="lg:grid lg:grid-cols-[1fr,300px] lg:gap-8">
|
||||
<main>
|
||||
<Link href="/show-coverage" className="text-sm text-[var(--color-text-info,#60a5fa)] hover:underline">
|
||||
← All events
|
||||
</Link>
|
||||
@@ -245,7 +248,16 @@ export default async function EventCoveragePage({
|
||||
</ul>
|
||||
)}
|
||||
</section>
|
||||
</main>
|
||||
</main>
|
||||
|
||||
{/* Sidebar: 300x600 + rotating 300x250s */}
|
||||
<aside className="mt-10 lg:mt-0" aria-label="Advertisements">
|
||||
<div className="lg:sticky lg:top-24">
|
||||
<SidebarAdStack />
|
||||
</div>
|
||||
</aside>
|
||||
</div>
|
||||
</div>
|
||||
<Footer />
|
||||
</div>
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user