/* ============================================================
   GREENFIELD PORTFOLIO CEO SUMMIT — offsite.greenfield-growth.com
   Private registration microsite. Light mode only, by design.

   Tokens inherited from greenfield-v2 (styles.css :root) and its
   light-mode surfaces (knowledge.css, legal.css). Structure and
   restraint borrowed from the Norwest CEO Summit site, along with its
   display face; colour, body type and voice are Greenfield's.

   Radius system (one documented scale, applied everywhere):
     buttons and pills  -> var(--r-pill)
     cards and surfaces -> var(--r-card)
     inputs and controls-> var(--r-input)

   Accent: a single accent (--accent, brand gold) for calls to action,
   with navy carrying focus and selected states because gold cannot meet
   the 3:1 those need. The footer is an inherited component and keeps its
   own internal blue hovers; that is the one documented exception.
   ============================================================ */

*, *::before, *::after {
    margin: 0;
    padding: 0;
    box-sizing: border-box;
}

/* Author `display` declarations outrank the UA rule for [hidden], so any
   flex container toggled with the hidden attribute would keep its box.
   This makes the attribute authoritative, which the form relies on. */
[hidden] { display: none !important; }

:root {
    /* Brand navy */
    --navy: #011132;
    --navy-deep: #000a1f;
    --navy-light: #021b4a;

    /* Warm beige ground, so the white sheet reads as a sheet. Replaces the
       cool #f4f5f5 borrowed from Knowledge + Legal, which sat too close to
       the card to separate from it. */
    --paper: #e9e7e0;
    --card: #ffffff;
    --ink: #010c33;
    --ink-soft: rgba(1, 12, 51, 0.62);
    /* Darkened again, from #667070, when the ground went beige: #667070
       measures 4.36:1 on the main site's grey, 4.67:1 on #f4f5f5 and only
       4.12:1 on this beige. Every use here is small text and has to clear
       4.5:1. This is 5.66:1 on white and 4.57:1 on the beige ground. */
    --muted: #5f6969;
    --hair: #cad2d1;
    --hair-soft: rgba(1, 12, 51, 0.09);

    /* Single accent: brand gold, replacing the emerald so teal is not the
       page's signature colour. Navy on gold is 8.41:1, effectively the same
       as the emerald it replaces (8.36:1), and it sits with the golden-hour
       photography rather than against it. */
    --accent: #d4a843;
    --accent-deep: #c2962f;
    --accent-wash: rgba(212, 168, 67, 0.13);

    /* Gold measures 2.21:1 on white, so it cannot carry a focus ring or a
       checked-state indicator, both of which need 3:1. Navy does that work
       at 18.62:1. Gold means "go here"; navy means "you chose this". */
    --focus: #011132;
    --focus-ring: rgba(1, 17, 50, 0.15);
    --selected-wash: rgba(1, 17, 50, 0.05);

    /* Error (harmonised with the brand, AA on white) */
    --error: #a83a20;
    --error-line: #cc6449;
    --error-wash: rgba(168, 58, 32, 0.05);

    /* Typography.
       Display is DM Serif Display — the face the Norwest reference itself
       uses. It ships one weight (400), which is all it needs at display
       sizes. Manrope stays the body, UI and form face, at 500 rather than
       400 so nothing on the page reads thin next to the serif. */
    --font: 'Manrope', -apple-system, BlinkMacSystemFont, sans-serif;
    --font-display: 'DM Serif Display', Georgia, 'Times New Roman', serif;
    --display-ls: -0.015em;

    /* Layout */
    --container-max: 1400px;
    --container-pad: clamp(20px, 4vw, 80px);
    --section-pad: clamp(80px, 10vw, 160px);

    /* How far the white sheet rides up over the banner. Small on purpose:
       the sheet should sit down onto the photograph's bottom edge, not
       float in front of it. Was clamp(96px, 14vh, 168px), from when the
       banner was a full-height hero the card had to climb out of. */
    --card-overlap: clamp(20px, 2.6vh, 36px);

    /* The sheet's horizontal padding. A token because the agenda band has to
       cancel it exactly to run full width. */
    --sheet-pad: clamp(24px, 3.4vw, 56px);

    /* Radius scale — square. Everything on the page has a hard corner:
       the sheet, the photo cards, the buttons, the form controls. The token
       names are kept because they are used in ~20 places and still mark
       which kind of thing is being cornered; only the values changed.
       Two deliberate exceptions survive: the radio indicator stays a circle,
       because a radio that is not round reads as a checkbox, and the
       inherited footer keeps its own radii (see the footer section). */
    --r-pill: 0;
    --r-card: 0;
    --r-input: 0;

    /* Easing */
    --ease-out-expo: cubic-bezier(0.16, 1, 0.3, 1);
    --ease-out-quart: cubic-bezier(0.25, 1, 0.5, 1);
    --ease-out: cubic-bezier(0.23, 1, 0.32, 1);
}

html {
    font-size: 16px;
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
    scroll-behavior: smooth;
}

@media (prefers-reduced-motion: reduce) {
    html { scroll-behavior: auto; }
}

body {
    font-family: var(--font);
    background: var(--paper);
    color: var(--ink);
    overflow-x: hidden;
    line-height: 1.5;
}

a { color: inherit; text-decoration: none; }
img, video { max-width: 100%; display: block; }

button, input, select, textarea {
    font-family: inherit;
    font-size: inherit;
    color: inherit;
}

::selection {
    background: rgba(1, 17, 50, 0.16);
    color: var(--ink);
}

/* Consistent focus treatment for everything keyboard-reachable */
:focus-visible {
    outline: 2px solid var(--focus);
    outline-offset: 3px;
    border-radius: 0;
}

.skip-link {
    position: absolute;
    left: 16px;
    top: -60px;
    z-index: 100;
    padding: 12px 20px;
    background: var(--card);
    color: var(--ink);
    font-size: 0.85rem;
    font-weight: 600;
    border-radius: var(--r-input);
    box-shadow: 0 8px 30px rgba(1, 12, 51, 0.18);
    transition: top 200ms var(--ease-out);
}

.skip-link:focus { top: 16px; }

/* Watched by the nav observer. Absolute at the document top and out of the
   flow, so it changes no layout; 4px rather than 1px so a sub-pixel scroll
   position cannot leave it ambiguously intersecting. */
.nav-sentinel {
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
    height: 4px;
    pointer-events: none;
}


/* ---------- SHARED PRIMITIVES ---------- */

.container {
    max-width: var(--container-max);
    margin: 0 auto;
    padding: 0 var(--container-pad);
}

/* Serif caps, which is the reference's actual signature move: a serif used
   small. Sized up from 12px to 14px and the tracking eased from 0.08em to
   0.04em, because serif caps need more room per glyph and less air between
   them than a bold sans does. */
.microlabel {
    font-family: var(--font-display);
    /* Up from 0.875rem: at 14px these read as captions rather than as the
       labels for the three facts they sit above. */
    font-size: 1.0625rem;
    font-weight: 400;
    letter-spacing: 0.04em;
    text-transform: uppercase;
    /* Brand navy, not --muted. These label the three facts in the card and
       at #5f6969 they sat back far enough to read as captions. 18.62:1. */
    color: var(--navy);
    line-height: 1.3;
}

.section-title {
    font-family: var(--font-display);
    font-size: clamp(2rem, 4vw, 3.25rem);
    font-weight: 400;
    letter-spacing: var(--display-ls);
    line-height: 1.1;
    color: var(--ink);
    max-width: 24ch;
    text-wrap: balance;
}

.prose {
    /* A long measure on purpose: these are short paragraphs and the
       wide line fills the desktop composition. Type scales up with it
       so the character count per line stays readable. */
    max-width: min(100%, 1000px);
    font-size: clamp(1.0625rem, 1.2vw, 1.1875rem);
    font-weight: 500;
    line-height: 1.72;
    color: var(--ink-soft);
}

.prose p + p { margin-top: 1.4em; }

/* Inside the sheet, every block of copy runs the full width of the card.
   The primitives each carry a measure of their own — .prose caps at 1000px,
   .lead-line at 76ch, .agenda-note at 62ch — and on a ~1250px card those
   stop the text short of the right edge by different amounts, so the sheet
   reads as having a ragged right margin that does not match its left. The
   card's own padding is the margin now, and it is equal on both sides.

   The trade is line length: at the full width these run past the 45-75
   characters that is comfortable for continuous reading. Accepted
   deliberately — the paragraphs here are short. */
.page-card .prose,
.page-card .lead-line,
.page-card .agenda-note {
    max-width: none;
}


/* ---------- BUTTONS ---------- */

.btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 10px;
    padding: 15px 32px;
    border: 1px solid transparent;
    border-radius: var(--r-pill);
    font-size: 0.9rem;
    font-weight: 600;
    letter-spacing: 0.01em;
    white-space: nowrap;
    cursor: pointer;
    transition: transform 160ms var(--ease-out),
                background-color 200ms ease,
                border-color 200ms ease,
                box-shadow 200ms ease;
}

/* Navy fill for the light sections */
.btn-primary {
    background: var(--navy);
    color: #ffffff;
    box-shadow: 0 2px 14px rgba(1, 17, 50, 0.16);
}

@media (hover: hover) and (pointer: fine) {
    .btn-primary:hover {
        background: var(--navy-light);
        transform: translateY(-1px);
        box-shadow: 0 10px 28px rgba(1, 17, 50, 0.22);
    }
}

.btn-primary:active { transform: scale(0.97); }

/* White fill, navy text — the Register button wherever it sits over dark or
   over photography: the nav, the hero and the closing CTA card. 18.62:1, and
   the brightest thing on a navy page, which is what a single primary action
   should be. */
.btn-accent {
    background: #ffffff;
    color: var(--navy);
    box-shadow: 0 4px 24px rgba(0, 0, 0, 0.24);
}

@media (hover: hover) and (pointer: fine) {
    .btn-accent:hover {
        background: #ffffff;
        transform: translateY(-1px);
        box-shadow: 0 12px 34px rgba(0, 0, 0, 0.32);
    }
}

.btn-accent:active { transform: scale(0.97); }

/* Quiet outlined button, for secondary moves like leaving the form */
.btn-quiet {
    background: transparent;
    border-color: var(--hair);
    color: var(--ink);
}

@media (hover: hover) and (pointer: fine) {
    .btn-quiet:hover {
        border-color: var(--ink);
        background: rgba(1, 12, 51, 0.03);
    }
}

.btn-quiet:active { transform: scale(0.97); }

