Align site colors with GRV brand book palette.
Some checks failed
Deploy to Cloudflare Workers (OpenNext) / deploy (push) Has been cancelled

Centralize primary, secondary, tertiary, and neutral tokens and apply them across theme variables and UI components.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
kirukib 2026-06-04 14:45:22 +03:00
parent 6bdb2204b3
commit cb404ec079
61 changed files with 341 additions and 296 deletions

View File

@ -33,7 +33,7 @@ export default function ContactPage() {
<CardContent> <CardContent>
<a <a
href={`mailto:${ch.email}`} href={`mailto:${ch.email}`}
className="font-medium text-[#1f3d7e] hover:underline" className="font-medium text-[#30614c] hover:underline"
> >
{ch.email} {ch.email}
</a> </a>

View File

@ -29,7 +29,7 @@ export default function ExhibitPage() {
<ul className="space-y-3 text-left"> <ul className="space-y-3 text-left">
{benefits.map((b) => ( {benefits.map((b) => (
<li key={b} className="flex gap-2 text-sm"> <li key={b} className="flex gap-2 text-sm">
<span className="text-[#ffb300]"></span> <span className="text-[#37a47a]"></span>
{b} {b}
</li> </li>
))} ))}

View File

@ -30,39 +30,53 @@
--font-display: var(--font-display); --font-display: var(--font-display);
--font-wordmark: "Google Sans Flex Variable", system-ui, sans-serif; --font-wordmark: "Google Sans Flex Variable", system-ui, sans-serif;
--font-hero-serif: var(--font-hero-serif); --font-hero-serif: var(--font-hero-serif);
--color-brand-green: #1a5c38; --color-brand-primary: #37a47a;
--color-brand-green-dark: #0d3d26; --color-brand-secondary: #b9d8c9;
--color-brand-gold: #ffb300; --color-brand-tertiary: #30614c;
--color-brand-blue: #1f3d7e; --color-brand-black: #000000;
--color-brand-navy: #0f0404; --color-brand-grey-1: #5b5b5b;
--color-surface-muted: #f7f7f7; --color-brand-grey-2: #a0a0a0;
--color-text-muted: #767676; --color-brand-grey-3: #dbdbdb;
--color-brand-white: #ffffff;
--color-brand-green: var(--color-brand-primary);
--color-brand-green-dark: var(--color-brand-tertiary);
--color-surface-muted: #e8f2ec;
--color-text-muted: #5b5b5b;
} }
:root { :root {
--radius: 0.75rem; --radius: 0.75rem;
--background: #ffffff; --brand-primary: #37a47a;
--foreground: #0d3d26; --brand-secondary: #b9d8c9;
--card: #ffffff; --brand-tertiary: #30614c;
--card-foreground: #0d3d26; --brand-black: #000000;
--popover: #ffffff; --brand-grey-1: #5b5b5b;
--popover-foreground: #0d3d26; --brand-grey-2: #a0a0a0;
/* Primary: brand green · Secondary: white */ --brand-grey-3: #dbdbdb;
--primary: #1a5c38; --brand-white: #ffffff;
--primary-foreground: #ffffff; --brand-white-soft: #fafafa;
--secondary: #ffffff; --brand-surface-muted: #e8f2ec;
--secondary-foreground: #1a5c38; --background: var(--brand-white);
--muted: #f0f5f2; --foreground: var(--brand-tertiary);
--muted-foreground: #5a6b62; --card: var(--brand-white);
--accent: #ffb300; --card-foreground: var(--brand-tertiary);
--accent-foreground: #0d3d26; --popover: var(--brand-white);
--popover-foreground: var(--brand-tertiary);
--primary: var(--brand-primary);
--primary-foreground: var(--brand-white);
--secondary: var(--brand-secondary);
--secondary-foreground: var(--brand-tertiary);
--muted: var(--brand-surface-muted);
--muted-foreground: var(--brand-grey-1);
--accent: var(--brand-primary);
--accent-foreground: var(--brand-white);
--destructive: #dc2626; --destructive: #dc2626;
--border: #dce8e0; --border: var(--brand-grey-3);
--input: #dce8e0; --input: var(--brand-grey-3);
--ring: #1a5c38; --ring: var(--brand-primary);
--hero: #0d3d26; --hero: var(--brand-tertiary);
--section-muted: #f0f5f2; --section-muted: var(--brand-surface-muted);
--section-inverse: #1a5c38; --section-inverse: var(--brand-primary);
} }
@layer base { @layer base {
@ -96,12 +110,12 @@
text-wrap: balance; text-wrap: balance;
} }
.section-inverse { .section-inverse {
background-color: #1a5c38; background-color: var(--brand-primary);
color: #fafafa; color: var(--brand-white-soft);
} }
.section-green { .section-green {
background-color: #1a5c38; background-color: var(--brand-primary);
color: #fafafa; color: var(--brand-white-soft);
} }
@keyframes geometric-mess-drift { @keyframes geometric-mess-drift {
@ -249,10 +263,10 @@
/* Admission ticket — side notches + rounded body */ /* Admission ticket — side notches + rounded body */
.ticket-admission { .ticket-admission {
border-radius: 1rem; border-radius: 1rem;
--ticket-notch-fill: var(--section-inverse, #1a5c38); --ticket-notch-fill: var(--section-inverse, var(--brand-primary));
} }
.ticket-admission[data-ticket-notch="light"] { .ticket-admission[data-ticket-notch="light"] {
--ticket-notch-fill: #f0f5f2; --ticket-notch-fill: var(--brand-surface-muted);
} }
.ticket-admission::before, .ticket-admission::before,
.ticket-admission::after { .ticket-admission::after {
@ -278,11 +292,11 @@
:root { :root {
--rift-scroll: 0; --rift-scroll: 0;
--rift-canvas: #fbfdfb; --rift-canvas: #fbfdfb;
--rift-stroke: rgba(26, 92, 56, 0.18); --rift-stroke: rgba(55, 164, 122, 0.18);
--rift-stroke-minor: rgba(26, 92, 56, 0.26); --rift-stroke-minor: rgba(55, 164, 122, 0.26);
--rift-stroke-inverse: rgba(255, 255, 255, 0.25); --rift-stroke-inverse: rgba(255, 255, 255, 0.25);
--rift-accent: #ffb300; --rift-accent: var(--brand-secondary);
--rift-channel: #1a5c38; --rift-channel: var(--brand-primary);
} }
.rift-profile-partners .rift-contour-minor, .rift-profile-partners .rift-contour-minor,
@ -469,7 +483,7 @@
background: radial-gradient( background: radial-gradient(
ellipse 80% 60% at 50% 55%, ellipse 80% 60% at 50% 55%,
rgba(45, 122, 82, 0.14) 0%, rgba(45, 122, 82, 0.14) 0%,
rgba(26, 92, 56, 0.06) 45%, rgba(55, 164, 122, 0.06) 45%,
transparent 72% transparent 72%
); );
mix-blend-mode: soft-light; mix-blend-mode: soft-light;
@ -584,7 +598,7 @@
/* Readable brand-green copy on all white sections */ /* Readable brand-green copy on all white sections */
.section-white { .section-white {
color: #0d3d26; color: var(--brand-tertiary);
} }
.section-white .topo-content-layer, .section-white .topo-content-layer,
@ -599,26 +613,26 @@
.section-white .topo-content-readable :is(h1, h2, h3, h4, h5, h6, p, li, label, summary), .section-white .topo-content-readable :is(h1, h2, h3, h4, h5, h6, p, li, label, summary),
.section-white .topo-content-layer a:not([data-slot="button"]), .section-white .topo-content-layer a:not([data-slot="button"]),
.section-white .topo-content-readable a:not([data-slot="button"]) { .section-white .topo-content-readable a:not([data-slot="button"]) {
color: #0d3d26; color: var(--brand-tertiary);
text-shadow: none; text-shadow: none;
} }
.section-white .topo-content-layer .text-foreground, .section-white .topo-content-layer .text-foreground,
.section-white .topo-content-readable .text-foreground { .section-white .topo-content-readable .text-foreground {
color: #1a5c38; color: var(--brand-primary);
} }
.section-white .topo-content-layer .text-muted-foreground, .section-white .topo-content-layer .text-muted-foreground,
.section-white .topo-content-readable .text-muted-foreground { .section-white .topo-content-readable .text-muted-foreground {
color: #3d5248; color: var(--brand-grey-1);
} }
.section-white .topo-prose-surface-light :is(h1, h2, h3, h4, p, li, span) { .section-white .topo-prose-surface-light :is(h1, h2, h3, h4, p, li, span) {
color: #0d3d26; color: var(--brand-tertiary);
} }
.section-white .topo-prose-surface-light .text-muted-foreground { .section-white .topo-prose-surface-light .text-muted-foreground {
color: #3d5248; color: var(--brand-grey-1);
} }
.section-white .topo-card-surface, .section-white .topo-card-surface,
@ -626,41 +640,41 @@
.section-white .bg-white.topo-card-surface :is(h1, h2, h3, h4, p, span), .section-white .bg-white.topo-card-surface :is(h1, h2, h3, h4, p, span),
.section-white [data-slot="card"], .section-white [data-slot="card"],
.section-white [data-slot="card"] :is(h1, h2, h3, h4, p, span, li, label) { .section-white [data-slot="card"] :is(h1, h2, h3, h4, p, span, li, label) {
color: #1a5c38; color: var(--brand-primary);
} }
.section-white .topo-card-surface .text-muted-foreground, .section-white .topo-card-surface .text-muted-foreground,
.section-white [data-slot="card"] .text-muted-foreground, .section-white [data-slot="card"] .text-muted-foreground,
.section-white .bg-white .text-muted-foreground { .section-white .bg-white .text-muted-foreground {
color: #3d5248; color: var(--brand-grey-1);
} }
.section-white [data-slot="accordion-trigger"] { .section-white [data-slot="accordion-trigger"] {
color: #0d3d26; color: var(--brand-tertiary);
} }
.section-white [data-slot="button"][data-variant="outline"], .section-white [data-slot="button"][data-variant="outline"],
.section-white [data-slot="button"][data-variant="ghost"], .section-white [data-slot="button"][data-variant="ghost"],
.section-white [data-slot="button"][data-variant="link"] { .section-white [data-slot="button"][data-variant="link"] {
color: #1a5c38; color: var(--brand-primary);
} }
.section-white [data-slot="button"][data-variant="outline"] { .section-white [data-slot="button"][data-variant="outline"] {
border-color: rgba(26, 92, 56, 0.35); border-color: rgba(55, 164, 122, 0.35);
} }
.section-white [data-slot="button"][data-variant="ghost"]:hover, .section-white [data-slot="button"][data-variant="ghost"]:hover,
.section-white [data-slot="button"][data-variant="link"]:hover { .section-white [data-slot="button"][data-variant="link"]:hover {
color: #0d3d26; color: var(--brand-tertiary);
background-color: rgba(26, 92, 56, 0.06); background-color: rgba(55, 164, 122, 0.06);
} }
header.section-white { header.section-white {
color: #0d3d26; color: var(--brand-tertiary);
} }
header.section-white .text-muted-foreground { header.section-white .text-muted-foreground {
color: #3d5248; color: var(--brand-grey-1);
} }
.section-white:has(.topo-curvy-extend) { .section-white:has(.topo-curvy-extend) {
@ -673,7 +687,7 @@
.topo-prose-surface-light { .topo-prose-surface-light {
background: #ffffff; background: #ffffff;
border: 1px solid rgba(26, 92, 56, 0.12); border: 1px solid rgba(55, 164, 122, 0.12);
box-shadow: none; box-shadow: none;
backdrop-filter: none; backdrop-filter: none;
} }
@ -730,7 +744,7 @@
.section-green .bg-white :is(h1, h2, h3, h4, p, span, li, label), .section-green .bg-white :is(h1, h2, h3, h4, p, span, li, label),
.section-green [data-slot="card"], .section-green [data-slot="card"],
.section-green [data-slot="card"] :is(h1, h2, h3, h4, p, span, li, label, a) { .section-green [data-slot="card"] :is(h1, h2, h3, h4, p, span, li, label, a) {
color: #1a5c38; color: var(--brand-primary);
text-shadow: none; text-shadow: none;
} }
@ -739,27 +753,27 @@
.section-green [data-slot="card"] .text-muted-foreground, .section-green [data-slot="card"] .text-muted-foreground,
.section-green [data-slot="card"] [data-slot="card-description"], .section-green [data-slot="card"] [data-slot="card-description"],
.section-green .topo-card-surface [data-slot="card-description"] { .section-green .topo-card-surface [data-slot="card-description"] {
color: #3d5248; color: var(--brand-grey-1);
} }
.section-green .ticket-admission, .section-green .ticket-admission,
.section-green .ticket-admission :is(h1, h2, h3, h4, p, span, li, label) { .section-green .ticket-admission :is(h1, h2, h3, h4, p, span, li, label) {
color: #1a5c38; color: var(--brand-primary);
text-shadow: none; text-shadow: none;
} }
.section-green .ticket-admission .text-muted-foreground, .section-green .ticket-admission .text-muted-foreground,
.section-green .ticket-admission p { .section-green .ticket-admission p {
color: #3d5248; color: var(--brand-grey-1);
} }
.topo-card-link, .topo-card-link,
.topo-card-link svg { .topo-card-link svg {
color: #1a5c38; color: var(--brand-primary);
} }
.topo-card-link:hover, .topo-card-link:hover,
.topo-card-link:hover svg { .topo-card-link:hover svg {
color: #0d3d26; color: var(--brand-tertiary);
} }
.section-green .topo-on-green-bg [data-slot="button"][data-variant="outline"] { .section-green .topo-on-green-bg [data-slot="button"][data-variant="outline"] {
@ -799,30 +813,30 @@
.section-green .topo-card-surface [data-slot="button"][data-variant="link"], .section-green .topo-card-surface [data-slot="button"][data-variant="link"],
.section-green .bg-white [data-slot="button"][data-variant="ghost"], .section-green .bg-white [data-slot="button"][data-variant="ghost"],
.section-green .bg-white [data-slot="button"][data-variant="link"] { .section-green .bg-white [data-slot="button"][data-variant="link"] {
color: #1a5c38; color: var(--brand-primary);
} }
.section-green [data-slot="card"] [data-slot="button"][data-variant="ghost"]:hover, .section-green [data-slot="card"] [data-slot="button"][data-variant="ghost"]:hover,
.section-green [data-slot="card"] [data-slot="button"][data-variant="link"]:hover, .section-green [data-slot="card"] [data-slot="button"][data-variant="link"]:hover,
.section-green .topo-card-surface [data-slot="button"][data-variant="ghost"]:hover, .section-green .topo-card-surface [data-slot="button"][data-variant="ghost"]:hover,
.section-green .topo-card-surface [data-slot="button"][data-variant="link"]:hover { .section-green .topo-card-surface [data-slot="button"][data-variant="link"]:hover {
color: #0d3d26; color: var(--brand-tertiary);
background-color: rgba(26, 92, 56, 0.06); background-color: rgba(55, 164, 122, 0.06);
} }
.section-green [data-slot="card"] [data-slot="button"][data-variant="outline"], .section-green [data-slot="card"] [data-slot="button"][data-variant="outline"],
.section-green .topo-card-surface [data-slot="button"][data-variant="outline"], .section-green .topo-card-surface [data-slot="button"][data-variant="outline"],
.section-green .bg-white [data-slot="button"][data-variant="outline"] { .section-green .bg-white [data-slot="button"][data-variant="outline"] {
border-color: rgba(26, 92, 56, 0.4); border-color: rgba(55, 164, 122, 0.4);
color: #1a5c38; color: var(--brand-primary);
background-color: transparent; background-color: transparent;
} }
.section-green [data-slot="card"] [data-slot="button"][data-variant="outline"]:hover, .section-green [data-slot="card"] [data-slot="button"][data-variant="outline"]:hover,
.section-green .topo-card-surface [data-slot="button"][data-variant="outline"]:hover { .section-green .topo-card-surface [data-slot="button"][data-variant="outline"]:hover {
border-color: rgba(26, 92, 56, 0.55); border-color: rgba(55, 164, 122, 0.55);
color: #0d3d26; color: var(--brand-tertiary);
background-color: rgba(26, 92, 56, 0.06); background-color: rgba(55, 164, 122, 0.06);
} }
.section-green [data-slot="card"] [data-slot="button"] svg, .section-green [data-slot="card"] [data-slot="button"] svg,
@ -830,14 +844,14 @@
color: currentColor; color: currentColor;
} }
.section-green .topo-on-green-bg [data-slot="button"][data-variant="default"]:not([class*="bg-[#ffb300]"]) { .section-green .topo-on-green-bg [data-slot="button"][data-variant="default"]:not([class*="bg-white"]) {
background-color: #ffb300; background-color: var(--brand-white);
color: #0f0404; color: var(--brand-tertiary);
} }
.section-green .topo-on-green-bg [data-slot="button"][data-variant="default"]:not([class*="bg-[#ffb300]"]):hover { .section-green .topo-on-green-bg [data-slot="button"][data-variant="default"]:not([class*="bg-white"]):hover {
background-color: #e6a200; background-color: var(--brand-white-soft);
color: #0f0404; color: var(--brand-tertiary);
} }
.topo-pattern-clearance-section { .topo-pattern-clearance-section {

View File

@ -28,7 +28,7 @@ export default function PartnersPage() {
description={<p className="text-lg leading-relaxed">{partnersIntro.subheadline}</p>} description={<p className="text-lg leading-relaxed">{partnersIntro.subheadline}</p>}
> >
<div className="flex flex-wrap gap-3"> <div className="flex flex-wrap gap-3">
<Button className="rounded-full bg-[#ffb300] text-[#0f0404] hover:bg-[#ffb300]/90" asChild> <Button className="rounded-full bg-[#37a47a] text-[#ffffff] hover:bg-[#37a47a]/90" asChild>
<Link href="#partnership-form">Become a partner</Link> <Link href="#partnership-form">Become a partner</Link>
</Button> </Button>
<ChampionStartupModal /> <ChampionStartupModal />

View File

@ -27,7 +27,7 @@ export default async function PaymentSuccessPage({ searchParams }: Props) {
/> />
<Section> <Section>
<div className="mx-auto max-w-lg text-center"> <div className="mx-auto max-w-lg text-center">
<CheckCircle2 className="mx-auto size-16 text-[#1a5c38]" /> <CheckCircle2 className="mx-auto size-16 text-[#37a47a]" />
<p className="mt-6 text-muted-foreground"> <p className="mt-6 text-muted-foreground">
Your registration has been received. Order reference:{" "} Your registration has been received. Order reference:{" "}
<span className="font-mono font-medium text-foreground">{orderId}</span> <span className="font-mono font-medium text-foreground">{orderId}</span>

View File

@ -30,12 +30,12 @@ export default function PitchCompetitionPage() {
} }
description={ description={
<> <>
<p className="text-xl text-[#1f3d7e]">{pitchCompetition.subheadline}</p> <p className="text-xl text-[#30614c]">{pitchCompetition.subheadline}</p>
<p className="mt-4 leading-relaxed">{pitchCompetition.description}</p> <p className="mt-4 leading-relaxed">{pitchCompetition.description}</p>
</> </>
} }
> >
<Button className="rounded-full bg-[#ffb300] text-[#0f0404] hover:bg-[#ffb300]/90" asChild> <Button className="rounded-full bg-[#37a47a] text-[#ffffff] hover:bg-[#37a47a]/90" asChild>
<Link href={site.links.pitchApplyUrl}>Apply now</Link> <Link href={site.links.pitchApplyUrl}>Apply now</Link>
</Button> </Button>
</PageRiftHeader> </PageRiftHeader>
@ -45,7 +45,7 @@ export default function PitchCompetitionPage() {
<ul className="mt-6 space-y-3"> <ul className="mt-6 space-y-3">
{pitchCompetition.criteria.map((c) => ( {pitchCompetition.criteria.map((c) => (
<li key={c} className="flex gap-2 text-muted-foreground"> <li key={c} className="flex gap-2 text-muted-foreground">
<span className="text-[#ffb300]"></span> <span className="text-[#37a47a]"></span>
{c} {c}
</li> </li>
))} ))}

View File

@ -19,31 +19,31 @@ export default function PrivacyPage() {
eyebrow="Legal" eyebrow="Legal"
title={<h1 className="text-4xl font-bold">{privacyPolicy.title}</h1>} title={<h1 className="text-4xl font-bold">{privacyPolicy.title}</h1>}
description={ description={
<p className="text-sm text-[#3d5248]">Last updated: {privacyPolicy.updated}</p> <p className="text-sm text-[#5b5b5b]">Last updated: {privacyPolicy.updated}</p>
} }
/> />
<Section> <Section>
<TopoProseSurface className="max-w-2xl space-y-6"> <TopoProseSurface className="max-w-2xl space-y-6">
<p className="text-[#3d5248] leading-relaxed">{privacyPolicy.intro}</p> <p className="text-[#5b5b5b] leading-relaxed">{privacyPolicy.intro}</p>
{privacyPolicy.sections.map((section) => ( {privacyPolicy.sections.map((section) => (
<section key={section.heading}> <section key={section.heading}>
<h2 className="text-lg font-semibold text-[#1a5c38]">{section.heading}</h2> <h2 className="text-lg font-semibold text-[#37a47a]">{section.heading}</h2>
<p className="mt-2 text-[#3d5248] leading-relaxed">{section.body}</p> <p className="mt-2 text-[#5b5b5b] leading-relaxed">{section.body}</p>
</section> </section>
))} ))}
<p className="border-t border-[#1a5c38]/12 pt-6 text-[#3d5248] leading-relaxed"> <p className="border-t border-[#37a47a]/12 pt-6 text-[#5b5b5b] leading-relaxed">
{privacyPolicy.moreDetails} {privacyPolicy.moreDetails}
</p> </p>
</TopoProseSurface> </TopoProseSurface>
<div className="mt-8 flex flex-wrap gap-3"> <div className="mt-8 flex flex-wrap gap-3">
<Button className="rounded-full bg-[#1a5c38] text-white hover:bg-[#0d3d26]" asChild> <Button className="rounded-full bg-[#37a47a] text-white hover:bg-[#30614c]" asChild>
<Link href="/contact">Contact us</Link> <Link href="/contact">Contact us</Link>
</Button> </Button>
<Button variant="outline" className="rounded-full border-[#1a5c38]/30 text-[#1a5c38]" asChild> <Button variant="outline" className="rounded-full border-[#37a47a]/30 text-[#37a47a]" asChild>
<Link href={`mailto:${privacyPolicy.contactEmail}`}>{privacyPolicy.contactEmail}</Link> <Link href={`mailto:${privacyPolicy.contactEmail}`}>{privacyPolicy.contactEmail}</Link>
</Button> </Button>
</div> </div>

View File

@ -41,7 +41,7 @@ export default function ProgramPage() {
/> />
</div> </div>
<CardHeader> <CardHeader>
<p className="text-xs font-semibold uppercase text-[#ffb300]">{day.date}</p> <p className="text-xs font-semibold uppercase text-[#37a47a]">{day.date}</p>
<CardTitle>{day.title}</CardTitle> <CardTitle>{day.title}</CardTitle>
<CardDescription>{day.description}</CardDescription> <CardDescription>{day.description}</CardDescription>
</CardHeader> </CardHeader>
@ -73,7 +73,7 @@ export default function ProgramPage() {
</Card> </Card>
))} ))}
</div> </div>
<Button className="mt-10 rounded-full bg-[#ffb300] text-[#0f0404]" asChild> <Button className="mt-10 rounded-full bg-[#37a47a] text-[#ffffff]" asChild>
<Link href="/pitch-competition">Pitch competition details</Link> <Link href="/pitch-competition">Pitch competition details</Link>
</Button> </Button>
</Section> </Section>

View File

@ -37,7 +37,7 @@ export default function SpeakersPage() {
</h1> </h1>
} }
description={ description={
<p className="text-lg text-[#3d5248]"> <p className="text-lg text-[#5b5b5b]">
{site.dates.label} · {site.venue.name} {site.dates.label} · {site.venue.name}
</p> </p>
} }
@ -64,7 +64,7 @@ export default function SpeakersPage() {
)} )}
</div> </div>
<div className="mt-16 text-center"> <div className="mt-16 text-center">
<Button className="rounded-full bg-[#ffb300] text-[#0f0404]" asChild> <Button className="rounded-full bg-[#37a47a] text-[#ffffff]" asChild>
<Link href="/payment">Get tickets</Link> <Link href="/payment">Get tickets</Link>
</Button> </Button>
</div> </div>

View File

@ -47,10 +47,10 @@ export function BrandLogo({
const primaryClass = isFooter const primaryClass = isFooter
? "text-white" ? "text-white"
: "text-[#1a5c38]"; : "text-[#37a47a]";
const secondaryClass = isFooter const secondaryClass = isFooter
? "text-white/85" ? "text-white/85"
: "text-[#0d3d26]/90"; : "text-[#30614c]/90";
const primarySize = compact const primarySize = compact
? "text-[12px] sm:text-[13px] md:text-sm" ? "text-[12px] sm:text-[13px] md:text-sm"
@ -97,7 +97,7 @@ export function BrandLogo({
return ( return (
<Link <Link
href={href} href={href}
className="shrink-0 rounded-sm focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[#1a5c38] focus-visible:ring-offset-2" className="shrink-0 rounded-sm focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[#37a47a] focus-visible:ring-offset-2"
aria-label={siteName} aria-label={siteName}
> >
{content} {content}

View File

@ -15,7 +15,7 @@ export function FooterTopoPattern({ className }: Props) {
return ( return (
<div <div
className={cn( className={cn(
"pointer-events-none absolute inset-0 z-0 overflow-hidden bg-[#1a5c38]", "pointer-events-none absolute inset-0 z-0 overflow-hidden bg-[#37a47a]",
className className
)} )}
aria-hidden aria-hidden
@ -37,7 +37,7 @@ export function FooterTopoPattern({ className }: Props) {
))} ))}
</svg> </svg>
<div <div
className="absolute inset-0 bg-gradient-to-t from-[#0d3d26]/18 via-transparent to-transparent" className="absolute inset-0 bg-gradient-to-t from-[#30614c]/18 via-transparent to-transparent"
aria-hidden aria-hidden
/> />
</div> </div>

View File

@ -38,7 +38,7 @@ export function FooterTopographicBand({ className }: Props) {
V76 V76
C1120 92 860 58 600 74 C1120 92 860 58 600 74
S240 98 0 82 Z" S240 98 0 82 Z"
fill="#1a5c38" fill="#37a47a"
/> />
<path <path
d="M0 82 d="M0 82
@ -56,7 +56,7 @@ export function FooterTopographicBand({ className }: Props) {
V148 V148
C1000 164 740 136 480 152 C1000 164 740 136 480 152
S160 172 0 156 Z" S160 172 0 156 Z"
fill="#1a5c38" fill="#37a47a"
/> />
<path <path
d="M0 156 d="M0 156
@ -64,7 +64,7 @@ export function FooterTopographicBand({ className }: Props) {
S1280 134 1440 158 S1280 134 1440 158
V220 V220
H0 Z" H0 Z"
fill="#1a5c38" fill="#37a47a"
/> />
{/* Logo-like contour strokes */} {/* Logo-like contour strokes */}
@ -102,7 +102,7 @@ export function FooterTopographicBand({ className }: Props) {
</svg> </svg>
{/* Fade into solid footer green */} {/* Fade into solid footer green */}
<div className="absolute inset-x-0 bottom-0 h-16 bg-gradient-to-b from-transparent to-[#1a5c38]" /> <div className="absolute inset-x-0 bottom-0 h-16 bg-gradient-to-b from-transparent to-[#37a47a]" />
</div> </div>
); );
} }

View File

@ -15,8 +15,8 @@ export function PartnerLogoPlaceholder({ className, size = "md" }: Props) {
return ( return (
<div <div
className={cn( className={cn(
"flex items-center justify-center rounded-xl border-2 border-dashed border-[#1f3d7e]/25 bg-[#f7f7f7]", "flex items-center justify-center rounded-xl border-2 border-dashed border-[#30614c]/25 bg-[#fafafa]",
"font-semibold uppercase tracking-wide text-[#1f3d7e]/45", "font-semibold uppercase tracking-wide text-[#30614c]/45",
sizeClasses[size], sizeClasses[size],
className className
)} )}

View File

@ -110,7 +110,7 @@ export function RiftFlowLines({
export function RiftCardConnector({ className }: { className?: string }) { export function RiftCardConnector({ className }: { className?: string }) {
return ( return (
<div className={cn("relative flex justify-center py-0.5", className)} aria-hidden> <div className={cn("relative flex justify-center py-0.5", className)} aria-hidden>
<div className="h-6 w-px bg-gradient-to-b from-[#1a5c38]/20 via-[#1a5c38]/35 to-[#1a5c38]/20" /> <div className="h-6 w-px bg-gradient-to-b from-[#37a47a]/20 via-[#37a47a]/35 to-[#37a47a]/20" />
</div> </div>
); );
} }

View File

@ -4,9 +4,11 @@ import { useMemo } from "react";
import { mixHex } from "@/lib/rift-colors"; import { mixHex } from "@/lib/rift-colors";
import { cn } from "@/lib/utils"; import { cn } from "@/lib/utils";
const GREEN = "#1a5c38"; import { BRAND_COLORS } from "@/content/brand-colors";
const GOLD = "#ffb300";
const BLUE = "#1f3d7e"; const GREEN: string = BRAND_COLORS.primary;
const GOLD: string = BRAND_COLORS.secondary;
const BLUE: string = BRAND_COLORS.tertiary;
/** Long curved paths that pulse across the page background */ /** Long curved paths that pulse across the page background */
const PULSE_CURVES = [ const PULSE_CURVES = [

View File

@ -14,9 +14,11 @@ import {
import { mixHex } from "@/lib/rift-colors"; import { mixHex } from "@/lib/rift-colors";
import { cn } from "@/lib/utils"; import { cn } from "@/lib/utils";
const GREEN = "#1a5c38"; import { BRAND_COLORS } from "@/content/brand-colors";
const GOLD = "#ffb300";
const BLUE = "#1f3d7e"; const GREEN: string = BRAND_COLORS.primary;
const GOLD: string = BRAND_COLORS.secondary;
const BLUE: string = BRAND_COLORS.tertiary;
type Props = { type Props = {
variant: "hero" | "ambient" | "header"; variant: "hero" | "ambient" | "header";
@ -100,7 +102,7 @@ export function RiftTopographyLayer({
{isHero && ( {isHero && (
<> <>
<div <div
className="absolute inset-0 bg-gradient-to-b from-[#fbfdfb] via-white to-[#f0f5f2]" className="absolute inset-0 bg-gradient-to-b from-[#fbfdfb] via-white to-[#e8f2ec]"
aria-hidden aria-hidden
/> />
<div <div

View File

@ -6,9 +6,11 @@ import { cn } from "@/lib/utils";
const MESH_W = 140; const MESH_W = 140;
const MESH_H = 100; const MESH_H = 100;
import { BRAND_GREEN_SHADES } from "@/content/brand-colors";
/** Narrow green range — low contrast between “stones” on section backgrounds */ /** Narrow green range — low contrast between “stones” on section backgrounds */
const ROCK_TONES = ["#1a5c38", "#1d5f3c", "#216342", "#246845", "#286a48", "#2b6e4b"] as const; const ROCK_TONES = BRAND_GREEN_SHADES;
const GROUT = "rgba(8, 38, 22, 0.2)"; const GROUT = "rgba(48, 97, 76, 0.2)";
const ROCK_MESH = buildVoronoiMesh(42, MESH_W, MESH_H, 0x475256, { const ROCK_MESH = buildVoronoiMesh(42, MESH_W, MESH_H, 0x475256, {
siteGenerator: "poisson", siteGenerator: "poisson",
@ -30,7 +32,7 @@ function rockFill(cell: VoronoiCell, index: number) {
const cx = cell.points.reduce((s, p) => s + p[0], 0) / cell.points.length; const cx = cell.points.reduce((s, p) => s + p[0], 0) / cell.points.length;
const cy = cell.points.reduce((s, p) => s + p[1], 0) / cell.points.length; const cy = cell.points.reduce((s, p) => s + p[1], 0) / cell.points.length;
const yNorm = cy / MESH_H; const yNorm = cy / MESH_H;
const gradient = mixHex("#2a6f4a", "#1a5c38", Math.min(1, yNorm * 0.45 + 0.25)); const gradient = mixHex("#2a6f4a", "#37a47a", Math.min(1, yNorm * 0.45 + 0.25));
const tone = ROCK_TONES[(index * 11 + Math.floor(cx * 0.55)) % ROCK_TONES.length]; const tone = ROCK_TONES[(index * 11 + Math.floor(cx * 0.55)) % ROCK_TONES.length];
return mixHex(gradient, tone, 0.38); return mixHex(gradient, tone, 0.38);
} }
@ -55,7 +57,7 @@ export function RoundedRockVoronoiBackground({
return ( return (
<div <div
className={cn( className={cn(
"pointer-events-none absolute overflow-hidden bg-[#1a5c38]", "pointer-events-none absolute overflow-hidden bg-[#37a47a]",
style?.height != null ? "left-0 right-0" : "inset-0", style?.height != null ? "left-0 right-0" : "inset-0",
className className
)} )}
@ -83,7 +85,7 @@ export function RoundedRockVoronoiBackground({
<div className="absolute inset-0 opacity-[0.18] grain" aria-hidden /> <div className="absolute inset-0 opacity-[0.18] grain" aria-hidden />
{gradient && ( {gradient && (
<div <div
className="absolute inset-0 bg-gradient-to-b from-[#2a6f4a]/8 via-transparent to-[#0d3d26]/10" className="absolute inset-0 bg-gradient-to-b from-[#2a6f4a]/8 via-transparent to-[#30614c]/10"
aria-hidden aria-hidden
/> />
)} )}

View File

@ -26,7 +26,7 @@ export function TopoCurvyExtend({ className }: Props) {
<path <path
d="M-40 24 C 200 2, 480 44, 720 14 S 1180 4, 1480 28" d="M-40 24 C 200 2, 480 44, 720 14 S 1180 4, 1480 28"
fill="none" fill="none"
stroke="#1a5c38" stroke="#37a47a"
strokeWidth="1.25" strokeWidth="1.25"
strokeOpacity="0.45" strokeOpacity="0.45"
strokeLinecap="round" strokeLinecap="round"
@ -34,7 +34,7 @@ export function TopoCurvyExtend({ className }: Props) {
<path <path
d="M0 8 C 280 32, 560 4, 880 28 S 1240 42, 1480 12" d="M0 8 C 280 32, 560 4, 880 28 S 1240 42, 1480 12"
fill="none" fill="none"
stroke="#1a5c38" stroke="#37a47a"
strokeWidth="1" strokeWidth="1"
strokeOpacity="0.32" strokeOpacity="0.32"
strokeLinecap="round" strokeLinecap="round"
@ -43,7 +43,7 @@ export function TopoCurvyExtend({ className }: Props) {
<path <path
d="M120 42 C 320 64, 520 34, 720 78 S 980 46, 1240 88, 1480 52" d="M120 42 C 320 64, 520 34, 720 78 S 980 46, 1240 88, 1480 52"
fill="none" fill="none"
stroke="#1a5c38" stroke="#37a47a"
strokeWidth="1.2" strokeWidth="1.2"
strokeOpacity="0.38" strokeOpacity="0.38"
strokeLinecap="round" strokeLinecap="round"
@ -60,7 +60,7 @@ export function TopoCurvyExtend({ className }: Props) {
<path <path
d="M80 68 C 360 96, 600 72, 840 118 S 1100 86, 1380 128" d="M80 68 C 360 96, 600 72, 840 118 S 1100 86, 1380 128"
fill="none" fill="none"
stroke="#1a5c38" stroke="#37a47a"
strokeWidth="0.9" strokeWidth="0.9"
strokeOpacity="0.28" strokeOpacity="0.28"
strokeLinecap="round" strokeLinecap="round"
@ -77,7 +77,7 @@ export function TopoCurvyExtend({ className }: Props) {
<path <path
d="M360 38 L360 132" d="M360 38 L360 132"
fill="none" fill="none"
stroke="#1a5c38" stroke="#37a47a"
strokeWidth="0.75" strokeWidth="0.75"
strokeOpacity="0.3" strokeOpacity="0.3"
strokeLinecap="round" strokeLinecap="round"
@ -85,7 +85,7 @@ export function TopoCurvyExtend({ className }: Props) {
<path <path
d="M720 14 L720 148" d="M720 14 L720 148"
fill="none" fill="none"
stroke="#1a5c38" stroke="#37a47a"
strokeWidth="0.9" strokeWidth="0.9"
strokeOpacity="0.35" strokeOpacity="0.35"
strokeLinecap="round" strokeLinecap="round"
@ -101,7 +101,7 @@ export function TopoCurvyExtend({ className }: Props) {
<path <path
d="M520 34 L520 118" d="M520 34 L520 118"
fill="none" fill="none"
stroke="#1a5c38" stroke="#37a47a"
strokeWidth="0.65" strokeWidth="0.65"
strokeOpacity="0.25" strokeOpacity="0.25"
strokeLinecap="round" strokeLinecap="round"

View File

@ -1,12 +1,7 @@
import { BRAND_GREEN_SHADES } from "@/content/brand-colors";
/** GRV greens for wavy interlocking footer tessellation. */ /** GRV greens for wavy interlocking footer tessellation. */
export const WAVY_TESS_PALETTE = [ export const WAVY_TESS_PALETTE = BRAND_GREEN_SHADES;
"#1a5c38",
"#1d5f3c",
"#216342",
"#246845",
"#286a48",
"#2b6e4b",
] as const;
export type WavyTessCell = { d: string; fill: string }; export type WavyTessCell = { d: string; fill: string };

View File

@ -23,7 +23,7 @@ export function AddToCalendar({ className, variant = "outline" }: Props) {
variant === "inverse" variant === "inverse"
? "rounded-full border-white/30 bg-transparent text-white hover:bg-white/10" ? "rounded-full border-white/30 bg-transparent text-white hover:bg-white/10"
: variant === "default" : variant === "default"
? "rounded-full bg-[#ffb300] text-[#0f0404] hover:bg-[#ffb300]/90" ? "rounded-full bg-[#37a47a] text-[#ffffff] hover:bg-[#37a47a]/90"
: "rounded-full"; : "rounded-full";
return ( return (

View File

@ -5,17 +5,17 @@ export function BoothPackages() {
return ( return (
<div className="grid gap-6 md:grid-cols-3"> <div className="grid gap-6 md:grid-cols-3">
{boothPackages.map((pkg) => ( {boothPackages.map((pkg) => (
<Card key={pkg.id} className="topo-card-surface border-border bg-white text-[#1a5c38]"> <Card key={pkg.id} className="topo-card-surface border-border bg-white text-[#37a47a]">
<CardHeader> <CardHeader>
<CardTitle className="text-lg">{pkg.name}</CardTitle> <CardTitle className="text-lg">{pkg.name}</CardTitle>
<CardDescription className="font-medium text-[#1a5c38]/90">{pkg.size}</CardDescription> <CardDescription className="font-medium text-[#37a47a]/90">{pkg.size}</CardDescription>
</CardHeader> </CardHeader>
<CardContent className="space-y-4"> <CardContent className="space-y-4">
<p className="text-sm text-[#3d5248] leading-relaxed">{pkg.description}</p> <p className="text-sm text-[#5b5b5b] leading-relaxed">{pkg.description}</p>
<ul className="space-y-2"> <ul className="space-y-2">
{pkg.highlights.map((h) => ( {pkg.highlights.map((h) => (
<li key={h} className="flex gap-2 text-sm"> <li key={h} className="flex gap-2 text-sm">
<span className="text-[#ffb300]"></span> <span className="text-[#37a47a]"></span>
{h} {h}
</li> </li>
))} ))}

View File

@ -98,7 +98,7 @@ export function ExhibitorBoothForm() {
</div> </div>
<fieldset className="space-y-4"> <fieldset className="space-y-4">
<legend className="text-sm font-semibold uppercase tracking-wider text-[#1f3d7e]"> <legend className="text-sm font-semibold uppercase tracking-wider text-[#30614c]">
Contact Contact
</legend> </legend>
<div className="grid gap-4 sm:grid-cols-2"> <div className="grid gap-4 sm:grid-cols-2">
@ -134,7 +134,7 @@ export function ExhibitorBoothForm() {
</fieldset> </fieldset>
<fieldset className="space-y-4"> <fieldset className="space-y-4">
<legend className="text-sm font-semibold uppercase tracking-wider text-[#1f3d7e]"> <legend className="text-sm font-semibold uppercase tracking-wider text-[#30614c]">
Company & products Company & products
</legend> </legend>
<div className="space-y-2"> <div className="space-y-2">
@ -188,7 +188,7 @@ export function ExhibitorBoothForm() {
</fieldset> </fieldset>
<fieldset className="space-y-4"> <fieldset className="space-y-4">
<legend className="text-sm font-semibold uppercase tracking-wider text-[#1f3d7e]"> <legend className="text-sm font-semibold uppercase tracking-wider text-[#30614c]">
Booth requirements Booth requirements
</legend> </legend>
<div className="space-y-2"> <div className="space-y-2">
@ -247,14 +247,14 @@ export function ExhibitorBoothForm() {
{error && <p className="text-sm text-destructive">{error}</p>} {error && <p className="text-sm text-destructive">{error}</p>}
{status === "success" && ( {status === "success" && (
<p className="text-sm text-[#1f3d7e]"> <p className="text-sm text-[#30614c]">
Thank you! We received your booth request and will follow up with availability and pricing. Thank you! We received your booth request and will follow up with availability and pricing.
</p> </p>
)} )}
<Button <Button
type="submit" type="submit"
className="w-full rounded-full bg-[#ffb300] text-[#0f0404] hover:bg-[#ffb300]/90 sm:w-auto" className="w-full rounded-full bg-[#37a47a] text-[#ffffff] hover:bg-[#37a47a]/90 sm:w-auto"
disabled={status === "loading"} disabled={status === "loading"}
> >
{status === "loading" ? "Submitting…" : "Submit booth request"} {status === "loading" ? "Submitting…" : "Submit booth request"}

View File

@ -41,7 +41,7 @@ export function DataConsentField({
/> />
<Label htmlFor={id} className="text-sm font-normal leading-snug text-muted-foreground"> <Label htmlFor={id} className="text-sm font-normal leading-snug text-muted-foreground">
{labelPrefix}{" "} {labelPrefix}{" "}
<Link href="/privacy" className="font-medium text-[#1a5c38] underline underline-offset-2"> <Link href="/privacy" className="font-medium text-[#37a47a] underline underline-offset-2">
{dataConsent.privacyLinkText} {dataConsent.privacyLinkText}
</Link> </Link>
. .

View File

@ -11,7 +11,7 @@ export function AttendSummitSection() {
return ( return (
<Section id="attend" variant="muted" className="py-14 md:py-20"> <Section id="attend" variant="muted" className="py-14 md:py-20">
<div className="topo-on-green-bg mx-auto max-w-3xl text-center"> <div className="topo-on-green-bg mx-auto max-w-3xl text-center">
<p className="text-xs font-semibold uppercase tracking-widest text-[#ffb300]"> <p className="text-xs font-semibold uppercase tracking-widest text-[#b9d8c9]">
{attendCopy.eyebrow} {attendCopy.eyebrow}
</p> </p>
<h2 className="mt-3 text-3xl font-bold tracking-tight text-white md:text-4xl"> <h2 className="mt-3 text-3xl font-bold tracking-tight text-white md:text-4xl">
@ -33,15 +33,15 @@ export function AttendSummitSection() {
delay={i * 75} delay={i * 75}
as="article" as="article"
className={cn( className={cn(
"topo-card-surface group flex flex-col rounded-2xl border border-border bg-white p-6 text-[#1a5c38] shadow-sm", "topo-card-surface group flex flex-col rounded-2xl border border-border bg-white p-6 text-[#37a47a] shadow-sm",
"transition-shadow duration-200 hover:border-[#1a5c38]/25 hover:shadow-md" "transition-shadow duration-200 hover:border-[#37a47a]/25 hover:shadow-md"
)} )}
> >
<span className="inline-flex size-11 items-center justify-center rounded-xl bg-[#1a5c38]/10 text-[#1a5c38]"> <span className="inline-flex size-11 items-center justify-center rounded-xl bg-[#37a47a]/10 text-[#37a47a]">
<Icon className="size-5" strokeWidth={1.75} aria-hidden /> <Icon className="size-5" strokeWidth={1.75} aria-hidden />
</span> </span>
<h3 className="mt-4 text-lg font-bold text-[#0d3d26]">{path.title}</h3> <h3 className="mt-4 text-lg font-bold text-[#30614c]">{path.title}</h3>
<p className="mt-2 flex-1 text-sm leading-relaxed text-[#3d5248]"> <p className="mt-2 flex-1 text-sm leading-relaxed text-[#5b5b5b]">
{path.description} {path.description}
</p> </p>
<Button <Button
@ -61,7 +61,7 @@ export function AttendSummitSection() {
<div className="mt-10 flex flex-wrap items-center justify-center gap-3"> <div className="mt-10 flex flex-wrap items-center justify-center gap-3">
<Button <Button
className="rounded-full bg-[#ffb300] px-8 text-[#0f0404] hover:bg-[#ffb300]/90" className="rounded-full bg-[#37a47a] px-8 text-[#ffffff] hover:bg-[#37a47a]/90"
asChild asChild
> >
<Link href="/payment">Get tickets</Link> <Link href="/payment">Get tickets</Link>

View File

@ -17,13 +17,13 @@ export function BoothAcquisitionBand() {
/> />
</div> </div>
<div className="order-1 lg:order-2"> <div className="order-1 lg:order-2">
<p className="text-xs font-semibold uppercase tracking-widest text-[#ffb300]"> <p className="text-xs font-semibold uppercase tracking-widest text-[#b9d8c9]">
{exhibitCopy.eyebrow} {exhibitCopy.eyebrow}
</p> </p>
<h2 className="mt-3 text-3xl font-bold md:text-4xl">{exhibitCopy.headline}</h2> <h2 className="mt-3 text-3xl font-bold md:text-4xl">{exhibitCopy.headline}</h2>
<p className="mt-4 text-[#3d5248] leading-relaxed">{exhibitCopy.subheadline}</p> <p className="mt-4 text-[#5b5b5b] leading-relaxed">{exhibitCopy.subheadline}</p>
<div className="mt-8 flex flex-wrap gap-3"> <div className="mt-8 flex flex-wrap gap-3">
<Button className="rounded-full bg-[#ffb300] text-[#0f0404] hover:bg-[#ffb300]/90" asChild> <Button className="rounded-full bg-[#37a47a] text-[#ffffff] hover:bg-[#37a47a]/90" asChild>
<Link href="/exhibit#reserve-booth">Reserve a booth</Link> <Link href="/exhibit#reserve-booth">Reserve a booth</Link>
</Button> </Button>
<Button variant="outline" className="topo-card-link rounded-full" asChild> <Button variant="outline" className="topo-card-link rounded-full" asChild>

View File

@ -22,7 +22,7 @@ export function ExperienceCards() {
<div className="mt-12 grid gap-6 md:grid-cols-3"> <div className="mt-12 grid gap-6 md:grid-cols-3">
{experiences.map((exp, i) => ( {experiences.map((exp, i) => (
<ScrollReveal key={exp.id} variant="card" delay={i * 90} as="div"> <ScrollReveal key={exp.id} variant="card" delay={i * 90} as="div">
<Card className="topo-card-surface overflow-hidden border-0 bg-white text-[#1a5c38]"> <Card className="topo-card-surface overflow-hidden border-0 bg-white text-[#37a47a]">
<div className="relative h-48"> <div className="relative h-48">
<Image <Image
src="/branding/booth-mockup.png" src="/branding/booth-mockup.png"
@ -32,11 +32,11 @@ export function ExperienceCards() {
/> />
</div> </div>
<CardHeader> <CardHeader>
<p className="text-xs font-medium uppercase text-[#3d5248]"> <p className="text-xs font-medium uppercase text-[#5b5b5b]">
Day {i + 1} Day {i + 1}
</p> </p>
<CardTitle>{exp.title}</CardTitle> <CardTitle>{exp.title}</CardTitle>
<CardDescription className="text-[#3d5248]">{exp.description}</CardDescription> <CardDescription className="text-[#5b5b5b]">{exp.description}</CardDescription>
</CardHeader> </CardHeader>
<CardContent> <CardContent>
<Button <Button

View File

@ -19,10 +19,10 @@ export function Faq() {
{faqs.map((faq, i) => ( {faqs.map((faq, i) => (
<AccordionItem key={faq.id} value={faq.id}> <AccordionItem key={faq.id} value={faq.id}>
<AccordionTrigger className="text-left"> <AccordionTrigger className="text-left">
<span className="mr-3 text-[#ffb300]">{String(i + 1).padStart(2, "0")}.</span> <span className="mr-3 text-[#37a47a]">{String(i + 1).padStart(2, "0")}.</span>
{faq.question} {faq.question}
</AccordionTrigger> </AccordionTrigger>
<AccordionContent className="text-[#3d5248]">{faq.answer}</AccordionContent> <AccordionContent className="text-[#5b5b5b]">{faq.answer}</AccordionContent>
</AccordionItem> </AccordionItem>
))} ))}
</Accordion> </Accordion>

View File

@ -84,7 +84,7 @@ export function Hero() {
<div className="topo-content-layer topo-content-readable relative z-20 mx-auto flex min-h-[min(100svh,900px)] w-full max-w-6xl flex-col items-center justify-center px-4 py-24 text-center md:px-6"> <div className="topo-content-layer topo-content-readable relative z-20 mx-auto flex min-h-[min(100svh,900px)] w-full max-w-6xl flex-col items-center justify-center px-4 py-24 text-center md:px-6">
<TopoProseSurface className="mx-auto flex w-full max-w-4xl flex-col items-center text-center"> <TopoProseSurface className="mx-auto flex w-full max-w-4xl flex-col items-center text-center">
<ScrollReveal immediate variant="fade-up" delay={0}> <ScrollReveal immediate variant="fade-up" delay={0}>
<p className="text-xs font-semibold uppercase tracking-[0.2em] text-[#1a5c38]/80 md:text-sm"> <p className="text-xs font-semibold uppercase tracking-[0.2em] text-[#37a47a]/80 md:text-sm">
{site.dates.label} · {site.venue.address} {site.dates.label} · {site.venue.address}
</p> </p>
</ScrollReveal> </ScrollReveal>
@ -92,18 +92,18 @@ export function Hero() {
<ScrollReveal immediate variant="fade-up" delay={200}> <ScrollReveal immediate variant="fade-up" delay={200}>
<h1 <h1
className={cn( className={cn(
"rift-hero-heading rift-hero-title mt-6 font-display text-3xl font-bold leading-[1.05] tracking-tight text-[#0d3d26] sm:text-4xl md:text-5xl lg:text-6xl" "rift-hero-heading rift-hero-title mt-6 font-display text-3xl font-bold leading-[1.05] tracking-tight text-[#30614c] sm:text-4xl md:text-5xl lg:text-6xl"
)} )}
> >
<span className="font-wordmark block uppercase tracking-wide"> <span className="font-wordmark block uppercase tracking-wide">
Great Rift Valley Great Rift Valley
</span> </span>
<span className="mt-1 block text-[#ffb300]">Innovation Summit</span> <span className="mt-1 block text-[#37a47a]">Innovation Summit</span>
</h1> </h1>
</ScrollReveal> </ScrollReveal>
<ScrollReveal immediate variant="fade-up" delay={400}> <ScrollReveal immediate variant="fade-up" delay={400}>
<p className="mx-auto mt-6 max-w-2xl text-lg text-[#1a5c38]/80 md:text-xl"> <p className="mx-auto mt-6 max-w-2xl text-lg text-[#37a47a]/80 md:text-xl">
{site.tagline} Presented by {site.presentedBy}. {site.tagline} Presented by {site.presentedBy}.
</p> </p>
</ScrollReveal> </ScrollReveal>
@ -111,7 +111,7 @@ export function Hero() {
<ScrollReveal immediate variant="fade-up" delay={500}> <ScrollReveal immediate variant="fade-up" delay={500}>
<div className="mt-8 flex flex-wrap items-center justify-center gap-3"> <div className="mt-8 flex flex-wrap items-center justify-center gap-3">
<Button <Button
className="rounded-full bg-[#ffb300] px-8 text-[#0f0404] hover:bg-[#ffb300]/90" className="rounded-full bg-[#37a47a] px-8 text-[#ffffff] hover:bg-[#37a47a]/90"
asChild asChild
> >
<Link href={site.links.pitchApplyUrl}> <Link href={site.links.pitchApplyUrl}>
@ -120,13 +120,13 @@ export function Hero() {
</Button> </Button>
<Button <Button
variant="outline" variant="outline"
className="rounded-full border-[#1a5c38]/30 bg-white/80 text-[#1a5c38] backdrop-blur-sm" className="rounded-full border-[#37a47a]/30 bg-white/80 text-[#37a47a] backdrop-blur-sm"
asChild asChild
> >
<Link href="/payment">Get tickets</Link> <Link href="/payment">Get tickets</Link>
</Button> </Button>
</div> </div>
<p className="mt-4 text-sm text-[#1a5c38]/70"> <p className="mt-4 text-sm text-[#37a47a]/70">
<HeroGrantLine /> <HeroGrantLine />
</p> </p>
</ScrollReveal> </ScrollReveal>

View File

@ -79,7 +79,7 @@ export function LastYearWinnerMark({
type="button" type="button"
data-winner-interactive data-winner-interactive
className={cn( className={cn(
"shrink-0 rounded-lg outline-none focus-visible:ring-2 focus-visible:ring-[#1a5c38]/40", "shrink-0 rounded-lg outline-none focus-visible:ring-2 focus-visible:ring-[#37a47a]/40",
isOpen && "relative z-30" isOpen && "relative z-30"
)} )}
aria-label={ aria-label={
@ -98,14 +98,14 @@ export function LastYearWinnerMark({
className={cn( className={cn(
"flex h-10 shrink-0 items-center gap-2 rounded-lg border px-2.5 shadow-sm transition-colors", "flex h-10 shrink-0 items-center gap-2 rounded-lg border px-2.5 shadow-sm transition-colors",
onLight onLight
? "border-[#1a5c38]/15 bg-white/95 hover:border-[#1a5c38]/30 hover:bg-white" ? "border-[#37a47a]/15 bg-white/95 hover:border-[#37a47a]/30 hover:bg-white"
: "border-white/25 bg-white/90 hover:border-white/50 hover:bg-white", : "border-white/25 bg-white/90 hover:border-white/50 hover:bg-white",
logoOnly && "px-2", logoOnly && "px-2",
isOpen && isOpen &&
(onLight (onLight
? "border-[#1a5c38]/40 ring-2 ring-[#1a5c38]/15" ? "border-[#37a47a]/40 ring-2 ring-[#37a47a]/15"
: "border-white/60 ring-2 ring-white/25"), : "border-white/60 ring-2 ring-white/25"),
isPinned && "border-[#ffb300]/70 ring-2 ring-[#ffb300]/25", isPinned && "border-[#37a47a]/70 ring-2 ring-[#37a47a]/25",
className className
)} )}
> >
@ -120,7 +120,7 @@ export function LastYearWinnerMark({
onError={() => setFailed(true)} onError={() => setFailed(true)}
/> />
) : company.initials ? ( ) : company.initials ? (
<span className="text-[10px] font-bold leading-none text-[#1a5c38]"> <span className="text-[10px] font-bold leading-none text-[#37a47a]">
{company.initials} {company.initials}
</span> </span>
) : ( ) : (
@ -134,7 +134,7 @@ export function LastYearWinnerMark({
)} )}
</div> </div>
{company.name ? ( {company.name ? (
<span className="max-w-[7.5rem] truncate text-[11px] font-medium text-[#1a5c38]"> <span className="max-w-[7.5rem] truncate text-[11px] font-medium text-[#37a47a]">
{company.name} {company.name}
</span> </span>
) : null} ) : null}
@ -148,7 +148,7 @@ export function LastYearWinnerMark({
sideOffset={8} sideOffset={8}
collisionPadding={12} collisionPadding={12}
data-winner-interactive data-winner-interactive
className="z-50 w-72 max-w-[calc(100vw-2rem)] shrink-0 overflow-hidden border-[#1a5c38]/15 bg-white p-0 shadow-lg" className="z-50 w-72 max-w-[calc(100vw-2rem)] shrink-0 overflow-hidden border-[#37a47a]/15 bg-white p-0 shadow-lg"
onMouseEnter={handleEnter} onMouseEnter={handleEnter}
onMouseLeave={handleLeave} onMouseLeave={handleLeave}
onOpenAutoFocus={(e) => e.preventDefault()} onOpenAutoFocus={(e) => e.preventDefault()}

View File

@ -30,7 +30,7 @@ function FounderPhoto({ company }: { company: LastYearWinner }) {
alt="" alt=""
width={48} width={48}
height={48} height={48}
className="size-12 shrink-0 rounded-full border-2 border-[#1a5c38]/15 object-cover" className="size-12 shrink-0 rounded-full border-2 border-[#37a47a]/15 object-cover"
onError={() => setFailed(true)} onError={() => setFailed(true)}
/> />
); );
@ -49,7 +49,7 @@ function FounderPhoto({ company }: { company: LastYearWinner }) {
return ( return (
<div <div
className="flex size-12 shrink-0 items-center justify-center rounded-full border-2 border-[#1a5c38]/15 bg-[#f0f5f2] text-sm font-bold text-[#1a5c38]" className="flex size-12 shrink-0 items-center justify-center rounded-full border-2 border-[#37a47a]/15 bg-[#e8f2ec] text-sm font-bold text-[#37a47a]"
aria-hidden aria-hidden
> >
{initials} {initials}
@ -72,24 +72,24 @@ export function LastYearWinnerTip({ company, className, showClose, onClose }: Pr
<div className="flex min-w-0 gap-2.5 px-3 pt-3 pb-2"> <div className="flex min-w-0 gap-2.5 px-3 pt-3 pb-2">
<FounderPhoto company={company} /> <FounderPhoto company={company} />
<div className="min-w-0 flex-1"> <div className="min-w-0 flex-1">
<p className="truncate text-[11px] font-semibold uppercase tracking-wider text-[#1a5c38]"> <p className="truncate text-[11px] font-semibold uppercase tracking-wider text-[#37a47a]">
{name} {name}
</p> </p>
{company.founderName ? ( {company.founderName ? (
<p className="truncate text-[10px] text-[#3d5248]/80">{company.founderName}</p> <p className="truncate text-[10px] text-[#5b5b5b]/80">{company.founderName}</p>
) : null} ) : null}
<p className="mt-1 line-clamp-2 text-[11px] leading-snug text-[#3d5248]"> <p className="mt-1 line-clamp-2 text-[11px] leading-snug text-[#5b5b5b]">
{impact.summary} {impact.summary}
</p> </p>
</div> </div>
</div> </div>
{headline ? ( {headline ? (
<div className="mx-3 mb-2 overflow-hidden rounded-lg border border-[#1a5c38]/12 bg-[#f0f5f2] px-2.5 py-2 text-center"> <div className="mx-3 mb-2 overflow-hidden rounded-lg border border-[#37a47a]/12 bg-[#e8f2ec] px-2.5 py-2 text-center">
<p className="truncate text-[10px] font-bold uppercase tracking-wider text-[#1a5c38]/75"> <p className="truncate text-[10px] font-bold uppercase tracking-wider text-[#37a47a]/75">
{headline.label} {headline.label}
</p> </p>
<p className="winner-impact-value mt-0.5 truncate font-display text-xl font-extrabold tracking-tight text-[#0d3d26]"> <p className="winner-impact-value mt-0.5 truncate font-display text-xl font-extrabold tracking-tight text-[#30614c]">
{headline.value} {headline.value}
</p> </p>
</div> </div>
@ -99,10 +99,10 @@ export function LastYearWinnerTip({ company, className, showClose, onClose }: Pr
<dl className="grid min-w-0 grid-cols-2 gap-1.5 px-3 pb-2"> <dl className="grid min-w-0 grid-cols-2 gap-1.5 px-3 pb-2">
{supporting.map((m) => ( {supporting.map((m) => (
<div key={m.label} className="min-w-0 rounded-md bg-[#f7faf8] px-1.5 py-1.5 text-center"> <div key={m.label} className="min-w-0 rounded-md bg-[#f7faf8] px-1.5 py-1.5 text-center">
<dt className="truncate text-[9px] font-semibold uppercase tracking-wide text-[#1a5c38]/65"> <dt className="truncate text-[9px] font-semibold uppercase tracking-wide text-[#37a47a]/65">
{m.label} {m.label}
</dt> </dt>
<dd className="truncate text-xs font-bold text-[#0d3d26]">{m.value}</dd> <dd className="truncate text-xs font-bold text-[#30614c]">{m.value}</dd>
</div> </div>
))} ))}
</dl> </dl>
@ -111,7 +111,7 @@ export function LastYearWinnerTip({ company, className, showClose, onClose }: Pr
{showFooter ? ( {showFooter ? (
<div <div
className={cn( className={cn(
"flex w-full min-w-0 items-center gap-1.5 border-t border-[#1a5c38]/10 bg-[#f7faf8]/80 px-2.5 py-2", "flex w-full min-w-0 items-center gap-1.5 border-t border-[#37a47a]/10 bg-[#f7faf8]/80 px-2.5 py-2",
showClose && onClose ? "justify-between" : "justify-end" showClose && onClose ? "justify-between" : "justify-end"
)} )}
> >
@ -120,7 +120,7 @@ export function LastYearWinnerTip({ company, className, showClose, onClose }: Pr
type="button" type="button"
data-winner-interactive data-winner-interactive
onClick={onClose} onClick={onClose}
className="inline-flex size-7 shrink-0 items-center justify-center rounded-full border border-[#1a5c38]/15 bg-white text-[#1a5c38] shadow-sm transition-colors hover:bg-[#f0f5f2]" className="inline-flex size-7 shrink-0 items-center justify-center rounded-full border border-[#37a47a]/15 bg-white text-[#37a47a] shadow-sm transition-colors hover:bg-[#e8f2ec]"
aria-label="Close impact details" aria-label="Close impact details"
> >
<X className="size-3.5" aria-hidden /> <X className="size-3.5" aria-hidden />
@ -131,7 +131,7 @@ export function LastYearWinnerTip({ company, className, showClose, onClose }: Pr
<Button <Button
variant="outline" variant="outline"
size="icon-sm" size="icon-sm"
className="rounded-full border-[#1a5c38]/20 text-[#1a5c38] hover:bg-[#f0f5f2]" className="rounded-full border-[#37a47a]/20 text-[#37a47a] hover:bg-[#e8f2ec]"
asChild asChild
> >
<Link href={viewHref} aria-label="View startup" {...externalLinkProps(viewHref)}> <Link href={viewHref} aria-label="View startup" {...externalLinkProps(viewHref)}>
@ -142,7 +142,7 @@ export function LastYearWinnerTip({ company, className, showClose, onClose }: Pr
{donateHref ? ( {donateHref ? (
<Button <Button
size="icon-sm" size="icon-sm"
className="rounded-full bg-[#1a5c38] text-white hover:bg-[#0d3d26]" className="rounded-full bg-[#37a47a] text-white hover:bg-[#30614c]"
asChild asChild
> >
<Link href={donateHref} aria-label="Donate" {...externalLinkProps(donateHref)}> <Link href={donateHref} aria-label="Donate" {...externalLinkProps(donateHref)}>

View File

@ -61,13 +61,13 @@ export function LastYearWinnersScroll({ variant = "on-green", className }: Props
<div <div
className={cn( className={cn(
"pt-8", "pt-8",
onLight ? "mt-8 border-t border-[#1a5c38]/12" : "mt-10 border-t border-white/15", onLight ? "mt-8 border-t border-[#37a47a]/12" : "mt-10 border-t border-white/15",
className className
)} )}
> >
<p <p
className={cn( className={cn(
"text-center text-[10px] font-semibold uppercase tracking-[0.2em] text-[#ffb300]" "text-center text-[10px] font-semibold uppercase tracking-[0.2em] text-[#37a47a]"
)} )}
> >
{lastYearWinnersCopy.eyebrow} {lastYearWinnersCopy.eyebrow}
@ -75,13 +75,13 @@ export function LastYearWinnersScroll({ variant = "on-green", className }: Props
<p <p
className={cn( className={cn(
"mt-2 text-center text-lg font-bold tracking-tight md:text-xl", "mt-2 text-center text-lg font-bold tracking-tight md:text-xl",
onLight ? "text-[#0d3d26]" : "text-white" onLight ? "text-[#30614c]" : "text-white"
)} )}
> >
{lastYearWinnersCopy.headline} {lastYearWinnersCopy.headline}
</p> </p>
<p className="mt-2 text-center"> <p className="mt-2 text-center">
<span className="inline-block rounded-full bg-white px-3 py-1 text-[11px] font-medium text-[#1a5c38] shadow-sm"> <span className="inline-block rounded-full bg-white px-3 py-1 text-[11px] font-medium text-[#37a47a] shadow-sm">
{lastYearWinnersCopy.hoverHint} {lastYearWinnersCopy.hoverHint}
</span> </span>
</p> </p>
@ -92,13 +92,13 @@ export function LastYearWinnersScroll({ variant = "on-green", className }: Props
<div <div
className={cn( className={cn(
"pointer-events-none absolute inset-y-0 left-0 z-10 w-10 bg-gradient-to-r to-transparent", "pointer-events-none absolute inset-y-0 left-0 z-10 w-10 bg-gradient-to-r to-transparent",
onLight ? "from-white" : "from-[#1a5c38]" onLight ? "from-white" : "from-[#37a47a]"
)} )}
/> />
<div <div
className={cn( className={cn(
"pointer-events-none absolute inset-y-0 right-0 z-10 w-10 bg-gradient-to-l to-transparent", "pointer-events-none absolute inset-y-0 right-0 z-10 w-10 bg-gradient-to-l to-transparent",
onLight ? "from-white" : "from-[#1a5c38]" onLight ? "from-white" : "from-[#37a47a]"
)} )}
/> />
<div <div

View File

@ -53,7 +53,7 @@ export function Newsletter() {
</div> </div>
<Button <Button
type="submit" type="submit"
className="rounded-full bg-[#ffb300] text-[#0f0404] hover:bg-[#ffb300]/90" className="rounded-full bg-[#37a47a] text-[#ffffff] hover:bg-[#37a47a]/90"
disabled={status === "loading"} disabled={status === "loading"}
> >
{status === "loading" ? "Signing up…" : "Sign up"} {status === "loading" ? "Signing up…" : "Sign up"}

View File

@ -5,9 +5,9 @@ export function PartnerMarquee() {
const slots = Array.from({ length: 8 }, (_, i) => i); const slots = Array.from({ length: 8 }, (_, i) => i);
return ( return (
<section className="section-white relative overflow-hidden border-y border-border bg-white py-8 text-[#0d3d26]"> <section className="section-white relative overflow-hidden border-y border-border bg-white py-8 text-[#30614c]">
<WavyContourLinesBackground className="z-0" /> <WavyContourLinesBackground className="z-0" />
<p className="relative z-10 mb-6 text-center text-xs font-semibold uppercase tracking-widest text-[#3d5248]"> <p className="relative z-10 mb-6 text-center text-xs font-semibold uppercase tracking-widest text-[#5b5b5b]">
With the support of With the support of
</p> </p>
<div className="relative z-10 overflow-hidden"> <div className="relative z-10 overflow-hidden">

View File

@ -7,18 +7,18 @@ export function PurposeBand() {
<Section id="about"> <Section id="about">
<div className="grid items-center gap-10 lg:grid-cols-2"> <div className="grid items-center gap-10 lg:grid-cols-2">
<TopoProseSurface> <TopoProseSurface>
<p className="text-xs font-semibold uppercase tracking-widest text-[#ffb300]"> <p className="text-xs font-semibold uppercase tracking-widest text-[#37a47a]">
About this summit About this summit
</p> </p>
<h2 className="mt-3 text-3xl font-bold md:text-4xl"> <h2 className="mt-3 text-3xl font-bold md:text-4xl">
A first-of-its-kind gathering for Ethiopia&apos;s innovators A first-of-its-kind gathering for Ethiopia&apos;s innovators
</h2> </h2>
<p className="mt-4 text-[#3d5248] leading-relaxed"> <p className="mt-4 text-[#5b5b5b] leading-relaxed">
The Great Rift Valley Innovation Summit, presented by the Ethiopian Diaspora Trust The Great Rift Valley Innovation Summit, presented by the Ethiopian Diaspora Trust
Fund (EDTF), convenes entrepreneurs, investors, companies, startups, and jobseekers to Fund (EDTF), convenes entrepreneurs, investors, companies, startups, and jobseekers to
advance tech-enabled innovation in agriculture, healthcare, and education. advance tech-enabled innovation in agriculture, healthcare, and education.
</p> </p>
<p className="mt-4 text-[#3d5248] leading-relaxed"> <p className="mt-4 text-[#5b5b5b] leading-relaxed">
Programming includes an exhibitor hall, workshops and panel discussions, and the Programming includes an exhibitor hall, workshops and panel discussions, and the
inaugural Great Rift Valley Pitch Competition<PurposeGrantText /> Ten companies will inaugural Great Rift Valley Pitch Competition<PurposeGrantText /> Ten companies will
be selected from the most impactful ventures. be selected from the most impactful ventures.

View File

@ -24,13 +24,13 @@ export function Speakers() {
return ( return (
<Section id="speakers"> <Section id="speakers">
<TopoProseSurface className="max-w-3xl"> <TopoProseSurface className="max-w-3xl">
<p className="text-xs font-semibold uppercase tracking-widest text-[#ffb300]"> <p className="text-xs font-semibold uppercase tracking-widest text-[#37a47a]">
Lineup Lineup
</p> </p>
<h2 className="mt-2 text-4xl font-bold tracking-tight md:text-5xl"> <h2 className="mt-2 text-4xl font-bold tracking-tight md:text-5xl">
Meet the voices of GRV Summit Meet the voices of GRV Summit
</h2> </h2>
<p className="mt-4 text-[#3d5248] leading-relaxed"> <p className="mt-4 text-[#5b5b5b] leading-relaxed">
Keynotes, panelists, judges, and opening speakers {site.dates.label} at{" "} Keynotes, panelists, judges, and opening speakers {site.dates.label} at{" "}
{site.venue.name}. {site.venue.name}.
</p> </p>
@ -40,12 +40,12 @@ export function Speakers() {
{(Object.entries(grouped) as [SpeakerGroup, typeof speakers][]).map( {(Object.entries(grouped) as [SpeakerGroup, typeof speakers][]).map(
([group, list]) => ( ([group, list]) => (
<div key={group}> <div key={group}>
<div className="mb-2 flex flex-wrap items-end justify-between gap-4 border-b border-[#1a5c38]/15 pb-4"> <div className="mb-2 flex flex-wrap items-end justify-between gap-4 border-b border-[#37a47a]/15 pb-4">
<div> <div>
<h3 className="text-2xl font-bold md:text-3xl"> <h3 className="text-2xl font-bold md:text-3xl">
{speakerGroupLabels[group]} {speakerGroupLabels[group]}
</h3> </h3>
<p className="mt-1 text-sm text-[#3d5248]">{site.dates.label}</p> <p className="mt-1 text-sm text-[#5b5b5b]">{site.dates.label}</p>
</div> </div>
</div> </div>
<div className="grid gap-4 sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4"> <div className="grid gap-4 sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4">
@ -59,7 +59,7 @@ export function Speakers() {
</div> </div>
<div className="mt-12 flex flex-wrap justify-center gap-3"> <div className="mt-12 flex flex-wrap justify-center gap-3">
<Button className="rounded-full bg-[#ffb300] text-[#0f0404] hover:bg-[#ffb300]/90" asChild> <Button className="rounded-full bg-[#37a47a] text-[#ffffff] hover:bg-[#37a47a]/90" asChild>
<Link href="/program">View full program</Link> <Link href="/program">View full program</Link>
</Button> </Button>
<Button variant="outline" className="rounded-full" asChild> <Button variant="outline" className="rounded-full" asChild>

View File

@ -10,13 +10,13 @@ export function SponsorTiers() {
return ( return (
<Section id="partners"> <Section id="partners">
<TopoProseSurface className="mx-auto max-w-3xl text-center"> <TopoProseSurface className="mx-auto max-w-3xl text-center">
<p className="text-xs font-semibold uppercase tracking-widest text-[#ffb300]"> <p className="text-xs font-semibold uppercase tracking-widest text-[#37a47a]">
Partners Partners
</p> </p>
<h2 className="mt-2 text-3xl font-bold text-[#0d3d26] md:text-4xl"> <h2 className="mt-2 text-3xl font-bold text-[#30614c] md:text-4xl">
Partners &amp; sponsors Partners &amp; sponsors
</h2> </h2>
<p className="mt-3 text-[#3d5248]"> <p className="mt-3 text-[#5b5b5b]">
Logo slots below are open partner with GRV Summit and feature your brand here. Logo slots below are open partner with GRV Summit and feature your brand here.
</p> </p>
</TopoProseSurface> </TopoProseSurface>
@ -24,7 +24,7 @@ export function SponsorTiers() {
{partnerTiers.slice(0, 2).map((tier) => ( {partnerTiers.slice(0, 2).map((tier) => (
<div key={tier.id}> <div key={tier.id}>
<Separator className="mb-6" /> <Separator className="mb-6" />
<h3 className="text-center text-sm font-semibold uppercase tracking-wider text-[#1a5c38]"> <h3 className="text-center text-sm font-semibold uppercase tracking-wider text-[#37a47a]">
{tier.name} {tier.name}
</h3> </h3>
<div className="mt-6 flex flex-wrap items-center justify-center gap-6"> <div className="mt-6 flex flex-wrap items-center justify-center gap-6">
@ -32,7 +32,7 @@ export function SponsorTiers() {
<PartnerLogoPlaceholder <PartnerLogoPlaceholder
key={`${tier.id}-${i}`} key={`${tier.id}-${i}`}
size="md" size="md"
className="border-[#1a5c38]/20 bg-[#f0f5f2] text-[#1a5c38]/50" className="border-[#37a47a]/20 bg-[#e8f2ec] text-[#37a47a]/50"
/> />
))} ))}
</div> </div>
@ -40,7 +40,7 @@ export function SponsorTiers() {
))} ))}
</div> </div>
<div className="mt-10 text-center"> <div className="mt-10 text-center">
<Button className="rounded-full bg-[#ffb300] text-[#0f0404] hover:bg-[#ffb300]/90" asChild> <Button className="rounded-full bg-[#37a47a] text-[#ffffff] hover:bg-[#37a47a]/90" asChild>
<Link href="/partners">Become a partner</Link> <Link href="/partners">Become a partner</Link>
</Button> </Button>
</div> </div>

View File

@ -6,7 +6,7 @@ export function StatsGrid() {
return ( return (
<Section variant="muted" id="stats"> <Section variant="muted" id="stats">
<TopoProseSurface className="topo-on-green-bg mx-auto max-w-3xl text-center"> <TopoProseSurface className="topo-on-green-bg mx-auto max-w-3xl text-center">
<p className="text-xs font-semibold uppercase tracking-widest text-[#ffb300]"> <p className="text-xs font-semibold uppercase tracking-widest text-[#b9d8c9]">
The future starts here The future starts here
</p> </p>
<h2 className="mt-3 text-3xl font-bold text-white md:text-4xl"> <h2 className="mt-3 text-3xl font-bold text-white md:text-4xl">
@ -17,18 +17,18 @@ export function StatsGrid() {
{site.stats.map((stat) => ( {site.stats.map((stat) => (
<div <div
key={stat.label} key={stat.label}
className="topo-card-surface rounded-2xl border border-border bg-white p-6 text-center text-[#1a5c38] shadow-sm" className="topo-card-surface rounded-2xl border border-border bg-white p-6 text-center text-[#37a47a] shadow-sm"
> >
{stat.type === "cycling" ? ( {stat.type === "cycling" ? (
<CyclingGrantAmount <CyclingGrantAmount
showCaption showCaption
valueClassName="text-3xl font-bold text-[#1a5c38] md:text-4xl" valueClassName="text-3xl font-bold text-[#37a47a] md:text-4xl"
captionClassName="text-[#3d5248]" captionClassName="text-[#5b5b5b]"
/> />
) : ( ) : (
<p className="text-3xl font-bold text-[#1a5c38] md:text-4xl">{stat.value}</p> <p className="text-3xl font-bold text-[#37a47a] md:text-4xl">{stat.value}</p>
)} )}
<p className="mt-2 text-sm text-[#3d5248]">{stat.label}</p> <p className="mt-2 text-sm text-[#5b5b5b]">{stat.label}</p>
</div> </div>
))} ))}
</div> </div>

View File

@ -7,7 +7,7 @@ export function TicketsBand() {
return ( return (
<Section variant="inverse" id="tickets"> <Section variant="inverse" id="tickets">
<div className="relative text-center"> <div className="relative text-center">
<p className="text-xs font-semibold uppercase tracking-widest text-[#ffb300]"> <p className="text-xs font-semibold uppercase tracking-widest text-[#b9d8c9]">
Tickets Tickets
</p> </p>
<h2 className="mt-2 text-3xl font-bold uppercase tracking-tight md:text-4xl"> <h2 className="mt-2 text-3xl font-bold uppercase tracking-tight md:text-4xl">
@ -31,7 +31,7 @@ export function TicketsBand() {
<p className="mt-10 text-center text-sm text-white/50"> <p className="mt-10 text-center text-sm text-white/50">
Accepted: Visa, Mastercard, AMEX ·{" "} Accepted: Visa, Mastercard, AMEX ·{" "}
<Link href="/payment" className="text-[#ffb300] hover:underline"> <Link href="/payment" className="text-[#b9d8c9] hover:underline">
Bank transfer & invoice Bank transfer & invoice
</Link> </Link>
</p> </p>

View File

@ -8,10 +8,10 @@ export function TopicMarquee() {
return ( return (
<Section id="topics" className="overflow-hidden py-12"> <Section id="topics" className="overflow-hidden py-12">
<TopoProseSurface className="mx-auto mb-8 max-w-3xl text-center"> <TopoProseSurface className="mx-auto mb-8 max-w-3xl text-center">
<p className="text-xs font-semibold uppercase tracking-widest text-[#ffb300]"> <p className="text-xs font-semibold uppercase tracking-widest text-[#37a47a]">
Program themes Program themes
</p> </p>
<h2 className="mt-2 text-2xl font-bold text-[#0d3d26] md:text-3xl"> <h2 className="mt-2 text-2xl font-bold text-[#30614c] md:text-3xl">
Topics shaping the summit Topics shaping the summit
</h2> </h2>
</TopoProseSurface> </TopoProseSurface>
@ -21,7 +21,7 @@ export function TopicMarquee() {
<Badge <Badge
key={`${topic}-${i}`} key={`${topic}-${i}`}
variant="secondary" variant="secondary"
className="shrink-0 rounded-full border border-[#1a5c38]/15 bg-[#f0f5f2] px-4 py-2 text-sm text-[#1a5c38]" className="shrink-0 rounded-full border border-[#37a47a]/15 bg-[#e8f2ec] px-4 py-2 text-sm text-[#37a47a]"
> >
{topic} {topic}
</Badge> </Badge>

View File

@ -9,7 +9,7 @@ export function Venue() {
<Section id="venue" variant="muted"> <Section id="venue" variant="muted">
<div className="grid gap-8 lg:grid-cols-2"> <div className="grid gap-8 lg:grid-cols-2">
<div className="topo-on-green-bg"> <div className="topo-on-green-bg">
<p className="text-xs font-semibold uppercase tracking-widest text-[#ffb300]">The venue</p> <p className="text-xs font-semibold uppercase tracking-widest text-[#b9d8c9]">The venue</p>
<h2 className="mt-2 text-3xl font-bold text-white">{site.venue.name}</h2> <h2 className="mt-2 text-3xl font-bold text-white">{site.venue.name}</h2>
<p className="mt-4 text-white/85">{site.venue.address}</p> <p className="mt-4 text-white/85">{site.venue.address}</p>
<Button <Button

View File

@ -52,11 +52,11 @@ export function FooterNewsletter() {
} }
return ( return (
<div className="relative z-10 mx-auto max-w-5xl rounded-3xl border border-[#1a5c38]/14 bg-white p-6 shadow-md shadow-[#1a5c38]/6 md:p-10"> <div className="relative z-10 mx-auto max-w-5xl rounded-3xl border border-[#37a47a]/14 bg-white p-6 shadow-md shadow-[#37a47a]/6 md:p-10">
<div className="grid gap-8 lg:grid-cols-[1fr_1.2fr] lg:items-start"> <div className="grid gap-8 lg:grid-cols-[1fr_1.2fr] lg:items-start">
<div> <div>
<BrandLogo href={undefined} /> <BrandLogo href={undefined} />
<h2 className="mt-4 text-2xl font-bold text-[#0d3d26] md:text-3xl">Stay up to date!</h2> <h2 className="mt-4 text-2xl font-bold text-[#30614c] md:text-3xl">Stay up to date!</h2>
<p className="mt-2 text-sm text-muted-foreground leading-relaxed"> <p className="mt-2 text-sm text-muted-foreground leading-relaxed">
Get announcements about tickets, lineup, and the next Great Rift Valley Innovation Get announcements about tickets, lineup, and the next Great Rift Valley Innovation
Summit edition before anyone else. Summit edition before anyone else.
@ -91,11 +91,11 @@ export function FooterNewsletter() {
/> />
{error && <p className="text-sm text-destructive">{error}</p>} {error && <p className="text-sm text-destructive">{error}</p>}
{status === "done" && ( {status === "done" && (
<p className="text-sm text-[#1a5c38]">You&apos;re on the list thank you!</p> <p className="text-sm text-[#37a47a]">You&apos;re on the list thank you!</p>
)} )}
<Button <Button
type="submit" type="submit"
className="w-full rounded-full bg-[#1a5c38] text-white hover:bg-[#0d3d26] sm:w-auto" className="w-full rounded-full bg-[#37a47a] text-white hover:bg-[#30614c] sm:w-auto"
disabled={status === "loading"} disabled={status === "loading"}
> >
{status === "loading" ? "Signing up…" : "Sign up"} {status === "loading" ? "Signing up…" : "Sign up"}

View File

@ -58,7 +58,7 @@ export function FooterSocialLinks({ className }: Props) {
target="_blank" target="_blank"
rel="noopener noreferrer" rel="noopener noreferrer"
aria-label={label} aria-label={label}
className="inline-flex size-10 items-center justify-center rounded-full border border-[#1a5c38]/18 bg-[#f7faf8] text-[#1a5c38] shadow-sm transition-colors hover:border-[#1a5c38]/35 hover:bg-[#e8f2ec] hover:text-[#0d3d26]" className="inline-flex size-10 items-center justify-center rounded-full border border-[#37a47a]/18 bg-[#f7faf8] text-[#37a47a] shadow-sm transition-colors hover:border-[#37a47a]/35 hover:bg-[#e8f2ec] hover:text-[#30614c]"
> >
<Icon className="size-[18px]" /> <Icon className="size-[18px]" />
</Link> </Link>

View File

@ -11,7 +11,7 @@ export function FooterSurface({ children, className }: Props) {
return ( return (
<div <div
className={cn( className={cn(
"rounded-2xl border border-[#1a5c38]/14 bg-white p-6 shadow-md shadow-[#1a5c38]/6 md:p-8", "rounded-2xl border border-[#37a47a]/14 bg-white p-6 shadow-md shadow-[#37a47a]/6 md:p-8",
className className
)} )}
> >

View File

@ -119,7 +119,7 @@ export function MobileNavDropdown({ open, onClose }: DropdownProps) {
<Link <Link
href="/program" href="/program"
onClick={onClose} onClick={onClose}
className="mt-1 block rounded-xl px-3 py-2.5 text-sm font-semibold text-[#ffb300] hover:bg-white/5" className="mt-1 block rounded-xl px-3 py-2.5 text-sm font-semibold text-[#b9d8c9] hover:bg-white/5"
> >
View full program View full program
</Link> </Link>
@ -138,7 +138,7 @@ export function MobileNavDropdown({ open, onClose }: DropdownProps) {
> >
<span>{link.label}</span> <span>{link.label}</span>
{"badge" in link && link.badge && ( {"badge" in link && link.badge && (
<span className="rounded-md bg-[#ffb300] px-2 py-0.5 text-[10px] font-bold uppercase tracking-wide text-[#0f0404]"> <span className="rounded-md bg-[#37a47a] px-2 py-0.5 text-[10px] font-bold uppercase tracking-wide text-[#ffffff]">
{link.badge} {link.badge}
</span> </span>
)} )}
@ -152,7 +152,7 @@ export function MobileNavDropdown({ open, onClose }: DropdownProps) {
onClick={onClose} onClick={onClose}
className={cn( className={cn(
"flex h-12 min-w-0 flex-1 items-center justify-center rounded-full", "flex h-12 min-w-0 flex-1 items-center justify-center rounded-full",
"bg-white px-4 text-sm font-bold text-[#0f0404] transition-transform active:scale-[0.98]" "bg-white px-4 text-sm font-bold text-[#ffffff] transition-transform active:scale-[0.98]"
)} )}
> >
Apply to pitch Apply to pitch

View File

@ -32,10 +32,10 @@ export function TicketsMarqueeCta({
onClick={onNavigate} onClick={onNavigate}
aria-label={ariaLabel} aria-label={ariaLabel}
className={cn( className={cn(
"relative flex items-center overflow-hidden rounded-full bg-[#ffb300] text-[#0f0404]", "relative flex items-center overflow-hidden rounded-full bg-[#37a47a] text-[#ffffff]",
"shadow-md transition-colors hover:bg-[#ffb300]/90", "shadow-md transition-colors hover:bg-[#37a47a]/90",
"[&:hover_.ticket-menu-marquee]:[animation-duration:6s]", "[&:hover_.ticket-menu-marquee]:[animation-duration:6s]",
"focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[#ffb300] focus-visible:ring-offset-2", "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[#37a47a] focus-visible:ring-offset-2",
className className
)} )}
> >

View File

@ -40,7 +40,7 @@ export function PageRiftHeader({
return ( return (
<header <header
className={cn( className={cn(
"section-white group/topo-section relative isolate min-h-[220px] overflow-x-hidden overflow-y-visible border-b border-[#1a5c38]/10 bg-white pt-24 pb-10 md:min-h-[260px] md:pb-12", "section-white group/topo-section relative isolate min-h-[220px] overflow-x-hidden overflow-y-visible border-b border-[#37a47a]/10 bg-white pt-24 pb-10 md:min-h-[260px] md:pb-12",
className className
)} )}
> >
@ -50,13 +50,13 @@ export function PageRiftHeader({
<div className="topo-content-layer topo-content-readable relative z-10 mx-auto max-w-6xl px-4 pt-4 md:px-6"> <div className="topo-content-layer topo-content-readable relative z-10 mx-auto max-w-6xl px-4 pt-4 md:px-6">
<TopoProseSurface className="max-w-3xl"> <TopoProseSurface className="max-w-3xl">
{eyebrow && ( {eyebrow && (
<p className="text-xs font-semibold uppercase tracking-widest text-[#ffb300]"> <p className="text-xs font-semibold uppercase tracking-widest text-[#37a47a]">
{eyebrow} {eyebrow}
</p> </p>
)} )}
<div className="mt-3">{title}</div> <div className="mt-3">{title}</div>
{description && ( {description && (
<div className="mt-4 text-[#3d5248] leading-relaxed">{description}</div> <div className="mt-4 text-[#5b5b5b] leading-relaxed">{description}</div>
)} )}
</TopoProseSurface> </TopoProseSurface>
{children && <div className="relative z-[15] mt-8">{children}</div>} {children && <div className="relative z-[15] mt-8">{children}</div>}

View File

@ -39,8 +39,8 @@ export function Section({
id={id} id={id}
className={cn( className={cn(
"group/topo-section relative isolate py-16 md:py-24", "group/topo-section relative isolate py-16 md:py-24",
isGreen && "section-green bg-[#1a5c38]", isGreen && "section-green bg-primary",
!isGreen && "section-white bg-white text-[#0d3d26]", !isGreen && "section-white bg-white text-[#30614c]",
!isGreen && "overflow-x-hidden overflow-y-visible", !isGreen && "overflow-x-hidden overflow-y-visible",
isGreen && "overflow-hidden", isGreen && "overflow-hidden",
className className

View File

@ -58,14 +58,14 @@ export function SiteEntryPrompt() {
aria-labelledby="entry-consent-title" aria-labelledby="entry-consent-title"
aria-describedby="entry-consent-desc" aria-describedby="entry-consent-desc"
className={cn( className={cn(
"fixed bottom-4 right-4 z-[200] w-[min(calc(100vw-2rem),24rem)] rounded-2xl border border-[#1a5c38]/15 bg-white p-5 shadow-[0_12px_40px_rgba(13,61,38,0.18)] transition-all duration-500 ease-out", "fixed bottom-4 right-4 z-[200] w-[min(calc(100vw-2rem),24rem)] rounded-2xl border border-[#37a47a]/15 bg-white p-5 shadow-[0_12px_40px_rgba(13,61,38,0.18)] transition-all duration-500 ease-out",
visible ? "translate-y-0 opacity-100" : "translate-y-3 opacity-0" visible ? "translate-y-0 opacity-100" : "translate-y-3 opacity-0"
)} )}
> >
<button <button
type="button" type="button"
onClick={handleDecline} onClick={handleDecline}
className="absolute top-3 right-3 rounded-full p-1 text-[#3d5248] transition-colors hover:bg-[#1a5c38]/8 hover:text-[#0d3d26]" className="absolute top-3 right-3 rounded-full p-1 text-[#5b5b5b] transition-colors hover:bg-[#37a47a]/8 hover:text-[#30614c]"
aria-label="Decline and close" aria-label="Decline and close"
> >
<X className="size-4" /> <X className="size-4" />
@ -73,29 +73,29 @@ export function SiteEntryPrompt() {
<h2 <h2
id="entry-consent-title" id="entry-consent-title"
className="pr-6 text-lg font-bold leading-snug text-[#0d3d26]" className="pr-6 text-lg font-bold leading-snug text-[#30614c]"
> >
{copy.title} {copy.title}
</h2> </h2>
<p id="entry-consent-desc" className="mt-2 text-sm leading-relaxed text-[#3d5248]"> <p id="entry-consent-desc" className="mt-2 text-sm leading-relaxed text-[#5b5b5b]">
{copy.description} {copy.description}
</p> </p>
<div className="mt-4 flex items-start gap-3 rounded-lg border border-[#1a5c38]/12 bg-[#f0f5f2]/80 p-3"> <div className="mt-4 flex items-start gap-3 rounded-lg border border-[#37a47a]/12 bg-[#e8f2ec]/80 p-3">
<Checkbox <Checkbox
id="site-entry-consent" id="site-entry-consent"
checked={checked} checked={checked}
onCheckedChange={(v) => setChecked(v === true)} onCheckedChange={(v) => setChecked(v === true)}
className="mt-0.5 border-[#1a5c38]/40 data-[state=checked]:border-[#1a5c38] data-[state=checked]:bg-[#1a5c38]" className="mt-0.5 border-[#37a47a]/40 data-[state=checked]:border-[#37a47a] data-[state=checked]:bg-[#37a47a]"
/> />
<Label <Label
htmlFor="site-entry-consent" htmlFor="site-entry-consent"
className="text-sm font-normal leading-snug text-[#3d5248]" className="text-sm font-normal leading-snug text-[#5b5b5b]"
> >
{copy.checkboxLabel}{" "} {copy.checkboxLabel}{" "}
<Link <Link
href={copy.privacyHref} href={copy.privacyHref}
className="font-medium text-[#1a5c38] underline underline-offset-2" className="font-medium text-[#37a47a] underline underline-offset-2"
> >
{dataConsent.privacyLinkText} {dataConsent.privacyLinkText}
</Link> </Link>
@ -108,7 +108,7 @@ export function SiteEntryPrompt() {
type="button" type="button"
disabled={!checked} disabled={!checked}
onClick={handleAccept} onClick={handleAccept}
className="rounded-full bg-[#1a5c38] text-white hover:bg-[#0d3d26] disabled:opacity-50" className="rounded-full bg-[#37a47a] text-white hover:bg-[#30614c] disabled:opacity-50"
> >
{copy.acceptCta} {copy.acceptCta}
</Button> </Button>
@ -116,7 +116,7 @@ export function SiteEntryPrompt() {
type="button" type="button"
variant="outline" variant="outline"
onClick={handleDecline} onClick={handleDecline}
className="rounded-full border-[#1a5c38]/30 text-[#1a5c38] hover:bg-[#1a5c38]/6" className="rounded-full border-[#37a47a]/30 text-[#37a47a] hover:bg-[#37a47a]/6"
> >
{copy.declineCta} {copy.declineCta}
</Button> </Button>

View File

@ -46,7 +46,7 @@ const footerColumns = [
export function SiteFooter() { export function SiteFooter() {
return ( return (
<footer className="site-footer section-white relative overflow-hidden bg-white pt-8 text-[#0d3d26] md:pt-10"> <footer className="site-footer section-white relative overflow-hidden bg-white pt-8 text-[#30614c] md:pt-10">
<GeometricMessBackground /> <GeometricMessBackground />
<div className="relative z-10 space-y-6 px-4 pb-12 md:space-y-8 md:px-6"> <div className="relative z-10 space-y-6 px-4 pb-12 md:space-y-8 md:px-6">
@ -57,13 +57,13 @@ export function SiteFooter() {
<div className="grid gap-10 sm:grid-cols-2 lg:grid-cols-4"> <div className="grid gap-10 sm:grid-cols-2 lg:grid-cols-4">
{footerColumns.map((col) => ( {footerColumns.map((col) => (
<div key={col.title}> <div key={col.title}>
<h3 className="text-sm font-semibold text-[#1a5c38]">{col.title}</h3> <h3 className="text-sm font-semibold text-[#37a47a]">{col.title}</h3>
<ul className="mt-4 space-y-2.5"> <ul className="mt-4 space-y-2.5">
{col.links.map((link) => ( {col.links.map((link) => (
<li key={link.href}> <li key={link.href}>
<Link <Link
href={link.href} href={link.href}
className="text-sm text-[#3d5248] transition-colors hover:text-[#0d3d26]" className="text-sm text-[#5b5b5b] transition-colors hover:text-[#30614c]"
{...("external" in link && link.external {...("external" in link && link.external
? { target: "_blank", rel: "noopener noreferrer" } ? { target: "_blank", rel: "noopener noreferrer" }
: {})} : {})}
@ -77,9 +77,9 @@ export function SiteFooter() {
))} ))}
</div> </div>
<div className="mt-10 flex flex-col gap-6 border-t border-[#1a5c38]/12 pt-8 sm:flex-row sm:items-center sm:justify-between"> <div className="mt-10 flex flex-col gap-6 border-t border-[#37a47a]/12 pt-8 sm:flex-row sm:items-center sm:justify-between">
<div> <div>
<p className="text-xs font-semibold uppercase tracking-widest text-[#1a5c38]"> <p className="text-xs font-semibold uppercase tracking-widest text-[#37a47a]">
Follow us Follow us
</p> </p>
<FooterSocialLinks className="mt-4" /> <FooterSocialLinks className="mt-4" />
@ -89,7 +89,7 @@ export function SiteFooter() {
<FooterSurface className="mt-6 py-5 md:py-6"> <FooterSurface className="mt-6 py-5 md:py-6">
<div className="flex flex-col items-center justify-between gap-4 sm:flex-row"> <div className="flex flex-col items-center justify-between gap-4 sm:flex-row">
<p className="text-center text-xs font-medium uppercase tracking-wider text-[#3d5248] sm:text-left"> <p className="text-center text-xs font-medium uppercase tracking-wider text-[#5b5b5b] sm:text-left">
{site.shortName} · {site.dates.label} · Presented by {site.presentedBy} {site.shortName} · {site.dates.label} · Presented by {site.presentedBy}
</p> </p>
<p className="text-center text-xs text-[#5c6b62] sm:text-right"> <p className="text-center text-xs text-[#5c6b62] sm:text-right">

View File

@ -23,7 +23,7 @@ const navPills = [
]; ];
const pillClass = const pillClass =
"inline-flex items-center gap-1.5 rounded-full bg-[#1a5c38]/10 px-4 py-2 text-sm font-medium text-[#0d3d26] transition-colors hover:bg-[#1a5c38]/15"; "inline-flex items-center gap-1.5 rounded-full bg-[#37a47a]/10 px-4 py-2 text-sm font-medium text-[#30614c] transition-colors hover:bg-[#37a47a]/15";
export function SiteHeader() { export function SiteHeader() {
const [mobileOpen, setMobileOpen] = useState(false); const [mobileOpen, setMobileOpen] = useState(false);
@ -34,8 +34,8 @@ export function SiteHeader() {
<div <div
className={cn( className={cn(
"flex items-center gap-2 rounded-full", "flex items-center gap-2 rounded-full",
"border border-[#1a5c38]/10 bg-white/95 px-2 py-2", "border border-[#37a47a]/10 bg-white/95 px-2 py-2",
"shadow-lg shadow-[#1a5c38]/10 backdrop-blur-md" "shadow-lg shadow-[#37a47a]/10 backdrop-blur-md"
)} )}
> >
<BrandLogo className="min-w-0 shrink pl-0.5" compact /> <BrandLogo className="min-w-0 shrink pl-0.5" compact />
@ -62,7 +62,7 @@ export function SiteHeader() {
<DropdownMenuItem asChild> <DropdownMenuItem asChild>
<Link <Link
href="/pitch-competition" href="/pitch-competition"
className="mt-1 cursor-pointer rounded-xl bg-[#1a5c38] p-3 text-white" className="mt-1 cursor-pointer rounded-xl bg-[#37a47a] p-3 text-white"
> >
Pitch Competition Pitch Competition
</Link> </Link>
@ -74,7 +74,7 @@ export function SiteHeader() {
<Link key={link.href} href={link.href} className={pillClass}> <Link key={link.href} href={link.href} className={pillClass}>
{link.label} {link.label}
{link.badge && ( {link.badge && (
<span className="rounded bg-[#1a5c38] px-1.5 py-0.5 text-[10px] font-bold uppercase tracking-wide text-white"> <span className="rounded bg-[#37a47a] px-1.5 py-0.5 text-[10px] font-bold uppercase tracking-wide text-white">
{link.badge} {link.badge}
</span> </span>
)} )}

View File

@ -156,11 +156,11 @@ export function ChampionStartupModal() {
/> />
{error && <p className="text-sm text-destructive">{error}</p>} {error && <p className="text-sm text-destructive">{error}</p>}
{status === "success" && ( {status === "success" && (
<p className="text-sm text-[#1a5c38]">Thank you for championing this startup!</p> <p className="text-sm text-[#37a47a]">Thank you for championing this startup!</p>
)} )}
<Button <Button
type="submit" type="submit"
className="w-full rounded-full bg-[#1f3d7e] hover:bg-[#1f3d7e]/90" className="w-full rounded-full bg-[#30614c] hover:bg-[#30614c]/90"
disabled={status === "loading"} disabled={status === "loading"}
> >
{status === "loading" ? "Submitting…" : "Submit recommendation"} {status === "loading" ? "Submitting…" : "Submit recommendation"}

View File

@ -11,7 +11,7 @@ type Props = {
export function PartnerCard({ partner, tierLabel }: Props) { export function PartnerCard({ partner, tierLabel }: Props) {
return ( return (
<Card className="topo-card-surface h-full border-border/80 bg-white text-[#1a5c38]"> <Card className="topo-card-surface h-full border-border/80 bg-white text-[#37a47a]">
{tierLabel && ( {tierLabel && (
<p className="px-6 pt-6 text-xs font-semibold uppercase tracking-widest text-muted-foreground"> <p className="px-6 pt-6 text-xs font-semibold uppercase tracking-widest text-muted-foreground">
{tierLabel} {tierLabel}
@ -20,7 +20,7 @@ export function PartnerCard({ partner, tierLabel }: Props) {
<CardHeader className={tierLabel ? "pt-2" : undefined}> <CardHeader className={tierLabel ? "pt-2" : undefined}>
<PartnerLogoPlaceholder <PartnerLogoPlaceholder
size="lg" size="lg"
className="w-full border-[#1a5c38]/20 bg-[#f0f5f2] text-[#1a5c38]/50" className="w-full border-[#37a47a]/20 bg-[#e8f2ec] text-[#37a47a]/50"
/> />
</CardHeader> </CardHeader>
<CardContent className="flex flex-1 flex-col"> <CardContent className="flex flex-1 flex-col">

View File

@ -12,14 +12,14 @@ export function PartnerSectionBlock({ section, showTitle = true }: Props) {
<div className="space-y-8"> <div className="space-y-8">
{showTitle && ( {showTitle && (
<> <>
<h2 className="text-3xl font-bold tracking-tight text-[#0d3d26]"> <h2 className="text-3xl font-bold tracking-tight text-[#30614c]">
{section.title} {section.title}
</h2> </h2>
<Separator /> <Separator />
</> </>
)} )}
{section.tierLabel && ( {section.tierLabel && (
<p className="text-xs font-semibold uppercase tracking-widest text-[#1a5c38]"> <p className="text-xs font-semibold uppercase tracking-widest text-[#37a47a]">
{section.tierLabel} {section.tierLabel}
</p> </p>
)} )}

View File

@ -9,7 +9,7 @@ export function PartnershipCtaBand() {
return ( return (
<section <section
id="partnership-form" id="partnership-form"
className="group/topo-section section-green relative isolate overflow-hidden bg-[#1a5c38] py-16 md:py-24" className="group/topo-section section-green relative isolate overflow-hidden bg-[#37a47a] py-16 md:py-24"
> >
<RoundedRockVoronoiBackground className="z-0" /> <RoundedRockVoronoiBackground className="z-0" />
<TopoSectionProvider tone="green"> <TopoSectionProvider tone="green">

View File

@ -54,7 +54,7 @@ export function PartnershipInquiryForm() {
} }
return ( return (
<div className="topo-card-surface rounded-2xl bg-white p-6 text-[#1a5c38] shadow-xl md:p-8"> <div className="topo-card-surface rounded-2xl bg-white p-6 text-[#37a47a] shadow-xl md:p-8">
<h3 className="text-xl font-bold text-foreground">Request Partnership Information</h3> <h3 className="text-xl font-bold text-foreground">Request Partnership Information</h3>
<form onSubmit={onSubmit} className="mt-6 space-y-4"> <form onSubmit={onSubmit} className="mt-6 space-y-4">
<div className="grid gap-4 sm:grid-cols-2"> <div className="grid gap-4 sm:grid-cols-2">
@ -105,13 +105,13 @@ export function PartnershipInquiryForm() {
/> />
{error && <p className="text-sm text-destructive">{error}</p>} {error && <p className="text-sm text-destructive">{error}</p>}
{status === "success" && ( {status === "success" && (
<p className="text-sm text-[#1a5c38]"> <p className="text-sm text-[#37a47a]">
Thank you! We received your request and will be in touch. Thank you! We received your request and will be in touch.
</p> </p>
)} )}
<Button <Button
type="submit" type="submit"
className="w-full rounded-lg bg-[#ffb300] py-6 text-base font-semibold text-[#0f0404] hover:bg-[#ffb300]/90" className="w-full rounded-lg bg-[#37a47a] py-6 text-base font-semibold text-[#ffffff] hover:bg-[#37a47a]/90"
disabled={status === "loading"} disabled={status === "loading"}
> >
{status === "loading" ? "Sending…" : "Next"} {status === "loading" ? "Sending…" : "Next"}

View File

@ -87,13 +87,13 @@ export function PaymentForm() {
className={cn( className={cn(
"rounded-xl border p-4 text-left transition-colors", "rounded-xl border p-4 text-left transition-colors",
ticketId === t.id ticketId === t.id
? "border-[#1f3d7e] bg-[#1f3d7e]/5 ring-2 ring-[#1f3d7e]" ? "border-[#30614c] bg-[#30614c]/5 ring-2 ring-[#30614c]"
: "border-border hover:border-[#1f3d7e]/40", : "border-border hover:border-[#30614c]/40",
t.soldOut && "opacity-50" t.soldOut && "opacity-50"
)} )}
> >
<p className="font-semibold">{t.name}</p> <p className="font-semibold">{t.name}</p>
<p className="mt-1 text-lg font-bold text-[#1f3d7e]">${t.priceUsd}</p> <p className="mt-1 text-lg font-bold text-[#30614c]">${t.priceUsd}</p>
{t.soldOut && <p className="text-xs text-destructive">Sold out</p>} {t.soldOut && <p className="text-xs text-destructive">Sold out</p>}
</button> </button>
))} ))}
@ -132,7 +132,7 @@ export function PaymentForm() {
className={cn( className={cn(
"rounded-xl border p-4 text-left", "rounded-xl border p-4 text-left",
paymentMethod === m.id paymentMethod === m.id
? "border-[#ffb300] ring-2 ring-[#ffb300]" ? "border-[#37a47a] ring-2 ring-[#37a47a]"
: "border-border" : "border-border"
)} )}
> >
@ -191,12 +191,12 @@ export function PaymentForm() {
</div> </div>
<div className="mt-2 flex justify-between text-lg font-bold"> <div className="mt-2 flex justify-between text-lg font-bold">
<span>Total</span> <span>Total</span>
<span className="text-[#1f3d7e]">${total} USD</span> <span className="text-[#30614c]">${total} USD</span>
</div> </div>
</div> </div>
<Button <Button
type="submit" type="submit"
className="w-full rounded-full bg-[#ffb300] text-[#0f0404] hover:bg-[#ffb300]/90" className="w-full rounded-full bg-[#37a47a] text-[#ffffff] hover:bg-[#37a47a]/90"
disabled={status === "loading" || tier.soldOut} disabled={status === "loading" || tier.soldOut}
> >
{status === "loading" {status === "loading"

View File

@ -13,7 +13,7 @@ export function SpeakerCard({ speaker, className, revealDelay = 0 }: Props) {
<ScrollReveal variant="card" delay={revealDelay} as="div" className={className}> <ScrollReveal variant="card" delay={revealDelay} as="div" className={className}>
<Link <Link
href="/speakers" href="/speakers"
className="topo-card-surface topo-card-layer group relative z-20 isolate block overflow-hidden rounded-2xl border border-border bg-white p-4 text-[#1a5c38] shadow-sm transition-all hover:border-[#1a5c38]/25 hover:shadow-md" className="topo-card-surface topo-card-layer group relative z-20 isolate block overflow-hidden rounded-2xl border border-border bg-white p-4 text-[#37a47a] shadow-sm transition-all hover:border-[#37a47a]/25 hover:shadow-md"
> >
<div className="relative mx-auto aspect-[4/5] w-full max-h-[220px] overflow-hidden rounded-xl bg-muted/30"> <div className="relative mx-auto aspect-[4/5] w-full max-h-[220px] overflow-hidden rounded-xl bg-muted/30">
<Image <Image
@ -24,13 +24,13 @@ export function SpeakerCard({ speaker, className, revealDelay = 0 }: Props) {
sizes="(max-width: 768px) 50vw, 25vw" sizes="(max-width: 768px) 50vw, 25vw"
/> />
</div> </div>
<h3 className="mt-4 text-lg font-bold leading-tight text-[#0d3d26] group-hover:text-[#1a5c38]"> <h3 className="mt-4 text-lg font-bold leading-tight text-[#30614c] group-hover:text-[#37a47a]">
{speaker.name} {speaker.name}
</h3> </h3>
<p className="mt-1 text-sm text-[#3d5248]">{speaker.title}</p> <p className="mt-1 text-sm text-[#5b5b5b]">{speaker.title}</p>
<p className="mt-0.5 text-sm font-medium text-[#1a5c38]/90">{speaker.company}</p> <p className="mt-0.5 text-sm font-medium text-[#37a47a]/90">{speaker.company}</p>
{speaker.panel && ( {speaker.panel && (
<p className="mt-2 line-clamp-2 text-xs text-[#3d5248]">{speaker.panel}</p> <p className="mt-2 line-clamp-2 text-xs text-[#5b5b5b]">{speaker.panel}</p>
)} )}
</Link> </Link>
</ScrollReveal> </ScrollReveal>

View File

@ -40,14 +40,14 @@ export function TicketCard({ tier, index, featured, compact }: Props) {
> >
<div <div
className={cn( className={cn(
"topo-card-surface ticket-admission relative w-full overflow-hidden bg-white text-[#0f0404]", "topo-card-surface ticket-admission relative w-full overflow-hidden bg-white text-[#ffffff]",
"shadow-[0_12px_40px_rgba(0,0,0,0.18)]", "shadow-[0_12px_40px_rgba(0,0,0,0.18)]",
featured && "ring-2 ring-[#ffb300]/50" featured && "ring-2 ring-[#37a47a]/50"
)} )}
data-ticket-notch={compact ? "light" : "inverse"} data-ticket-notch={compact ? "light" : "inverse"}
> >
{featured && ( {featured && (
<span className="absolute right-3 top-3 z-10 rounded-full bg-[#ffb300] px-2.5 py-0.5 text-[10px] font-bold uppercase tracking-wider text-[#0f0404]"> <span className="absolute right-3 top-3 z-10 rounded-full bg-[#37a47a] px-2.5 py-0.5 text-[10px] font-bold uppercase tracking-wider text-[#ffffff]">
Popular Popular
</span> </span>
)} )}
@ -62,11 +62,11 @@ export function TicketCard({ tier, index, featured, compact }: Props) {
<div <div
className={cn( className={cn(
"relative flex shrink-0 md:w-[30%]", "relative flex shrink-0 md:w-[30%]",
"border-b border-dashed border-[#1a5c38]/20 md:border-b-0 md:border-r" "border-b border-dashed border-[#37a47a]/20 md:border-b-0 md:border-r"
)} )}
> >
<div className="flex w-full flex-row items-center justify-between gap-3 p-4 md:flex-col md:items-stretch md:justify-between md:py-5 md:pl-5 md:pr-4"> <div className="flex w-full flex-row items-center justify-between gap-3 p-4 md:flex-col md:items-stretch md:justify-between md:py-5 md:pl-5 md:pr-4">
<div className="flex items-center gap-2 text-[#1a5c38] md:flex-col md:items-start"> <div className="flex items-center gap-2 text-[#37a47a] md:flex-col md:items-start">
<Ticket className="size-4 shrink-0" strokeWidth={2} aria-hidden /> <Ticket className="size-4 shrink-0" strokeWidth={2} aria-hidden />
<span className="text-[10px] font-bold uppercase tracking-[0.18em]"> <span className="text-[10px] font-bold uppercase tracking-[0.18em]">
Admit one Admit one
@ -75,13 +75,13 @@ export function TicketCard({ tier, index, featured, compact }: Props) {
<div className="text-right md:text-left"> <div className="text-right md:text-left">
<p <p
className={cn( className={cn(
"font-bold tabular-nums leading-none text-[#1f3d7e]", "font-bold tabular-nums leading-none text-[#30614c]",
compact ? "text-2xl" : "text-3xl" compact ? "text-2xl" : "text-3xl"
)} )}
> >
{price} {price}
</p> </p>
<p className="mt-1 text-[10px] font-medium uppercase tracking-wide text-[#3d5248]"> <p className="mt-1 text-[10px] font-medium uppercase tracking-wide text-[#5b5b5b]">
{schedule} {schedule}
</p> </p>
</div> </div>
@ -91,10 +91,10 @@ export function TicketCard({ tier, index, featured, compact }: Props) {
{/* Main — name, one line, details popover, CTA */} {/* Main — name, one line, details popover, CTA */}
<div className="flex flex-1 flex-col justify-between gap-4 p-4 md:p-5"> <div className="flex flex-1 flex-col justify-between gap-4 p-4 md:p-5">
<div className="min-w-0 pr-8 md:pr-0"> <div className="min-w-0 pr-8 md:pr-0">
<h3 className="text-lg font-bold leading-tight text-[#0d3d26] md:text-xl"> <h3 className="text-lg font-bold leading-tight text-[#30614c] md:text-xl">
{tier.name} {tier.name}
</h3> </h3>
<p className="mt-1.5 line-clamp-2 text-sm text-[#3d5248]"> <p className="mt-1.5 line-clamp-2 text-sm text-[#5b5b5b]">
{ticketTagline(tier)} {ticketTagline(tier)}
</p> </p>
</div> </div>
@ -103,7 +103,7 @@ export function TicketCard({ tier, index, featured, compact }: Props) {
<TicketInclusionsPopover tier={tier} serial={serial} /> <TicketInclusionsPopover tier={tier} serial={serial} />
<Button <Button
className={cn( className={cn(
"w-full rounded-full bg-[#ffb300] text-[#0f0404] hover:bg-[#ffb300]/90", "w-full rounded-full bg-[#37a47a] text-[#ffffff] hover:bg-[#37a47a]/90",
featured && "ticket-cta-pulse" featured && "ticket-cta-pulse"
)} )}
disabled={tier.soldOut} disabled={tier.soldOut}
@ -123,7 +123,7 @@ export function TicketCard({ tier, index, featured, compact }: Props) {
</div> </div>
<div <div
className="h-1 w-full bg-gradient-to-r from-[#1a5c38] via-[#ffb300] to-[#1f3d7e]" className="h-1 w-full bg-gradient-to-r from-[#37a47a] via-[#37a47a] to-[#30614c]"
aria-hidden aria-hidden
/> />
</div> </div>

View File

@ -26,7 +26,7 @@ export function TicketInclusionsPopover({ tier, serial, className }: Props) {
variant="ghost" variant="ghost"
size="sm" size="sm"
className={cn( className={cn(
"topo-card-link h-8 gap-1.5 rounded-full px-3 text-xs font-medium hover:bg-[#1a5c38]/8", "topo-card-link h-8 gap-1.5 rounded-full px-3 text-xs font-medium hover:bg-[#37a47a]/8",
className className
)} )}
aria-label={`What's included in ${tier.name}`} aria-label={`What's included in ${tier.name}`}
@ -37,10 +37,10 @@ export function TicketInclusionsPopover({ tier, serial, className }: Props) {
</PopoverTrigger> </PopoverTrigger>
<PopoverContent <PopoverContent
align="start" align="start"
className="w-[min(calc(100vw-2rem),20rem)] border-[#1a5c38]/15 p-0" className="w-[min(calc(100vw-2rem),20rem)] border-[#37a47a]/15 p-0"
> >
<div className="border-b border-border/80 px-4 py-3"> <div className="border-b border-border/80 px-4 py-3">
<p className="text-xs font-semibold uppercase tracking-wider text-[#1a5c38]"> <p className="text-xs font-semibold uppercase tracking-wider text-[#37a47a]">
{tier.name} {tier.name}
</p> </p>
<p className="mt-1 text-sm leading-relaxed text-muted-foreground"> <p className="mt-1 text-sm leading-relaxed text-muted-foreground">
@ -50,7 +50,7 @@ export function TicketInclusionsPopover({ tier, serial, className }: Props) {
<ul className="space-y-2 px-4 py-3"> <ul className="space-y-2 px-4 py-3">
{tier.features.map((feature) => ( {tier.features.map((feature) => (
<li key={feature} className="flex gap-2 text-sm text-foreground"> <li key={feature} className="flex gap-2 text-sm text-foreground">
<span className="font-bold text-[#ffb300]" aria-hidden> <span className="font-bold text-[#37a47a]" aria-hidden>
</span> </span>
{feature} {feature}

30
content/brand-colors.ts Normal file
View File

@ -0,0 +1,30 @@
/**
* GRV Summit brand palette (brand book COLOR PALETTE).
* Primary / secondary / tertiary sampled from brand assets; neutrals per spec.
*/
export const BRAND_COLORS = {
primary: "#37a47a",
secondary: "#b9d8c9",
tertiary: "#30614c",
black: "#000000",
grey1: "#5b5b5b",
grey2: "#a0a0a0",
grey3: "#dbdbdb",
white: "#ffffff",
/** Brand book lists RGB 250,250,250 for white */
whiteSoft: "#fafafa",
/** Tinted surfaces derived from secondary */
surfaceMuted: "#e8f2ec",
} as const;
/** Greens for wavy tessellation / footer depth */
export const BRAND_GREEN_SHADES = [
BRAND_COLORS.primary,
"#3da67f",
"#43a884",
"#49aa89",
"#4fac8e",
"#55ae93",
] as const;
export const BRAND_GREEN = BRAND_COLORS.primary;

View File

@ -12,7 +12,7 @@ export const SITE_TOPO_PATTERN = "topo-main" as const satisfies TopoPatternId;
export const MAIN_WHITE_PATTERN_SRC = "/patterns/mainwhite.svg"; export const MAIN_WHITE_PATTERN_SRC = "/patterns/mainwhite.svg";
export const MAIN_GREEN_PATTERN_SRC = "/patterns/main.svg"; export const MAIN_GREEN_PATTERN_SRC = "/patterns/main.svg";
export const BRAND_GREEN = "#1a5c38"; export { BRAND_GREEN } from "@/content/brand-colors";
export type TopoPatternAsset = { export type TopoPatternAsset = {
src: string; src: string;