/* Network of Directors, design direction A. Tokens and rules from design-refs/design-direction-a.md.
   Round 2 (2026-09-02): a neutral near-black ground and a neutral light, white ink, the one control a white
   pill, and Connor's green ("sage greens and black dark colors") kept at trace weight only: eyebrows, rules,
   the focus ring and the gradients' mid stop, never a control. Sora (a geometric sans) for display headlines,
   Archivo Black for the wordmark, Hanken Grotesk for body. No serif, no SwarmSystem token appears here.
   Contrast on the ground: --ink-d 17.9:1, --mut-d 8.4:1, --sage-text 8.5:1. On the light: --ink-l 17.3:1,
   --mut-l 6.1:1, --sage-deep 6.8:1. */
:root{
  --ground:#0b0b0b;--panel:#161616;--light:#f5f5f3;--paper:#fafaf8;
  --ink-d:#f4f4f2;--mut-d:#a9a9a5;--ink-l:#111111;--mut-l:#5d5d5a;
  --sage-text:#9fb08f;--sage-deep:#4b5a43;--sage-veil:rgba(75,90,67,.30);
  --r:14px;--rs:6px;
  --display:'Sora','Hanken Grotesk',system-ui,-apple-system,'Segoe UI',sans-serif;
  --logo:'Archivo','Sora',system-ui,-apple-system,'Segoe UI',sans-serif;
  --sans:'Hanken Grotesk',system-ui,-apple-system,'Segoe UI',sans-serif;
  --wrap:1400px;--pad:96px;--gut:20px;
}
/* palette B, for the ledger's side-by-side crops only: the same page with no green at all. The generator's
   PALETTE constant puts data-palette="b" on the html element; the default ships A. */