/* The hero button is .btn-accent with a little more presence and its own
   spacing; the treatment itself lives in .btn-accent so there is one
   definition of the white Register button, not two. */
.hero-cta { padding: 17px 38px; }

.btn:disabled,
.btn[aria-disabled="true"] {
    opacity: 0.55;
    cursor: not-allowed;
    transform: none;
    box-shadow: none;
}


/* ============================================================
   NAV — fixed. Transparent over the hero so the photography is
   uninterrupted, navy once scrolled or on any page without a hero.
   Logo left; Register and the menu toggle right, clear of the
   middle of the image.
   ============================================================ */

.nav {
    position: fixed;
    top: 0;
    left: 0;
    right: 0;
    z-index: 60;
    transition: background-color 320ms ease, box-shadow 320ms ease;
}

.nav-inner {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 20px;
    max-width: var(--container-max);
    margin: 0 auto;
    /* Generous over the banner: with no bar behind it, the logo and the
       toggle are sitting on a photograph and want air above them rather than
       to be jammed against the top edge. Was clamp(10px, 1.3vw, 14px), which
       was sized for a 72px bar. */
    padding: clamp(18px, 2.2vw, 30px) var(--container-pad);
    transition: padding 320ms ease;
}

/* No bar on this page, in any state but one. Three treatments were tried and
   removed here in turn — a translucent navy gradient, then a lighter version
   of it, then a solid white bar — and each of them read as a strip laid
   across the top of the photograph. What is left is the logo and the toggle
   sitting directly on the picture, in white, with nothing behind them.

   The header is fixed, though, so past the banner it would otherwise be
   navy type floating over the white sheet and crossing whatever text happens
   to be under it. So: nothing over the banner, a bar once the banner has
   scrolled behind it. .is-open is the other exception — the menu panel is
   navy, so the header goes navy with it while the panel is down and the logo
   swaps to white. */
.nav[data-nav-over-hero]:not(.is-scrolled):not(.is-open) {
    background: transparent;
    -webkit-backdrop-filter: none;
    backdrop-filter: none;
    box-shadow: none;
}

/* White rather than the navy .nav.is-scrolled gives every other page: by the
   time this appears it is sitting on the white sheet, and navy would read as
   a slab dropped on top of it. The mark and toggle shift to navy as this bar
   arrives, preserving contrast without adding weight over the hero. */
.nav[data-nav-over-hero].is-scrolled:not(.is-open) {
    background: rgba(255, 255, 255, 0.94);
    -webkit-backdrop-filter: blur(20px) saturate(180%);
    backdrop-filter: blur(20px) saturate(180%);
    box-shadow: 0 1px 0 rgba(1, 12, 51, 0.08),
                0 8px 28px rgba(1, 12, 51, 0.06);
}

/* Compress back to the original 72px once there is a bar to sit in: the extra
   air was for the photograph, not for a white strip. */
.nav[data-nav-over-hero].is-scrolled:not(.is-open) .nav-inner {
    padding-top: clamp(10px, 1.3vw, 14px);
    padding-bottom: clamp(10px, 1.3vw, 14px);
}

/* Solid state: scrolled past the hero, a page with no hero, or the menu
   open — otherwise the bar and the panel below it read as two pieces. */
.nav--solid,
.nav.is-scrolled,
.nav.is-open {
    background: rgba(1, 17, 50, 0.97);
    -webkit-backdrop-filter: blur(20px) saturate(180%);
    backdrop-filter: blur(20px) saturate(180%);
    box-shadow: 0 1px 0 rgba(255, 255, 255, 0.06);
}

.nav-logo {
    position: relative;
    display: inline-flex;
    transition: opacity 300ms ease;
}

/* Extends the tap target to ~45px without moving anything visually */
.nav-logo::after {
    content: '';
    position: absolute;
    inset: -10px;
}

/* Sized up from clamp(118px, 10vw, 146px). The reference sets its wordmark
   large enough to be the anchor of the banner rather than a mark in a bar. */
.nav-logo img {
    /* Down about 30% from clamp(168px, 15.5vw, 240px). The footer mark is
       sized separately and is untouched. */
    width: clamp(118px, 10.8vw, 168px);
    height: auto;
}

/* Only one of the two marks is ever in the layout. The navy one is for the
   white bar; the white one is for the transparent hero and navy menu states. */
.nav-logo-mark--navy { display: none; }

.nav[data-nav-over-hero].is-scrolled:not(.is-open) .nav-logo-mark--navy { display: block; }
.nav[data-nav-over-hero].is-scrolled:not(.is-open) .nav-logo-mark--white { display: none; }

@media (hover: hover) and (pointer: fine) {
    .nav-logo:hover { opacity: 0.78; }
}

/* Navy type on the white scroll-state bar. */
.nav[data-nav-over-hero].is-scrolled:not(.is-open) .nav-links a {
    color: var(--navy);
}

@media (hover: hover) and (pointer: fine) {
    .nav[data-nav-over-hero].is-scrolled:not(.is-open)
        .nav-links a:not([aria-disabled="true"]):hover {
        color: var(--navy);
        opacity: 0.65;
    }
}

/* The menu toggle follows the mark: white over the hero, navy on its white
   scroll-state bar. */
.nav[data-nav-over-hero].is-scrolled:not(.is-open) .nav-toggle-bars span {
    background: var(--navy);
}

.nav-right {
    display: flex;
    align-items: center;
    gap: clamp(8px, 1.2vw, 16px);
}

.nav-cta {
    padding: 11px 24px;
    font-size: 0.8125rem;
}

/* Once the transparent hero header rests on its white scroll-state bar, the
   direct action switches to navy so it remains distinct from the surface. */
.nav[data-nav-over-hero].is-scrolled:not(.is-open) .nav-cta {
    background: var(--navy);
    color: #ffffff;
    box-shadow: 0 2px 8px rgba(1, 17, 50, 0.18);
}

@media (hover: hover) and (pointer: fine) {
    .nav[data-nav-over-hero].is-scrolled:not(.is-open) .nav-cta:hover {
        background: var(--navy-light);
        box-shadow: 0 4px 8px rgba(1, 17, 50, 0.22);
    }
}

/* ---------- Inline links (desktop) ----------
   Visible above 860px so the pages are discoverable without a click;
   below that they collapse into the menu panel. */

.nav-links {
    display: flex;
    align-items: center;
    gap: clamp(18px, 2.2vw, 30px);
    margin-right: clamp(4px, 0.8vw, 12px);
}

.nav-links a {
    font-size: 0.82rem;
    font-weight: 600;
    letter-spacing: 0.01em;
    white-space: nowrap;
    color: rgba(255, 255, 255, 0.86);
    transition: color 200ms ease;
}

.nav-links a[aria-current="page"] { color: var(--accent); }

/* Not yet built: shown at final size and weight so the bar reads correctly,
   but with no pointer affordance and no hover, because clicking does nothing. */
.nav-links a[aria-disabled="true"],
.nav-menu a[aria-disabled="true"] {
    cursor: default;
    color: rgba(255, 255, 255, 0.62);
}

@media (hover: hover) and (pointer: fine) {
    .nav-links a:not([aria-disabled="true"]):hover { color: #ffffff; }
}

/* ---------- Menu toggle (hamburger) ---------- */

.nav-toggle {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 44px;
    height: 44px;
    /* Keep the control clear of the viewport edge while still preserving a
       balanced gap from the new Register action. */
    margin-right: 0;
    border: none;
    background: none;
    cursor: pointer;
}

.nav-toggle-bars {
    display: flex;
    flex-direction: column;
    gap: 5px;
}

.nav-toggle-bars span {
    display: block;
    width: 26px;
    height: 2px;
    background: #ffffff;
    border-radius: 0;
    transition: transform 300ms var(--ease-out-expo),
                opacity 200ms ease;
}

/* Bars fold into a cross while the menu is open */
.nav.is-open .nav-toggle-bars span:nth-child(1) {
    transform: translateY(6.5px) rotate(45deg);
}

.nav.is-open .nav-toggle-bars span:nth-child(2) { opacity: 0; }

.nav.is-open .nav-toggle-bars span:nth-child(3) {
    transform: translateY(-6.5px) rotate(-45deg);
}

/* ---------- Menu panel ---------- */

.nav-menu {
    background: rgba(1, 17, 50, 0.98);
    -webkit-backdrop-filter: blur(20px) saturate(180%);
    backdrop-filter: blur(20px) saturate(180%);
    border-top: 1px solid rgba(255, 255, 255, 0.08);
}

.nav-menu:not([hidden]) {
    animation: menu-in 260ms var(--ease-out) both;
}

@keyframes menu-in {
    from { opacity: 0; transform: translateY(-10px); }
    to   { opacity: 1; transform: none; }
}

.nav-menu-inner {
    display: flex;
    flex-direction: column;
    max-width: var(--container-max);
    margin: 0 auto;
    padding: 6px var(--container-pad) 20px;
}

.nav-menu a {
    padding: 15px 0;
    font-size: 1rem;
    font-weight: 500;
    letter-spacing: -0.01em;
    color: rgba(255, 255, 255, 0.88);
    border-bottom: 1px solid rgba(255, 255, 255, 0.07);
    transition: color 200ms ease;
}

.nav-menu a:last-child { border-bottom: none; }

.nav-menu a[aria-current="page"] { color: var(--accent); }

@media (hover: hover) and (pointer: fine) {
    .nav-menu a:not([aria-disabled="true"]):hover { color: var(--accent); }
}

/* ---------- The desktop / mobile switch ----------
   Above 860px the links carry navigation and the toggle is gone. The panel
   is force-hidden too, so resizing up from a mobile width with the menu
   open cannot leave an orphaned panel behind a hidden toggle. */

@media (min-width: 861px) {
    .nav:not([data-nav-over-hero]) .nav-toggle { display: none; }
    .nav:not([data-nav-over-hero]) .nav-menu { display: none !important; }
}

@media (max-width: 860px) {
    .nav-links { display: none; }
}

/* index.html is the exception: no inline links at any width, and the toggle
   is the whole of the navigation. The markup has no .nav-links there, so this
   is only belt and braces. */
.nav[data-nav-over-hero] .nav-links { display: none; }


/* Light ground for the pages that are not the landing page. The body already
   carries --paper, so this is belt and braces, but the class is on their
   <body> and a rule that exists is one less thing to wonder about. */
.page-light { background: var(--paper); }


/* Anchor targets must clear the fixed nav, or a jump from the menu lands
   with the section heading hidden underneath it. */
[id^="s-"] { scroll-margin-top: calc(72px + 24px); }


/* Utility. This is what keeps the word "Menu" beside the hamburger available
   to a screen reader and invisible on screen. It, .page-light and the anchor
   offset above all sat between the old BANNER block and HERO, and went out
   with the banner CSS by accident. */
.sr-only {
    position: absolute;
    width: 1px;
    height: 1px;
    padding: 0;
    margin: -1px;
    overflow: hidden;
    clip: rect(0, 0, 0, 0);
    white-space: nowrap;
    border: 0;
}


/* ============================================================
   HERO
   ============================================================ */

.hero {
    position: relative;
    display: flex;
    align-items: flex-end;
    /* A band across the top, not a viewport-filling hero. Was
       640px / 80svh, which pushed everything else below the fold and made
       the photograph the page rather than the page's header. Raised once from
       54svh/580 to open up the space between the logo, which is pinned to the
       top, and the title, which is pinned to the bottom — the band's height
       is the only thing that gap is made of. */
    min-height: 470px;
    /* clamp, not min-height + max-height: when min-height exceeds max-height
       the minimum wins, so on a tall window the cap did nothing and the band
       grew back into a full hero. */
    min-height: clamp(470px, 61svh, 660px);
    background: var(--navy-deep);
    overflow: hidden;
    /* Leave room for the sheet that rides up over this edge, plus enough
       again to lift the copy clear of the sunlit pool deck at the foot of
       the photograph. Well more than the reference's ~45px gap, and the
       reason is measured: sampling this image row by row behind the copy, the
       ground runs about 2.5:1 against white down at the pool and 3.5–4:1 up
       on the vineyard and treeline. The copy sits as high as the composition
       allows so it gets the better half of that. */
    padding-bottom: calc(var(--card-overlap) + clamp(78px, 9.6vh, 132px));
}

/* Wrapper element keeps iOS from mishandling a bare positioned video */
.hero-media {
    position: absolute;
    inset: 0;
    z-index: 0;
}

.hero-picture {
    display: block;
    width: 100%;
    height: 100%;
}

.hero-img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    /* Let the wide scene hold the vineyard rows and sunrise at every desktop
       width; mobile switches to its separately composed portrait source. */
    object-position: center center;
    /* A slow camera push. The first attempt at this was 7% over 40s with
       ease-in-out, which measured as running but sat below the perception
       threshold: barely 7px a second at its fastest, and parked at a near
       standstill at both ends of the cycle. Now 10% over 20s, and paired
       with a small translate, because a pure centre scale moves the middle
       of the frame hardly at all and it is the drift that reads as motion. */
    animation: hero-drift 20s ease-in-out infinite alternate;
}

@keyframes hero-drift {
    /* Never starts at scale 1: the translate needs headroom inside the
       overflow, or an edge would show. */
    from { transform: scale(1.04) translate3d(0.7%, 0.5%, 0); }
    to   { transform: scale(1.14) translate3d(-0.9%, -0.7%, 0); }
}

/* Almost nothing: a touch of weight in the last quarter, most of which the
   sheet covers anyway. Gone, in order: the lower-left ellipse at 84% navy
   behind the copy, the top band, the overall wash, and then the deeper ramp
   that replaced them — each read as a filter over the picture. All of the
   copy's legibility now comes from the text-shadows below.
   Do not reintroduce a scrim here; brighten or reposition the copy instead. */
.hero-scrim {
    position: absolute;
    inset: 0;
    z-index: 1;
    background: linear-gradient(180deg,
        rgba(1, 17, 50, 0) 62%,
        rgba(1, 17, 50, 0.10) 82%,
        rgba(1, 17, 50, 0.26) 100%);
}

.hero-body {
    position: relative;
    z-index: 2;
    width: 100%;
}

.hero-inner {
    max-width: var(--container-max);
    margin: 0 auto;
    padding: 0 var(--container-pad);
}

.hero-title {
    max-width: 20ch;
    /* Back up to display scale. 60px was sized for a four-word title over a
       tall hero; "CEO Summit 2026" is short, the banner is short, and the
       reference sets its title at roughly 90px on a 1900px viewport. */
    font-family: var(--font-display);
    font-size: clamp(2.375rem, 5.4vw, 5.75rem);
    font-weight: 400;
    letter-spacing: var(--display-ls);
    line-height: 1.02;
    color: #ffffff;
    text-wrap: balance;
    /* Does the work the scrim used to. Two shadows: a tight one for edge
       definition on light ground, a wide soft one to seat the type. */
    text-shadow: 0 1px 3px rgba(1, 12, 51, 0.55),
                 0 2px 12px rgba(1, 12, 51, 0.5),
                 0 6px 40px rgba(1, 12, 51, 0.55);
}

/* Label under the title. The reference sets a short rule before it; that was
   built and then dropped — the line reads cleaner without it. */
.hero-eyebrow {
    display: flex;
    align-items: center;
    /* Tight to the title on purpose: the two of them have to share one band
       of darker photograph, and a generous gap dropped this line onto the
       sunlit loungers below it. */
    margin-top: clamp(12px, 1.5vh, 22px);
    font-size: clamp(1.0625rem, 1.5vw, 1.6875rem);
    /* Light and open, matching the reference: it sets this line at about a
       400 with neutral-to-open tracking, which is what stops it reading as a
       slab under the serif title. It was 600 at -0.005em, then briefly 500
       tracked in at -0.022em, which made it narrower but no lighter — the
       weight was the problem, not the width. */
    font-weight: 400;
    letter-spacing: 0.008em;
    /* White, to match the title. Navy was tried here while the bar above was
       transparent and the two needed to agree; with the bar now white and the
       inversion confined to it, navy on the photograph read as a stray. See
       the README for the contrast this measures — it is the one place on the
       page that does not clear AA, and it is a deliberate call. */
    color: #ffffff;
    /* Soft shadows only, and kept quiet. There was a hard 1px ring here —
       four zero-blur offsets boxing in each glyph — which separated the type
       well but read as an outline drawn around it and thickened it into the
       bargain. The reference carries no shadow at all; its photograph is dark
       where the line sits and ours is not, so this is the least that still
       holds the line up. See the README on what that costs. */
    text-shadow: 0 1px 4px rgba(1, 12, 51, 0.55),
                 0 3px 18px rgba(1, 12, 51, 0.6);
}

.hero-sub {
    max-width: 46ch;
    margin-top: clamp(18px, 2.2vh, 30px);
    font-size: clamp(1rem, 1.25vw, 1.1875rem);
    font-weight: 400;
    line-height: 1.65;
    color: rgba(255, 255, 255, 0.86);
}

.hero-cta {
    display: inline-flex;
    margin-top: clamp(28px, 3.6vh, 44px);
}


/* ============================================================
   PAGE CARD — one white sheet on the beige ground, sitting down
   onto the banner's bottom edge. The reference's central move:
   the content is a single sheet, not a stack of bands.
   ============================================================ */

.page-card-wrap {
    position: relative;
    z-index: 3;
    margin-top: calc(-1 * var(--card-overlap));
}

.page-card {
    background: var(--card);
    border-radius: var(--r-card);
    padding: 0 var(--sheet-pad);
    box-shadow: 0 24px 70px rgba(1, 12, 51, 0.10),
                0 2px 8px rgba(1, 12, 51, 0.04);
}

/* Sections inside the sheet keep their .container markup so they stay
   portable, but the sheet's own padding is the only inset that applies —
   otherwise every section would be indented twice. */
.page-card .container {
    max-width: none;
    padding: 0;
}

/* The full-width hairlines that divide the sheet into its bands */
.sheet-rule {
    height: 1px;
    background: rgba(1, 12, 51, 0.14);
}

/* Between two sections rather than between two rows of one card. Needs its
   own air: sitting flush against the navy agenda band, the hairline simply
   disappeared into the edge of it. */
.sheet-rule--section {
    margin-bottom: clamp(40px, 5vw, 76px);
}


/* ============================================================
   KEY INFO — the facts, as columns across the top of the sheet
   ============================================================ */

.keyinfo {
    padding-top: clamp(28px, 3.2vw, 46px);
}

.keyinfo-card {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    padding-bottom: clamp(28px, 3.2vw, 46px);
}

.keyinfo-col {
    display: flex;
    flex-direction: column;
    gap: 14px;
    padding: 0 clamp(20px, 2.4vw, 40px);
}

/* First and last sit flush with the sheet's own padding, so the columns
   line up with the rules above and below them rather than floating inside
   a second, narrower measure. */
.keyinfo-col:first-child { padding-left: 0; }
.keyinfo-col:last-child { padding-right: 0; }

/* Thin vertical rules between columns, as in the reference */
.keyinfo-col + .keyinfo-col {
    border-left: 1px solid var(--hair-soft);
}

/* ---- Registration call to action ----
   Navy panel, picture cut across it on a diagonal. The navy is this element's
   own background; the diagonal is where the picture has been clipped away, so
   there is no second coloured layer and no seam baked into the artwork. */
.cta-slash {
    position: relative;
    isolation: isolate;
    margin: clamp(30px, 3.6vw, 52px) 0;
    background: var(--navy);
    overflow: hidden;
}

.cta-slash-media {
    position: absolute;
    inset: 0 0 0 auto;
    width: 56%;
    /* 18% at the top, 0 at the bottom: the picture reaches further left the
       lower you look, which is what leans the seam. 56% is what puts the seam
       where the mockup has it -- the clip only decides the angle, the width
       decides where it starts. */
    clip-path: polygon(18% 0, 100% 0, 100% 100%, 0 100%);
}

.cta-slash-media img {
    display: block;
    width: 100%;
    height: 100%;
    object-fit: cover;
    object-position: center;
}

.cta-slash-body {
    position: relative;
    z-index: 1;
    /* Stops short of the seam at its NARROWEST point -- the top, at 54% -- not
       its widest, so no line of text can run under the picture at any height. */
    max-width: 46%;
    padding: clamp(34px, 4.4vw, 68px) 0 clamp(34px, 4.4vw, 68px) clamp(28px, 3.4vw, 56px);
}

.cta-slash-title {
    font-family: var(--font-display);
    /* Sized against the card, not the viewport: the mockup sets this at about
       3.5% of the panel's width and holds the heading on one line, and 3.4vw
       was nearer 4.5% here, which broke it in two. */
    font-size: clamp(1.75rem, 2.9vw, 2.75rem);
    font-weight: 400;
    letter-spacing: var(--display-ls);
    line-height: 1.05;
    color: #ffffff;
}

/* Manrope, not the display face: this is body copy, and the site sets prose in
   the sans everywhere else. Only the heading is serif. */