[data-palette="b"]{--sage-text:#a9a9a5;--sage-deep:#5d5d5a;--sage-veil:rgba(93,93,90,.30)}
@media (max-width:700px){:root{--pad:56px;--gut:16px}}
*{box-sizing:border-box}
html{-webkit-text-size-adjust:100%;scroll-behavior:smooth}
body{margin:0;background:var(--ground);color:var(--ink-d);font:400 18px/1.62 var(--sans);font-feature-settings:"kern","liga"}
img{max-width:100%;display:block}
a{color:inherit}
:focus-visible{outline:2px solid var(--sage-text);outline-offset:3px}
/* No italics anywhere, and emphasis never changes color. Operator ruling 2026-09-16:
   slanted type and a recolored phrase mid sentence both read as machine written. Emphasis
   stays semantic in the markup and visually inherits. */
em,i,cite,dfn,address,var{font-style:normal}
em,i,strong b,mark{color:inherit}
mark{background:none}
.light :focus-visible{outline-color:var(--sage-deep)}
.skip{position:absolute;left:-999px;top:8px;background:var(--ink-d);color:var(--ground);padding:8px 14px;border-radius:999px;z-index:100;font-weight:600;text-decoration:none}
.skip:focus{left:8px}
.wrap{max-width:calc(var(--wrap) + var(--gut) * 2);margin:0 auto;padding:0 var(--gut)}
.wrap.narrow{max-width:800px;margin:0 auto}
main{position:relative;z-index:1;background:var(--ground)}
.band{padding:var(--pad) 0;scroll-margin-top:84px} /* round 3: a sticky 60px nav at top:12px plus 12 of breath, so #faq and #register land under nothing */
.band.dark{background:var(--ground);color:var(--ink-d)}
.band.light{background:var(--light);color:var(--ink-l)}
.band-head{margin:0 0 16px;text-wrap:balance;letter-spacing:-.02em}
.light .band-head{font:300 clamp(30px,3.4vw,48px)/1.05 var(--display)}
.dark .band-head{font:500 clamp(26px,3vw,42px)/1.08 var(--sans)}
.sub-head{margin:0 0 28px;font-size:18px;line-height:1.55;max-width:60ch;color:var(--mut-d)}
.light .sub-head{color:var(--mut-l)}
.eyebrow{font:600 12px/1 var(--sans);letter-spacing:.16em;text-transform:uppercase;color:var(--sage-deep);margin:0 0 14px}
/* Title case across the site (operator: "cap case titles ... always"). Visual only; DOM text stays sentence case
   for SEO/AEO. Excludes the wordmark (.brand, .foot-mark) so "Network of Directors" keeps its lowercase "of". */
.band-head,.hero-copy h1,.rules,.talk-hero h1,.talk-summary .band-head,.ev-title,.holding .band-head,
.faq-item h3,.talk-body h2,.rel-name,.spk-hero-panel h1,.spk-name,.speaker-row h2,
.action-title{text-transform:capitalize}
/* Title case on navigation, footer links, breadcrumbs and CTAs too, for a consistent cap-case system */
.nav-links a,.subnav a,.foot-links a,.btn,.crumbs li{text-transform:capitalize}
/* 2026-09-16 (operator: a few titles and buttons on phones were not cap case): the pinned seat bar, the drawer, card values
   and names, the contact thank-you, the legal page headings */
.seat-bar,.drawer a,.fact-value,.tool-name,.cf-done h2,.legal-page h2{text-transform:capitalize}

/* the strip (round 3, operator: "we will probably want to have a secondary navigation above the main menu"): six
   quiet page names the capsule does not carry, right-aligned, no fill, no border, no second control, 32 tall.
   Under 700 it is gone; the footer carries the same six. The gate's subnav holds the six and the column. */
/* Secondary header hidden for launch (reversible: set display back to flex). Operator ruling 2026-09-15. */
.subnav{width:calc(100% - var(--gut) * 2);max-width:var(--wrap);margin:6px auto 0;height:34px;display:flex;gap:22px;justify-content:flex-end;align-items:center;font:500 14px/1 var(--sans);color:var(--mut-d)}
.subnav a{text-decoration:none;opacity:.8;transition:opacity .15s}
.subnav a:hover{opacity:1}
@media (max-width:700px){.subnav{display:none}}
/* nav: a capsule the same width as the hero card and every stack (operator, round 2: "the menu navigation is the
   same width as the hero image and that's the column width of the entire website", "make the main navigation full
   height with the full border radius at 100 px on each side"). Full height means the contents fill the 60px bar:
   the pill is 48 tall inside a 6px inset, so the radii are concentric (30 outside, 24 inside). Round 3 (operator:
   "when you scroll the header is sticky with the menu but it's like glass. Anything that goes behind it kind of
   shapes throughout that"): the capsule is sticky at 12px, above main (z-index 1) and below the skip link (100),
   and its fill is the glass below. The gate's navSticky and glass hold both. */
.nav{position:sticky;top:12px;z-index:5;width:calc(100% - var(--gut) * 2);max-width:var(--wrap);margin:6px auto 12px;display:flex;align-items:center;gap:20px;min-height:60px;padding:6px 6px 6px 28px;border-radius:100px;
  background:var(--panel);color:var(--ink-d)}
/* the glass (round 3): --panel with an alpha so the closed palette holds, blurred and slightly saturated backdrop.
   The nav's is heavier because it sits over moving faces. Never on .btn: the pill stays solid --ink-d. Two
   fallbacks: no backdrop-filter support, and a reduced-transparency preference, both back to the flat panel. */
.glass{background:rgba(22,22,22,.55);-webkit-backdrop-filter:blur(18px) saturate(1.4);backdrop-filter:blur(18px) saturate(1.4)}
.nav.glass{background:rgba(22,22,22,.62);-webkit-backdrop-filter:blur(20px) saturate(1.6);backdrop-filter:blur(20px) saturate(1.6)}
@supports not ((backdrop-filter:blur(1px)) or (-webkit-backdrop-filter:blur(1px))){.glass,.nav.glass{background:var(--panel)}}
@media (prefers-reduced-transparency:reduce){.glass,.nav.glass{background:var(--panel);-webkit-backdrop-filter:none;backdrop-filter:none}}

/* The refraction is applied by app.js per element (ported from nikdelvin/liquid-glass, MIT): under
   :root.refract each .glass panel gets an inline backdrop-filter naming a displacement map sized to that
   panel, so the bend lives at the rim and the center stays legible. It is set from JS, not here, because a
   backdrop-filter naming a filter id absent from the document would drop the whole chain. Chromium only; the
   head gate excludes Safari, which keeps the plain-blur .glass floor above. ORDER LAW: the CSS blur in that
   inline value runs BEFORE the url() so the bend is applied last and survives. Never blur after the url(). */
/* a refracted panel is a still surface: the displacement map is a static ramp and never animates, so
   there is nothing here for reduced motion to calm. Reduced TRANSPARENCY is the preference that matters
   and it is refused twice: in the gate before the class is set, and here if the class already is. */
@media (prefers-reduced-transparency:reduce){:root.refract .glass,:root.refract .nav.glass{background:var(--panel);-webkit-backdrop-filter:none;backdrop-filter:none}}

/* THE SURFACE (2026-09-06, third build). Everything above bends what is BEHIND the panel. Nothing above
   put anything ON it, and that was the actual bug behind two rounds of "still looks like blur."
   A lens only shows where the backdrop has structure to bend. Behind these cards is a dim photograph
   under a 50 percent black tint, so there was very little to work with and the bend had nothing to
   report. What makes a pane read as glass over a dark backdrop is surface light: a sheen lying across
   the face, and an edge lit like it has thickness. Neither needs a filter, so both live on .glassy and
   ship to EVERY engine, Safari included. .refract stays the Chromium-only bend on top.
   THE TINT GOES THE OTHER WAY, UP, and the measurement is why. The first cut of this block lowered it
   .50 to .42 to let more backdrop through, and asserted in this comment that body copy still cleared
   4.5:1. That was written before it was measured and it was false. Measured properly (glyphs hidden,
   brightest cell under each text run's own box, worst of 21 runs): round 4 sits at 3.29:1, the .42 cut
   took it to 2.66:1, and it turned out the tint was not even the main cost. Dropping the in-lens blur
   18 to 3 was, because averaging is what was holding the backdrop down. Seeing through the glass and
   reading text on it are the same dial.
   So the blur goes back to 18, exactly round 4, the rim narrows to 8 percent so the bend lives at the
   edge instead of under the copy, and the tint goes UP to .58 to pay for the sheen. That lands at
   3.50:1, better than the round 4 build this replaces, with 2 runs under 4.5:1 instead of 3.
   Those figures are at deviceScaleFactor 1. DPR CHANGES THE ANSWER and it caught this work out once:
   at DPR 2 the hero photo resolves a higher-detail source, the backdrop gets brighter, and round 4
   falls to 2.87:1 while this build reads 5.92:1 with nothing under 4.5:1. Absolute numbers are only
   comparable within one DPR. The ordering is what holds: this build beats round 4 at both.
   A brighter diagonal light band across the face was measured and REJECTED. It looked more like glass
   and cost too much: 3.37:1 at the mildest setting and 1.85:1 at the strongest, all worse than the
   corner sheen that shipped. Surface light is close to free; a band across the copy is not.
   Note what that last number means: THIS DESIGN WAS ALREADY UNDER 4.5:1 BEFORE ANY OF THIS WORK. The
   hero copy over a photograph does not meet AA and did not in round 4 either. That is a real finding
   and it is the operator's call, not something to be quietly absorbed here. Re-measure on any change:
   scratchpad contrast2.mjs is the harness.
   The sheen is a 135deg white ramp that dies at 44 percent. It is a light, not a color, so the closed
   palette holds. background-image (not the shorthand) so it layers over the tint and under the text. */
/* 2026-09-15 "more dramatic" pass: corner sheen peak and bottom bounce raised for a glossier face.
   Tint (background-color) held exactly at round 4 .58/.62 (it pays for text contrast), and the sheen
   still dies by ~44% so it never crosses the copy. The rejected "band across the face" is not reintroduced. */
/* 2026-09-21, operator: "too hard to read". Measured on the shipped hero before the change: the smallest
   text on the card (--mut-d) read 2.65:1 on Next event, 1.64:1 on Where and 1.82:1 on Cost, against the
   blurred photo behind each one. That is the finding the round 4 note above left to the operator, now called.
   The tint is the fix and it is measured, not chosen: against the brightest blurred backdrop under these
   three cards, --mut-d needs alpha .82 to clear 4.5:1. Shipped at .86 so a future hero photo has headroom.
   The card is frosted now rather than see-through: the room still reads through it as diffused color, the
   copy no longer competes with a window. The corner sheen dies at 22 percent instead of 44 so it lights the
   rim and never crosses .fact-label, which is the smallest text and sits in that exact corner. */
:root.glassy .fact.glass{background-color:rgba(22,22,22,.86);
  background-image:linear-gradient(135deg,rgba(255,255,255,.16) 0%,rgba(255,255,255,.05) 11%,rgba(255,255,255,0) 22%),
                   linear-gradient(to top,rgba(255,255,255,.05) 0%,rgba(255,255,255,0) 30%)}
:root.glassy .nav.glass{background-color:rgba(22,22,22,.48);
  background-image:linear-gradient(135deg,rgba(255,255,255,.22) 0%,rgba(255,255,255,.065) 16%,rgba(255,255,255,0) 40%),
                   linear-gradient(to top,rgba(255,255,255,.075) 0%,rgba(255,255,255,0) 40%)}
/* the bevel. Five insets: the shared hairline, a lit top edge, a lit left edge, a faint bottom bounce,
   and a soft dark pooling at the foot. Together they are what the eye reads as thickness. The bottom
   pool is the one that stops it looking like a sticker; it is the underside of the pane in shadow. */
:root.glassy .fact.glass,:root.glassy .nav.glass{
  box-shadow:inset 0 0 0 1px rgba(255,255,255,.10),
             inset 0 1px 0 rgba(255,255,255,.64),
             inset 1px 0 0 rgba(255,255,255,.22),
             inset 0 -1px 0 rgba(255,255,255,.13),
             inset 0 -22px 28px -26px rgba(0,0,0,.60)}

/* THE NON-REFRACT PANE (2026-09-21, third cut, operator: "you can't even see through it anymore ...
   it doesn't have the liquid glass like it does on desktop on Chrome"). The desktop lens that app.js
   sets inline is  blur(1px) url(displacement) saturate(1.6) brightness(1.02)  over the .48 tint, the
   sheen and the bevel above. Read that again: ONE pixel of blur. It is nearly clear glass, and the
   rim bend is what makes it read as a lens. The two cuts before this one went the wrong way, adding
   blur (18, 26, 28px) and then a second inset pane, and the operator saw an opaque bar with a second
   menu drawn inside it. Both are gone. This rule is the desktop lens with exactly one term removed,
   the url(), because that is the only term WebKit will not paint. Everything else is identical to
   desktop and comes from the same rules desktop uses. What an iPhone will not show is the bend at
   the rim; there is no CSS route to it in WebKit, and the honest fallback is parity on every other
   term rather than a heavier effect that reads as frosting. Applies to iOS (every browser there is
   WebKit, see the head gate) and to desktop Safari. Chromium keeps the inline lens and never hits it. */
:root.glassy:not(.refract) .nav.glass{
  -webkit-backdrop-filter:blur(1px) saturate(1.6) brightness(1.02);
          backdrop-filter:blur(1px) saturate(1.6) brightness(1.02)}
/* Measured after the cut above: the brand over the roster reads 2.99:1 on this pane against 5.05:1 on
   desktop, at the SAME .48 tint. Desktop passes only because the displacement smears the bright tile
   before it reaches the text; take the url() away and the same tint fails. The tint cannot go up, that
   is the exact thing the operator refused ("can't even see through it"). So the legibility lives on
   the text instead of the pane: a soft dark halo under the brand and the links, and under the three
   toggle bars, which are the only white on the pane at phone width. Scoped to the non-refract pane so
   desktop, which already passes, is untouched. It is not a design element and it is invisible over
   dark content; it only does anything over a bright tile, which is the only place it is needed. */
:root.glassy:not(.refract) .nav .brand,:root.glassy:not(.refract) .nav-links a{text-shadow:0 1px 2px rgba(0,0,0,.62),0 0 10px rgba(0,0,0,.35)}
:root.glassy:not(.refract) .nav-toggle .nt-bar{box-shadow:0 1px 2px rgba(0,0,0,.55)}
/* reduced transparency is refused in the gate before .glassy is ever set, so this is belt and braces
   for a preference that flips after load. */
@media (prefers-reduced-transparency:reduce){:root.glassy .glass,:root.glassy .nav.glass{
  background-color:var(--panel);background-image:none;-webkit-backdrop-filter:none;backdrop-filter:none}}
/* while the page scrolls every pane runs the LIGHT lens (one displacement pass, set per element by app.js block 7 as
   --lens-light) and the full chromatic bend returns the moment the page is still. !important because the bend is
   an inline style. Operator 2026-09-16: a plain blur here read as "just transparent"; the rim must always bend. */
:root.refract.scrolling .glass:not(.fact),:root.refract.scrolling .nav.glass{-webkit-backdrop-filter:var(--lens-light)!important;backdrop-filter:var(--lens-light)!important}
.nav .btn{height:48px;padding:0 24px;border-radius:100px}
/* the edge of every card on the dark ground: an inset shadow, never a border, so the hero card's clip-path
   cannot halve it and no box dimension moves */
.nav,.hero-card,.fact,.talk,.ev-card,.close-panel,#gallery .gph{box-shadow:inset 0 0 0 1px rgba(255,255,255,.10), inset 0 1px 0 rgba(255,255,255,.06)}
.brand{font:700 18px/1 var(--logo);letter-spacing:-.01em;text-decoration:none;white-space:nowrap}
.nav-links{display:flex;gap:28px;margin-left:auto;font-size:16px;font-weight:500}
.nav-links a{text-decoration:none;opacity:.72;transition:opacity .15s}
.nav-links a:hover{opacity:1}
@media (max-width:900px){
  .nav{flex-wrap:wrap;gap:8px 14px;padding:8px 8px 10px 24px;border-radius:100px}
  .nav-links{order:3;width:100%;margin:0;overflow-x:auto;gap:18px;padding-bottom:2px;scrollbar-width:none;font-size:14px;white-space:nowrap}
  .nav-links::-webkit-scrollbar{display:none}
  .nav .btn{margin-left:auto;height:44px}
}

/* the one button */
.btn{display:inline-flex;align-items:center;justify-content:center;background:var(--ink-d);color:var(--ground);font:600 15px/1 var(--sans);padding:12px 20px;border-radius:999px;text-decoration:none;white-space:nowrap;transition:transform .15s ease,background .15s ease}
.btn:hover{background:#ffffff;transform:translateY(-1px)}
.btn:active{transform:scale(.98)}
.btn-lg{padding:16px 28px;font-size:16px}
/* on a light band the pill inverts. A modifier the generator applies, never a rule scoped to .band.light .btn:
   the event card is a dark card inside a light band and its pill stays white */
.btn.on-light{background:var(--ground);color:var(--light)}
.btn.on-light:hover{background:#000000}

/* hero (round 4, 2026-09-03): the frame holds the copy and the three cards, and the photograph is the frame's whole
   ground. Operator: "I don't want to have crossover from the cards onto the hero section so tighten up the hero section.
   Make that parallax background so it looks like glass and then the cards underneath it." The copy sits top left in
   flow, the cards at the foot inside the frame, so every card is glass over the room and nothing straddles the frame's
   edge; the frame is as tall as its contents (no aspect ratio: 32 + copy + 24 + cards + 16 at 1440; the reduced-motion read is the one that sets the budget, the rotated rows lift the first tile 32px in motion). clip-path, not
   overflow:hidden: overflow would make the frame a scroll container and freeze the view() timeline. The photograph is
   the live site's 1024 by 683 copy rendered at 1.367x; the full-resolution frame (a camera original, A7_02217) is an
   ask to Connor, and the lighter blur makes the upscale a little more visible until it arrives. The gate's cardsInside
   holds every card inside the frame; heroCopyClear holds the pill 16 above the cards; heroBlur holds 6.9 under the words. */
.hero{padding:0 0 12px}
.hero-card{position:relative;width:calc(100% - var(--gut) * 2);max-width:var(--wrap);margin:12px auto 0;border-radius:var(--r);clip-path:inset(0 round var(--r));background:var(--panel);isolation:isolate;padding:32px 48px 16px;display:flex;flex-direction:column;gap:24px}
.hero-card .room,.hero-card .room-blur{position:absolute;left:0;right:0;top:-10%;width:100%;height:120%;object-fit:cover;object-position:center 42%;z-index:0}
/* the blur copy (round 4, operator: "the blur is still too much and we need to reduce it to the left so it's more like
   50% and we can see more of the people in the background ... right now it just looks like somebody who's stressed
   out"): half of round 3's radius, 9px against 18, and the mask releases from 38 percent instead of 62 (.45 at 54, .18 at
   70, .08 at the edge). The words get their separation from the wash below, not from the blur. The gate's
   heroBlurRadius holds the radius at or under 10 at 1440; heroBlurRelease reads the release off the pixels. */
.hero-card .room-blur{filter:blur(9px);-webkit-mask-image:linear-gradient(to right,#000 0%,#000 38%,rgba(0,0,0,.45) 54%,rgba(0,0,0,.18) 70%,rgba(0,0,0,.08) 100%);mask-image:linear-gradient(to right,#000 0%,#000 38%,rgba(0,0,0,.45) 54%,rgba(0,0,0,.18) 70%,rgba(0,0,0,.08) 100%)}
/* parallax with no scroll listener: a view() timeline over the exit range, whose length is the frame's own height, so
   progress is 0 at load and the full 6 percent is spent as the frame leaves. Never animation-range: cover, which spends
   60 percent of its range before anybody scrolls. Reduced motion already zeroes animation. */
#hero img.room,#hero img.room-blur{animation:heroPan linear both;animation-timeline:view();animation-range:exit 0% exit 100%}
@keyframes heroPan{from{transform:translateY(0)}to{transform:translateY(-6%)}}
/* the copy, in flow at the frame's top left, its own stacking context so the wash sits under the words and over the
   photograph. The wash (round 3's "black left-to-right color background", kept) is the .scrim inside the copy block, bled
   to the frame's edges and 40px below the pill, so it covers the words' zone exactly and never the cards: .90 at the
   left edge, .88 through 46 percent (the headline's widest line ends near 49), .62 at 56, .22 at 66, gone by 76. The old upward layer is gone with the foot the copy no longer
   sits on. Measured by the gate's heroBlur at both ends of the pan. */
.hero-copy{position:relative;z-index:1;isolation:isolate;max-width:none}
.hero-copy .scrim{position:absolute;left:-48px;right:-48px;top:-32px;bottom:-28px;z-index:-1;pointer-events:none;
  background:linear-gradient(to right, rgba(11,11,11,.90) 0%, rgba(11,11,11,.88) 46%, rgba(11,11,11,.62) 56%, rgba(11,11,11,.22) 66%, rgba(11,11,11,0) 76%);
  -webkit-mask-image:linear-gradient(to bottom,#000 0,#000 calc(100% - 40px),transparent 100%);mask-image:linear-gradient(to bottom,#000 0,#000 calc(100% - 40px),transparent 100%)}
.hero-copy h1{font:300 clamp(34px,4.4vw,64px)/.98 var(--display);letter-spacing:-.015em;margin:0 0 18px;text-wrap:balance;padding-bottom:.08em;max-width:860px}
.hero-copy .sub{font-size:clamp(17px,1.45vw,20px);line-height:1.5;margin:0 0 22px;max-width:46ch}
/* the three cards, inside the frame (round 4), glass over the photograph; no button, no link (round 3, the gate's
   noCardButtons). Card 3 carries the reason line now, so Free is never printed without it and nothing sits under the frame. */
.fact-cards{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:16px;position:relative;z-index:1;margin:0}
.fact{display:flex;flex-direction:column;gap:4px;padding:16px;border-radius:var(--r);background:var(--panel)}
.fact.glass{background:rgba(22,22,22,.86);-webkit-backdrop-filter:blur(28px) saturate(1.25);backdrop-filter:blur(28px) saturate(1.25)}
/* heavier blur than the shared .glass floor: these three sit over faces and a window, and 18px still let
   hard edges through the tint. Was .40 through round 4, when the cards sat over the dark foot of the old
   room photo; the hero is a lit room now and .40 stopped being readable. See the measurement above. */
.fact p{margin:0}
.fact-label{font:600 11px/1 var(--sans);letter-spacing:.18em;text-transform:uppercase;color:var(--mut-d)}
.fact-value{font:600 19px/1.2 var(--sans)}
.fact-sub{font-size:15px;line-height:1.45;color:var(--mut-d)}
.fact-lead{font:600 15px/1.35 var(--sans);color:var(--ink-d);margin-top:8px}
.fact.fact-free .fact-value{font:600 clamp(24px,2.4vw,32px)/1.15 var(--sans);letter-spacing:-.02em}
/* the clock (round 4, operator: "Make it just counting down on the seconds. Make that all one line. Put the days, hours,
   and minutes, seconds on one line, and put the doors open in on above it"): the label on its own line, the four groups
   on one row under it, each number over its unit, the seconds ticking at every width in motion. Under reduced motion the
   seconds pair leaves and the clock ticks once a minute (design-a.js behavior 5); with JS off the shell never shows. A
   clock to the doors, never a checkout timer: no red, no boxes, no flip, no seats line. The same shell sits in the closing
   panel (operator: "Having the countdown live on the last section, Come to the next one"). The gate's countdown reads the
   row's geometry and both shells. */
.countdown{display:flex;flex-direction:column;gap:7px;margin-top:8px;font-variant-numeric:tabular-nums}
.cd-label,.cd-l{font:600 10px/1 var(--sans);letter-spacing:.16em;text-transform:uppercase;color:var(--mut-d)}
.cd-row{display:flex;gap:18px;align-items:flex-start}
.cd-g{display:flex;flex-direction:column;gap:4px;min-width:44px}
.cd-n{font:600 26px/1 var(--sans);color:var(--ink-d)}
.cd-now{font:600 15px/1.2 var(--sans);color:var(--ink-d)}
.nojs [data-countdown]{display:none}
.link-d{color:var(--sage-text);font-weight:600;text-decoration:none;border-bottom:1px solid var(--sage-deep);padding-bottom:1px}
@media (max-width:700px){
  /* 2026-09-21, operator: "you can't really see anything and it doesn't look good ... I'd rather just
     have it be a colored background for mobile specifically." A 3:2 room photograph inside a tall phone
     frame is cropped to a sliver of itself: object-fit:cover throws away most of the width, what is left
     is faces at the edge of the frame, and it reads as mud behind the copy. The picture is dropped below
     700px and the hero sits on --ground, the same black the page already uses, so the headline and the
     three cards are the only things in the frame. Desktop is untouched and still carries the photo.
     The scrim and the blurred backdrop go with it: both exist ONLY to manage a photograph. Left in, the
     scrim paints an .82 to .86 wash over flat black and renders as a visible band behind the copy.
     The card's own hairline goes too, or a black card on a black page draws an outline around nothing. */
  .hero-card{padding:24px 18px 18px;gap:26px;background:var(--ground);box-shadow:none}
  .hero-card .room,.hero-card .room-blur{display:none}
  .hero-copy .scrim{display:none}
  .fact-cards{grid-template-columns:1fr;gap:12px}
  .fact{padding:16px}
  .cd-row{gap:14px}
}

/* roster: seventeen identical tiles in two slow rows, opposite directions, crossing at a slight angle
   (operator, 2026-09-02: "two rows that are dynamic galleries", "the name and the title inside of the
   image ... a gradient transparency comes up over the top so that we can see the title overlay").
   Pure CSS loop: JS off runs it unchanged; reduced motion renders a static wall (see the end of this file).
   Geometry at 1440: tile 260, trailing margin 16, pitch 276; one set is half the track, so translateX(-50%)
   lands exactly one set later and the loop never jumps. 34.5 px/s on both rows: 2484/34.5 = 72s, 2208/34.5 = 64s. */
.roster{padding-top:22px;overflow:hidden}
.roster .band-head{margin-bottom:6px}
.order{color:var(--mut-d);margin:0;font-size:15px}
.tc-note{color:var(--mut-d);margin:-10px 0 22px;font-size:15px}
.mq{padding:24px 0}
.mq-row{overflow:hidden;position:relative;z-index:1;transform:rotate(-1.5deg);-webkit-mask-image:linear-gradient(90deg,transparent 0,#000 6%,#000 94%,transparent 100%);mask-image:linear-gradient(90deg,transparent 0,#000 6%,#000 94%,transparent 100%)}
.mq-row + .mq-row{z-index:0;transform:rotate(1.5deg);margin-top:-18px}
.mq-track{display:flex;width:max-content;animation:mq 72s linear infinite;animation-delay:-7s}
.mq-row + .mq-row .mq-track{animation-duration:64s;animation-direction:reverse;animation-delay:-11s}
@keyframes mq{from{transform:translateX(0)}to{transform:translateX(-50%)}}
.mq-track figure{margin:0 16px 0 0;flex:0 0 260px;width:260px;position:relative}
.mq-track .ph{width:100%;aspect-ratio:1;border-radius:var(--r);overflow:hidden;background:var(--panel);position:relative}
/* the caption zone: a color overlay that turns to the ground; over the worst pixel the name measures 12.3:1, the line 6.6:1 */
.mq-track .ph::after{content:"";position:absolute;inset:0;pointer-events:none;background:linear-gradient(to bottom, rgba(11,11,11,0) 32%, var(--sage-veil) 54%, rgba(11,11,11,.90) 68%, rgba(11,11,11,.96) 100%)}
.mq-track img{width:100%;height:100%;object-fit:cover;object-position:center 30%;filter:saturate(.86) contrast(1.06)}
.mq-track figcaption{position:absolute;left:0;right:0;bottom:0;display:flex;flex-direction:column;gap:2px;padding:0 12px 12px}
.mq-track strong{font:600 15px/1.2 var(--sans)}
.mq-track span{font-size:13px;line-height:1.35;color:var(--mut-d);display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden;transition:color .2s}
.mq-track figure:hover span{color:var(--ink-d)}
.mq-track .tc{display:flex;align-items:center;gap:8px;font:600 12px/1 var(--sans);letter-spacing:.12em;text-transform:uppercase;color:rgba(244,244,242,.45)}
.mq-track .tc i{width:24px;height:1px;background:var(--sage-text);opacity:.4}
@media (max-width:700px){
  .mq-track figure{flex-basis:148px;width:148px}
  .mq-track{animation-duration:43s}
  .mq-row + .mq-row .mq-track{animation-duration:38s}
  .mq-track span{-webkit-line-clamp:1}
}

/* what this is and the flow, one band (operator, 2026-09-02: "information about the event above it and then
   the flow below it with four cards"): his sentence left, his rules and the walk-in answer right, then four
   portrait cards in the FoundersCard band 2 shape, title and caption set into the bottom over the roster gradient */
.what .band-head{max-width:20ch;margin:0}
.rules{font:300 clamp(24px,2.6vw,34px)/1.2 var(--display);margin:0 0 22px;letter-spacing:-.01em}
.body{font-size:18px;max-width:62ch;margin:0 0 22px}
.text-link{color:var(--sage-deep);font-weight:600;text-decoration:none;border-bottom:1px solid var(--sage-deep);padding-bottom:1px}
.flow-grid{display:grid;grid-template-columns:minmax(0,5fr) minmax(0,7fr);gap:40px;align-items:start}
@media (max-width:900px){.flow-grid{grid-template-columns:1fr;gap:20px}}
.flow-label{margin:56px 0 18px}
.flow-cards{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:24px}
.fcard{margin:0;position:relative;aspect-ratio:9/11;border-radius:var(--r);overflow:hidden;background:var(--panel);color:var(--ink-d)}
.fcard img{position:absolute;inset:0;width:100%;height:100%;object-fit:cover;filter:saturate(.86) contrast(1.06)}
/* the roster gradient with its stops raised, so a two-line title and a four-line caption both sit inside the 0.90 floor */
.fcard::after{content:"";position:absolute;inset:0;pointer-events:none;background:linear-gradient(to bottom, rgba(11,11,11,0) 18%, var(--sage-veil) 40%, rgba(11,11,11,.90) 55%, rgba(11,11,11,.96) 100%)}
.fcard figcaption{position:absolute;left:0;right:0;bottom:0;z-index:1;display:flex;flex-direction:column;gap:6px;padding:0 14px 14px}
.fcard .num{font:600 11px/1 var(--sans);letter-spacing:.18em;color:var(--sage-text)}
.fcard strong{font:600 16px/1.2 var(--sans);letter-spacing:-.01em}
.fcard .txt{font-size:13px;line-height:1.35;color:var(--mut-d)}
.fcard.rule strong{color:var(--sage-text)}
.fcard.rule .bar{display:block;width:24px;height:2px;background:var(--sage-text)}
@media (max-width:700px){
  .flow-label{margin-top:40px}
  .flow-cards{grid-template-columns:repeat(2,minmax(0,1fr));gap:16px}
  .fcard .txt{display:none}
  .fcard.rule .txt{display:block}
}

/* watch band: four talks, all four play; head centered (operator, 2026-09-02: "who is taught in the room, that's maybe centered") */
.watch .band-head,.watch .sub-head{text-align:center}
.watch .sub-head{margin-left:auto;margin-right:auto}
.talks{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:16px}
@media (max-width:900px){
  .talks{display:flex;gap:14px;overflow-x:auto;scroll-snap-type:x mandatory;margin:0 calc(var(--gut) * -1);padding:0 var(--gut) 6px;scrollbar-width:none}
  .talks::-webkit-scrollbar{display:none}
  .talks{scroll-padding-inline:var(--gut)} /* 2026-09-16: the snap honors the gutter, so the first card is not edge to edge */
  .talk{flex:0 0 78%;scroll-snap-align:start}
}
.talk{display:flex;flex-direction:column;gap:12px;text-decoration:none;background:var(--panel);border-radius:var(--r);overflow:hidden;padding-bottom:14px}
.talk .media{position:relative;aspect-ratio:16/9;background:var(--ground);display:block}
.talk .media img{width:100%;height:100%;object-fit:cover;transition:opacity .2s}
.talk .media iframe{position:absolute;inset:0;width:100%;height:100%;border:0}
.talk.playing .media img{opacity:0}
.talk .who{display:flex;flex-direction:column;gap:2px;padding:0 14px}
.talk .who strong{font:600 16px/1.25 var(--sans)}
.talk .who span{font-size:14px;color:var(--mut-d)}
.talk-cta{padding:0 14px;font:600 12px/1 var(--sans);letter-spacing:.08em;text-transform:uppercase;color:var(--sage-text)}

/* faq: opens on doubt */
.q{border-top:1px solid rgba(17,17,17,.14);padding:4px 0}
.q:last-of-type{border-bottom:1px solid rgba(17,17,17,.14)}
.q summary{cursor:pointer;list-style:none;font:500 clamp(18px,1.6vw,22px)/1.3 var(--sans);padding:16px 44px 16px 0;position:relative}
.q summary::-webkit-details-marker{display:none}
.q summary::after{content:"+";position:absolute;right:4px;top:10px;font:300 30px/1 var(--display);color:var(--sage-deep)}
.q[open] summary::after{content:"\2212"}
.q p{margin:0 0 18px;color:var(--mut-l);max-width:62ch;font-size:17px}

/* calendar band: the next event as one card, read from events.json like every other event surface */
.calendar .band-head{margin-bottom:22px;text-align:center}
/* round 4 (operator: "tighten up the section between questions people ask before they come and when the room meets
   next"): the two light bands share one breath, 40 under the last question and 32 over the calendar head, 72 against
   the 192 two full paddings gave. The gate's faqGap holds the distance under 120. */
.faq{padding:48px 0 var(--pad)}
.calendar{padding-top:var(--pad)}
/* the full event card (round 2, round 3) as a command-center read (round 4, operator: "add just some different colors to
   it or make it just a little bit more modern and like command center information"): a status strip across the top on
   the sage veil (status, date, doors, venue, cost, each a key over a value), the poster beside the columns, the panel
   and the schedule on their own veiled panels, the schedule as a timeline with tabular times in sage. Every color is a
   token or a token at alpha; sage stays trace weight (keys, times, one status word), never a control. The poster still
   sets the columns' row: at 1440 the card's inner width is 1344, so three columns get (1344 - 320 - 84) / 3 = 313 each
   beside the 320 poster, which is 414 tall (1000 by 1294); the gate's evCardHeight holds the row at the poster's height
   and every column's content under 416. Stacked under 900 with the poster at its natural height. */
.ev-card{background:var(--ground);color:var(--ink-d);border-radius:var(--r);padding:20px 28px 26px;display:grid;grid-template-columns:320px repeat(3,minmax(0,1fr));grid-template-rows:auto minmax(0,1fr);gap:22px 28px;align-items:stretch}
.ev-card[data-cols="3"]{grid-template-columns:320px repeat(2,minmax(0,1fr))}
.ev-card[data-cols="2"]{grid-template-columns:320px minmax(0,1fr)}
.ev-card p{margin:0}
.ev-card.on-dark{background:var(--panel);margin-top:8px}
.ev-strip{grid-column:1/-1;display:flex;flex-wrap:wrap;gap:12px 40px;padding:14px 18px;border-radius:var(--rs);background:var(--sage-veil)}
.ev-stat{display:flex;flex-direction:column;gap:4px;min-width:0}
.ev-k{font:600 10px/1 var(--sans);letter-spacing:.16em;text-transform:uppercase;color:var(--sage-text)}
.ev-v{font:600 15px/1.25 var(--sans);font-variant-numeric:tabular-nums;white-space:nowrap}
.ev-v.ev-status{color:var(--sage-text)}
.ev-card .ev-cover{border-radius:var(--rs);overflow:hidden;background:var(--panel);height:100%}
.ev-card .ev-cover img{width:100%;height:100%;object-fit:cover;display:block}
.ev-main,.ev-panel,.ev-side{display:flex;flex-direction:column;gap:8px;min-width:0}
.ev-panel,.ev-side{background:rgba(75,90,67,.14);border-radius:var(--rs);padding:16px 16px 14px}
.ev-main .ev-actions{margin-top:auto}
.ev-card .fact-label{color:var(--sage-text)}
.ev-title{font:600 clamp(24px,2.4vw,32px)/1.15 var(--sans);letter-spacing:-.02em;margin:0}
.ev-venue{color:var(--mut-d)}
.ev-summary{font-size:17px;line-height:1.55;max-width:62ch;margin:6px 0 0}
.ev-panel ul,.ev-schedule{list-style:none;margin:2px 0 0;padding:0;display:flex;flex-direction:column;gap:0}
.ev-panel li{display:flex;flex-direction:column;gap:1px;padding:7px 0;border-top:1px solid rgba(159,176,143,.18)}
.ev-panel li:first-child{border-top:0;padding-top:2px}
.ev-panel strong{font:600 15px/1.3 var(--sans)}
.ev-panel span,.ev-schedule span,.ev-line{font-size:14px;color:var(--mut-d)}
.ev-schedule li{display:grid;grid-template-columns:86px minmax(0,1fr);gap:10px;padding:8px 0;border-top:1px solid rgba(159,176,143,.18)}
.ev-schedule li:first-child{border-top:0;padding-top:2px}
.ev-schedule time{font:600 13px/1.4 var(--sans);color:var(--sage-text);font-variant-numeric:tabular-nums;white-space:nowrap}
@media (max-width:900px){.ev-card,.ev-card[data-cols="3"],.ev-card[data-cols="2"]{grid-template-columns:1fr;grid-template-rows:none;gap:18px}.ev-card .ev-cover{height:auto}.ev-card .ev-cover img{height:auto}.ev-strip{gap:10px 26px}}
.ev-meta{display:flex;flex-wrap:wrap;gap:6px 18px;color:var(--mut-d);font-size:16px}
.ev-actions{display:flex;flex-wrap:wrap;align-items:center;gap:12px 22px;padding-top:10px}
.ev-note{margin:18px 0 0;color:var(--mut-l);font-size:15px}

/* closing and the footer revealed behind it. The closing band is centered (operator, 2026-09-02: "The call
   to action needs to be centered") and never shorter than the footer it reveals: the four-column footer
   measures 535 at 1440 (gate field footH); 572 is three rows of 180 plus two gaps of 16, and clears it. The
   gate's footerOverlap check holds this line. */
/* the wall (round 3, operator: "three rows where the full background is an image: one row going to the right,
   the next row going to the left, the bottom row going to the right. Maybe at all kinds of different speeds"):
   the band's whole background, three rows of the room's own frames on the roster keyframe, no tilt, no caption,
   no scrim on the frames. Speeds top to bottom 19.5, 26 and 34.5 px/s (207, 155 and 117 seconds per 4032px
   set of twelve), the middle row reversed: on a wall of planes nearer is faster, so the bottom row runs at the
   roster's speed and the top at half of it; nothing runs faster than the roster. Frames 320 by 180 at 1440
   and 240 by 135 under 700. The copy sits on its own panel above the wall (below). */
#gallery{position:absolute;inset:0;display:flex;flex-direction:column;justify-content:center;gap:16px;z-index:0;padding:0}
#gallery .mq-row{transform:none;margin:0;z-index:0;-webkit-mask-image:none;mask-image:none}
/* rows one and three declare their direction: the roster rule .mq-row + .mq-row reverses every following row otherwise (phase 7 repair, 2026-09-03) */
#gallery .mq-row:nth-child(1) .mq-track{animation-duration:calc(var(--n) * 336s / 19.5);animation-direction:normal;animation-delay:-13s}
#gallery .mq-row:nth-child(2) .mq-track{animation-duration:calc(var(--n) * 336s / 26);animation-direction:reverse;animation-delay:-29s}
#gallery .mq-row:nth-child(3) .mq-track{animation-duration:calc(var(--n) * 336s / 34.5);animation-direction:normal;animation-delay:-41s}
#gallery figure{margin:0 16px 0 0;flex:0 0 320px;width:320px;position:relative}
#gallery .gph{width:100%;aspect-ratio:16/9;border-radius:var(--r);overflow:hidden;background:var(--panel);position:relative}
#gallery img{width:100%;height:100%;object-fit:cover;filter:saturate(.86) contrast(1.06)}
@media (max-width:700px){
  #gallery figure{flex-basis:240px;width:240px}
  #gallery .mq-row:nth-child(1) .mq-track{animation-duration:calc(var(--n) * 256s / 19.5)}
  #gallery .mq-row:nth-child(2) .mq-track{animation-duration:calc(var(--n) * 256s / 26)}
  #gallery .mq-row:nth-child(3) .mq-track{animation-duration:calc(var(--n) * 256s / 34.5)}
}
.closing{position:relative;z-index:1;min-height:572px;overflow:hidden;display:flex;align-items:center;justify-content:center;padding:64px 0}
/* the copy's panel (round 3): centered over the wall, tinted glass. The tint is the contrast floor: a lit frame
   reaches about .69 luminance after a 24px blur, .69 x (1 - .90) = .069, which rates 8.0 against --ink-d; the
   gate's closingContrast reads it off the pixels at three fixed offsets of the tracks. The eyebrow and the sub
   line set in --ink-d here: at .90 the muted ink rates 3.8 and the sage 3.9, both under 4.5. */
.close-panel{position:relative;z-index:1;max-width:800px;margin:0 auto;padding:40px 48px;border-radius:var(--r);background:rgba(11,11,11,.90);-webkit-backdrop-filter:blur(24px);backdrop-filter:blur(24px);text-align:center}
/* Recap-page CTA: the blue sky with clouds lives ONLY inside the "Come to the next one" container (operator:
   "the clouds should only be in the container and that one be parallax"). The sky is painted as the panel's own
   background with background-attachment:fixed, so it is pinned to the viewport while the panel scrolls over it,
   and overflow:hidden + the panel's border-radius CLIP it to the rounded box, so no sky bleeds into the section
   around it. Fixed attachment needs no transform/filter/backdrop-filter on the panel or any ancestor, so the
   panel's blur is dropped here (there is nothing behind it to frost anymore). A dark scrim over the sky keeps the
   white CTA text legible. Works in every desktop browser with no scroll listener; mobile and reduced motion fall
   back to a static (scroll-attached) sky, still clipped to the container. */
.talk-close .close-panel{overflow:hidden;-webkit-backdrop-filter:none;backdrop-filter:none;
  background-color:#0b1220;
  background-image:linear-gradient(rgba(8,11,18,.55),rgba(8,11,18,.72)),url(img/sky-clouds.jpg);
  background-size:cover;background-position:center;background-attachment:fixed}
@media (max-width:700px){.talk-close .close-panel{background-attachment:scroll}}
@media (prefers-reduced-motion:reduce){.talk-close .close-panel{background-attachment:scroll}}
.close-panel .eyebrow,.close-panel .sub-head{color:var(--ink-d)}
.close-panel .sub-head{margin-left:auto;margin-right:auto}
.close-panel .band-head{margin-bottom:10px}
/* the closing clock (round 4): the same shell as card 1, centered, the labels in ink so they clear 4.5 on the .90 panel */
.close-panel .countdown{align-items:center;margin:2px auto 24px}
.close-panel .cd-row{justify-content:center}
.close-panel .cd-label,.close-panel .cd-l{color:var(--ink-d);opacity:.78}
.foot{position:sticky;bottom:0;z-index:0;background:var(--panel);color:var(--ink-d);padding:56px 0 0}
@media (max-width:700px){.foot{position:static}.closing{min-height:437px;padding:56px 0}.close-panel{padding:28px 20px}}
.foot-mark{font:800 clamp(38px,6.5vw,88px)/1 var(--logo);letter-spacing:-.02em;margin:0 0 28px}
/* four columns routing every page (2026-09-02); heads in --mut-d, 7.97:1 on --panel where --sage-deep measures 3.46:1 */
.foot-grid{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:28px 24px;margin-bottom:34px}
@media (max-width:700px){.foot-grid{grid-template-columns:repeat(2,minmax(0,1fr))}}
.foot-head{color:var(--mut-d);margin:0 0 12px}
.foot-links{display:flex;flex-direction:column;gap:10px;font-weight:500}
.foot-links a{text-decoration:none;opacity:.9}
.chips{list-style:none;margin:0 0 26px;padding:0;display:flex;flex-wrap:wrap;gap:10px}
.chip{width:120px;height:48px;border-radius:var(--rs);background:var(--light);display:flex;align-items:center;justify-content:center;padding:10px 12px}
.chip img{max-width:100%;max-height:100%;object-fit:contain;width:auto;height:auto}
.chip-text{font:600 10.5px/1.2 var(--sans);letter-spacing:.04em;color:var(--ink-l);text-align:center;text-transform:uppercase}
.chips.big{margin:24px 0}
.chips.big .chip{width:150px;height:60px}
.foot-host{margin:0 0 6px;color:var(--mut-d);font-size:15px}
.foot-line{margin:0;color:var(--mut-d);font-size:14px}
/* copyright bar: full-bleed true-black strip, standard notice left, "Powered by SwarmSystem" right */
.foot-legal{background:#000;margin-top:44px;padding:20px 0}
.foot-legal-row{display:flex;flex-wrap:wrap;gap:8px 24px;align-items:center;justify-content:space-between}
.foot-copy,.foot-powered{margin:0;font:500 13px/1.5 var(--sans);color:var(--mut-d)}
.foot-powered a{color:var(--ink-d);text-decoration:none;border-bottom:1px solid transparent;transition:border-color .15s ease}
.foot-powered a:hover{border-bottom-color:var(--sage-text)}
@media (max-width:560px){.foot-legal-row{justify-content:center;text-align:center}}
/* "Powered by SwarmSystem" carries the one SwarmSystem mark on this client site: a small live red pulse.
   Brand red #dc2626, halo alpha <= .30, 4s calm breath, static under reduced motion (the ambient law). */
.foot-legal{position:relative;overflow:hidden}
.foot-legal-row{position:relative;z-index:1}
/* the SwarmSystem mark: a small red hexagon beside the credit. Brand red #dc2626, a 4s calm
   pulse, static under reduced motion (the ambient law). The Field 4 Throughput background field
   was removed for launch so the footer stays light; only the hexagon remains. */
.foot-powered{display:inline-flex;align-items:center;gap:8px}
.foot-powered::before{content:"";flex:none;width:10px;height:10px;background:#dc2626;
  clip-path:polygon(25% 5%,75% 5%,100% 50%,75% 95%,25% 95%,0 50%);animation:sw-hex 4s ease-in-out infinite}
@keyframes sw-hex{0%,100%{opacity:.6;transform:scale(.9)}50%{opacity:1;transform:scale(1)}}
.foot-nap{margin:10px 0 0;font-style:normal;color:var(--mut-d);font-size:14px;line-height:1.55}
.foot-nap .foot-nap-name{color:var(--ink-d);font-weight:600}
@media (prefers-reduced-motion:reduce){.foot-powered::before{animation:none}}
/* Breadcrumbs: a quiet trail under the nav on every interior page, for best-practice navigation */
.crumbs{padding:16px 0 0}
.crumbs ol{list-style:none;margin:0;padding:0;display:flex;flex-wrap:wrap;align-items:center;gap:6px 8px;font:500 13.5px/1.3 var(--sans)}
.crumbs li{display:flex;align-items:center;gap:6px 8px;color:var(--mut-d)}
.crumbs li+li::before{content:"/";color:var(--sage-deep)}
.crumbs a{color:var(--mut-d);text-decoration:none;transition:color .15s ease}
.crumbs a:hover{color:var(--sage-text)}
.crumbs li[aria-current="page"]{color:var(--ink-d)}

/* holding pages, and the calendar page's first band (no 72vh floor: the talks follow right under the card) */
.holding{min-height:72vh;padding-top:64px}
.cal-next{padding-top:64px;padding-bottom:48px}
.holding .band-head{font:500 clamp(28px,3.4vw,44px)/1.08 var(--sans)}
.hold-fig{margin:24px 0;border-radius:var(--r);overflow:hidden;background:var(--panel)}
.hold-fig img{width:100%;height:auto}

/* the speaker page (round 4, operator: "build a speaker page that has the video at the top, has a summary, and then kind
   of writes a blog page"): one page per speaker at /speakers/<slug>/, rendered from design-refs/talks/<slug>.json. The
   video first on the ground, as the poster with one play control that swaps in the player on demand (never autoplay;
   with JS off the poster is a link to YouTube); the summary and the takeaways on the light; the writeup as a reading
   measure with pull quotes; the speaker and the closing on the ground. The talk page is the video's one home on the
   site; an event page, later, links here. The gate's talkPage reads the shape. */
.talk-hero{padding-top:40px;padding-bottom:56px}
.talk-crumb{font:600 13px/1 var(--sans);letter-spacing:.02em;color:var(--mut-d);text-decoration:none;display:inline-block;margin-bottom:22px}
/* the event-page H1 spans the full column width (operator): no max-width, no balance (so the lines
   run edge to edge instead of being centered short), and a larger clamp so the type fills the column */
.talk-hero h1{font:300 clamp(40px,6.2vw,92px)/1.02 var(--display);letter-spacing:-.02em;margin:0 0 16px;max-width:none;padding-bottom:.08em}
.talk-hero .talk-line{font-size:18px;color:var(--mut-d);max-width:60ch;margin:0 0 28px}
.talk-hero .talk-line strong{color:var(--ink-d);font-weight:600}
.player{position:relative;aspect-ratio:16/9;border-radius:var(--r);overflow:hidden;background:var(--panel);box-shadow:inset 0 0 0 1px rgba(255,255,255,.10)}
.player img{width:100%;height:100%;object-fit:cover}
.player iframe{position:absolute;inset:0;width:100%;height:100%;border:0}
.player .play{position:absolute;inset:0;display:flex;align-items:center;justify-content:center;background:linear-gradient(to top, rgba(11,11,11,.55) 0%, rgba(11,11,11,.10) 40%, rgba(11,11,11,0) 100%);text-decoration:none;border:0;cursor:pointer;padding:0;font:inherit;color:inherit}
.player .play .btn{pointer-events:none}
.js .player a.play{display:none}
.nojs .player button.play{display:none}
.talk-meta{display:flex;flex-wrap:wrap;gap:8px 24px;margin:16px 0 0;font-size:14px;color:var(--mut-d)}
.talk-meta a{color:var(--sage-text);font-weight:600;text-decoration:none}
.talk-summary{padding:64px 0 40px}
.talk-summary .band-head{font:300 clamp(28px,3vw,40px)/1.1 var(--display);margin-bottom:18px}
.talk-summary .lede{font:300 clamp(20px,1.7vw,24px)/1.45 var(--display);margin:0 0 30px;letter-spacing:-.005em}
.takeaways-head{font:600 12px/1 var(--sans);letter-spacing:.16em;text-transform:uppercase;color:var(--sage-text);margin:38px 0 18px}
.takeaways{list-style:none;margin:8px 0 0;padding:0;display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:16px}
/* "Tools and resources mentioned" and "Top three action items": small linked cards under the summary */
.action-sub{color:var(--mut-d);margin:0 0 18px;font-size:15px;line-height:1.5}
.tool-grid{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:16px;margin:0}
.tool-card{display:flex;flex-direction:column;align-items:flex-start;gap:8px;padding:20px;border-radius:var(--r);text-decoration:none;color:inherit;transition:transform .18s ease, box-shadow .18s ease}
.tool-card:hover{transform:translateY(-3px)}
.tool-mark{display:inline-flex;align-items:center;justify-content:center;width:40px;height:40px;border-radius:10px;background:rgba(159,176,143,.16);color:var(--sage-text);font:400 15px/1 var(--logo);letter-spacing:-.01em;box-shadow:inset 0 0 0 1px rgba(159,176,143,.30)}
.tool-kind{font:600 10px/1 var(--sans);letter-spacing:.16em;text-transform:uppercase;color:var(--mut-d)}
.tool-name{margin:0;font:600 17px/1.2 var(--sans);letter-spacing:-.01em;color:var(--ink-d)}
.tool-what{margin:0;font-size:14px;line-height:1.5;color:#cfcfca}
.tool-use{margin:2px 0 0;font-size:13px;line-height:1.5;color:var(--mut-d)}
.tool-use span{display:block;font:600 10px/1 var(--sans);letter-spacing:.14em;text-transform:uppercase;color:var(--sage-text);margin-bottom:5px}
.tool-link{margin-top:auto;padding-top:8px;display:inline-flex;align-items:center;gap:6px;font:600 13px/1 var(--sans);color:var(--sage-text)}
.tool-link svg{transition:transform .15s ease}
.tool-card:hover .tool-link svg{transform:translateX(2px)}
@media (max-width:900px){.tool-grid{grid-template-columns:repeat(2,minmax(0,1fr))}}
@media (max-width:520px){.tool-grid{grid-template-columns:1fr}}
/* Speaker ventures size to the real count so a speaker with two or three ventures fills the row
   instead of leaving empty columns. Distel's four-card grid keeps the plain .tool-grid rule above. */
.tool-grid.tg-3{grid-template-columns:repeat(3,minmax(0,1fr))}
.tool-grid.tg-2{grid-template-columns:repeat(2,minmax(0,1fr));max-width:680px}
.tool-grid.tg-1{grid-template-columns:minmax(0,1fr);max-width:420px}
@media (max-width:900px){.tool-grid.tg-3,.tool-grid.tg-2{grid-template-columns:repeat(2,minmax(0,1fr));max-width:none}}
@media (max-width:520px){.tool-grid.tg-3,.tool-grid.tg-2{grid-template-columns:1fr}}
.action-grid{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:16px}
.action-card{display:flex;flex-direction:column;gap:10px;padding:22px 22px 24px;border-radius:var(--r)}
.action-num{font:600 12px/1 var(--sans);letter-spacing:.16em;color:var(--sage-text)}
.action-title{margin:0;font:600 18px/1.25 var(--sans);letter-spacing:-.01em;color:var(--ink-d)}
.action-step{margin:0;font-size:14.5px;line-height:1.55;color:#cfcfca}
@media (max-width:760px){.action-grid{grid-template-columns:1fr}}
.takeaways li{list-style:none;padding:22px 22px 24px;font-size:15px;line-height:1.55;color:#c9c9c4}
.takeaways li .tk-num{display:block;font:600 12px/1 var(--sans);letter-spacing:.14em;color:var(--sage-text);margin-bottom:14px}
.takeaways li strong{display:block;font:600 17px/1.3 var(--sans);letter-spacing:-.01em;margin-bottom:6px;color:var(--ink-d)}
.talk-body{padding:20px 0 8px}
.talk-body h2{font:500 clamp(22px,2.2vw,30px)/1.2 var(--sans);letter-spacing:-.015em;margin:40px 0 12px;color:var(--ink-d)}
.talk-body>h2:first-child{margin-top:8px}
.talk-body p{font-size:18px;line-height:1.68;margin:0 0 18px;color:#cfcfca}
.talk-body blockquote{margin:26px 0;padding:0 0 0 22px;border-left:2px solid var(--sage-deep);font:300 clamp(21px,1.9vw,27px)/1.35 var(--display);letter-spacing:-.005em;color:var(--ink-d)}
.talk-body blockquote p{font:inherit;margin:0;color:inherit}
.talk-body blockquote footer{font:600 13px/1.3 var(--sans);color:var(--mut-d);margin-top:10px;letter-spacing:.02em}
.talk-note{font-size:14px;color:var(--mut-d);margin:32px 0 0}
/* Long-form article body + AEO blocks (2026-09-15): the writeup is now the page's primary content, visible and
   crawlable, structured with question headings for search and answer engines. */
.talk-article{padding:8px 0 16px}
.talk-article .talk-body{padding:0}
.talk-article .talk-body h2{scroll-margin-top:92px}
.talk-answer{font:400 19px/1.6 var(--sans);color:#e6e6e2;margin:0 0 30px}
.talk-answer strong{color:var(--ink-d)}
.talk-toc{margin:0 0 40px;padding:20px 24px}
.talk-toc .toc-head{margin:0 0 12px;font:600 12px/1 var(--sans);letter-spacing:.14em;text-transform:uppercase;color:var(--sage-text)}
.talk-toc ul{list-style:none;margin:0;padding:0;display:flex;flex-wrap:wrap;gap:8px 10px}
.talk-toc a{font:500 14px/1 var(--sans);color:var(--mut-d);text-decoration:none;padding:9px 15px;border-radius:999px;box-shadow:inset 0 0 0 1px rgba(255,255,255,.14);transition:color .15s ease, box-shadow .15s ease}
.talk-toc a:hover{color:var(--ink-d);box-shadow:inset 0 0 0 1px rgba(255,255,255,.30)}
.talk-faq{padding:8px 0 8px}
.talk-faq .band-head{margin-bottom:22px}
/* home FAQ hands off to the full page; the FAQ page groups its questions under small labels (2026-09-16) */
.faq-more{margin:28px 0 0;text-align:center}
.faq-page{padding:40px 0 56px}
.faq-page .faq-group{margin:44px 0 6px;font:600 12px/1 var(--sans);letter-spacing:.16em;text-transform:uppercase;color:var(--sage-deep)}
.faq-page .faq-group:first-child{margin-top:12px}
.faq-page .q p a{color:var(--sage-deep);font-weight:600;text-decoration:none;border-bottom:1px solid var(--sage-deep)}
/* sponsors page: the venture-card pattern from the speaker pages, with the sponsor logo as the mark (2026-09-16) */
.spon-logo{display:inline-flex;align-items:center;justify-content:center;width:124px;height:56px;border-radius:10px;background:var(--light);padding:8px 12px}
.spon-logo img{max-width:100%;max-height:100%;width:auto;height:auto;object-fit:contain;display:block}
.spon-logo.spon-text{font:600 10.5px/1.25 var(--sans);letter-spacing:.06em;text-transform:uppercase;color:var(--ink-l);text-align:center}
.spon-grid .tool-card{padding:22px}
.spon-grid .tool-what{color:#d6d6d0}
.spon-grid .tool-use+.tool-use{margin-top:8px}
.spon-grid .tool-use a{color:var(--sage-text);font-weight:600;text-decoration:none}
.spon-grid a.tool-link{text-decoration:none}
.spon-grid a.tool-link:hover svg{transform:translateX(2px)}
.spon-note{padding:8px 0 24px}
.spon-note p{font-size:18px;line-height:1.6;max-width:62ch;margin:0 0 14px;color:#cfcfca}
.spon-note .wrap{text-align:center}
.spon-note p{margin-left:auto;margin-right:auto}
/* contact page: one form on the left, two short cards on the right; inputs sit on the dark panel (2026-09-16) */
.contact{padding-top:8px}
.contact-grid{display:grid;grid-template-columns:minmax(0,1fr) 320px;gap:24px;align-items:start}
.cf-form,.cf-done{position:relative;padding:32px}
.cf-row{display:grid;grid-template-columns:1fr 1fr;gap:16px}
.cf-field{display:block;margin:0 0 18px;font:600 13px/1.3 var(--sans);letter-spacing:.02em;color:var(--mut-d)}
.cf-field small{font-weight:400;opacity:.7}
.cf-field input,.cf-field select,.cf-field textarea{display:block;width:100%;margin-top:8px;padding:12px 14px;font:400 16px/1.4 var(--sans);color:var(--ink-d);background:rgba(255,255,255,.04);border:1px solid rgba(255,255,255,.14);border-radius:var(--rs);outline:none;transition:border-color .15s ease,background .15s ease}
.cf-field select{appearance:none;-webkit-appearance:none;padding-right:40px;cursor:pointer;background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23a9a9a5' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M6 9l6 6 6-6'/%3E%3C/svg%3E");background-repeat:no-repeat;background-position:right 14px center;background-size:16px 16px}
.cf-field select option{background:var(--panel);color:var(--ink-d)}
.cf-field textarea{min-height:150px;resize:vertical}
.cf-field input:focus,.cf-field select:focus,.cf-field textarea:focus{border-color:var(--sage-text);background:rgba(255,255,255,.06)}
.cf-field input::placeholder,.cf-field textarea::placeholder{color:var(--mut-d);opacity:.6}
.cf-hp{position:absolute;left:-9999px;width:1px;height:1px;overflow:hidden}
.cf-consent{margin:0 0 20px;font-size:14px;line-height:1.5;color:var(--mut-d)}
.cf-actions{display:flex;align-items:center;gap:16px;flex-wrap:wrap;margin:0}
.cf-actions .btn:disabled{opacity:.6;cursor:wait;transform:none}
.cf-err{font-size:14px;line-height:1.4;color:#e2b4a8}
.cf-done h2{font:500 clamp(24px,2.6vw,34px)/1.12 var(--sans);letter-spacing:-.01em;margin:0 0 12px}
.cf-done p{max-width:52ch;color:var(--mut-d)}
.cf-done .btn{margin-top:8px}
.cf-side{display:grid;gap:16px}
.cf-card{padding:24px}
.cf-card .eyebrow{margin-bottom:10px}
.cf-card p{margin:0 0 12px;font-size:16px;line-height:1.55;color:var(--mut-d)}
@media (max-width:900px){.contact-grid{grid-template-columns:1fr}}
@media (max-width:600px){.cf-row{grid-template-columns:1fr;gap:0}.cf-form,.cf-done{padding:24px 18px}}
.faq-list{display:grid;gap:14px}
.faq-item{padding:24px 28px}
.faq-item h3{margin:0 0 8px;font:600 18px/1.32 var(--sans);letter-spacing:-.01em;color:var(--ink-d)}
.faq-item p{margin:0;font-size:16px;line-height:1.6;color:#cfcfca}
@media (max-width:700px){.faq-item{padding:20px 20px}.talk-toc{padding:18px 18px}}
/* Related speakers: a compact 4-up cross-link to other people who have taken the mic, for awareness and internal
   links. Cards link to the speaker's spot on the hub. Surface-only glass, same as the rest of the recap page. */
.talk-related{padding:64px 0 8px}
.talk-related .band-head{margin-bottom:6px}
.talk-related .rel-sub{color:var(--mut-d);margin:0 0 26px;font-size:16px;line-height:1.55}
.rel-grid{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:16px}
.rel-grid.rg-3{grid-template-columns:repeat(3,minmax(0,1fr))}
.rel-card{display:flex;flex-direction:column;padding:14px;border-radius:var(--r);text-decoration:none;color:inherit;transition:transform .18s ease, box-shadow .18s ease}
.rel-card:hover{transform:translateY(-3px)}
.rel-photo{aspect-ratio:1;border-radius:10px;overflow:hidden;background:var(--ground);margin-bottom:14px;box-shadow:inset 0 0 0 1px rgba(255,255,255,.08)}
.rel-photo img{width:100%;height:100%;object-fit:cover;object-position:center 22%;filter:saturate(.88) contrast(1.05)}
.rel-name{margin:0 0 3px;font:600 16px/1.2 var(--sans);letter-spacing:-.01em;color:var(--ink-d)}
.rel-role{margin:0;font:500 13px/1.4 var(--sans);color:var(--sage-text)}
.rel-cta{margin-top:12px;display:inline-flex;align-items:center;gap:6px;font:600 13px/1 var(--sans);color:var(--mut-d);transition:color .15s ease}
.rel-card:hover .rel-cta{color:var(--ink-d)}
.rel-cta svg{transition:transform .15s ease}
.rel-card:hover .rel-cta svg{transform:translateX(2px)}
.rel-all{margin:34px 0 0;text-align:center}
.spk{scroll-margin-top:90px}
@media (max-width:900px){.rel-grid,.rel-grid.rg-3{grid-template-columns:repeat(2,minmax(0,1fr))}}
@media (max-width:520px){.rel-grid,.rel-grid.rg-3{grid-template-columns:1fr}}
.talk-speaker{padding:64px 0}
.speaker-row{display:grid;grid-template-columns:160px minmax(0,1fr);gap:28px;align-items:center}
.speaker-row .ph{aspect-ratio:1;border-radius:var(--r);overflow:hidden;background:var(--panel)}
.speaker-row .ph img{width:100%;height:100%;object-fit:cover;object-position:center 30%;filter:saturate(.86) contrast(1.06)}
.speaker-row h2{font:600 clamp(22px,2.2vw,30px)/1.15 var(--sans);letter-spacing:-.015em;margin:0 0 6px}
.speaker-row p{margin:0 0 12px;color:var(--mut-d);max-width:60ch}
.speaker-row .links{display:flex;flex-wrap:wrap;gap:8px 22px;font-size:15px}
.talk-close{padding:72px 0 88px;text-align:center}
.talk-close .band-head{margin-bottom:8px}
.talk-close .sub-head{margin-left:auto;margin-right:auto;margin-bottom:22px}
/* Speaker page only (scoped by data-band, so event recaps are untouched):
   left-align the in-body "watch his talk" button with more space above it,
   and add top separation to the closing CTA below the related speakers grid. */
[data-band="speaker-bio"] .rel-all{margin-top:52px;text-align:left}
[data-band="speaker-cta"].talk-close{padding-top:112px}
/* Recap page glass content cards (2026-09-15): surface-only glass over the flat black ground, no per-element
   refract, because nothing sits behind them to bend (the speakers-hub call). The sheen and the lit bevel are
   what read as glass over the dark ground; base is a solid --panel for Safari and reduced transparency. */
.g-card{background:var(--panel);border-radius:var(--r);box-shadow:inset 0 0 0 1px rgba(255,255,255,.10), inset 0 1px 0 rgba(255,255,255,.06)}
:root.glassy .g-card{
  background-color:rgba(22,22,22,.58);
  background-image:linear-gradient(135deg,rgba(255,255,255,.07) 0%,rgba(255,255,255,.025) 18%,rgba(255,255,255,0) 42%),
                   linear-gradient(to top,rgba(255,255,255,.025) 0%,rgba(255,255,255,0) 34%);
  box-shadow:inset 0 0 0 1px rgba(255,255,255,.07),
             inset 0 1px 0 rgba(255,255,255,.18),
             inset 1px 0 0 rgba(255,255,255,.07),
             inset 0 -1px 0 rgba(255,255,255,.05),
             inset 0 -24px 30px -28px rgba(0,0,0,.45)}
/* the event fact strip under the player: reuses the .fact layout, glassed with .g-card (never .glass, so
   app.js does not spend a displacement filter refracting flat black). */
.talk-facts{margin-top:22px}
/* one featured quote between the summary and the takeaways, in the serif promise voice */
.talk-pull{margin:30px 0 6px;padding:0 0 0 24px;border-left:2px solid var(--sage-deep)}
.talk-pull p{font:300 clamp(24px,2.6vw,34px)/1.26 var(--display);letter-spacing:-.01em;color:var(--ink-d);margin:0}
.talk-pull footer{font:600 13px/1.3 var(--sans);color:var(--mut-d);margin-top:12px;letter-spacing:.02em}
/* the full writeup folds away by default so the page stays digestible; native details, works with JS off */
.talk-deep{margin-top:52px}
.talk-deep>summary{list-style:none;cursor:pointer;display:inline-flex;align-items:center;gap:10px;font:600 15px/1 var(--sans);color:var(--ink-d);padding:13px 22px;border-radius:999px;background:rgba(24,24,24,.66);box-shadow:inset 0 0 0 1px rgba(255,255,255,.16), inset 0 1px 0 rgba(255,255,255,.10);transition:background .15s ease, box-shadow .15s ease}
.talk-deep>summary::-webkit-details-marker{display:none}
:root.glassy .talk-deep>summary{background-image:linear-gradient(135deg,rgba(255,255,255,.20) 0%,rgba(255,255,255,0) 60%)}
.talk-deep>summary:hover{background-color:rgba(34,34,34,.78);box-shadow:inset 0 0 0 1px rgba(255,255,255,.26), inset 0 1px 0 rgba(255,255,255,.14)}
.talk-deep>summary .chev{transition:transform .2s ease}
.talk-deep[open]>summary .chev{transform:rotate(180deg)}
/* speaker and close read as glassed panels on the black ground */
.talk-speaker .speaker-row{padding:28px 32px;grid-template-columns:260px minmax(0,1fr);align-items:center}
.talk-speaker .speaker-row .ph{aspect-ratio:1;height:auto;min-height:0}
.talk-speaker .speaker-row p{max-width:none}
.talk-speaker .speaker-row>div:last-child{display:flex;flex-direction:column;justify-content:center}
.talk-close-panel{padding:48px 40px}
@media (max-width:700px){.talk-speaker .speaker-row{padding:22px 20px;grid-template-columns:120px minmax(0,1fr);align-items:center}.talk-speaker .speaker-row .ph{aspect-ratio:1;height:auto;min-height:0}.talk-close-panel{padding:36px 22px}}
@media (max-width:900px){.takeaways{grid-template-columns:repeat(2,minmax(0,1fr))}}
@media (max-width:700px){.takeaways{grid-template-columns:1fr}.speaker-row{grid-template-columns:96px minmax(0,1fr);gap:16px}.talk-hero h1{max-width:none}.talk-hero{padding-top:24px}}

/* motion off: every band keeps its finished state */
@media (prefers-reduced-motion:reduce){
  html{scroll-behavior:auto}
  *,*::before,*::after{transition:none!important;animation:none!important}
  /* the roster loop becomes a static wall: all seventeen render, none clipped, clones hidden */
  .mq-track{flex-wrap:wrap;width:auto;transform:none;justify-content:center;row-gap:16px;padding:0 var(--gut)}
  .mq-row,.mq-row + .mq-row{transform:none;margin-top:0;-webkit-mask-image:none;mask-image:none}
  /* the wall's three rows are three still, clipped lines offset by a third, never a ninety-frame wrap */
  #gallery .mq-track{flex-wrap:nowrap;width:max-content;transform:none;justify-content:flex-start;padding:0}
  .tile-clone,.frame-clone{display:none}
}

/* holding-page links (round 4): the talk pages that exist, listed on /speakers/ until that page is designed */
.hold-links{list-style:none;margin:0 0 20px;padding:0;display:flex;flex-direction:column;gap:10px;font-size:17px}

/* ============================================================================
   Speakers hub (2026-09-15). A sibling of the home page: same dark ground, same
   glass. Two glass treatments are used on purpose. The nav and the hero panel
   are .glass, so app.js refracts them over imagery the way the home hero cards
   refract over the room photo. The seventeen speaker cards are .glassy surface
   only (sheen, lit bevel, a light blur), never .refract: refraction pays off
   over a photo, and seventeen displacement filters over a flat band would cost
   a great deal to show almost nothing. The grid sits over a faint sage wash so
   the glass has something to sit above. Client tokens only.
   ============================================================================ */

/* Hero: a framed event photo with a glass copy panel, dimmed for legibility. */
.spk-hero{padding-top:20px;padding-bottom:clamp(30px,4vw,56px)}
.spk-stage{position:relative;border-radius:var(--r);overflow:hidden;min-height:clamp(320px,42vw,440px);display:flex;align-items:center;
  box-shadow:inset 0 0 0 1px rgba(255,255,255,.10), inset 0 1px 0 rgba(255,255,255,.06)}
.spk-stage>.bg{position:absolute;inset:0;width:100%;height:100%;object-fit:cover;object-position:center 42%;filter:saturate(.9) contrast(1.03) brightness(.7)}
.spk-stage::after{content:"";position:absolute;inset:0;pointer-events:none;
  background:linear-gradient(95deg, rgba(11,11,11,.82) 0%, rgba(11,11,11,.52) 46%, rgba(11,11,11,.18) 100%)}
.spk-hero-panel{position:relative;z-index:1;margin:clamp(18px,3vw,40px);max-width:600px;padding:30px 32px;border-radius:var(--r);background:var(--panel)}
.spk-hero-panel .eyebrow{color:var(--sage-text)}
.spk-hero-panel h1{margin:0 0 14px;font:300 clamp(30px,4.4vw,52px)/1.04 var(--display);letter-spacing:-.015em;text-wrap:balance}
.spk-hero-panel .sub{margin:0;font-size:clamp(17px,1.6vw,20px);line-height:1.5;color:var(--ink-d);max-width:46ch;opacity:.92}
.spk-hero-meta{margin:16px 0 0;font:600 13px/1 var(--sans);letter-spacing:.02em;color:var(--mut-d)}

/* Grid section: a faint sage wash gives the glass a backdrop on the flat band. */
.spk-section{position:relative;overflow:hidden}
.spk-section::before{content:"";position:absolute;inset:0;pointer-events:none;
  background:radial-gradient(120% 90% at 12% -10%, var(--sage-veil), transparent 52%),
             radial-gradient(90% 80% at 108% 118%, rgba(75,90,67,.16), transparent 50%)}
.spk-section .wrap{position:relative;z-index:1}
.spk-section .sub-head{margin-bottom:34px}

/* Three to a row on desktop, two on tablet, one on phone. */
.spk-grid{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:16px}

/* Card: photo up top, everything else below. Even padding on all four sides frames the
   photo instead of bleeding it to the edge. The .glassy surface, with a solid fallback
   where blur or transparency is off. */
.spk{position:relative;display:flex;flex-direction:column;padding:32px;border-radius:var(--r);
  background:rgba(22,22,22,.55);-webkit-backdrop-filter:blur(10px) saturate(1.2);backdrop-filter:blur(10px) saturate(1.2);
  box-shadow:inset 0 0 0 1px rgba(255,255,255,.10), inset 0 1px 0 rgba(255,255,255,.06);
  transition:transform .18s ease, box-shadow .18s ease}
@supports not ((backdrop-filter:blur(1px)) or (-webkit-backdrop-filter:blur(1px))){.spk{background:var(--panel)}}
:root.glassy .spk{background-color:rgba(22,22,22,.46);
  background-image:linear-gradient(135deg,rgba(255,255,255,.20) 0%,rgba(255,255,255,.06) 18%,rgba(255,255,255,0) 42%),
                   linear-gradient(to top,rgba(255,255,255,.07) 0%,rgba(255,255,255,0) 38%);
  box-shadow:inset 0 0 0 1px rgba(255,255,255,.10),
             inset 0 1px 0 rgba(255,255,255,.55),
             inset 1px 0 0 rgba(255,255,255,.18),
             inset 0 -1px 0 rgba(255,255,255,.12),
             inset 0 -20px 26px -24px rgba(0,0,0,.55)}
@media (prefers-reduced-transparency:reduce){.spk{background-color:var(--panel);background-image:none;-webkit-backdrop-filter:none;backdrop-filter:none}}
:root.glassy .spk-hero-panel.glass{background-color:rgba(11,11,11,.56);
  background-image:linear-gradient(135deg,rgba(255,255,255,.20) 0%,rgba(255,255,255,.06) 16%,rgba(255,255,255,0) 40%),
                   linear-gradient(to top,rgba(255,255,255,.06) 0%,rgba(255,255,255,0) 40%);
  box-shadow:inset 0 0 0 1px rgba(255,255,255,.10),
             inset 0 1px 0 rgba(255,255,255,.50),
             inset 0 -20px 28px -26px rgba(0,0,0,.60)}

.spk.has-talk{box-shadow:inset 0 0 0 1px var(--sage-veil), inset 0 1px 0 rgba(255,255,255,.06)}
:root.glassy .spk.has-talk{box-shadow:inset 0 0 0 1px rgba(159,176,143,.34),
             inset 0 1px 0 rgba(255,255,255,.55),
             inset 1px 0 0 rgba(255,255,255,.18),
             inset 0 -1px 0 rgba(255,255,255,.12),
             inset 0 -20px 26px -24px rgba(0,0,0,.55)}
@media (prefers-reduced-motion:no-preference){.spk:hover{transform:translateY(-3px)}}

/* Photo band across the top, inset by the card padding and rounded to match. A shorter
   crop keeps the image from dominating the card. */
.spk-photo{position:relative;aspect-ratio:1;border-radius:10px;overflow:hidden;background:var(--ground);
  box-shadow:inset 0 0 0 1px rgba(255,255,255,.08)}
.spk-face{width:100%;height:100%;object-fit:cover;object-position:center 22%;
  filter:saturate(.88) contrast(1.05);display:block}

/* Body below the photo. margin-top:auto on the foot pins links to the bottom so every
   card lines up even when a bio runs a line longer. */
.spk-body{display:flex;flex-direction:column;gap:5px;padding:12px 2px 0;flex:1 1 auto;min-width:0}
.spk-name{margin:0;font:600 19px/1.2 var(--sans);letter-spacing:-.01em;color:var(--ink-d)}
.spk-line{margin:0;font:500 13.5px/1.4 var(--sans);letter-spacing:.005em;color:var(--sage-text)}
.spk-bio{margin:4px 0 0;font-size:15px;line-height:1.55;color:var(--mut-d)}

.spk-foot{margin-top:auto;padding-top:12px;display:flex;align-items:center;justify-content:flex-start;gap:14px;min-height:20px}
.spk-social{display:flex;gap:12px;align-items:center}
.spk-social:empty{display:none}
.spk-social a{display:inline-flex;color:var(--mut-d);transition:color .15s ease, transform .15s ease}
.spk-social a:hover{color:var(--sage-text);transform:translateY(-1px)}
.spk-social svg{width:18px;height:18px;fill:currentColor;display:block}
/* Recap link, styled as a clear sage pill button so the click target is obvious. */
.spk-recap{display:inline-flex;align-items:center;gap:8px;font:600 14px/1 var(--sans);color:var(--sage-text);text-decoration:none;white-space:nowrap;
  padding:11px 18px;border-radius:999px;background:rgba(159,176,143,.10);
  box-shadow:inset 0 0 0 1px rgba(159,176,143,.50);transition:background .15s ease, color .15s ease, box-shadow .15s ease}
.spk-recap svg{width:16px;height:16px;fill:none;stroke:currentColor;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;transition:transform .15s ease}
.spk-recap:hover{background:rgba(159,176,143,.20);color:#c9d6bc;box-shadow:inset 0 0 0 1px rgba(159,176,143,.80)}
.spk-recap:hover svg{transform:translateX(2px)}

.spk-cta-alt{margin:16px 0 0}
.spk-cta-alt .text-link{color:var(--sage-text);border-bottom-color:var(--sage-text)}

@media (max-width:980px){.spk-grid{grid-template-columns:repeat(2,minmax(0,1fr))}}
@media (max-width:700px){
  .spk-stage{min-height:300px}
  .spk-hero-panel{margin:14px;padding:22px 18px}
}
@media (max-width:560px){.spk-grid{grid-template-columns:1fr}}

/* ===== PHONE CHROME (2026-09-16, operator). Under 900px the capsule keeps the wordmark on the left and a
   hamburger on the right; its links and its button leave it. The menu is nav.drawer, off screen to the right
   until html.drawer-open (app.js block 9), with the same five links as the capsule plus the strip. Save your
   seat is a.seat-bar pinned to the bottom of the screen, so the call to action is on screen at every scroll
   position. The three elements sit in every page's markup and are display:none above 900px. ===== */
.nav-toggle{display:none;width:44px;height:44px;margin-left:auto;padding:0;border:0;border-radius:50%;background:transparent;color:var(--ink-d);cursor:pointer;flex-direction:column;align-items:center;justify-content:center;gap:5px;flex:0 0 auto}
.nav-toggle .nt-bar{display:block;width:20px;height:2px;border-radius:2px;background:currentColor;transition:transform .25s ease,opacity .2s ease}
:root.drawer-open .nav-toggle .nt-bar:nth-child(1){transform:translateY(7px) rotate(45deg)}
:root.drawer-open .nav-toggle .nt-bar:nth-child(2){opacity:0}
:root.drawer-open .nav-toggle .nt-bar:nth-child(3){transform:translateY(-7px) rotate(-45deg)}
.drawer-scrim{position:fixed;inset:0;z-index:8;background:rgba(0,0,0,.58);opacity:0;transition:opacity .28s ease}
.drawer{position:fixed;top:0;right:0;bottom:0;z-index:9;width:min(320px,84vw);padding:100px 28px 28px;display:flex;flex-direction:column;gap:4px;background:var(--panel);box-shadow:inset 1px 0 0 rgba(255,255,255,.08);transform:translateX(100%);transition:transform .28s ease;overflow-y:auto}
.drawer[hidden],.drawer-scrim[hidden]{display:none}
.drawer a{font:500 22px/1.2 var(--sans);color:var(--ink-d);text-decoration:none;padding:12px 0;opacity:.82}
.drawer a[aria-current]{opacity:1;color:var(--sage-text)}
.drawer a.drawer-seat{display:inline-flex;align-items:center;justify-content:center;height:52px;margin-top:22px;padding:0 24px;opacity:1;font:600 16px/1 var(--sans);color:var(--ground);border-radius:999px}
:root.drawer-open .drawer{transform:none}
:root.drawer-open .drawer-scrim{opacity:1}
:root.drawer-open .nav{z-index:10}
:root.drawer-open{overflow:hidden}
.seat-bar{display:none}
@media (max-width:900px){
  .nav{flex-wrap:nowrap;gap:12px;padding:6px 6px 6px 20px;min-height:56px}
  .nav .nav-links,.nav .btn{display:none}
  .nav-toggle{display:flex}
  .seat-bar{position:fixed;left:16px;right:16px;bottom:calc(12px + env(safe-area-inset-bottom));z-index:7;display:flex;align-items:center;justify-content:center;height:52px;border-radius:999px;background:var(--ink-d);color:var(--ground);font:600 16px/1 var(--sans);text-decoration:none;box-shadow:0 8px 28px rgba(0,0,0,.45)}
  .seat-bar:active{transform:scale(.98)}
  .foot{padding-bottom:84px}
}

/* ===== PHONE LAYOUT (2026-09-16, operator) ===== */
@media (max-width:700px){
  /* the homepage's closing card keeps the page gutter instead of running edge to edge */
  .closing .close-panel{margin:0 var(--gut)}
  /* the speaker card on a talk page and on a speaker page: portrait on top, the copy under it */
  .speaker-row,.talk-speaker .speaker-row{grid-template-columns:1fr;gap:18px;align-items:start}
  .speaker-row .ph{width:100%;aspect-ratio:1}
  .talk-speaker .speaker-row{padding:18px 18px 22px}
}
/* the sky behind "Come to the next one" on phones and tablets: background-attachment:fixed is ignored there, so
   the sky becomes a layer inside the clipped panel that pans with the scroll position (the heroPan pattern).
   Engines without scroll timelines get the sky still, and reduced motion zeroes the animation. */
@media (max-width:1024px){
  /* overflow:hidden makes the panel a scroll container, which would pin the layer's view() timeline to the panel itself; the clip moves to clip-path (the hero-card pattern) */
  .talk-close .close-panel{background-image:none;background-attachment:scroll;overflow:visible;clip-path:inset(0 round var(--r))}
  .talk-close .close-panel::before{content:"";position:absolute;left:0;right:0;top:-18%;height:136%;z-index:-1;pointer-events:none;background:linear-gradient(rgba(8,11,18,.55),rgba(8,11,18,.72)),url(img/sky-clouds.jpg) center/cover}
  @supports (animation-timeline: view()){.talk-close .close-panel::before{animation:skyPan linear both;animation-timeline:view();animation-range:entry 0% exit 100%}}
}
@keyframes skyPan{from{transform:translateY(-9%)}to{transform:translateY(9%)}}

/* ===== LEGAL PAGES (2026-09-16): privacy and terms, prose on the light band ===== */
.legal-page{padding:32px 0 72px}
.legal-page .updated{margin:0 0 8px;font:600 12px/1 var(--sans);letter-spacing:.16em;text-transform:uppercase;color:var(--sage-deep)}
.legal-page h2{margin:40px 0 10px;font:600 22px/1.25 var(--sans);letter-spacing:-.01em;color:var(--ink-l)}
.legal-page h2:first-of-type{margin-top:8px}
.legal-page p,.legal-page li{font-size:17px;line-height:1.65;color:#2a2a27;max-width:66ch}
.legal-page p{margin:0 0 14px}
.legal-page ul{margin:0 0 14px;padding-left:22px}
.legal-page li{margin:0 0 8px}
.legal-page a{color:var(--sage-deep);font-weight:600;text-decoration:none;border-bottom:1px solid var(--sage-deep)}
.legal-page .lead{font-size:18px;color:var(--ink-l)}
/* the footer address is a link to the map (2026-09-16): reads as the address, underlines the venue on hover */
.foot-map{color:inherit;text-decoration:none}
.foot-map:hover .foot-nap-name{text-decoration:underline;text-underline-offset:3px}

/* ===== ABOUT + AUTHOR (2026-09-16) ===== */
.byline{margin:-12px 0 26px;font:500 14px/1.5 var(--sans);color:var(--mut-d)}
.byline a{color:var(--sage-text);text-decoration:none;border-bottom:1px solid var(--sage-deep)}
.about-photo{padding:0 0 8px}
.about-fig{margin:0}
.about-fig figcaption{padding:10px 2px 0;font:500 13px/1.45 var(--sans);color:var(--mut-d)}
.talk-body .thirds{margin:18px 0 26px}
.talk-body .thirds .tool-what{color:#d6d6d0}
.author-list{margin:0 0 14px;padding-left:20px}
.author-list li{margin:0 0 10px;line-height:1.55}
.author-list li strong{color:var(--ink-d);font-weight:600}
@media (max-width:700px){.talk-body .thirds{grid-template-columns:1fr}}