.cta-slash-text {
    margin-top: clamp(12px, 1.4vw, 20px);
    font-family: var(--font);
    font-size: clamp(0.9375rem, 1.1vw, 1.0625rem);
    font-weight: 500;
    line-height: 1.6;
    color: rgba(255, 255, 255, 0.86);
}

/* Pale on navy, which is the inverse of the button on the white sheet above.
   Square, like every other button here. */
.cta-slash-btn {
    margin-top: clamp(20px, 2.4vw, 34px);
    background: #f2f2ef;
    color: var(--navy);
}

.cta-slash-btn:hover {
    background: #ffffff;
}

@media (max-width: 860px) {
    /* The picture goes under the words instead of beside them, and the seam
       moves to its top edge. In flow rather than absolute: the panel's height
       is then the content plus the picture, with nothing to keep in step. */
    .cta-slash-media {
        position: static;
        display: block;
        width: 100%;
        clip-path: polygon(0 16%, 100% 0, 100% 100%, 0 100%);
        /* Positive, not negative: the picture now follows the words, and the
           triangle the clip removes shows the card's navy behind it, so
           nothing needs to be pulled over anything. */
        margin-top: clamp(24px, 6vw, 40px);
    }

    .cta-slash-media img {
        height: auto;
    }

    .cta-slash-body {
        max-width: none;
        padding: clamp(30px, 7vw, 44px) clamp(24px, 6vw, 40px) 0;
    }

    .cta-slash-btn {
        display: flex;
        width: 100%;
    }
}

.keyinfo-value {
    /* Up from clamp(1rem, 1.15vw, 1.125rem). These three are the page's
       actual content — when, where, what address — and were set smaller than
       the prose below them. .keyinfo-note and .keyinfo-link inherit it. */
    font-size: clamp(1.0625rem, 1.35vw, 1.3125rem);
    font-weight: 500;
    line-height: 1.5;
    letter-spacing: -0.015em;
    color: var(--ink);
}

/* Same type as .keyinfo-value, deliberately: these are values too, and at
   14px/400 they read as footnotes to the column beside them rather than as
   the same class of information. Inheriting rather than restating it is what
   keeps the three columns matching. */
.keyinfo-note,
.keyinfo-link {
    display: block;
    font-size: inherit;
    font-weight: inherit;
    line-height: inherit;
    letter-spacing: inherit;
}

.keyinfo-note { color: var(--muted); }

/* Navy text with an emerald underline: the accent still marks it as a
   link, but the type itself clears AA, which emerald at 14px cannot. */
.keyinfo-link {
    position: relative;
    color: var(--ink);
    text-decoration: underline;
    text-decoration-color: var(--accent);
    text-decoration-thickness: 1.5px;
    text-underline-offset: 3px;
    transition: color 200ms ease, text-decoration-color 200ms ease;
    width: fit-content;
}

/* Same trick: a 45px tap target on a 21px line of type */
.keyinfo-link::after {
    content: '';
    position: absolute;
    inset: -12px -8px;
}

@media (hover: hover) and (pointer: fine) {
    .keyinfo-link:hover {
        color: var(--ink);
        text-decoration-color: var(--accent-deep);
        text-decoration-thickness: 2px;
    }
}


/* ============================================================
   OVERVIEW
   ============================================================ */

/* Tightened from clamp(72px, 9vw, 130px) at the top: inside the sheet a
   hairline already separates this from the registration line, so the old
   full-section gap read as a hole rather than a break. */
.overview {
    padding: clamp(40px, 4.6vw, 68px) 0 clamp(44px, 5vw, 76px);
}

/* Rule-then-sentence, the same figure the banner eyebrow uses. Sits between
   a section title and its body as a one-line summary. */
/* Was a flex row with a rule in front of the sentence; the rule is gone, so
   this is a plain block again. */
.lead-line {
    margin-top: clamp(20px, 2.2vw, 30px);
    max-width: 76ch;
    font-size: clamp(1.0625rem, 1.2vw, 1.1875rem);
    font-weight: 500;
    line-height: 1.6;
    color: var(--ink);
}

/* Was a two-column grid with a photograph in the right-hand one. The
   photograph is gone, so the prose takes the sheet's own measure. */
.overview-body {
    margin-top: clamp(28px, 3.4vw, 44px);
}


/* ============================================================
   SHEET BAND — a navy strip that runs the full width of the
   card. Cancels the sheet's padding with a negative margin and
   puts it back inside, so the band goes edge to edge while its
   copy still lines up with everything above it. --sheet-pad is
   a token because .page-card and this have to agree exactly.

   Two instances: the agenda, and the Guest Speakers header.
   ============================================================ */

.sheet-band {
    margin: 0 calc(-1 * var(--sheet-pad));
    background: var(--navy);
    color: #ffffff;
}

.sheet-band-inner {
    padding: clamp(44px, 5vw, 76px) var(--sheet-pad) clamp(40px, 4.6vw, 68px);
}

/* A header strip rather than a section: title only, so it needs far less */
.sheet-band-inner--slim {
    padding-top: clamp(30px, 3.4vw, 48px);
    padding-bottom: clamp(30px, 3.4vw, 48px);
}

.sheet-band-title {
    font-family: var(--font-display);
    /* Larger than .section-title on the white sheet: these sit alone on a
       navy band with nothing else to hold the eye. */
    font-size: clamp(2.25rem, 4.6vw, 3.75rem);
    font-weight: 400;
    letter-spacing: var(--display-ls);
    line-height: 1.1;
    color: #ffffff;
}


/* ---------- AGENDA: a sheet band with a CTA and a note ---------- */

.agenda-btn {
    display: inline-flex;
    margin-top: clamp(24px, 2.8vw, 38px);
}

/* White at 16% rather than the sheet's navy hairline: this one is on navy.
   Used twice — under the button, and between the two days. */
.agenda-rule {
    height: 1px;
    margin: clamp(30px, 3.4vw, 48px) 0 clamp(28px, 3.2vw, 42px);
    background: rgba(255, 255, 255, 0.16);
}

.agenda-note {
    font-size: clamp(1rem, 1.15vw, 1.125rem);
    font-weight: 400;
    line-height: 1.7;
    color: rgba(255, 255, 255, 0.72);
}

/* A clear final choice after the schedule: FAQ remains quiet and useful,
   while Register carries the page's established white-on-navy primary CTA. */
.agenda-actions {
    display: grid;
    grid-template-columns: 1fr 1.18fr;
    gap: 12px;
    width: min(100%, 500px);
    margin-top: clamp(32px, 4vw, 52px);
}

.agenda-actions .btn {
    min-height: 52px;
}

.agenda-faq {
    border-color: rgba(255, 255, 255, 0.58);
    color: #ffffff;
    background: transparent;
}

@media (hover: hover) and (pointer: fine) {
    .agenda-faq:hover {
        border-color: #ffffff;
        background: rgba(255, 255, 255, 0.1);
    }
}

/* The schedule. One grid shared by the day header and every row under it, so
   the date lines up with the session titles and the day label lines up with
   the times — which is the whole structure of the reference layout. */
.agenda-day-head,
.agenda-row {
    display: grid;
    grid-template-columns: minmax(120px, 16%) 1fr;
    gap: clamp(16px, 2vw, 40px);
}

.agenda-day-head {
    align-items: baseline;
    margin-bottom: clamp(20px, 2.4vw, 32px);
}

.agenda-day-label {
    font-size: clamp(1.0625rem, 1.4vw, 1.375rem);
    font-weight: 600;
    /* Caps, as the reference sets it. Tracked out a little because caps at
       this size close up without it. */
    text-transform: uppercase;
    letter-spacing: 0.06em;
    color: #ffffff;
}

.agenda-day-date {
    font-size: clamp(1.25rem, 1.8vw, 1.75rem);
    font-weight: 600;
    letter-spacing: -0.015em;
    color: #ffffff;
}

.agenda-rows { list-style: none; }

.agenda-row {
    align-items: baseline;
    padding: clamp(9px, 1vw, 13px) 0;
}

.agenda-time {
    font-size: clamp(0.875rem, 0.95vw, 0.9375rem);
    font-weight: 500;
    font-variant-numeric: tabular-nums;
    letter-spacing: 0.01em;
    white-space: nowrap;
    /* 5.9:1 on the navy: quiet next to the session, still comfortably AA */
    color: rgba(255, 255, 255, 0.66);
}

.agenda-what {
    font-size: clamp(1rem, 1.15vw, 1.125rem);
    font-weight: 500;
    line-height: 1.45;
    letter-spacing: -0.005em;
    color: #ffffff;
}


/* ============================================================
   GUEST SPEAKERS — cards under a sheet band. Distinct from the
   .speaker cards on speakers.html, which are white-on-white in
   a three-up grid; these put the name and role on navy, four
   across, as the reference does.
   ============================================================ */

.guests-grid {
    display: grid;
    grid-template-columns: repeat(4, 1fr);
    gap: clamp(16px, 1.8vw, 26px);
    /* No closing space of its own. The band between the last card and the next
       section belongs to .guests-note, which sits in the middle of it. */
    padding: clamp(36px, 4vw, 56px) 0 0;
}

/* Centred in the gap rather than tucked under the cards: the same space above
   it as below, so it reads as its own line between two sections instead of a
   footnote hanging off the row. Larger than a caption for the same reason.
   Set left, so it starts on the same edge as the first card above it. */
.guests-note {
    margin: 0;
    padding: clamp(40px, 4.4vw, 64px) 0;
    text-align: left;
    font-size: clamp(1rem, 1.2vw, 1.1875rem);
    line-height: 1.6;
    color: var(--muted);
}

.guest {
    display: flex;
    flex-direction: column;
}

/* The portrait, and the biography that rides over it.
 *
 * It is a <button> because the reveal has to work by tap and by keyboard, not
 * only by hover -- on a phone there is no hover at all. So three things open
 * it: hover on a pointer device, keyboard focus, and .is-open from main.js.
 *
 * A ratio and a ground are kept for the three slots that are still empty, so
 * the row holds its shape rather than collapsing. */
.guest-photo {
    position: relative;
    display: block;
    width: 100%;
    aspect-ratio: 4 / 5;
    padding: 0;
    border: 0;
    background: #d9dcdc;
    overflow: hidden;
    text-align: left;
    -webkit-tap-highlight-color: transparent;
}

/* Only the filled slots are interactive. */
.guest-photo[data-guest-toggle] { cursor: pointer; }

.guest-photo img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    display: block;
    /* Slower than the scrim and the text: the picture should feel like it is
       still settling as the words arrive, not racing them. */
    transition: transform 700ms cubic-bezier(0.22, 0.61, 0.36, 1);
}

/* Weighted to the bottom, where the text sits, so the face stays readable
   through it rather than being flattened under an even wash. */
.guest-scrim {
    position: absolute;
    inset: 0;
    background: linear-gradient(180deg,
                rgba(1, 17, 50, 0.22) 0%,
                rgba(1, 17, 50, 0.72) 48%,
                rgba(1, 17, 50, 0.93) 100%);
    opacity: 0;
    transition: opacity 300ms cubic-bezier(0.22, 0.61, 0.36, 1);
}

.guest-bio {
    position: absolute;
    left: clamp(14px, 1.4vw, 20px);
    right: clamp(14px, 1.4vw, 20px);
    bottom: clamp(14px, 1.4vw, 20px);
    color: #ffffff;
    font-size: clamp(0.8125rem, 0.9vw, 0.9375rem);
    line-height: 1.5;
    letter-spacing: 0.002em;
    opacity: 0;
    transform: translateY(9px);
    transition: opacity 240ms cubic-bezier(0.22, 0.61, 0.36, 1),
                transform 420ms cubic-bezier(0.22, 0.61, 0.36, 1);
}

/* The affordance. Without it nobody on a touch screen learns there is
   anything under the portrait at all. Rotates into a close mark when open. */
.guest-more {
    position: absolute;
    right: clamp(12px, 1.1vw, 15px);
    top: clamp(12px, 1.1vw, 15px);
    width: 26px;
    height: 26px;
    display: grid;
    place-items: center;
    border-radius: 50%;
    color: #ffffff;
    background: rgba(1, 17, 50, 0.46);
    backdrop-filter: blur(3px);
    -webkit-backdrop-filter: blur(3px);
    transition: transform 380ms cubic-bezier(0.22, 0.61, 0.36, 1),
                background-color 300ms ease;
}

/* ---- The open state, from any of the three routes ---- */
.guest-photo[data-guest-toggle].is-open .guest-scrim,
.guest-photo[data-guest-toggle]:focus-visible .guest-scrim {
    opacity: 1;
}

.guest-photo[data-guest-toggle].is-open .guest-bio,
.guest-photo[data-guest-toggle]:focus-visible .guest-bio {
    opacity: 1;
    transform: none;
    /* Let the scrim get ahead of the words. Entering only -- leaving has no
       delay, because an exit that lingers reads as lag. */
    transition-delay: 80ms;
}

.guest-photo[data-guest-toggle].is-open img,
.guest-photo[data-guest-toggle]:focus-visible img {
    transform: scale(1.045);
}

.guest-photo[data-guest-toggle].is-open .guest-more {
    transform: rotate(45deg);
    background: rgba(1, 17, 50, 0.72);
}

@media (hover: hover) and (pointer: fine) {
    .guest-photo[data-guest-toggle]:hover .guest-scrim { opacity: 1; }
    .guest-photo[data-guest-toggle]:hover .guest-bio {
        opacity: 1;
        transform: none;
        transition-delay: 80ms;
    }
    .guest-photo[data-guest-toggle]:hover img { transform: scale(1.045); }
    .guest-photo[data-guest-toggle]:hover .guest-more {
        background: rgba(1, 17, 50, 0.72);
    }
}

@media (prefers-reduced-motion: reduce) {
    .guest-photo img,
    .guest-bio,
    .guest-more {
        transition-duration: 1ms;
    }
    .guest-photo[data-guest-toggle].is-open img,
    .guest-photo[data-guest-toggle]:focus-visible img,
    .guest-photo[data-guest-toggle]:hover img {
        transform: none;
    }
    .guest-bio { transform: none; }
}

/* A column so the rule and the role can be pushed to the bottom. Without that,
   a name that wraps to two lines -- "Professor Amir Goldberg" does -- drops its
   own rule and role lower than the three beside it, and the row reads ragged
   even though every card is exactly the same height. */
.guest-info {
    flex: 1;
    display: flex;
    flex-direction: column;
    padding: clamp(16px, 1.6vw, 22px) clamp(16px, 1.6vw, 22px) clamp(18px, 1.8vw, 26px);
    background: var(--navy);
}

.guest-name {
    display: flex;
    /* Top, not centre. Two lines are reserved below, so centring pushed a
       one-line name half a line down -- the four names started at three
       different heights -- and on the two-line name it parked the LinkedIn
       mark between the lines instead of beside the first one. */
    align-items: flex-start;
    gap: 7px;
    /* Two lines are reserved whether the name needs them or not. "Professor
       Amir Goldberg" takes two; the other three take one. Reserving the space
       is what keeps the rule and the title beneath it on the same line across
       the row -- the titles themselves run to one, two and three lines, so
       nothing downstream can be relied on to align them. */
    line-height: 1.3;
    min-height: calc(2 * 1.3em);
    font-size: clamp(1rem, 1.15vw, 1.1875rem);
    font-weight: 500;
    letter-spacing: -0.01em;
    color: #ffffff;
}

/* The LinkedIn mark sits before the name. The glyph is 14px but the box is 24,
   which is the smallest target WCAG 2.2 accepts -- on a phone this sits inside
   a card whose whole photograph is also tappable, so it has to be hard to hit
   by accident and easy to hit on purpose. */
.guest-li {
    flex: none;
    display: grid;
    place-items: center;
    width: 24px;
    height: 24px;
    margin-left: -5px;          /* pull the padding back so the name keeps its line */
    color: rgba(255, 255, 255, 0.58);
    transition: color 200ms ease;
}

.guest-li:hover,
.guest-li:focus-visible {
    color: #ffffff;
}

.guest-rule {
    height: 1px;
    margin: clamp(10px, 1.1vw, 14px) 0 0;
    background: rgba(255, 255, 255, 0.28);
}

.guest-role {
    margin-top: clamp(10px, 1.1vw, 14px);
    font-size: clamp(0.875rem, 0.95vw, 0.9375rem);
    font-weight: 500;
    line-height: 1.45;
    color: rgba(255, 255, 255, 0.78);
}


/* ============================================================
   SCAFFOLDED PAGES — agenda, speakers, faq
   Shared shell, then one distinct layout family each: a schedule,
   a card grid, and an accordion.
   ============================================================ */

/* No padding at the top: the sheet rides up over the banner instead, the way
   the landing page does. .page-card-wrap on the container supplies the
   negative margin and the stacking. */
/* No padding at either end. The sheet rides up over the banner at the top,
   and .page-card--page supplies its own bottom padding; the gap down to the
   footer is the footer's own padding-top, so there is one source for it and
   every page has the same one. This used to carry var(--section-pad) at the
   bottom, from when the content sat on the paper ground rather than in a
   sheet — it made the gap here 161px against the landing page's 41px. */
.page-main {
    background: var(--paper);
    padding: 0;
}

/* The landing page's sections carry their own vertical rhythm; these pages
   put their content straight into the sheet, so the sheet supplies it. */
.page-card--page {
    padding-top: clamp(36px, 4.4vw, 64px);
    padding-bottom: clamp(36px, 4.4vw, 64px);
}

.page-lede { max-width: 74ch; }

/* ---------- Notice: says plainly what is not real yet ---------- */

/* A tinted panel with a hairline all the way round, deliberately not a thick
   accent border down one side: that side-tab treatment is a well-worn tell. */
.notice {
    max-width: 74ch;
    margin-top: clamp(28px, 3.4vw, 44px);
    padding: 22px 26px;
    background: var(--accent-wash);
    border: 1px solid rgba(212, 168, 67, 0.38);
    border-radius: var(--r-input);
}

/* For the speakers page, where mistaking placeholders for the real lineup
   would be a genuine problem rather than a cosmetic one. */
.notice--strong {
    background: rgba(168, 58, 32, 0.06);
    border-color: rgba(168, 58, 32, 0.30);
}

.notice-title {
    font-size: 0.9375rem;
    font-weight: 700;
    letter-spacing: -0.01em;
    color: var(--ink);
}

.notice-body {
    margin-top: 7px;
    font-size: 0.9375rem;
    font-weight: 500;
    line-height: 1.65;
    color: var(--ink-soft);
}

.notice-body strong { color: var(--ink); font-weight: 700; }

/* ---------- AGENDA: a schedule ---------- */

.sched {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: clamp(24px, 3vw, 48px);
    margin-top: clamp(36px, 4.5vw, 60px);
}

.sched-day {
    background: var(--card);
    border: 1px solid var(--hair-soft);
    border-radius: var(--r-card);
    padding: clamp(24px, 2.6vw, 36px);
}

.sched-day-title {
    font-family: var(--font-display);
    font-size: clamp(1.5rem, 2.2vw, 2rem);
    font-weight: 400;
    letter-spacing: var(--display-ls);
    line-height: 1.1;
    color: var(--ink);
    padding-bottom: 18px;
    border-bottom: 1px solid var(--hair-soft);
}

.sched-list { list-style: none; }

.sched-row {
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    gap: 4px 20px;
    padding: 18px 0;
    border-bottom: 1px dashed var(--hair);
}

.sched-row:last-child { border-bottom: none; padding-bottom: 0; }

/* Dashed rule and a muted time, so an unfilled slot reads as deliberately
   empty rather than as a rendering fault. */
.sched-time {
    flex: 0 0 12ch;
    font-family: var(--font-display);
    font-size: 0.8125rem;
    letter-spacing: 0.04em;
    text-transform: uppercase;
    color: var(--muted);
}

.sched-what {
    flex: 1 1 14ch;
    font-size: 1.0625rem;
    font-weight: 500;
    letter-spacing: -0.01em;
    color: var(--ink);
}


/* ---------- SPEAKERS: a card grid ---------- */

.speakers {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    gap: clamp(20px, 2.4vw, 34px);
    margin-top: clamp(36px, 4.5vw, 60px);
}

.speaker {
    background: var(--card);
    border: 1px solid var(--hair-soft);
    border-radius: var(--r-card);
    overflow: hidden;
}

.speaker-photo {
    aspect-ratio: 4 / 5;
    background: #e8eaea;
    overflow: hidden;
}

.speaker-photo img { width: 100%; height: 100%; object-fit: cover; }

.speaker-info { padding: 20px 22px 24px; }

.speaker-name {
    font-family: var(--font-display);
    font-size: 1.25rem;
    font-weight: 400;
    letter-spacing: var(--display-ls);
    color: var(--ink);
}

.speaker-role {
    margin-top: 5px;
    font-size: 0.875rem;
    font-weight: 500;
    color: var(--muted);
}


/* ---------- FAQ: an accordion ----------
   Native details/summary, so it works with no JS and keeps the built-in
   keyboard and screen-reader behaviour.

   No max-width on either the list or the answers. The earlier version of
   this capped .faq at 900px and .faq-a at 68ch, which left the accordion
   sitting in a column with the rest of the card empty beside it; both now
   run the full width of the sheet, like everything else on the page. */

.faq {
    margin-top: clamp(4px, 1vw, 12px);
    border-top: 1px solid var(--hair-soft);
}

.faq-item { border-bottom: 1px solid var(--hair-soft); }

.faq-q {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 20px;
    padding: clamp(18px, 2vw, 24px) 0;
    cursor: pointer;
    font-size: clamp(0.9375rem, 1.05vw, 1.0625rem);
    font-weight: 700;
    letter-spacing: -0.01em;
    color: var(--ink);
    list-style: none;
    transition: color 200ms ease;
}

.faq-q::-webkit-details-marker { display: none; }

@media (hover: hover) and (pointer: fine) {
    .faq-q:hover { color: var(--navy); }
    .faq-q:hover .faq-chev { color: var(--ink); }
}

.faq-chev {
    flex-shrink: 0;
    color: var(--muted);
    transition: transform 250ms var(--ease-out), color 200ms ease;
}

.faq-item[open] .faq-chev { transform: rotate(180deg); }

.faq-a { padding: 0 0 clamp(20px, 2.2vw, 28px); }

.faq-a p {
    font-size: clamp(0.9375rem, 1.05vw, 1.0625rem);
    font-weight: 400;
    line-height: 1.7;
    color: var(--ink-soft);
}

.faq-a p + p,
.faq-a ul + p { margin-top: 0.9em; }

.qa-list {
    margin-top: 0.7em;
    padding-left: 1.1em;
    list-style: disc;
    font-size: clamp(0.9375rem, 1.05vw, 1.0625rem);
    line-height: 1.7;
    color: var(--ink-soft);
}

.qa-list li + li { margin-top: 0.35em; }

/* Navy with a gold underline, the same treatment the key-info address link
   gets: gold type at this size cannot clear AA, navy can. */
.qa-link {
    color: var(--ink);
    text-decoration: underline;
    text-decoration-color: var(--accent);
    text-decoration-thickness: 1.5px;
    text-underline-offset: 3px;
    transition: text-decoration-color 200ms ease;
}

@media (hover: hover) and (pointer: fine) {
    .qa-link:hover { text-decoration-color: var(--accent-deep); }
}


/* ============================================================
   REGISTER PAGE
   ============================================================ */

/* No padding at the top: the form card rides up over the banner instead, the
   way the sheet does on the landing page. .page-card-wrap on the container
   supplies the negative margin and the stacking. */
.register-main {
    background: var(--paper);
    padding: 0;
}

.form-card {
    --form-card-pad: clamp(30px, 4.4vw, 76px);
    position: relative;
    max-width: 1120px;
    margin: 0 auto;
    padding: var(--form-card-pad);
    background: var(--card);
    border: 1px solid var(--hair-soft);
    border-radius: var(--r-card);
    box-shadow: 0 18px 60px rgba(1, 12, 51, 0.07);
    transition: min-height 420ms var(--ease-out-expo);
    /* The fixed header should never cover the beginning of the confirmation. */
    scroll-margin-top: clamp(80px, 15vw, 116px);
}


/* ---------- FORM ---------- */

.rsvp {
    display: flex;
    flex-direction: column;
    /* One of the three values that make the gap between sections; the others
       are .form-section's margin-top and padding-top. Was 42 at desktop,
       which with the other two put 130px between one question and the next. */
    gap: clamp(22px, 2.5vw, 34px);
}

.rsvp.is-leaving {
    opacity: 0;
    filter: blur(3px);
    transform: scale(0.99);
    transition: opacity 240ms ease, filter 240ms ease, transform 240ms ease;
    pointer-events: none;
}

.fs { border: none; }

.fs-legend {
    padding: 0;
    font-size: 0.9375rem;
    font-weight: 700;
    letter-spacing: -0.01em;
    color: var(--ink);
}

.fs-hint { margin-top: 6px; }

/* ---------- Numbered sections ---------- */

/* The rule is a pseudo-element, not border-top. A fieldset's top border is
   notched by its own legend, so the line came out broken around each section
   title; this draws it straight across. */
.form-section + .form-section {
    position: relative;
    /* With the flex gap above, this puts ~98px between sections, down from
       ~130. Enough to separate them; not enough to read as nine forms. */
    margin-top: clamp(20px, 2.2vw, 30px);
    padding-top: clamp(22px, 2.5vw, 34px);
}

.form-section + .form-section::before {
    content: '';
    position: absolute;
    top: 0;
    left: 0;
    right: 0;
    height: 1px;
    background: var(--hair-soft);
}

/* A <legend> is placed at the fieldset's border-box edge and ignores its
   padding-top, which put every section title on top of the rule above it.
   Floating it drops it back into normal flow, where the padding applies.
   Kept as a real fieldset/legend because sections 4, 6 and 9 are radio and
   checkbox groups, and the legend is what gives them an accessible name.

   display:block, not flex: the legend used to hold a two-word title and now
   holds the question itself, which has to wrap as a sentence. */
.form-section .fs-legend {
    float: left;
    width: 100%;
    display: block;
    /* No measure: the question runs the full width of the card, like the
       fields under it. At 72ch it wrapped around 576px inside a ~1014px
       card, which read as a column of text beside empty space. */
    max-width: none;
    font-size: 1rem;
    /* Bold. The weights were the other way round — 700 on the little field
       labels, 500 on the questions — which put the emphasis on "First name"
       rather than on what was being asked. */
    font-weight: 700;
    line-height: 1.55;
    letter-spacing: -0.005em;
    color: var(--ink);
}

.form-section .field,
.form-section .field-pair,
.form-section .topics,
.form-section .choice-row {
    clear: both;
}

/* Tabular so the numbers align down the left edge of the form. Held back
   from the question text so the sentence reads first. */
.fs-num {
    font-variant-numeric: tabular-nums;
    font-weight: 700;
    color: var(--muted);
    margin-right: 4px;
}

/* An asterisk alone is not an accessible marker; the title carries the word
   for anyone who cannot see the glyph or its colour. */
.req {
    color: var(--accent-deep);
    text-decoration: none;
    cursor: help;
}

/* The legend is floated, so what follows it clears rather than flows beside
   it; this is the gap between the question and its inputs. */
.form-section .fs-legend + * {
    margin-top: clamp(16px, 1.9vw, 26px);
}

/* And between rows inside a section. .rsvp's flex gap only separates the
   sections themselves, so a section with two rows in it had them touching —
   an error message under one row sat directly against the next row's label.

   Child combinators throughout: .field-pair holds two .field siblings, so a
   descendant selector here matched the second column and pushed it down out
   of line with the first. */
.form-section > .field + .field,
.form-section > .field + .field-pair,
.form-section > .field-pair + .field,
.form-section > .field-pair + .field-pair,
.form-section > .field + .fs,
.form-section > .field-pair + .fs {
    margin-top: clamp(16px, 1.8vw, 24px);
}

/* A single acknowledgement, not a set of options: it should not stretch into
   a two-column grid on its own. */
.topics--single { grid-template-columns: 1fr; }


/* ---------- MULTI-SELECT ----------
   A disclosure over real checkboxes, not a <select multiple>. Native multiple
   selects need ctrl-click on a desktop, which people do not discover, and
   they cannot show a chosen-items summary. Keeping checkboxes underneath
   means the existing validation, the "No Restrictions" exclusivity and the
   "Other" reveal all keep working, and the control still submits as a normal
   checkbox group with no JS in the way. */

.ms { position: relative; }

.ms-toggle {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
    width: 100%;
    padding-right: 44px;
    text-align: left;
    cursor: pointer;
}

/* The chevron is absolute inside .ms, so it needs the same offset the
   select-wrap version gets, measured from the control rather than the group. */
.ms .select-chevron { right: 17px; }

.ms-toggle[aria-expanded="true"] .select-chevron { transform: translateY(-50%) rotate(180deg); }

/* Muted until something is chosen, so the control reads as a prompt */
.ms-value {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    color: var(--muted);
}

.ms-value[data-chosen] { color: var(--ink); }

.ms-panel {
    position: absolute;
    z-index: 20;
    top: calc(100% + 6px);
    left: 0;
    right: 0;
    max-height: 320px;
    overflow-y: auto;
    padding: 6px;
    background: var(--card);
    border: 1px solid var(--hair);
    box-shadow: 0 18px 40px rgba(1, 12, 51, 0.14);
}

.ms-option { display: block; cursor: pointer; }

.ms-option input {
    position: absolute;
    opacity: 0;
    width: 1px;
    height: 1px;
}

.ms-option-face {
    display: flex;
    align-items: center;
    gap: 11px;
    padding: 11px 12px;
    font-size: 0.9375rem;
    font-weight: 500;
    letter-spacing: -0.01em;
    color: var(--ink);
    transition: background-color 140ms ease;
}

.ms-option-face::before {
    content: '';
    flex-shrink: 0;
    width: 17px;
    height: 17px;
    border: 1.5px solid var(--hair);
    background: #ffffff no-repeat center;
    background-size: 11px 11px;
    transition: background-color 140ms ease, border-color 140ms ease;
}

.ms-option:has(input:checked) .ms-option-face::before {
    border-color: var(--navy);
    background-color: var(--navy);
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 12' fill='none'%3E%3Cpath d='M2.5 6.4L4.9 8.8L9.5 3.4' stroke='%23ffffff' stroke-width='1.7' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
}

.ms-option:has(input:focus-visible) .ms-option-face {
    outline: 2px solid var(--focus);
    outline-offset: -2px;
}

@media (hover: hover) and (pointer: fine) {
    .ms-option:hover .ms-option-face { background: #f4f6f6; }
}

.form-intro {
    padding: 22px 24px;
    background: var(--accent-wash);
    border-radius: var(--r-input);
    font-size: 0.9375rem;
    font-weight: 500;
    line-height: 1.6;
    color: var(--ink);
}

.field { display: flex; flex-direction: column; }

.field-label {
    margin-bottom: 8px;
    font-size: 0.9375rem;
    /* 500, not 700: these name the box; the question above carries the weight. */
    font-weight: 500;
    letter-spacing: -0.01em;
    color: var(--ink);
}

/* The note under the phone number: same size and colour as a hint, italic so
   it reads as an aside about the field rather than an instruction for it. */
.field-hint--note { font-style: italic; }

.field-hint {
    margin-top: 7px;
    font-size: 0.8125rem;
    font-weight: 400;
    line-height: 1.5;
    color: var(--muted);
}

.field-pair {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: clamp(16px, 2vw, 24px);
}

.input {
    width: 100%;
    padding: 17px 18px;
    background: #f7f8f8;
    border: 1px solid var(--hair);
    border-radius: var(--r-input);
    font-size: 1rem;
    font-weight: 500;
    letter-spacing: -0.01em;
    color: var(--ink);
    transition: background-color 180ms ease,
                border-color 180ms ease,
                box-shadow 180ms ease;
}

.input::placeholder { color: var(--muted); }

@media (hover: hover) and (pointer: fine) {
    .input:hover:not(:focus) { border-color: #9aa5a4; }
}

.input:focus {
    outline: none;
    background: #ffffff;
    border-color: var(--focus);
    box-shadow: 0 0 0 3px var(--focus-ring);
}

/* Filled state: a settled field reads slightly more solid */
.input:not(:placeholder-shown):not(:focus) { background: #ffffff; }

.textarea {
    resize: vertical;
    min-height: 110px;
    line-height: 1.6;
}

.select-wrap { position: relative; }

.select {
    appearance: none;
    -webkit-appearance: none;
    padding-right: 44px;
    cursor: pointer;
}

.select-chevron {
    position: absolute;
    right: 17px;
    top: 50%;
    transform: translateY(-50%);
    color: var(--muted);
    pointer-events: none;
}

/* Error state */
.input[aria-invalid="true"] {
    border-color: var(--error-line);
    background: var(--error-wash);
}

.input[aria-invalid="true"]:focus {
    border-color: var(--error);
    box-shadow: 0 0 0 3px rgba(168, 58, 32, 0.14);
}

.field-error {
    display: none;
    margin-top: 8px;
    font-size: 0.8125rem;
    font-weight: 600;
    line-height: 1.45;
    color: var(--error);
}

.field-error:not(:empty) {
    display: block;
    animation: err-in 180ms var(--ease-out) both;
}

@keyframes err-in {
    from { opacity: 0; transform: translateY(-3px); }
    to   { opacity: 1; transform: none; }
}


/* ---------- CHOICE: a two-option radio pair ----------
   Now used by section 6 (accommodation). It was written for an
   attend/decline question that no longer exists. */

.choice-row {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 12px;
    margin-top: 14px;
}

.choice { cursor: pointer; }

.choice input {
    position: absolute;
    width: 1px;
    height: 1px;
    opacity: 0;
    pointer-events: none;
}

.choice-face {
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 19px 22px;
    background: #f7f8f8;
    border: 1px solid var(--hair);
    border-radius: var(--r-input);
    font-size: 0.9375rem;
    font-weight: 600;
    letter-spacing: -0.01em;
    color: var(--ink);
    transition: background-color 180ms ease,
                border-color 180ms ease,
                box-shadow 180ms ease,
                transform 160ms var(--ease-out);
}

/* The radio dot, drawn on the face so the real input stays hidden
   but keyboard focus is still shown on the face below. */
.choice-face::before {
    content: '';
    flex-shrink: 0;
    width: 18px;
    height: 18px;
    border: 1.5px solid var(--hair);
    border-radius: 50%;
    background: #ffffff;
    transition: border-color 180ms ease, box-shadow 180ms ease;
}

@media (hover: hover) and (pointer: fine) {
    .choice:hover .choice-face { border-color: #9aa5a4; background: #ffffff; }
}

.choice:active .choice-face { transform: scale(0.985); }

.choice:has(input:checked) .choice-face {
    background: var(--selected-wash);
    border-color: var(--focus);
    color: var(--ink);
}

.choice:has(input:checked) .choice-face::before {
    border-color: var(--focus);
    border-width: 5px;
}

.choice:has(input:focus-visible) .choice-face {
    outline: 2px solid var(--focus);
    outline-offset: 3px;
}


/* ---------- TOPICS (multi-select) ---------- */

.topics {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 10px;
    margin-top: 14px;
}

.topic { cursor: pointer; }

.topic input {
    position: absolute;
    width: 1px;
    height: 1px;
    opacity: 0;
    pointer-events: none;
}

.topic-face {
    display: flex;
    align-items: flex-start;
    gap: 11px;
    height: 100%;
    padding: 16px 18px;
    background: #f7f8f8;
    border: 1px solid var(--hair);
    border-radius: var(--r-input);
    font-size: 0.875rem;
    font-weight: 500;
    line-height: 1.45;
    letter-spacing: -0.01em;
    color: var(--ink);
    transition: background-color 180ms ease,
                border-color 180ms ease,
                transform 160ms var(--ease-out);
}

.topic-face::before {
    content: '';
    flex-shrink: 0;
    width: 17px;
    height: 17px;
    margin-top: 1px;
    border: 1.5px solid var(--hair);
    border-radius: 0;
    background: #ffffff no-repeat center;
    background-size: 11px 11px;
    transition: background-color 180ms ease, border-color 180ms ease;
}

@media (hover: hover) and (pointer: fine) {
    .topic:hover .topic-face { border-color: #9aa5a4; background: #ffffff; }
}

.topic:active .topic-face { transform: scale(0.99); }

.topic:has(input:checked) .topic-face {
    background: var(--selected-wash);
    border-color: var(--focus);
}

.topic:has(input:checked) .topic-face::before {
    background-color: var(--focus);
    border-color: var(--focus);
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 12'%3E%3Cpath d='M2 6.2L4.6 8.8L10 3.4' fill='none' stroke='white' stroke-width='1.9' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
}

.topic:has(input:focus-visible) .topic-face {
    outline: 2px solid var(--focus);
    outline-offset: 3px;
}


/* ---------- FORM FOOT ---------- */

.form-foot {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 16px 24px;
    padding-top: clamp(10px, 1.6vw, 20px);
    border-top: 1px solid var(--hair-soft);
    margin-top: clamp(2px, 0.6vw, 8px);
}

.btn-submit {
    min-width: 210px;
    padding: 18px 36px;
}

.form-status {
    font-size: 0.8125rem;
    font-weight: 600;
    line-height: 1.45;
    color: var(--error);
}

/* Submitting state, ready for the Phase 2 network call */
.rsvp.is-busy .btn-submit {
    opacity: 0.6;
    pointer-events: none;
}


/* ---------- CONFIRMATION ---------- */

/* Centred: the form is left-aligned, but the end state is a single
   moment and centring it stops the wide card reading half-empty. */
.confirm {
    display: flex;
    flex-direction: column;
    align-items: center;
    text-align: center;
    gap: clamp(18px, 2.2vw, 28px);
    max-width: none;
    margin: 0 auto;
    padding: clamp(8px, 1.6vw, 24px) 0 0;
    overflow: visible;
}

.confirm-copy {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 18px;
    max-width: 56ch;
}

.confirm-art {
    display: block;
    align-self: center;
    width: calc(100% + (2 * var(--form-card-pad)));
    max-width: none;
    height: auto;
    margin: 0 calc(-1 * var(--form-card-pad)) calc(-1 * var(--form-card-pad));
}

.confirm[hidden] { display: none; }

.confirm.is-in {
    animation: confirm-in 480ms var(--ease-out-expo) both;
}

@keyframes confirm-in {
    from { opacity: 0; transform: translateY(12px); filter: blur(2px); }
    to   { opacity: 1; transform: none; filter: blur(0); }
}

.confirm-mark { color: var(--accent-deep); }  /* gold: the action completed */

.confirm.is-in .confirm-tick {
    stroke-dasharray: 24;
    stroke-dashoffset: 24;
    animation: tick-draw 420ms var(--ease-out) 180ms both;
}

@keyframes tick-draw {
    to { stroke-dashoffset: 0; }
}

.confirm-title {
    font-family: var(--font-display);
    font-size: clamp(1.625rem, 3vw, 2.375rem);
    font-weight: 400;
    letter-spacing: var(--display-ls);
    line-height: 1.15;
    color: var(--ink);
}

.confirm-body {
    font-size: 1.0625rem;
    font-weight: 500;
    line-height: 1.75;
    color: var(--ink-soft);
}

.confirm-back { margin-top: 10px; }

@media (max-width: 600px) {
    .confirm {
        gap: clamp(18px, 5vw, 24px);
    }

    .confirm-art {
        height: clamp(180px, 62vw, 244px);
        object-fit: cover;
        object-position: center bottom;
    }
}


/* ============================================================
   SCROLL REVEALS — quiet fade and rise, staggered
   ============================================================ */

.js .reveal {
    opacity: 0;
    transform: translateY(14px);
}

.js .reveal.is-in {
    opacity: 1;
    transform: none;
    transition: opacity 520ms var(--ease-out-expo),
                transform 520ms var(--ease-out-expo);
    transition-delay: calc(var(--i, 0) * 60ms);
}

/* Stagger the info-card columns individually */
.js .keyinfo-card.is-in .keyinfo-col {
    animation: col-in 520ms var(--ease-out-expo) both;
    animation-delay: calc(120ms + var(--i, 0) * 60ms);
}

@keyframes col-in {
    from { opacity: 0; transform: translateY(8px); }
    to   { opacity: 1; transform: none; }
}


/* ============================================================
   REDUCED MOTION — mandatory. Movement goes, meaning stays.
   ============================================================ */

@media (prefers-reduced-motion: reduce) {
    .js .reveal,
    .js .reveal.is-in {
        opacity: 1;
        transform: none;
        transition: none;
    }

    .js .keyinfo-card.is-in .keyinfo-col {
        animation: none;
        opacity: 1;
        transform: none;
    }

    .hero-img { animation: none; transform: none; }

    .confirm.is-in { animation: confirm-fade 200ms ease both; }
    .confirm.is-in .confirm-tick { animation: none; }

    @keyframes confirm-fade {
        from { opacity: 0; }
        to   { opacity: 1; }
    }

    .rsvp.is-leaving {
        transition: opacity 160ms ease;
        filter: none;
        transform: none;
    }

    .field-error:not(:empty) { animation: none; }

    .form-card { transition: none; }

    /* Keep press feedback legible without moving anything */
    .btn-primary:active,
    .hero-cta:active,
    .choice:active .choice-face,
    .topic:active .topic-face { transform: none; }

    .btn-primary:active { background: var(--navy-light); }

    .btn,
    .mast-logo,
    .input,
    .choice-face,
    .topic-face,
    .keyinfo-link {
        transition-duration: 120ms;
    }

    @media (hover: hover) and (pointer: fine) {
        .btn-primary:hover,
        .hero-cta:hover { transform: none; }
    }
}


/* ============================================================
   RESPONSIVE
   ============================================================ */

@media (max-width: 860px) {
    :root { --card-overlap: clamp(16px, 2.2vh, 26px); }

    /* Three columns get too narrow to hold an address, so they stack and the
       vertical rules become horizontal ones. */
    .keyinfo-card { grid-template-columns: 1fr; }

    .keyinfo-col { padding: 0; }

    .keyinfo-col + .keyinfo-col {
        border-left: none;
        border-top: 1px solid var(--hair-soft);
        margin-top: 22px;
        padding-top: 22px;
    }

    .hero-title { max-width: 22ch; }
    .hero-sub { max-width: 100%; }

    /* Two days stack; both speaker grids halve */
    .sched { grid-template-columns: 1fr; }
    .speakers { grid-template-columns: repeat(2, 1fr); }
    .guests-grid { grid-template-columns: repeat(2, 1fr); }

    .topics { grid-template-columns: 1fr; }
}

@media (max-width: 620px) {
    .nav-cta {
        padding: 9px 16px;
        font-size: 0.75rem;
    }

    /* The portraits stay in a compact two-by-two grid on phones. The content
       is purposefully short enough for this density, and keeping all four in
       view makes the guest list feel like a lineup rather than a feed. */
    .speakers { grid-template-columns: 1fr; }
    .guests-grid {
        grid-template-columns: repeat(2, minmax(0, 1fr));
        gap: 12px;
    }

    .guest-info { padding: 14px 13px 16px; }
    .guest-name { font-size: 0.9375rem; }
    .guest-role { font-size: 0.8125rem; }

    /* Taller than the desktop band only because the title wraps here; still
       a banner rather than a full-height hero. */
    .hero { min-height: 440px; min-height: clamp(440px, 58svh, 580px); }

    /* The portrait hero source is composed independently for this compact
       banner, so bring the vineyard and hills into the visible band. */
    .hero-img { object-position: center 40%; }

    .field-pair { grid-template-columns: 1fr; }
    .choice-row { grid-template-columns: 1fr; }

    /* Schedule rows stack: the time sits above what it belongs to */
    .sched-row { flex-direction: column; gap: 4px; }
    .sched-time { flex: none; }

    .agenda-day-head,
    .agenda-row { grid-template-columns: 1fr; gap: 3px; }
    .agenda-day-head { gap: 6px; }

    /* 16px minimum stops iOS from zooming the viewport on focus */
    .input { font-size: 16px; }

    .btn { width: 100%; }
    .hero-cta { width: auto; }
    .agenda-actions .btn { width: 100%; }
    .form-foot { align-items: stretch; }
}


/* ============================================================
   FOOTER — a second white card on the beige ground, not a band
   running on from the sheet. The gap of ground between the two
   is the whole point: the sheet ends, the page breathes, the
   footer is its own object.

   Replaces ~360 lines ported verbatim from greenfield-v2
   (.footer-c2 / .fc2-* / .fc-*), removed with the markup they
   styled. An earlier version of this footer was a dark band
   over the banner photograph; it went when the card came in.
   ============================================================ */

/* A gap of ground above it, so the sheet and the footer stay two objects —
   with none, two white blocks would run together. Nothing at the sides or
   below: the band goes edge to edge and the page ends on it. */
.site-foot {
    padding-top: clamp(20px, 2.4vw, 38px);
}

/* Full-bleed white. The .container inside keeps the logo aligned with the
   sheet above rather than with the window edge. Padding is about 30% down
   from clamp(36px, 4.4vw, 64px) / clamp(32px, 4vw, 56px). */
.site-foot-card {
    background: var(--card);
    /* No bottom padding: the artwork is the bottom of the card. */
    padding: clamp(25px, 3vw, 45px) 0 0;
    /* The legal row is deliberately lowered into the illustration. The
       matching negative art margin keeps the painting's top edge in place. */
    --site-foot-legal-overlay: clamp(180px, 16vw, 264px);
}

/* Full-bleed. The card runs the whole viewport width, so the picture does too
   -- it is a landscape, and a landscape with margins either side reads as a
   photograph someone pasted in rather than as the ground the page stands on.
   The band is cut 7.07:1 in the asset rather than cropped here, so the files
   are smaller and nothing has to be scaled at runtime.

   The negative margin is what puts the closing lines over the painting. It is
   deliberately small: enough that the legal line and the foot of the event
   block sit on the palest part of the sky, not so much that it reaches the
   mark and the map, which stay on white. */
.site-foot-art-wrap {
    position: relative;
    z-index: 0;
    margin-top: calc(clamp(26px, 3.2vw, 44px) - var(--site-foot-legal-overlay));
}

.site-foot-art {
    display: block;
    width: 100%;
    height: auto;
}


/* Above the painting, and the reason the text stays readable over it. */
.site-foot-body {
    position: relative;
    z-index: 1;
}

/* Below this the band would be a sliver -- 4.95:1 at 375px is 76px tall, and
   the vines become texture. Fix a height instead and let it crop the sides,
   keeping the rows legible. */

@media (max-width: 760px) {
    .site-foot-card {
        --site-foot-legal-overlay: clamp(112px, 28vw, 154px);
    }

    .site-foot-art {
        height: clamp(118px, 32vw, 170px);
        object-fit: cover;
        object-position: center bottom;
    }
}

/* The container alone lands the logo on the sheet's outer edge; the copy in
   the sheet sits one --sheet-pad further in. Adding it here puts the footer
   on the same line as everything above it. */
.site-foot-card .container {
    padding-left: calc(var(--container-pad) + var(--sheet-pad));
    padding-right: calc(var(--container-pad) + var(--sheet-pad));
}

/* The mark and map align to the same left/right rails as the content card
   above. The sitemap reads as a true footer navigation when it lands right. */
.site-foot-top {
    display: grid;
    grid-template-columns: 1fr auto;
    align-items: start;
    gap: clamp(20px, 3vw, 48px);
}

.site-foot-logo {
    display: inline-flex;
    justify-self: start;
    transition: opacity 300ms ease;
}

.site-foot-map {
    justify-self: end;
    display: flex;
    flex-wrap: wrap;
    justify-content: flex-end;
    gap: clamp(16px, 2vw, 34px);
    /* Optical, not measured: the mark and the title both sit a little below
       the top of their boxes, so a row of small caps level with the very top
       reads as if it has floated up. */
    padding-top: 6px;
    font-size: 0.9375rem;
    font-weight: 500;
}

.site-foot-map a {
    color: var(--ink);
    text-decoration: none;
    border-bottom: 1px solid transparent;
    padding-bottom: 2px;
    transition: border-color 220ms ease, color 220ms ease;
}

.site-foot-map a:hover,
.site-foot-map a:focus-visible {
    border-bottom-color: var(--accent);
}

/* Where you already are: stated for a screen reader by aria-current, and shown
   to everyone else by the rule that is already there rather than a colour. */
.site-foot-map a[aria-current="page"] {
    color: var(--muted);
    border-bottom-color: var(--hair-soft);
}

/* Left, under the mark. It sat right while it was the third column of the top
   row; it is its own block now. */
.site-foot-event {
    margin-top: clamp(22px, 2.6vw, 36px);
    text-align: left;
}

.site-foot-event .site-foot-title {
    margin-top: 0;
}

@media (max-width: 860px) {
    /* Stack without losing the two alignment rails: logo left, map right. */
    .site-foot-top {
        grid-template-columns: 1fr;
        gap: clamp(22px, 5vw, 34px);
    }

    .site-foot-map {
        justify-self: end;
        justify-content: flex-end;
        padding-top: 0;
    }

    .site-foot-event {
        justify-self: start;
        text-align: left;
    }
}


.site-foot-logo img {
    width: clamp(150px, 12vw, 186px);
    height: auto;
}

@media (hover: hover) and (pointer: fine) {
    .site-foot-logo:hover { opacity: 0.7; }
}

.site-foot-title {
    margin-top: clamp(20px, 2.4vw, 32px);
    font-family: var(--font-display);
    font-size: clamp(1.5rem, 2.4vw, 2rem);
    font-weight: 400;
    letter-spacing: var(--display-ls);
    line-height: 1.15;
    color: var(--ink);
}

.site-foot-meta {
    margin-top: clamp(8px, 1vw, 12px);
    font-size: clamp(0.9375rem, 1.05vw, 1.0625rem);
    font-weight: 500;
    color: var(--muted);
}

.site-foot-legal {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: clamp(14px, 1.6vw, 26px);
    margin-top: calc(clamp(30px, 3.6vw, 52px) + var(--site-foot-legal-overlay));
    padding-top: 0;
    border-top: 0;
    font-size: 0.8125rem;
    font-weight: 500;
    color: #fff;
    position: relative;
    z-index: 2;
    /* A soft black halo makes the legal copy legible without a hard letter
       outline, backing panel, or any interruption of the vineyard artwork. */
    text-shadow:
        0 1px 4px rgb(0 0 0 / 92%),
        0 0 10px rgb(0 0 0 / 78%),
        0 0 18px rgb(0 0 0 / 48%);
}

.site-foot-legal a {
    color: #fff;
    text-decoration: none;
    transition: color 200ms ease;
}

@media (hover: hover) and (pointer: fine) {
    .site-foot-legal a:hover { color: rgb(255 255 255 / 78%); }
}

/* Turnstile sits above the submit button. The widget is a fixed 300px iframe
   that cannot be restyled, so the only job here is to give it the same rhythm
   as the fields above it rather than let it crowd the button. */
.form-turnstile {
    margin-bottom: clamp(18px, 2vw, 26px);
}

/* At phone width the card's own padding leaves .form-foot about 273px, which
   is narrower than the widget's fixed 300px, so it broke out past the card's
   left and right padding. Cloudflare does not allow the iframe to be resized,
   and its "flexible" size still has a 300px floor, so scale it instead. The
   origin is the left edge so it stays aligned with the fields above it. */
@media (max-width: 430px) {
    .form-turnstile {
        transform: scale(0.88);
        transform-origin: left top;
        /* scale() does not change the space the element reserves, so claw back
           the ~9px the shrunken widget no longer fills. */
        margin-bottom: clamp(10px, 1.5vw, 18px);
    }
}

/* The data sentence above the security check. Quiet, but present: it is the
   only place the form says what happens to the answers. */
.form-privacy {
    max-width: 62ch;
    margin: 0 0 clamp(16px, 1.8vw, 22px);
    font-size: 0.875rem;
    line-height: 1.6;
    color: var(--muted);
}
