/* ============================================================
   BERNARD SAKYI - one stylesheet for the whole site
   ------------------------------------------------------------
   Structure, in order:
     1. Fonts        Ringside, four widths
     2. Tokens       colour, type, spacing, easing
     3. Reset
     4. Shell        .wrap / .top / .foot / grain - every page
     5. Splash       body.splash, the home screen
     6. Talks        body.stage, the process-doc pages
     7. Responsive

   Colour is deliberately black, white and grey throughout. When a
   brand colour is chosen it goes in --pop (§6) and nowhere else.
   ============================================================ */

/* ── 1. Fonts ────────────────────────────────────────────────
   Subset to Latin + the marks used here (® © ✱ · - ’ “ ”), TTF
   -> woff2, ~20K a face. Sources live in /Ringside at the repo root.
   Four widths carry four jobs:
     Wide       thin, large, numerals and quiet asides
     Regular    everything you actually read
     Condensed  labels, section heads, anything in caps
     Compressed the loudest line on the page
   ------------------------------------------------------------ */
@font-face { font-family: 'Ringside'; src: url('fonts/ringside/Ringside-RegularBook.woff2') format('woff2');
  font-weight: 400; font-style: normal; font-display: swap; }
@font-face { font-family: 'Ringside'; src: url('fonts/ringside/Ringside-RegularBookItalic.woff2') format('woff2');
  font-weight: 400; font-style: italic; font-display: swap; }
@font-face { font-family: 'Ringside'; src: url('fonts/ringside/Ringside-RegularMedium.woff2') format('woff2');
  font-weight: 500; font-style: normal; font-display: swap; }
@font-face { font-family: 'Ringside'; src: url('fonts/ringside/Ringside-RegularSemiBold.woff2') format('woff2');
  font-weight: 600; font-style: normal; font-display: swap; }

@font-face { font-family: 'Ringside Cond'; src: url('fonts/ringside/Ringside-CondensedBook.woff2') format('woff2');
  font-weight: 400; font-style: normal; font-display: swap; }
@font-face { font-family: 'Ringside Cond'; src: url('fonts/ringside/Ringside-CondensedSemiBold.woff2') format('woff2');
  font-weight: 600; font-style: normal; font-display: swap; }
@font-face { font-family: 'Ringside Cond'; src: url('fonts/ringside/Ringside-CondensedBlack.woff2') format('woff2');
  font-weight: 900; font-style: normal; font-display: swap; }

@font-face { font-family: 'Ringside Comp'; src: url('fonts/ringside/Ringside-CompressedBlack.woff2') format('woff2');
  font-weight: 900; font-style: normal; font-display: swap; }

@font-face { font-family: 'Ringside Wide'; src: url('fonts/ringside/Ringside-WideLight.woff2') format('woff2');
  font-weight: 300; font-style: normal; font-display: swap; }
@font-face { font-family: 'Ringside Wide'; src: url('fonts/ringside/Ringside-WideBook.woff2') format('woff2');
  font-weight: 400; font-style: normal; font-display: swap; }

/* Season Serif - the reading face. Everything you actually read is
   set in this; Ringside keeps the structure, labels and buttons. */
@font-face { font-family: 'Season Serif'; src: url('fonts/season/SeasonSerif-Regular.woff2') format('woff2');
  font-weight: 400; font-style: normal; font-display: swap; }
@font-face { font-family: 'Season Serif'; src: url('fonts/season/SeasonSerif-Light.woff2') format('woff2');
  font-weight: 300; font-style: normal; font-display: swap; }

/* ── 2. Tokens ───────────────────────────────────────────────── */
:root {
  --stage: #050505;
  --cream: #f7f7f5;
  --cream-70: rgba(247, 247, 245, 0.70);
  --cream-65: rgba(247, 247, 245, 0.66);
  --cream-55: rgba(247, 247, 245, 0.54);
  --cream-28: rgba(247, 247, 245, 0.28);
  --cream-22: rgba(247, 247, 245, 0.22);
  --cream-12: rgba(247, 247, 245, 0.12);

  --serif: 'Season Serif', Georgia, 'Times New Roman', serif;
  /* form fields only: the platform UI face, so typing never waits on a
     webfont. This is what Inter looks like natively on each OS. */
  --ui: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
  --sans: 'Ringside', -apple-system, BlinkMacSystemFont, 'Helvetica Neue', Arial, sans-serif;
  --cond: 'Ringside Cond', 'Arial Narrow', sans-serif;
  --comp: 'Ringside Comp', 'Ringside Cond', 'Haettenschweiler', sans-serif;
  --wide: 'Ringside Wide', 'Ringside', sans-serif;

  --g:    clamp(1rem, 2.5vw, 3rem);   /* page gutter */
  --maxw: 1500px;
  --pad:  clamp(1.15rem, 4vw, 3rem);  /* splash inset */

  --ease:      cubic-bezier(0.22, 1, 0.36, 1);
  --ease-soft: cubic-bezier(0.4, 0, 0.2, 1);
}

/* ── 3. Reset ────────────────────────────────────────────────── */
*, *::before, *::after { margin: 0; padding: 0; box-sizing: border-box; }

html {
  font-size: 15px;              /* everything is rem-based off this */
  scroll-behavior: smooth;
  /* Reserve the scrollbar on every page. Without this, short pages
     (Contact, Talks) render 15px wider than long ones (About), so the
     header and centred content jump sideways as you move between them. */
  scrollbar-gutter: stable;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}
body {
  background: var(--stage);
  color: var(--cream);
  font-family: var(--serif);
  font-size: 1.02rem;
  font-weight: 400;
  line-height: 1.55;
}
/* chrome stays in the grotesque: identity, footer, buttons */
.ident-text, .foot, .pill, .splash-pill { font-family: var(--sans); }
a, button { font-family: var(--sans); }
a { color: inherit; text-decoration: none; }
ul, ol { list-style: none; }
img { display: block; max-width: 100%; }
button { font-size: inherit; line-height: inherit; color: inherit; }

/* ── 4. Shell ────────────────────────────────────────────────── */
.wrap { width: 100%; max-width: var(--maxw); margin-inline: auto; padding-inline: var(--g); }

.top {
  padding-top: clamp(1.25rem, 2.5vw, 1.9rem);
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1.5rem;
}

/* sticky header on the scrolling (.stage) pages — content slides
   under a solid stage-coloured bar */
.stage > .wrap.top {
  position: sticky;
  top: 0;
  z-index: 100;
  padding-bottom: clamp(0.85rem, 1.8vw, 1.3rem);
  background: var(--stage);
}

/* identity: a small square face, name and role stacked beside it */
.ident { display: flex; align-items: center; gap: 0.7rem; min-width: 0; }
.ident-photo {
  flex: none;
  display: block;
  width: 40px;
  aspect-ratio: 1;
  border-radius: 6px;
  overflow: hidden;
  background: var(--cream-12);
}
.ident-photo img { width: 100%; height: 100%; object-fit: cover; transition: transform 0.5s var(--ease); }
.ident:hover .ident-photo img { transform: scale(1.06); }

.ident-text { display: block; min-width: 0; line-height: 1.35; }
.ident-text b {
  display: block;
  font-size: 0.92rem; font-weight: 500;
  letter-spacing: -0.005em;
  color: var(--cream);
}
.ident-text span { display: block; font-size: 0.8rem; color: var(--cream-55); text-wrap: pretty; }

.foot {
  margin-top: clamp(3.5rem, 7vw, 6rem);
  padding-block: clamp(2rem, 4vw, 3rem) clamp(2.5rem, 5vw, 4rem);
  border-top: 1px solid var(--cream-12);
  display: flex; align-items: baseline; justify-content: space-between;
  flex-wrap: wrap; gap: 0.9rem 1.5rem;
  font-size: 0.92rem;
  color: var(--cream-55);
}
.foot a {
  display: inline-block;
  padding-block: 0.4rem;      /* 21px tall was too small to tap */
  color: var(--cream);
  text-decoration: underline;
  text-underline-offset: 3px;
  text-decoration-thickness: 1px;
  text-decoration-color: var(--cream-22);
  transition: text-decoration-color 0.25s var(--ease);
}
.foot a:hover { text-decoration-color: var(--cream); }
.foot-links { display: flex; flex-wrap: wrap; align-items: center; gap: 0 1.25rem; }
.foot-lab { color: var(--cream-55); }

/* a fixed film of noise, so flat black has some tooth */
.grain {
  position: fixed; inset: 0; z-index: 9999;
  pointer-events: none;
  opacity: 0.06;
  background-image: url("data:image/svg+xml,%3Csvg viewBox='0 0 256 256' xmlns='http://www.w3.org/2000/svg'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='4' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");
  background-size: 180px 180px;
}

/* sections fade up as they arrive; main.js adds .revealed */
.reveal {
  opacity: 0;
  transform: translateY(28px);
  transition: opacity 0.75s var(--ease), transform 0.75s var(--ease);
}
.reveal.revealed { opacity: 1; transform: none; }
.reveal-d1 { transition-delay: 0.08s; }
.reveal-d2 { transition-delay: 0.16s; }

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  .reveal { opacity: 1; transform: none; transition: none; }
}

/* ============================================================
   5. SPLASH - body.splash, the home screen
   ------------------------------------------------------------
   One screen, no scroll: the portrait fills it, everything else
   sits in the corners.
   ============================================================ */
body.splash {
  height: 100%; overflow: hidden;
  /* the .sheet card (testimonials) needs these "doc" tokens too - they are
     otherwise only defined on the interior .stage pages */
  --doc:        #f0f0f0;
  --surface:    #f0f0f0;
  --doc-ink:    #0b0b0b;
  --doc-ink-60: rgba(11, 11, 11, 0.66);
  --doc-ink-40: rgba(11, 11, 11, 0.44);
  --doc-line:   rgba(11, 11, 11, 0.22);
  --doc-hair:   rgba(11, 11, 11, 0.13);
}
html:has(body.splash) { scrollbar-gutter: auto; }  /* never scrolls */
html:has(body.splash) { height: 100%; overflow: hidden; }

.splash-stage {
  position: fixed; inset: 0;
  height: 100svh;     /* smallest viewport → corners clear the toolbars */
  height: 100dvh;     /* honours mobile browser chrome where supported */
  overflow: hidden;
  /* NOTE: no `min-height: 100vh` - on iOS Safari 100vh is the *largest*
     viewport, which pushes the bottom bar behind the home indicator. */
}

.splash-stage::before {
  content: '';
  position: absolute; inset: 0;
  /* One cut-out serves both themes: the backdrop is just --stage showing
     through the transparency, so the toggle only changes a colour.
     Same canvas as the photo it replaced, so the framing that already
     worked carries over - 35% because his head sits high in the frame. */
  background: url('assets/hero-main.webp') center 35% / cover no-repeat;
  z-index: 0;
}
.splash .grain { z-index: 2; opacity: 0.05; }

.splash-pill {
  position: absolute; top: calc(var(--pad) + env(safe-area-inset-top));
  z-index: 3;
  display: inline-flex; align-items: center; gap: 0.5rem;
  padding: 0.7em 1.35em;
  font-family: var(--cond); font-synthesis: none;
  font-size: clamp(0.72rem, 1vw, 0.84rem);
  font-weight: 600;
  letter-spacing: 0.15em; text-transform: uppercase;
  line-height: 1;
  color: var(--cream);
  white-space: nowrap;
  background: rgba(247, 247, 245, 0.10);
  border: 1px solid var(--cream-28);
  border-radius: 999px;
  backdrop-filter: blur(14px) saturate(140%);
  -webkit-backdrop-filter: blur(14px) saturate(140%);
  transition: background 0.35s var(--ease-soft), border-color 0.35s var(--ease-soft), color 0.35s var(--ease-soft);
}
.splash-pill:hover { background: var(--cream); border-color: var(--cream); color: var(--stage); }
.splash-pill--l { left:  calc(var(--pad) + env(safe-area-inset-left)); }
.splash-pill--r { right: calc(var(--pad) + env(safe-area-inset-right)); }

.splash-bar {
  position: absolute; left: 0; right: 0; bottom: 0;
  z-index: 3;
  display: flex; align-items: flex-end; justify-content: space-between;
  gap: 1.25rem;
  padding: var(--pad);
  padding-left:   calc(var(--pad) + env(safe-area-inset-left));
  padding-right:  calc(var(--pad) + env(safe-area-inset-right));
  padding-bottom: calc(var(--pad) + env(safe-area-inset-bottom));
}

/* top-left on every screen, opposite the hamburger */
.splash-logo {
  position: absolute; z-index: 4;
  top:  calc(var(--pad) + env(safe-area-inset-top));
  left: calc(var(--pad) + env(safe-area-inset-left));
  display: block;
  transition: opacity 0.3s var(--ease-soft);
}
.splash-logo img { width: clamp(74px, 7.6vw, 108px); height: auto; }
.splash-logo:hover { opacity: 0.75; }

/* Kept for whatever goes bottom-left next - a wordmark, a mark, a line
   of type. Nothing uses it right now. */
.splash-word {
  font-family: var(--cond); font-synthesis: none;
  font-size: clamp(1.15rem, 2.4vw, 1.9rem);
  font-weight: 900; letter-spacing: -0.015em; text-transform: uppercase;
  line-height: 1;
  color: var(--cream);
  transition: opacity 0.3s var(--ease-soft);
}
.splash-word:hover { opacity: 0.7; }

.splash-links { display: flex; flex-direction: column; align-items: flex-end; gap: 0.5rem; margin-left: auto; }
.splash-links a {
  position: relative;
  font-family: var(--cond); font-synthesis: none;
  font-size: clamp(0.8rem, 1.15vw, 0.95rem);
  font-weight: 600;
  letter-spacing: 0.15em; text-transform: uppercase;
  line-height: 1;
  color: var(--cream-70);
  padding-bottom: 4px;
  white-space: nowrap;
  transition: color 0.3s var(--ease-soft);
}
.splash-links a::after {
  content: '';
  position: absolute; left: 0; right: 0; bottom: 0; height: 1px;
  background: var(--cream);
  transform: scaleX(0); transform-origin: left;
  transition: transform 0.35s var(--ease);
}
.splash-links a:hover { color: var(--cream); }
.splash-links a:hover::after { transform: scaleX(1); }

@media (prefers-reduced-motion: reduce) {
  .splash-links a::after { transition: none; }
}

.menu { position: relative; z-index: 40; display: flex; align-items: center; gap: 0.1rem; }

/* theme toggle - bare icon button, sits left of the hamburger */
.theme-toggle {
  display: grid; place-items: center;
  width: 2.5rem; height: 2.5rem;
  padding: 0; background: none; border: 0; border-radius: 0;
  color: var(--cream); cursor: pointer;
  transition: opacity 0.3s var(--ease-soft);
}
.theme-toggle:hover { opacity: 0.6; }
.theme-toggle svg { width: 19px; height: 19px; display: block; }
.theme-toggle .i-moon { display: none; }
html[data-theme="light"] .theme-toggle .i-sun  { display: none; }
html[data-theme="light"] .theme-toggle .i-moon { display: block; }

/* a bare hamburger - no pill, no border, no radius */
.menu-btn {
  display: grid; place-items: center;
  width: 2.5rem; height: 2.5rem;
  padding: 0;
  background: none;
  border: 0;
  border-radius: 0;
  color: var(--cream);
  cursor: pointer;
}
.menu-bars { position: relative; display: block; width: 24px; height: 11px; }
.menu-bars i {
  position: absolute; left: 0; right: 0;
  height: 3px;
  background: currentColor;
  transition: transform 0.35s var(--ease);
}
.menu-bars i:nth-child(1) { top: 0; }
.menu-bars i:nth-child(2) { bottom: 0; }
/* folds into a cross when the panel is down */
.menu.is-open .menu-bars i:nth-child(1) { transform: translateY(4px) rotate(45deg); }
.menu.is-open .menu-bars i:nth-child(2) { transform: translateY(-4px) rotate(-45deg); }

.menu-panel {
  position: absolute; top: calc(100% + 0.6rem); right: 0;
  min-width: 15.5rem;
  padding: 0.4rem;
  background: rgba(8, 8, 8, 0.94);
  border: 1px solid var(--cream-22);
  border-radius: 0;
  backdrop-filter: blur(18px) saturate(140%);
  -webkit-backdrop-filter: blur(18px) saturate(140%);
  /* "drops down slightly" - a short fall, not a curtain */
  opacity: 0;
  transform: translateY(-8px);
  pointer-events: none;
  /* visibility, not just opacity: an opacity-0 panel still holds its links
     in the tab order, so keyboard focus landed on an invisible menu. It
     flips only after the fade has finished, so the close still animates. */
  visibility: hidden;
  transition: opacity 0.28s var(--ease-soft), transform 0.32s var(--ease),
              visibility 0s linear 0.32s;
}
.menu.is-open .menu-panel {
  opacity: 1; transform: none; pointer-events: auto;
  visibility: visible;
  transition: opacity 0.28s var(--ease-soft), transform 0.32s var(--ease),
              visibility 0s;
}

.menu-panel a,
.menu-panel .is-soon {
  display: flex; align-items: baseline; justify-content: space-between;
  gap: 1.5rem;
  padding: 0.62rem 0.8rem;
  border-radius: 0;
  font-family: var(--sans);
  font-size: 0.94rem;
  line-height: 1.25;
  color: var(--cream-70);
  white-space: nowrap;
  transition: background 0.25s var(--ease-soft), color 0.25s var(--ease-soft);
}
.menu-panel a:hover { background: var(--cream-12); color: var(--cream); }
.menu-panel a[aria-current="page"] { color: var(--cream); background: var(--cream-12); }

.menu-panel .is-soon { color: var(--cream-28); cursor: default; }
.menu-panel .soon-tag {
  font-family: var(--cond); font-synthesis: none;
  font-size: 0.6rem; font-weight: 600;
  letter-spacing: 0.14em; text-transform: uppercase;
  opacity: 0;
  transition: opacity 0.25s var(--ease-soft);
}
.menu-panel .is-soon:hover .soon-tag { opacity: 1; }
.menu-rule { height: 1px; margin: 0.4rem 0; background: var(--cream-12); }

/* on the splash the menu is a fixed corner, not part of a top bar */
.splash .menu {
  position: absolute; z-index: 4;
  top: calc(var(--pad) + env(safe-area-inset-top));
  right: calc(var(--pad) + env(safe-area-inset-right));
}

/* ============================================================
   PAGE - shell for About / Contact / Lab
   ============================================================ */
.page-head { padding-top: clamp(3rem, 8vw, 6rem); text-align: center; }
.page-kicker {
  font-family: var(--cond); font-synthesis: none;
  font-size: 0.72rem; font-weight: 600;
  letter-spacing: 0.2em; text-transform: uppercase;
  color: var(--cream-55);
  margin-bottom: clamp(1.1rem, 2.4vw, 1.8rem);
}
.page-title {
  font-family: var(--cond); font-synthesis: none;
  font-size: clamp(2.6rem, 8vw, 6.5rem);
  font-weight: 900; line-height: 0.92; letter-spacing: -0.025em;
  max-width: 16ch; margin-inline: auto;
  text-wrap: balance;
}
.page-lede {
  margin: clamp(1.75rem, 3.5vw, 2.75rem) auto 0;
  max-width: 38rem;
  font-weight: 300;
  font-size: clamp(1.1rem, 1.6vw, 1.4rem);
  line-height: 1.5;
  color: var(--cream-65);
  text-wrap: pretty;
}
.page-body { margin: clamp(2.5rem, 5vw, 4rem) auto 0; max-width: 38rem; text-align: center; }
.page-body p { color: var(--cream-65); line-height: 1.7; }
.page-body p + p { margin-top: 1.15rem; }
.page-body a {
  color: var(--cream);
  text-decoration: underline; text-underline-offset: 3px;
  text-decoration-color: var(--cream-22);
  transition: text-decoration-color 0.25s var(--ease);
}
.page-body a:hover { text-decoration-color: var(--cream); }

/* ============================================================
   404
   ============================================================ */
.lost {
  min-height: 70svh;
  display: grid; align-content: center; justify-items: center;
  text-align: center;
  padding-block: clamp(3rem, 8vw, 6rem);
}
.lost-code {
  font-family: var(--comp); font-synthesis: none;
  font-size: clamp(6rem, 26vw, 17rem);
  font-weight: 900; line-height: 0.8; letter-spacing: 0.01em;
  color: var(--cream-12);
}
.lost h1 {
  font-family: var(--cond); font-synthesis: none;
  font-size: clamp(1.9rem, 5.5vw, 4rem);
  font-weight: 900; line-height: 0.96; letter-spacing: -0.02em;
  max-width: 18ch;
  text-wrap: balance;
}
.lost p {
  margin: clamp(1.2rem, 2.4vw, 1.8rem) auto 0;
  max-width: 30rem;
  color: var(--cream-65);
  line-height: 1.6;
}
.lost .talks-cta { margin-top: clamp(1.75rem, 3vw, 2.5rem); }
.lost-video {
  width: clamp(160px, 34vw, 280px);
  aspect-ratio: 1; height: auto;
  display: block; object-fit: cover;
  border-radius: clamp(14px, 2vw, 22px);
  margin-bottom: clamp(1.4rem, 3vw, 2.2rem);
}

/* 404 as a single no-scroll view, everything in frame (like the home splash) */
html:has(body.lost-view) { height: 100%; overflow: hidden; scrollbar-gutter: auto; }
body.lost-view {
  height: 100svh; height: 100dvh;
  overflow: hidden;
  display: flex; flex-direction: column;
}
body.lost-view > .wrap.top,
body.lost-view > footer.wrap { flex: 0 0 auto; }
body.lost-view > main.wrap {
  flex: 1 1 auto; min-height: 0;
  display: grid; place-items: center;
}
body.lost-view .lost { min-height: 0; padding-block: 0; }


/* a group row opens its children rather than downloading */
.kit-row--group { cursor: pointer; }
.kit-go--caret { display: inline-grid; place-items: center; width: 1.5rem; height: 1.5rem; color: var(--doc-ink-40); transition: transform 0.4s var(--ease), color 0.3s var(--ease-soft); }
.kit-go--caret svg { width: 10px; height: 7px; }
.kit-row--group:hover .kit-go--caret { color: var(--doc-ink); }
.kit-item.is-open .kit-go--caret { transform: rotate(180deg); color: var(--doc-ink); }

/* the prompt list stays shut until asked for */
.kit-sub {
  display: grid;
  grid-template-rows: 0fr;
  margin: 0 0 0 3.4rem;
  transition: grid-template-rows 0.45s var(--ease), margin 0.45s var(--ease);
}
.kit-item.is-open > .kit-sub { grid-template-rows: 1fr; margin-bottom: 0.9rem; }
.kit-sub > * { overflow: hidden; }

/* no rule under the last line of a list - the card edge ends it */
.doc-list li:last-child,
.kit-list > .kit-item:last-child { border-bottom: 0; }

@media (prefers-reduced-motion: reduce) {
  .kit-sub { transition: none; }
}

/* ============================================================
   TALKS - "the process doc"
   ------------------------------------------------------------
   Black stage, white paper laid on it, nothing else. The page
   runs on one accent token, --pop, which is white for now.
   Pick a colour later and this is the only line that changes.
   Type does the shouting: Condensed Black for anything loud,
   Wide Light for the one quiet moment, Regular for reading.
   ============================================================ */

body.stage {
  /* the accent - change these two lines when a colour is chosen */
  --pop:     #f7f7f5;
  --pop-ink: #050505;

  /* neutralise the warm site palette down to black, white, grey */
  --cream:    #f7f7f5;
  --cream-65: rgba(247, 247, 245, 0.66);
  --cream-55: rgba(247, 247, 245, 0.54);
  --cream-22: rgba(247, 247, 245, 0.22);
  --cream-12: rgba(247, 247, 245, 0.12);

  --doc:        #f0f0f0;
  --doc-ink:    #0b0b0b;
  --surface:    #f0f0f0;   /* base form/chip fills, neutralised */
  --doc-ink-60: rgba(11, 11, 11, 0.66);
  --doc-ink-40: rgba(11, 11, 11, 0.44);
  --doc-line:   rgba(11, 11, 11, 0.22);
  --doc-hair:   rgba(11, 11, 11, 0.13);

  background: var(--stage);
  color: var(--cream);
  padding-bottom: 0;          /* no dock to clear */
}
.stage .grain { opacity: 0.06; }

/* ============================================================
   Light theme — applies to the interior (.stage) pages only.
   The home splash (body.splash) is a photograph and stays dark.
   Toggled via <html data-theme="light"> (see main.js).
   ============================================================ */
html[data-theme="light"] body.stage {
  --stage:     #f6f6f4;
  --cream:     #161616;
  --cream-70:  rgba(22, 22, 22, 0.72);
  --cream-65:  rgba(22, 22, 22, 0.66);
  --cream-55:  rgba(22, 22, 22, 0.56);
  --cream-28:  rgba(22, 22, 22, 0.34);
  --cream-22:  rgba(22, 22, 22, 0.24);
  --cream-12:  rgba(22, 22, 22, 0.11);

  --pop:       #161616;
  --pop-ink:   #f6f6f4;

  --doc:       #ffffff;
  --surface:   #ffffff;
  --doc-ink:   #161616;
  --doc-ink-60:rgba(22, 22, 22, 0.62);
  --doc-ink-40:rgba(22, 22, 22, 0.42);
  --doc-line:  rgba(22, 22, 22, 0.20);
  --doc-hair:  rgba(22, 22, 22, 0.11);
}
/* the menu dropdown is a hardcoded dark panel — lighten it too */
html[data-theme="light"] body.stage .menu-panel {
  background: rgba(250, 250, 248, 0.96);
}
/* Nothing needed for the panel's contents: --cream-* are redefined to dark
   ink under this theme, so the links, soon-tags and rule all flip with it. */
/* Light mode swaps in the marks as their owners drew them. Only the
   source changes - same file dimensions, so layout and sizing are
   untouched. `content` means just one of the two ever downloads; if a
   browser ignores it, the grey set stays and nothing breaks. */
html[data-theme="light"] body.stage .client .c-dark { display: none; }
html[data-theme="light"] body.stage .client .c-lite { display: block; }
html[data-theme="light"] body.stage .grain { opacity: 0.03; }

/* Home splash also responds to the theme: a different photograph per mode,
   and the overlay marks flip dark so they read on the light backdrop. */
html[data-theme="light"] body.splash {
  --stage:    #f6f6f4;
  --cream:    #161616;
  --cream-70: rgba(22, 22, 22, 0.72);
  --cream-28: rgba(22, 22, 22, 0.34);
  --cream-22: rgba(22, 22, 22, 0.24);
  --cream-12: rgba(22, 22, 22, 0.11);
  /* keep the testimonial card a clean white panel in light mode too */
  --doc:        #ffffff;
  --surface:    #ffffff;
  --doc-ink:    #161616;
  --doc-ink-60: rgba(22, 22, 22, 0.62);
  --doc-ink-40: rgba(22, 22, 22, 0.42);
  --doc-line:   rgba(22, 22, 22, 0.20);
  --doc-hair:   rgba(22, 22, 22, 0.11);
}
/* the logo is a white SVG - invert it to black for light mode */
html[data-theme="light"] body.splash .splash-logo img { filter: invert(1); }
html[data-theme="light"] body.splash .menu-panel { background: rgba(250, 250, 248, 0.96); }
/* on mobile the light photo's subject fills the lower frame, so the
   bottom-right links land on dark - keep them light there in both modes */
@media (max-width: 620px) {   /* matches where the links become the bottom row */
  html[data-theme="light"] body.splash .splash-links a { color: rgba(247, 247, 245, 0.72); }
  html[data-theme="light"] body.splash .splash-links a:hover { color: #f7f7f5; }
  html[data-theme="light"] body.splash .splash-links a::after { background: #f7f7f5; }
}

/* the base sheet focuses in orange; this page has no colour yet */
.stage :focus-visible { outline: 2px solid var(--cream); outline-offset: 3px; }
.stage .doc :focus-visible,
.sheet :focus-visible { outline: 2px solid var(--doc-ink); outline-offset: 3px; }
.sheet .sheet-in:focus-visible { outline: none; }
.stage ::selection { background: var(--cream); color: var(--stage); }
.stage .doc ::selection,
.sheet ::selection { background: var(--doc-ink); color: var(--doc); }

/* ── top bar ─────────────────────────────────────────────────── */
.stage .brand-title { color: var(--cream-55); }
.stage .clock       { color: var(--cream-55); }
.stage .clock b     { color: var(--cream); }


.stage .foot {
  border-top-color: var(--cream-12);
  color: var(--cream-55);
  margin-top: clamp(3.5rem, 7vw, 6rem);
  padding-block: clamp(2rem, 4vw, 3rem) clamp(2.5rem, 5vw, 4rem);
}
.stage .foot a       { color: var(--cream); text-decoration-color: var(--cream-22); }
.stage .foot a:hover { color: var(--cream); text-decoration-color: var(--cream); }
.stage .foot-lab     { color: var(--cream-55); }

/* ── shared bits ─────────────────────────────────────────────── */
.eyebrow {
  display: flex; align-items: center; justify-content: center;
  gap: 0.7em;
  font-family: var(--cond); font-synthesis: none;
  font-size: 0.72rem; font-weight: 600;
  letter-spacing: 0.2em; text-transform: uppercase;
  color: var(--cream-55);
}
.eyebrow i { font-style: normal; opacity: 0.45; }

/* The pill. Everything that is a next step wears this shape,
   so there is only one button on the page. */
.pill {
  display: inline-flex; align-items: center; gap: 0.6em;
  padding: 0.95em 2.1em;
  border: 1px solid var(--cream-22);
  border-radius: 999px;
  font-family: var(--sans);
  font-size: clamp(1rem, 1.5vw, 1.3rem);
  font-weight: 500;
  line-height: 1;
  background: none;
  color: var(--cream);
  white-space: nowrap;
  text-decoration: none;
  cursor: pointer;
  transition: background 0.35s var(--ease-soft), color 0.35s var(--ease-soft), border-color 0.35s var(--ease-soft);
}
.pill:hover { background: var(--pop); border-color: var(--pop); color: var(--pop-ink); }
.pill--solid { background: var(--pop); border-color: var(--pop); color: var(--pop-ink); }
.pill--solid:hover { background: transparent; border-color: var(--cream-22); color: var(--cream); }

/* contact page: pill buttons only, with a quiet 'or' between them */
.contact-actions { display: flex; flex-wrap: wrap; gap: 0.9rem 1.1rem; justify-content: center; align-items: center; margin-top: 0.4rem; }
.contact-actions .pill { text-decoration: none; }   /* beats .page-body a underline */
.contact-or { font-family: var(--serif); font-size: 1.1rem; color: var(--cream-55); }

/* ── contact form: matches the page's own light/dark mode ─────── */
.cform-sec { max-width: 44rem; margin: clamp(2.75rem, 6vw, 5rem) auto 0; }
.cform-card {
  padding: 0;
}
.cform-kicker {
  font-family: var(--cond); font-synthesis: none;
  font-size: 0.66rem; font-weight: 600;
  letter-spacing: 0.16em; text-transform: uppercase;
  color: var(--cream-55);
  margin-bottom: clamp(1.4rem, 3vw, 2rem);
}
.cform { display: grid; gap: clamp(1.1rem, 2.2vw, 1.5rem); }
.cform-grid { display: grid; grid-template-columns: 1fr 1fr; gap: clamp(1.1rem, 2.2vw, 1.5rem); }
.cf-field { display: grid; gap: 0.5rem; }
.cf-label {
  font-family: var(--cond); font-synthesis: none;
  font-size: 0.66rem; font-weight: 600;
  letter-spacing: 0.16em; text-transform: uppercase;
  color: var(--cream-55);
}
.cf-req { color: #e5484d; }   /* the required-field asterisk */
.cf-in {
  width: 100%;
  font-family: var(--ui);
  font-size: 0.98rem; line-height: 1.55;
  color: var(--cream);
  background: none;
  border: 0; border-bottom: 1px solid var(--cream-22); border-radius: 0;
  padding: 0.5rem 0;
  transition: border-color 0.3s var(--ease-soft);
}
.cf-in::placeholder { color: var(--cream-55); }
.cf-in:focus { outline: none; border-bottom-color: var(--cream); }
textarea.cf-in { min-height: 7.5rem; resize: vertical; }
.cf-select {
  appearance: none; -webkit-appearance: none;
  padding-right: 1.6rem; cursor: pointer;
  /* light arrow for the dark page; overridden below in light mode */
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 9 6' fill='none'%3E%3Cpath d='M1 1l3.5 3.5L8 1' stroke='%23f7f7f5' stroke-opacity='.6' stroke-width='1.4' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 0.15rem center;
  background-size: 10px 7px;
}
.cf-select:invalid { color: var(--cream-55); }   /* the placeholder option */
html[data-theme="light"] body.stage .cf-select {
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 9 6' fill='none'%3E%3Cpath d='M1 1l3.5 3.5L8 1' stroke='%23161616' stroke-opacity='.6' stroke-width='1.4' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
}
/* the native option list is drawn by the OS — pin readable colours */
.cf-select option { color: #161616; background: #ffffff; }
.cf-err {
  font-size: 0.85rem; line-height: 1.45;
  color: var(--cream);
  padding-left: 0.75rem;
  border-left: 1px solid var(--cream);
}
.cf-err a { color: inherit; text-decoration: underline; text-underline-offset: 3px; }
.cf-actions { display: flex; align-items: center; flex-wrap: wrap; gap: 0.75rem 1.1rem; }
.cf-actions .pill { font-size: 1rem; padding: 0.85em 1.9em; }
.cf-actions .pill:disabled { opacity: 0.45; cursor: default; }
.cform-note { font-family: var(--serif); font-synthesis: none; font-size: 0.95rem; color: var(--cream-55); }

.cf-done { display: grid; justify-items: start; gap: 0.6rem; padding-block: clamp(0.5rem, 2vw, 1rem); }
.cf-done-mark { display: grid; place-items: center; width: 2.4rem; height: 2.4rem; margin-bottom: 0.4rem; }
.cf-done-mark svg { width: 100%; height: 100%; display: block; }
.cf-done h3 {
  font-family: var(--cond); font-synthesis: none;
  font-size: clamp(1.6rem, 3.6vw, 2.3rem);
  font-weight: 900; line-height: 0.98; letter-spacing: -0.02em;
  color: var(--cream);
}
.cf-done p { font-size: 0.95rem; line-height: 1.6; color: var(--cream-65); max-width: 30rem; }
/* [hidden] must beat .cform / .cf-done display:grid */
.cform-sec [hidden] { display: none !important; }
@media (max-width: 560px) {
  .cform-grid { grid-template-columns: 1fr; }
  .cform-note { flex-basis: 100%; }
}

/* ── hero ────────────────────────────────────────────────────── */
.talks-hero {
  padding-top: clamp(3rem, 9vw, 7rem);
  padding-bottom: clamp(3rem, 6vw, 5rem);
  text-align: center;
}
.talks-hero .eyebrow { margin-bottom: clamp(1.75rem, 3.5vw, 2.75rem); }

.talks-title {
  font-family: var(--cond); font-synthesis: none;
  font-size: clamp(2.9rem, 9.4vw, 8.5rem);
  font-weight: 900;
  line-height: 0.9;
  letter-spacing: -0.02em;
  text-wrap: balance;
  margin-inline: auto;
  max-width: 15ch;
}
.talks-title sup {
  font-size: 0.38em;
  vertical-align: 1.05em;
  letter-spacing: 0;
  font-weight: 400;
}

.talks-lede {
  margin: clamp(2.25rem, 4.5vw, 3.5rem) auto 0;
  max-width: 34rem;
  font-size: clamp(1rem, 1.2vw, 1.12rem);
  line-height: 1.6;
  color: var(--cream-65);
  text-wrap: pretty;
}
.talks-cta {
  margin-top: clamp(1.75rem, 3vw, 2.5rem);
  display: flex; flex-wrap: wrap;
  align-items: center; justify-content: center;
  gap: 0.75rem 1.1rem;
}
.talks-cta .sep { color: var(--cream-55); font-size: 1rem; }

/* ── marquee ─────────────────────────────────────────────────── */
.strip {
  margin-top: clamp(3rem, 6vw, 5rem);
  border-block: 1px solid var(--cream-12);
  padding-block: 1.15rem;
  overflow: hidden;
  --strip-speed: 34s;
}
.strip-track { display: flex; width: max-content; animation: strip var(--strip-speed) linear infinite; }
.strip:hover .strip-track { animation-play-state: paused; }
.strip-set { display: flex; align-items: center; flex-shrink: 0; }
.strip-set span {
  font-family: var(--comp); font-synthesis: none;
  font-size: clamp(1.6rem, 3.4vw, 2.9rem);
  font-weight: 900; line-height: 1;
  letter-spacing: 0.01em; text-transform: uppercase;
  padding-inline: 0.55em;
  color: var(--cream);
}
.strip-set i {
  font-style: normal; color: var(--cream-55);
  font-size: clamp(0.8rem, 1.5vw, 1.15rem);
}
@keyframes strip { to { transform: translateX(-50%); } }
@media (prefers-reduced-motion: reduce) {
  .strip-track { animation: none; }
}

/* ============================================================
   THE ARCHIVE - built to compound
   ------------------------------------------------------------
   Every talk is one row: a name that drops open into its doc.
   Ten talks from now the page is still a legible list, because
   the closed state is a single line of type and a rule.
   ============================================================ */
.talks { margin-top: clamp(3.5rem, 7vw, 6rem); }

.talks-bar {
  display: flex; align-items: baseline; justify-content: space-between;
  gap: 1.5rem; flex-wrap: wrap;
  padding-bottom: 1rem;
  font-family: var(--cond); font-synthesis: none;
  font-size: 0.72rem; font-weight: 600;
  letter-spacing: 0.18em; text-transform: uppercase;
}
.talks-bar span:last-child { color: var(--cream-55); }

.talk { border-top: 1px solid var(--cream-12); }
/* a rule closes the session list off */
.talk:last-of-type { border-bottom: 1px solid var(--cream-12); }
.talk-h { margin: 0; font-size: inherit; font-weight: inherit; }

.talk-head {
  display: grid;
  grid-template-columns: 4.5rem minmax(0, 1fr) 2.5rem;
  align-items: start;
  gap: 1.25rem;
  width: 100%;
  padding-block: clamp(1.5rem, 3.2vw, 2.5rem);
  padding-inline: 0;
  background: none; border: 0;
  font-family: var(--sans); font-size: inherit;
  color: inherit; text-align: left;
  cursor: pointer;
}
.talk-n {
  font-family: var(--wide); font-synthesis: none;
  font-weight: 300; font-size: clamp(1.3rem, 2vw, 1.7rem);
  line-height: 1.05;
  color: var(--cream-55);
  transition: color 0.35s var(--ease-soft);
}
.talk-head:hover .talk-n { color: var(--cream); }

/* the drop-down title: name on one line, billing beneath it */
.talk-name {
  display: block;
  font-family: var(--cond); font-synthesis: none;
  font-size: clamp(2rem, 5.6vw, 4.4rem);
  font-weight: 900; line-height: 0.94;
  letter-spacing: -0.02em;
  text-wrap: balance;
}
.talk-where {
  display: block;
  margin-top: clamp(0.5rem, 1vw, 0.8rem);
  font-family: var(--serif); font-synthesis: none;
  font-weight: 400;
  font-size: clamp(0.95rem, 1.5vw, 1.3rem);
  line-height: 1.25;
  letter-spacing: 0;
  color: var(--cream-65);
}

/* the sign: a plus that rotates into a minus */
.talk-sign {
  position: relative;
  width: 1.15rem; height: 1.15rem;
  margin-top: 0.55rem;
  justify-self: end;
}
.talk-sign::before,
.talk-sign::after {
  content: "";
  position: absolute; inset: 50% 0 auto 0;
  height: 1px;
  background: var(--cream);
  transition: transform 0.45s var(--ease);
}
.talk-sign::after { transform: rotate(90deg); }
.talk.is-open .talk-sign::after { transform: rotate(0deg); }

/* the drop. 0fr -> 1fr animates without measuring anything. */
.talk-body {
  display: grid;
  grid-template-rows: 0fr;
  transition: grid-template-rows 0.55s var(--ease);
}
.talk.is-open .talk-body { grid-template-rows: 1fr; }
.talk-body > div { overflow: hidden; }
.talk .doc { margin-bottom: clamp(1.5rem, 3vw, 2.5rem); }

@media (prefers-reduced-motion: reduce) {
  .talk-body { transition: none; }
}

/* ============================================================
   THE DOC - white paper resting on the black stage
   ============================================================ */

.doc {
  background: var(--doc);
  color: var(--doc-ink);
  border-radius: 0;
  padding: clamp(1.6rem, 3.6vw, 3.5rem);
  scroll-margin-top: 2rem;
}
.doc-body {
  display: grid;
  grid-template-columns: minmax(0, 0.8fr) minmax(0, 1.55fr);
  gap: clamp(1.5rem, 3.5vw, 3.5rem);
}

/* left rail - the particulars, on the same hairline rhythm
   as everything else in the doc */
.doc-facts { display: grid; }
.doc-facts > div {
  display: grid;
  grid-template-columns: 5rem minmax(0, 1fr);
  gap: 0.5rem;
  padding-block: 0.7rem;
  border-bottom: 1px solid var(--doc-hair);
}
.doc-facts > div:first-child { padding-top: 0; }
.doc-facts dt {
  font-family: var(--cond); font-synthesis: none;
  font-size: 0.64rem; font-weight: 600;
  letter-spacing: 0.14em; text-transform: uppercase;
  color: var(--doc-ink-40);
  padding-top: 0.15rem;
}
.doc-facts dd {
  font-size: 0.95rem; font-weight: 500; line-height: 1.35;
  color: var(--doc-ink);
}

.doc-tags { margin-top: clamp(1.25rem, 2.5vw, 1.75rem); display: flex; flex-wrap: wrap; gap: 0.4rem; }
.doc-tag {
  font-family: var(--cond); font-synthesis: none;
  font-size: 0.72rem; font-weight: 600;
  letter-spacing: 0.12em; text-transform: uppercase;
  padding: 0.42em 0.8em;
  border: 1px solid var(--doc-line);
  border-radius: 999px;
  color: var(--doc-ink-60);
}
.doc-side-note {
  margin-top: clamp(1.5rem, 3vw, 2.25rem);
  padding-top: clamp(1.1rem, 2vw, 1.5rem);
  border-top: 1px solid var(--doc-hair);
  max-width: 22rem;
  font-size: 0.86rem;
  line-height: 1.6;
  color: var(--doc-ink-40);
  text-wrap: pretty;
}

/* right rail - the document itself */
.doc-sec {
  font-family: var(--cond); font-synthesis: none;
  font-weight: 900;
  font-size: clamp(1.3rem, 2.2vw, 1.85rem);
  line-height: 1.05;
  letter-spacing: -0.015em;
  margin-bottom: clamp(1.1rem, 2.2vw, 1.6rem);
}
.doc-copy {
  font-size: clamp(0.95rem, 1.05vw, 1.02rem);
  line-height: 1.65;
  color: var(--doc-ink-60);
  max-width: 44rem;
  text-wrap: pretty;
}
.doc-copy p + p { margin-top: 0.9rem; }

.doc-label {
  margin-top: clamp(1.5rem, 2.8vw, 2.25rem);
  margin-bottom: 0.85rem;
  font-family: var(--cond); font-synthesis: none;
  font-size: 0.72rem; font-weight: 600;
  letter-spacing: 0.16em; text-transform: uppercase;
  color: var(--doc-ink-40);
}

/* the numbered list, a hairline under every line */
.doc-list { display: grid; counter-reset: doc-i; }
.doc-list li {
  display: grid;
  grid-template-columns: 1.7rem minmax(0, 1fr);
  gap: 0.35rem;
  padding-block: 0.62rem;
  border-bottom: 1px solid var(--doc-hair);
  font-size: clamp(0.95rem, 1.05vw, 1.02rem);
  line-height: 1.45;
  color: var(--doc-ink);
}
.doc-list li::before {
  content: counter(doc-i) ".";
  counter-increment: doc-i;
  color: var(--doc-ink-40);
  font-variant-numeric: tabular-nums;
}

/* ── materials ───────────────────────────────────────────────
   Straight off the process doc: a number, a name, a hairline.
   No badges, no bordered buttons - the rule does the work and
   the glyph on the right says what will happen if you click.
   ------------------------------------------------------------ */
.kit { margin-top: clamp(1.75rem, 3vw, 2.5rem); }
.kit-head {
  display: flex; align-items: baseline; justify-content: space-between;
  gap: 1rem; flex-wrap: wrap;
  padding-bottom: 0.8rem;
  font-family: var(--cond); font-synthesis: none;
  font-size: 0.72rem; font-weight: 600;
  letter-spacing: 0.16em; text-transform: uppercase;
}
.kit-head span:last-child { color: var(--doc-ink-40); }

.kit-list { display: grid; }
.kit-item { border-top: 1px solid var(--doc-hair); }
.kit-item:last-child { border-bottom: 1px solid var(--doc-hair); }

.kit-row {
  display: grid;
  grid-template-columns: 2.4rem minmax(0, 1fr) auto 1.4rem;
  align-items: baseline;
  gap: 0.6rem 1rem;
  width: 100%;
  padding-block: clamp(0.8rem, 1.6vw, 1.05rem);
  padding-inline: 0;
  background: none; border: 0;
  font-family: var(--sans); font-size: inherit;
  color: inherit; text-align: left;
  cursor: pointer;
}
.kit-n {
  font-variant-numeric: tabular-nums;
  font-size: 0.92rem;
  color: var(--doc-ink-40);
  transition: color 0.3s var(--ease-soft);
}
.kit-name {
  font-size: clamp(1rem, 1.35vw, 1.18rem);
  font-weight: 500;
  line-height: 1.3;
  letter-spacing: -0.01em;
  transition: transform 0.35s var(--ease);
}
.kit-meta {
  font-family: var(--cond); font-synthesis: none;
  font-size: 0.66rem; font-weight: 600;
  letter-spacing: 0.13em; text-transform: uppercase;
  color: var(--doc-ink-40);
  white-space: nowrap;
}
.kit-go {
  justify-self: end;
  font-size: 0.95rem; line-height: 1;
  color: var(--doc-ink-40);
  transition: color 0.3s var(--ease-soft), transform 0.35s var(--ease);
}
.kit-row:hover .kit-n,
.kit-row:hover .kit-meta,
.kit-row:hover .kit-go,
.kit-row:focus-visible .kit-go { color: var(--doc-ink); }
.kit-row:hover .kit-name { transform: translateX(4px); }
.kit-row:hover .kit-go { transform: translateY(3px); }
/* Prompt rows copy rather than download. The action is a round icon
   button on the right; the prompt itself never shows - it sits in a
   hidden <pre>. The tick replaces the sheets once it lands. */
.kit-go--copy {
  display: inline-grid;
  place-items: center;
  width: 1.5rem; height: 1.5rem;
  color: var(--doc-ink-40);
  transition: color 0.3s var(--ease-soft);
}
.kit-go--copy svg { grid-area: 1 / 1; width: 16px; height: 16px; }
.kit-go--copy .i-done { opacity: 0; transform: scale(0.7); transition: opacity 0.25s var(--ease), transform 0.25s var(--ease); }
.kit-go--copy .i-copy { transition: opacity 0.25s var(--ease); }

.kit-item--prompt .kit-row:hover .kit-go--copy { transform: none; color: var(--doc-ink); }
.kit-item.copied .kit-go--copy { color: var(--doc-ink); }
.kit-item.copied .kit-go--copy .i-copy { opacity: 0; }
.kit-item.copied .kit-go--copy .i-done { opacity: 1; transform: scale(1); }
.kit-item.copy-failed .kit-go--copy { color: var(--doc-ink); }
.kit-pre[hidden] { display: none; }

/* A group row is a label, not a link - nothing to click on it.
   Its children hang off a hairline so the nesting reads at a glance. */
.kit-row--label { cursor: default; }
.kit-sub {
  margin: 0.15rem 0 0.9rem 3.4rem;
}
.kit-sub .kit-item { border: 0; }
.kit-sub .kit-row {
  grid-template-columns: minmax(0, 1fr) auto;
  gap: 1rem;
  padding-block: 0.55rem;
}
.kit-sub .kit-name { font-size: clamp(0.95rem, 1.2vw, 1.05rem); font-weight: 400; }
.kit-sub .kit-row:hover .kit-name { transform: translateX(3px); }

/* ── closing ─────────────────────────────────────────────────── */
.talks-end {
  margin-top: clamp(4.5rem, 9vw, 8rem);
  text-align: center;
}
.talks-end h2 {
  font-family: var(--cond); font-synthesis: none;
  font-size: clamp(2.1rem, 6.4vw, 5rem);
  font-weight: 900; line-height: 0.94; letter-spacing: -0.02em;
  max-width: 16ch; margin-inline: auto;
  text-wrap: balance;
}
.talks-end p {
  margin: clamp(1.35rem, 2.5vw, 1.9rem) auto 0;
  max-width: 32rem;
  color: var(--cream-65);
  line-height: 1.6;
}

/* ── feedback card ───────────────────────────────────────────
   Same paper as the doc, so it reads as a page torn out of it
   rather than a browser dialog dropped on top.
   ------------------------------------------------------------ */
.sheet {
  position: fixed; inset: 0; z-index: 210;
  display: none;
  place-items: center;
  padding: clamp(1rem, 4vw, 3rem);
  /* No backdrop-filter here on purpose. A blurred full-viewport backdrop
     is re-computed every time the card above it repaints, which is once
     per keystroke - that was the typing lag. An opaque scrim costs nothing. */
  background: rgba(5, 5, 5, 0.94);
}
.sheet.open { display: grid; }
.sheet-card {
  position: relative;
  width: min(100%, 34rem);
  max-height: 88vh;
  overflow-y: auto;
  background: var(--doc);
  color: var(--doc-ink);
  border-radius: 0;                    /* hard edges, like the doc cards */
  padding: clamp(1.6rem, 3.4vw, 2.75rem);
  contain: paint;              /* keep keystroke repaints inside the card */
}
/* just the cross - no ring around it. The hit area stays 2.1rem so it is
   still comfortably tappable, the outline simply is not drawn. */
.sheet-x {
  position: absolute; top: clamp(0.9rem, 2vw, 1.35rem); right: clamp(0.9rem, 2vw, 1.35rem);
  width: 2.1rem; height: 2.1rem;
  display: grid; place-items: center;
  border: 0;
  border-radius: 0;
  background: none;
  color: var(--doc-ink-60);
  font-size: 1rem; line-height: 1;
  cursor: pointer;
  transition: color 0.25s var(--ease-soft), transform 0.25s var(--ease);
}
.sheet-x:hover { color: var(--doc-ink); transform: scale(1.12); }
.sheet-x:focus-visible { outline: 2px solid var(--doc-ink); outline-offset: 2px; }

.sheet-kicker {
  font-family: var(--cond); font-synthesis: none;
  font-size: 0.7rem; font-weight: 600;
  letter-spacing: 0.2em; text-transform: uppercase;
  color: var(--doc-ink-40);
}
.sheet-title {
  margin-top: 0.5rem;
  margin-bottom: clamp(1.35rem, 2.6vw, 1.9rem);
  font-family: var(--cond); font-synthesis: none;
  font-size: clamp(2rem, 5vw, 3.1rem);
  font-weight: 900; line-height: 0.94; letter-spacing: -0.02em;
}

.sheet-form { display: grid; gap: clamp(1.1rem, 2.2vw, 1.5rem); }
.sheet-field { display: grid; gap: 0.5rem; }
.sheet-label {
  font-family: var(--cond); font-synthesis: none;
  font-size: 0.66rem; font-weight: 600;
  letter-spacing: 0.16em; text-transform: uppercase;
  color: var(--doc-ink-40);
}
.sheet-in {
  width: 100%;
  font-family: var(--ui);
  font-size: 0.98rem;
  line-height: 1.55;
  color: var(--doc-ink);
  background: none;
  border: 0;
  border-bottom: 1px solid var(--doc-line);
  border-radius: 0;
  padding: 0.5rem 0;
  resize: vertical;
  transition: border-color 0.3s var(--ease-soft);
}
.sheet-in::placeholder { color: var(--doc-ink-40); }

.sheet-select {
  appearance: none; -webkit-appearance: none;
  padding-right: 1.6rem;
  cursor: pointer;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 9 6' fill='none'%3E%3Cpath d='M1 1l3.5 3.5L8 1' stroke='%230b0b0b' stroke-opacity='.55' stroke-width='1.4' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 0.15rem center;
  background-size: 10px 7px;
}
.sheet-select:invalid { color: var(--doc-ink-40); }   /* the placeholder option */
.sheet-in:focus { outline: none; border-bottom-color: var(--doc-ink); }
textarea.sheet-in { min-height: 7.5rem; }

.sheet-err {
  font-size: 0.85rem;
  line-height: 1.45;
  color: var(--doc-ink);
  padding-left: 0.75rem;
  border-left: 1px solid var(--doc-ink);
}
.sheet-actions { display: flex; align-items: center; flex-wrap: wrap; gap: 0.75rem 1.1rem; }
.sheet-actions .pill {
  background: var(--doc-ink); border-color: var(--doc-ink); color: var(--doc);
  font-size: 1rem;
  padding: 0.85em 1.9em;
}
.sheet-actions .pill:hover { background: transparent; color: var(--doc-ink); }
/* honeypot: off-screen rather than display:none, so bots that check
   for visibility still fill it in */
.sheet-bot {
  position: absolute;
  width: 1px; height: 1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}
.sheet-err a { color: inherit; text-decoration: underline; text-underline-offset: 3px; }
.sheet-actions .pill:disabled { opacity: 0.45; cursor: default; }

/* sent state. [hidden] has to win over the display below. */
.sheet [hidden] { display: none !important; }
.sheet-done { display: grid; justify-items: start; gap: 0.6rem; }
.sheet-done p { font-size: 0.95rem; line-height: 1.6; color: var(--doc-ink-60); max-width: 26rem; }
/* must out-rank .sheet-done p above, or the tick goes dark on dark */
/* The same verified badge that sits beside the testimonial names. It draws
   its own rosette and fill, so no disc behind it. */
.sheet-done p.sheet-done-mark {
  display: grid; place-items: center;
  width: 2.4rem; height: 2.4rem;
  margin-bottom: 0.4rem;
}
.sheet-done-mark svg { width: 100%; height: 100%; display: block; }
.sheet-done h3 {
  font-family: var(--cond); font-synthesis: none;
  font-size: clamp(1.6rem, 3.6vw, 2.3rem);
  font-weight: 900; line-height: 0.98; letter-spacing: -0.02em;
}
/* the card asked "How was it?"; once answered, it stops asking */
.sheet-card:has(.sheet-done:not([hidden])) .sheet-kicker,
.sheet-card:has(.sheet-done:not([hidden])) .sheet-title { display: none; }
.sheet-done .pill {
  margin-top: 0.9rem;
  background: var(--doc-ink); border-color: var(--doc-ink); color: var(--doc);
  font-size: 1rem; padding: 0.85em 1.9em;
}
.sheet-done .pill:hover { background: transparent; color: var(--doc-ink); }

/* ── responsive ──────────────────────────────────────────────── */
@media (max-width: 900px) {
  .doc-body { grid-template-columns: 1fr; gap: 1.75rem; }
  .doc-side-note { max-width: none; }
  .talk-head { grid-template-columns: 2.75rem minmax(0, 1fr) 1.75rem; gap: 0.9rem; }
}
@media (max-width: 620px) {
  /* three short lines read better than one that wraps mid-phrase */
  .talks-hero .eyebrow { flex-direction: column; align-items: center; gap: 0.35em; }

  /* the file meta drops under the name rather than squeezing it.
     Every cell is placed explicitly - leave one to auto-placement
     and it lands back in column 1. */
  .kit-row { grid-template-columns: 2rem minmax(0, 1fr) auto; row-gap: 0.25rem; }
  .kit-n    { grid-column: 1; grid-row: 1; }
  .kit-name { grid-column: 2; grid-row: 1; }
  .kit-go   { grid-column: 3; grid-row: 1; }
  .kit-meta { grid-column: 2; grid-row: 2; white-space: normal; }

  .kit-sub { margin-left: 0.9rem; }
  .kit-sub .kit-row { grid-template-columns: minmax(0, 1fr) auto; }
  .kit-sub .kit-name { grid-column: 1; }
  .kit-sub .kit-go { grid-column: 2; }
  .talks-cta { flex-direction: column; align-items: stretch; }
  .talks-cta .pill { justify-content: center; }
  .talks-cta .sep { display: none; }
}

/* the sub-list of prompts stays shut until asked for */
.kit-row--group { cursor: pointer; }
.kit-go--caret {
  display: inline-grid; place-items: center;
  width: 1.5rem; height: 1.5rem;
  color: var(--doc-ink-40);
  transition: transform 0.4s var(--ease), color 0.3s var(--ease-soft);
}
.kit-go--caret svg { width: 10px; height: 7px; }
.kit-row--group:hover .kit-go--caret { color: var(--doc-ink); }
.kit-item.is-open .kit-go--caret { transform: rotate(180deg); color: var(--doc-ink); }

.kit-sub {
  display: grid;
  grid-template-rows: 0fr;
  margin: 0 0 0 3.4rem;
  transition: grid-template-rows 0.45s var(--ease), margin 0.45s var(--ease);
}
.kit-item.is-open > .kit-sub { grid-template-rows: 1fr; margin-bottom: 0.9rem; }
.kit-sub > * { overflow: hidden; }

/* no rule under the last line of a list - the card edge ends it */
.doc-list li:last-child,
.kit-list > .kit-item:last-child { border-bottom: 0; }

@media (prefers-reduced-motion: reduce) {
  .kit-sub { transition: none; }
}

/* ============================================================
   CLIENTS - the logo wall
   ------------------------------------------------------------
   Equal columns keep the rows aligned; each mark then sits at its
   own optical width (--w, written by tools/logos.py) so a 6.5:1
   wordmark and a 1:1 crest carry the same visual weight instead of
   the same height. Re-run that script if the logos change.
   ============================================================ */
.clients { margin-top: clamp(3rem, 6vw, 5rem); }
.clients-lab {
  text-align: center;
  font-family: var(--cond); font-synthesis: none;
  font-size: 0.72rem; font-weight: 600;
  letter-spacing: 0.18em; text-transform: uppercase;
  color: var(--cream-55);
  padding-bottom: 1rem;
  border-bottom: 1px solid var(--cream-12);
}

.client-grid {
  --s: 1;                                  /* one dial scales the whole set */
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: clamp(1.6rem, 3.4vw, 3rem);
  padding-block: clamp(1.75rem, 3.5vw, 2.75rem);
}
.client { flex: 0 0 auto; display: grid; place-items: center; }
.client-break { flex: 0 0 100%; height: 0; }
.client-break--m { display: none; }
.client img {
  width: calc(var(--w) * var(--s) * 1px);
  height: auto;
  opacity: 0.9;
  transition: opacity 0.35s var(--ease-soft);
}
/* Two hand-drawn marks per logo - show the one that suits the theme. Both are
   native <img>, so the box is sized identically in every browser (fixes the
   mobile size mismatch) and each set renders exactly as its owner drew it. */
.client .c-lite { display: none; }
.client:hover img { opacity: 1; }

/* Even gaps beat aligned columns for a wall of mixed shapes: an equal-cell
   grid strands the square crests in empty space. Rows fill by what fits and
   the last one centres, so it reads deliberate at any width. */

/* Below this it becomes 5 / 5 / 4: the desktop break switches off and the
   two mobile ones switch on. Row weights are solved in tools/logos.py so
   all three rows end up with matching gaps. */
@media (max-width: 1180px) { .client-grid { --s: 0.94; } }
@media (max-width: 900px) {
  .client-grid { --s: 0.9; column-gap: clamp(0.9rem, 2.4vw, 1.75rem); row-gap: 2rem; }
  .client-break--d { display: none; }
  .client-break--m { display: block; }
}
@media (max-width: 720px) { .client-grid { --s: 0.74; row-gap: 1.75rem; } }
@media (max-width: 560px) { .client-grid { --s: 0.6;  column-gap: 0.8rem; row-gap: 1.5rem; } }
@media (max-width: 400px) { .client-grid { --s: 0.52; column-gap: 0.6rem; row-gap: 1.35rem; } }

/* ── an upcoming session: listed, flagged, nothing to open yet ── */
.talk-head--upcoming {
  display: grid;
  grid-template-columns: 4.5rem minmax(0, 1fr);
  align-items: start;
  gap: 1.25rem;
  width: 100%;
  padding-block: clamp(1.5rem, 3.2vw, 2.5rem);
}
/* the flag rides with the venue line */
.talk-sub {
  display: flex; align-items: center; flex-wrap: wrap;
  gap: 0.6rem 0.85rem;
  margin-top: clamp(0.5rem, 1vw, 0.8rem);
}
.talk-sub .talk-where { margin-top: 0; }
.talk-flag {
  padding: 0.42em 0.95em;
  border: 1px solid var(--cream-28);
  border-radius: 999px;
  font-family: var(--cond); font-synthesis: none;
  font-size: 0.62rem; font-weight: 600;
  letter-spacing: 0.16em; text-transform: uppercase;
  color: var(--cream-70);
  white-space: nowrap;
}
.talk.is-upcoming .talk-name { color: var(--cream); }
.talk.is-upcoming .talk-where { color: var(--cream-55); }

@media (max-width: 900px) {
  .talk-head--upcoming { grid-template-columns: 2.75rem minmax(0, 1fr); gap: 0.9rem; }
}

/* ── splash: small screens ───────────────────────────────────── */
@media (max-width: 620px) {
  .splash-pill { padding: 0.62em 1.05em; letter-spacing: 0.12em; }
  /* links stay stacked to the right; the testimonial trigger sits opposite */
  .splash-links { gap: 0.5rem; }
  .splash-links a { font-size: 0.78rem; letter-spacing: 0.12em; }
  /* on a phone there is no hover, so the underline is always on */
  .splash-links a::after { transform: scaleX(1); }
}

/* ============================================================
   Testimonials
   ============================================================ */
.splash-bar { justify-content: space-between; align-items: flex-end; gap: 1.25rem; }

/* the trigger, bottom-left of the splash */
.tst-open {
  /* The ring hangs outside the button by these amounts. The same values are
     used as margin, so the ring's outer edge lands on the button's margin
     box - which sits inside the bar's padding. That makes it impossible for
     the ring to reach the stage's overflow:hidden edge, whatever --pad is.
     Landscape phones shrink --pad to 0.9rem, which used to shave the left
     of the ring off. */
  --ring-x: 1.15em;
  --ring-y: 0.62em;
  margin: var(--ring-y) var(--ring-x);
  position: relative;
  align-self: flex-end;
  /* block, not the default inline-block: an inline button carries baseline
     descender space under its content, which pushed the ring a couple of
     pixels below the words */
  display: block;
  /* room for the ring to sit clear of the words */
  padding: 0.5em 0.9em;
  background: none; border: 0; cursor: pointer;
  /* iOS paints a translucent black box over a tapped control by default,
     which on this button is big enough to read as a black slab */
  -webkit-tap-highlight-color: transparent;
  font-family: var(--cond); font-synthesis: none;
  font-size: clamp(0.8rem, 1.15vw, 0.95rem); font-weight: 600;
  letter-spacing: 0.14em; text-transform: uppercase; line-height: 1.3;
  color: var(--cream);
  text-align: center;                 /* centred inside its own ring */
  max-width: 13em;
  transition: color 0.3s var(--ease-soft);
}
/* Gated on pointers that can actually hover. A tap on a touch screen leaves
   :hover stuck on, and this rule's black then painted the label out against
   the dark subject. Touch gets its brighten from the :active rule below,
   the same way .splash-links a does. */
@media (hover: hover) {
  .tst-open:hover { color: #fff; }
  html[data-theme="light"] body.splash .tst-open:hover { color: #000; }
}
.tst-open:active { color: #fff; }
.tst-open-label { position: relative; z-index: 1; display: block; }

/* The hand-drawn ring.
   The overhang is equal on opposing sides and the path is symmetric about
   the centre of its viewBox, so the label sits dead centre at any size or
   line count - no per-breakpoint nudging.
   preserveAspectRatio="none" lets the ellipse follow the shape of the text
   block; vector-effect="non-scaling-stroke" stops that uneven stretch from
   dragging the line weight with it, which is what made it look wobbly. */
.tst-scribble {
  position: absolute;
  left: calc(var(--ring-x) * -1);
  top:  calc(var(--ring-y) * -1);
  /* Sized explicitly rather than by inset. An <svg> carries the intrinsic
     ratio of its viewBox, so `height: auto` was resolving from 300:100 and
     spilling past the bottom - which is what pushed the ring off-centre. */
  width:  calc(100% + var(--ring-x) * 2);
  height: calc(100% + var(--ring-y) * 2);
  overflow: visible; pointer-events: none;
  color: var(--cream);
}
.tst-scribble-path {
  stroke-width: 2;
  stroke-linecap: butt;          /* round left a stray dot at the start - butt has none */
  stroke-dasharray: 100;
  stroke-dashoffset: 100;        /* hidden; path is ordered top -> left -> bottom -> right (anti-clockwise) */
  animation: tstDraw 1.1s cubic-bezier(0.45, 0, 0.2, 1) 0.9s forwards;
}
/* Draw once and stay. No loop, no fade-reset, nothing running backwards. */
@keyframes tstDraw {
  to { stroke-dashoffset: 0; }
}
@media (prefers-reduced-motion: reduce) {
  .tst-scribble-path { animation: none; stroke-dashoffset: 0; opacity: 1; }
}
/* over the dark subject on mobile light mode, keep it light like the links */
@media (max-width: 620px) {
  html[data-theme="light"] body.splash .tst-open,
  html[data-theme="light"] body.splash .tst-scribble { color: rgba(247, 247, 245, 0.92); }
  /* brightens on press exactly like .splash-links a - never to black */
  html[data-theme="light"] body.splash .tst-open:active,
  html[data-theme="light"] body.splash .tst-open:active .tst-scribble { color: #f7f7f5; }
  .tst-scribble-path { stroke-width: 1.75; }
  /* a narrower overhang so the ring keeps clear of the screen edge */
  .tst-open { --ring-x: 0.8em; }
}

/* the carousel, inside the on-brand .sheet card */
/* The quote gets the card's full width. Flanking it with arrows squeezed
   the measure to ~37 characters a line, which is what made the testimonials
   feel cramped - this puts it in the comfortable 60-70 range and moves the
   controls into a footer row instead. */
/* The card never scrolls. .sheet-card allows overflow-y for the review
   form, but here a scrollable card let the quote be pushed out of view
   and left the reader staring at an empty box. The quote is scaled to fit
   instead (see tstLevel), so there is never anything to scroll to. */
.tst-card { width: min(100%, 40rem); overflow: hidden; }
.tst-stage { margin-top: 0.4rem; }

.tst-foot {
  display: flex; align-items: center; justify-content: space-between;
  gap: 1rem;
  margin-top: clamp(1.4rem, 3vw, 2rem);
  /* no rule here - the only line in the card is the one above the name */
}
.tst-nav { display: flex; gap: 0.5rem; }
.tst-track {
  flex: 1 1 auto; min-width: 0;
  /* Matched to TST_SWITCH in main.js so the card resizes in step with the
     slide instead of finishing first and leaving a beat of empty card. */
  transition: height 0.62s var(--ease);
  align-items: flex-start;               /* slides keep their own height, so it can be measured */
  display: flex;
  /* overflow-y must be stated. A `visible` axis computes to `auto` as soon
     as the other axis is not visible, so overflow-x alone left the track
     scrollable vertically - and its scroll height is the TALLEST quote in
     the row, not the one on screen. That is the empty space a reader hit
     when they scrolled down on a short testimonial. */
  overflow-x: auto; overflow-y: hidden;
  /* auto, not smooth: tstSlide writes scrollLeft every frame, and smooth
     would have the browser animate each of those writes on top of the
     easing already being applied. */
  scroll-snap-type: x mandatory; scroll-behavior: auto;
  scrollbar-width: none; -webkit-overflow-scrolling: touch; overscroll-behavior-x: contain;
  /* A swipe across a quote was grabbing the text and dragging it out of
     place instead of moving the carousel. The gesture reads as a text
     selection-drag, so the text is taken out of selection here. */
  -webkit-user-select: none; user-select: none;
  -webkit-touch-callout: none;
  /* Sideways and nothing else. Without this a touch that drifts vertically
     is handed to the page behind the card. */
  touch-action: pan-x;
}
.tst-track::-webkit-scrollbar { display: none; }
.tst-track:focus-visible { outline: 2px solid var(--doc-ink); outline-offset: 4px; }
.tst-slide {
  flex: 0 0 100%; scroll-snap-align: center; margin: 0;
  display: flex; flex-direction: column;
  gap: clamp(1.5rem, 3vw, 2.1rem);
  justify-content: flex-start;
  padding: 0.25rem 0.15rem;
}
/* Read as prose, not as a block of filler: open leading and a measure that
   keeps lines in the 60-75 character range regardless of card width. */
.tst-quote {
  margin: 0;
  font-family: var(--serif);
  font-size: clamp(1.02rem, 1.5vw, 1.16rem);
  line-height: 1.78;
  color: var(--doc-ink);
  max-width: 38em;
  text-wrap: pretty;
}
.tst-quote p { margin: 0; }
.tst-quote p + p { margin-top: 1.05em; }   /* the breaks the writer intended */
.tst-quote + .tst-quote { margin-top: 1.05em; }

.tst-cite {
  display: flex; flex-direction: column; gap: 0.2rem;
  padding-top: clamp(0.9rem, 2vw, 1.2rem);
  border-top: 1px solid var(--doc-hair);   /* separates the voice from the words */
}
.tst-name {
  display: inline-flex; align-items: center; gap: 0.4rem;
  font-family: var(--sans); font-weight: 600; font-size: 0.95rem; color: var(--doc-ink);
}
.tst-role { font-family: var(--sans); font-size: 0.82rem; color: var(--doc-ink-60); line-height: 1.4; }
.tst-badge {
  width: 1.05em; height: 1.05em; flex: none; display: block;
  /* keep the mark on its own layer so it doesn't re-rasterise / jitter
     while the slide scrolls on mobile */
  transform: translateZ(0);
  backface-visibility: hidden;
}

.tst-btn {
  flex: none; width: clamp(2.2rem, 4vw, 2.6rem); aspect-ratio: 1;
  display: grid; place-items: center; padding: 0;
  border: 1px solid var(--doc-line); border-radius: 999px;
  background: none; color: var(--doc-ink); cursor: pointer;
  transition: background 0.3s var(--ease-soft), color 0.3s var(--ease-soft), border-color 0.3s var(--ease-soft);
}
.tst-btn svg { width: 7px; height: 12px; }
.tst-btn--prev svg { transform: rotate(180deg); }
.tst-btn:hover { background: var(--doc-ink); color: var(--doc); border-color: var(--doc-ink); }

.tst-count {
  font-family: var(--cond); font-synthesis: none;
  font-size: 0.72rem; font-weight: 600; letter-spacing: 0.14em;
  color: var(--doc-ink-60);            /* -40 measured 2.7:1, under the 4.5 floor */
}
@media (max-width: 620px) {
  .tst-btn { width: 2.4rem; }
  .tst-quote { font-size: 1rem; line-height: 1.72; }
}
@media (max-width: 380px) {
  .splash-links a { font-size: 0.72rem; letter-spacing: 0.07em; }
  .splash-logo img { width: 68px; }
}
/* landscape phones: almost no height, so everything tightens and the
   crop shifts up to keep his head in frame */
@media (max-height: 430px) and (orientation: landscape) {
  :root { --pad: 0.9rem; }
  .splash-logo img { width: 66px; }
  .splash-links { flex-direction: row; align-items: center; gap: 1.1rem; }
  .splash-stage::before { background-position: center 24%; }
  /* row layout sits over the subject here too - keep links light in light mode */
  html[data-theme="light"] body.splash .splash-links a { color: rgba(247, 247, 245, 0.72); }
  html[data-theme="light"] body.splash .splash-links a:hover { color: #f7f7f5; }
  html[data-theme="light"] body.splash .splash-links a::after { background: #f7f7f5; }
}

/* ============================================================
   PHOTO SLIDER - contact page
   ------------------------------------------------------------
   Nothing is ever cropped. The photos are all 3:4, so the track
   is sized to exactly that and every corner survives.
   A full-width 3:4 would stand 1600px tall on desktop, so the
   frame is driven by height instead - which leaves room either
   side for the arrows to flank the photo rather than sit on it.
   On a phone the photo takes the full width and the arrows drop
   underneath, pinned to its two edges.
   ============================================================ */
.shots { margin-top: clamp(3rem, 6vw, 5rem); }

.shots-stage {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: clamp(0.75rem, 2.4vw, 2rem);
}

.shots-track {
  /* exactly as wide as a 3:4 photo at this height, so the arrows land
     against the picture and not against empty page */
  width: calc(min(74vh, 720px) * 3 / 4);
  max-width: 100%;
  display: flex;
  overflow-x: auto;
  scroll-snap-type: x mandatory;
  scroll-behavior: smooth;
  scrollbar-width: none;
  -webkit-overflow-scrolling: touch;
  overscroll-behavior-x: contain;
}
.shots-track::-webkit-scrollbar { display: none; }
.shots-track:focus-visible { outline: 2px solid var(--cream); outline-offset: 3px; }

.shot {
  flex: 0 0 100%;
  scroll-snap-align: center;
  margin: 0;
  display: grid;
  place-items: center;
  height: min(74vh, 720px);
}
.shot img {
  max-width: 100%;
  max-height: 100%;
  width: auto; height: auto;
  object-fit: contain;          /* every corner, always */
  display: block;
}

.shots-btn {
  flex: none;
  width: clamp(2.5rem, 4.4vw, 3rem);
  aspect-ratio: 1;
  display: grid; place-items: center;
  padding: 0;
  border: 1px solid var(--cream-28);
  border-radius: 999px;
  background: none;
  color: var(--cream);
  cursor: pointer;
  transition: background 0.3s var(--ease-soft), border-color 0.3s var(--ease-soft),
              color 0.3s var(--ease-soft);
}
.shots-btn svg { width: 8px; height: 14px; }
.shots-btn--prev svg { transform: rotate(180deg); }
.shots-btn:hover { background: var(--cream); border-color: var(--cream); color: var(--stage); }

@media (max-width: 620px) {
  /* photo full width, arrows wrap onto their own line and sit centred under it */
  .shots-stage { flex-wrap: wrap; justify-content: center; gap: 0.75rem; }
  .shots-track {
    order: -1;
    flex: 0 0 100%;
    width: 100%;
    margin-bottom: clamp(0.85rem, 3vw, 1.15rem);
  }
  .shot { height: auto; aspect-ratio: 3 / 4; }
  .shot img { width: 100%; height: 100%; }
}
@media (prefers-reduced-motion: reduce) {
  .shots-track { scroll-behavior: auto; }
}

/* ============================================================
   14. Touch ergonomics
   ------------------------------------------------------------
   Phone-only sizing. Everything here is about the finger, not
   the look: the visual weight of each control is unchanged.
   ============================================================ */
@media (max-width: 620px) {
  /* iOS zooms the entire page in when a focused field measures under
     16px, and never zooms back out. This is the one number that has
     to be absolute rather than rem-scaled. */
  .sheet-in { font-size: 16px; }

  /* 2.5rem is 37.5px against a 44px guideline */
  .theme-toggle, .menu-btn { width: 2.95rem; height: 2.95rem; }

  /* The close X is 2.1rem - 31.5px. It has no border or background, so
     growing the button grows only the target, not the mark. The offset is
     pulled in by the same amount so the glyph stays where it was. */
  .sheet-x {
    width: 2.95rem; height: 2.95rem;
    top: calc(clamp(0.9rem, 2vw, 1.35rem) - 0.42rem);
    right: calc(clamp(0.9rem, 2vw, 1.35rem) - 0.42rem);
  }

  /* 36px rows in the dropdown, opened up to 44 */
  .menu-panel a,
  .menu-panel .is-soon { padding: 0.88rem 0.8rem; }

  /* The splash and footer links are 15-18px of text. Padding them would
     drag the underline off the baseline and reflow the row, so the hit
     area is grown with a transparent overlay instead - layout untouched.
     In portrait these stack in a column with a 7.5px gap, so the overlay
     may only claim half that gap on each side. Taking the full 44px here
     makes each link's overlay cover its neighbours' text, and the last
     one in the DOM wins the hit test - which silently kills every link
     above it. Grow into the gap, nothing more. */
  .splash-links a,
  .foot-links a { position: relative; }
  .splash-links a::before,
  .foot-links a::before {
    content: '';
    position: absolute;
    left: 0; right: 0;
    top: -3px; bottom: -3px;
  }
}

/* Landscape phones lay the splash links out in a single row, so there is
   no vertical neighbour to collide with and the overlay can take the full
   recommended target. Spelled out in full rather than inherited: a 667px
   landscape phone is wider than the 620px block above, so nothing from it
   applies here - including the content and position that make the overlay
   exist at all. */
@media (max-height: 430px) and (orientation: landscape) {
  .splash-links a { position: relative; }
  .splash-links a::before {
    content: '';
    position: absolute;
    left: 0; right: 0;
    top: 50%; height: 44px;
    transform: translateY(-50%);
  }
}

/* Short viewports - a small phone in portrait, or a laptop in landscape
   with little height to spare. The longest testimonial has nowhere to go
   there, and the card is not allowed to scroll, so room is reclaimed from
   the card's own chrome before tstLevel has to shrink the quote. */
@media (max-height: 660px) {
  .tst-card { max-height: 94vh; }
  .tst-card.sheet-card { padding: 1.15rem 1.2rem 1.3rem; }
  .tst-card .sheet-title {
    font-size: clamp(1.35rem, 4.6vw, 1.9rem);
    margin-top: 0.3rem;
    margin-bottom: 0.85rem;
  }
}

/* ============================================================
   NOTES — the writing
   ------------------------------------------------------------
   Two surfaces that the Talks archive never had: an editorial
   index (/notes) and the article pages themselves (/notes/<slug>).
   Both read on the black stage, the same reading mode as About,
   so Notes is a place you read — not another list that folds
   open. Every colour is a shared token, so both flip with the
   theme for free.
   ============================================================ */

/* ── index: masthead ─────────────────────────────────────────── */
.notes-head { padding-top: clamp(3rem, 8vw, 6rem); text-align: center; }
.notes-head .page-lede { font-weight: 300; }

/* a small category eyebrow, used by the lead and every row */
.n-cat {
  font-family: var(--cond); font-synthesis: none;
  font-size: 0.66rem; font-weight: 600;
  letter-spacing: 0.18em; text-transform: uppercase;
  color: var(--cream-55);
}

/* ── index: the linear ledger ─────────────────────────────────
   No boxes. Each note is one line in a running index — a big,
   thin Wide-Light numeral (the face this brand reserves for
   numerals), a Condensed-Black title, and a hairline. The list
   reads top to bottom like a contents page. Nothing inverts, so
   dark stays dark and light stays light; the numeral is the only
   ornament, and the rule is the only divider — one per entry,
   because a ledger needs its lines.
   ------------------------------------------------------------ */
.notes-list {
  max-width: 60rem;
  margin: clamp(2.75rem, 5vw, 4.5rem) auto 0;
}

.nrow {
  display: grid;
  grid-template-columns: minmax(2.5rem, 4.5rem) minmax(0, 1fr);
  gap: clamp(1rem, 3vw, 2.75rem);
  align-items: start;
  padding-block: clamp(1.75rem, 3.5vw, 2.85rem);
  border-top: 1px solid var(--cream-12);
  color: var(--cream);
}
.nrow:last-child { border-bottom: 1px solid var(--cream-12); }

/* the numeral — Ringside Wide Light, thin and large, a quiet aside */
.nrow-num {
  font-family: var(--wide); font-synthesis: none;
  font-weight: 300;
  font-size: clamp(1.35rem, 2.6vw, 2.1rem);
  line-height: 1; letter-spacing: 0.02em;
  font-variant-numeric: tabular-nums;
  color: var(--cream-28);
  transition: color 0.4s var(--ease-soft);
}

.nrow-main { min-width: 0; }
.nrow-head {
  display: flex; align-items: baseline; justify-content: space-between;
  gap: 1rem; flex-wrap: wrap;
  margin-bottom: clamp(0.7rem, 1.4vw, 1rem);
}
.nrow-meta {
  font-family: var(--cond); font-synthesis: none;
  font-size: 0.66rem; font-weight: 600;
  letter-spacing: 0.14em; text-transform: uppercase;
  color: var(--cream-55);
  white-space: nowrap;
}
.nrow-title {
  display: block;
  font-family: var(--cond); font-synthesis: none;
  font-weight: 900;
  font-size: clamp(1.85rem, 4.2vw, 3.35rem);
  line-height: 0.98; letter-spacing: -0.02em;
  color: var(--cream); text-wrap: balance;
  transition: transform 0.45s var(--ease);
}
.nrow-dek {
  display: block;
  margin-top: clamp(0.7rem, 1.4vw, 1rem);
  max-width: 42rem;
  font-family: var(--serif); font-synthesis: none; font-weight: 300;
  font-size: clamp(1rem, 1.3vw, 1.15rem);
  line-height: 1.55; color: var(--cream-65);
  text-wrap: pretty;
}

/* hover stays in-theme: the numeral lights up and the title steps
   toward it — no colour leaves the palette */
.nrow:hover .nrow-num { color: var(--cream); }
.nrow:hover .nrow-title { transform: translateX(clamp(6px, 1.2vw, 14px)); }

@media (max-width: 620px) {
  .nrow {
    grid-template-columns: 1fr;
    gap: 0.55rem;
    padding-block: clamp(1.5rem, 6vw, 2rem);
  }
  .nrow-num { font-size: 1.05rem; }
  .nrow:hover .nrow-title { transform: none; }
}
@media (prefers-reduced-motion: reduce) {
  .nrow-title { transition: none; }
}

/* ── the article page ────────────────────────────────────────── */
.article-nav {
  padding-top: clamp(1.5rem, 3vw, 2.5rem);
}
.article-back {
  display: inline-block;
  font-family: var(--cond); font-synthesis: none;
  font-size: 0.72rem; font-weight: 600;
  letter-spacing: 0.16em; text-transform: uppercase;
  color: var(--cream-55);
  transition: color 0.25s var(--ease-soft);
}
.article-back:hover { color: var(--cream); }

.article-head {
  padding-top: clamp(2rem, 5vw, 3.5rem);
  text-align: center;
}
.article-head .n-cat { display: block; margin-bottom: clamp(1.1rem, 2.4vw, 1.8rem); }
.article-title {
  font-family: var(--cond); font-synthesis: none;
  font-size: clamp(2.4rem, 7vw, 5.4rem);
  font-weight: 900; line-height: 0.92; letter-spacing: -0.025em;
  max-width: 18ch; margin-inline: auto;
  text-wrap: balance;
}
.article-dek {
  margin: clamp(1.35rem, 2.8vw, 2rem) auto 0;
  max-width: 40rem;
  font-family: var(--serif); font-synthesis: none;
  font-weight: 300;
  font-size: clamp(1.1rem, 1.6vw, 1.4rem);
  line-height: 1.5; color: var(--cream-65);
  text-wrap: pretty;
}
.article-meta {
  margin-top: clamp(1.5rem, 3vw, 2.25rem);
  display: flex; align-items: center; justify-content: center;
  flex-wrap: wrap; gap: 0.5rem 0.9rem;
  font-family: var(--cond); font-synthesis: none;
  font-size: 0.66rem; font-weight: 600;
  letter-spacing: 0.14em; text-transform: uppercase;
  color: var(--cream-55);
}
.article-meta i { font-style: normal; color: var(--cream-28); }

/* the reading column — serif on the stage, one honest measure */
.article {
  max-width: 40rem;
  margin: clamp(2.5rem, 5vw, 4rem) auto 0;
}
.article > * + * { margin-top: 1.35rem; }
.article p {
  font-size: clamp(1.08rem, 1.3vw, 1.2rem);
  line-height: 1.75; color: var(--cream-70);
  text-wrap: pretty;
}
.article strong { color: var(--cream); font-weight: 400; }
.article em { font-style: italic; }
.article a {
  color: var(--cream);
  text-decoration: underline; text-underline-offset: 3px;
  text-decoration-thickness: 1px; text-decoration-color: var(--cream-22);
  transition: text-decoration-color 0.25s var(--ease);
}
.article a:hover { text-decoration-color: var(--cream); }
.article h2 {
  font-family: var(--cond); font-synthesis: none;
  font-weight: 900; font-size: clamp(1.5rem, 2.6vw, 2.1rem);
  line-height: 1.02; letter-spacing: -0.02em; color: var(--cream);
  margin-top: clamp(2.4rem, 4.5vw, 3.5rem);
}
/* a line pulled loud, set in the condensed grotesque */
.article-pull {
  margin-block: clamp(2.25rem, 4.5vw, 3.25rem);
  padding-left: clamp(1.1rem, 2vw, 1.6rem);
  border-left: 2px solid var(--cream);
  font-family: var(--cond); font-synthesis: none;
  font-weight: 400; font-size: clamp(1.6rem, 3.4vw, 2.6rem);
  line-height: 1.08; letter-spacing: -0.015em; color: var(--cream);
  text-wrap: balance;
}
.article ul { display: grid; gap: 0.7rem; margin-top: 1.35rem; }
.article ul li {
  position: relative; padding-left: 1.6rem;
  font-size: clamp(1.05rem, 1.25vw, 1.15rem);
  line-height: 1.6; color: var(--cream-70);
}
.article ul li::before {
  content: "\2014"; position: absolute; left: 0; color: var(--cream-28);
}

/* next read: a quiet, centred promo — one rule to mark the end of
   the article, nothing more */
.article-next {
  margin-top: clamp(3rem, 6vw, 5rem);
  display: block;
  padding-top: clamp(2rem, 4vw, 3rem);
  border-top: 1px solid var(--cream-12);
  text-align: center;
}
.article-next .n-cat { display: block; margin-bottom: 0.7rem; }
.article-next-title {
  display: block;
  font-family: var(--cond); font-synthesis: none;
  font-size: clamp(1.6rem, 3.4vw, 2.6rem);
  font-weight: 900; line-height: 1; letter-spacing: -0.02em;
  text-wrap: balance;
  transition: opacity 0.3s var(--ease-soft);
}
.article-next:hover .article-next-title { opacity: 0.6; }

/* ============================================================
   WORK — the project index + case studies
   ------------------------------------------------------------
   A visual portfolio: a two-up grid of large tiles, each pairing
   a client with a brand idea, opening into a full case-study
   page. Tiles carry a logo or the name set as type; covers are
   image-ready — drop a real project shot in as a background on
   .wtile-cover / .case-fig and the layout doesn't move. Panels
   are a faint --cream wash, so dark stays dark and light stays
   light. No inversions anywhere.
   ============================================================ */

/* ── index: the opening statement ────────────────────────────── */
.work-intro {
  padding-top: clamp(2.5rem, 6vw, 5rem);
  max-width: 24ch;
  font-family: var(--cond); font-synthesis: none;
  font-weight: 900;
  font-size: clamp(1.9rem, 4.4vw, 3.4rem);
  line-height: 1; letter-spacing: -0.025em;
  color: var(--cream); text-wrap: balance;
}

/* ── index: the "Projects" rule ──────────────────────────────── */
.work-label {
  margin-top: clamp(2.5rem, 5vw, 4rem);
  padding-bottom: 1rem;
  border-bottom: 1px solid var(--cream-12);
  font-family: var(--cond); font-synthesis: none;
  font-size: 0.72rem; font-weight: 600;
  letter-spacing: 0.18em; text-transform: uppercase;
  color: var(--cream-55);
}

/* ── index: the tile grid ────────────────────────────────────── */
.work-grid {
  margin-top: clamp(1.5rem, 3vw, 2.5rem);
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: clamp(1.25rem, 3vw, 2.5rem) clamp(1rem, 2.2vw, 1.75rem);
}
.wtile { display: block; color: var(--cream); }

.wtile-cover {
  position: relative;
  aspect-ratio: 4 / 3;
  display: grid; place-items: center;
  padding: clamp(1.5rem, 3vw, 2.5rem);
  overflow: hidden;
  background: var(--cream-12);
  transition: background 0.45s var(--ease-soft);
}
.wtile:hover .wtile-cover { background: var(--cream-22); }

/* a client logo, centred and theme-aware (own flip — not scoped
   to .client here) */
.wtile-logo { display: grid; place-items: center; width: 100%; height: 100%; }
.wtile-logo img {
  max-width: min(58%, 220px); max-height: 46%;
  width: auto; height: auto;
  opacity: 0.85; transition: opacity 0.4s var(--ease-soft);
}
.wtile:hover .wtile-logo img { opacity: 1; }
.wtile-logo .c-lite { display: none; }
.wtile-logo .c-dark { display: block; }
html[data-theme="light"] body.stage .wtile-logo .c-lite { display: block; }
html[data-theme="light"] body.stage .wtile-logo .c-dark { display: none; }

/* a typographic cover for projects with no logo (the name is the art) */
.wtile-type {
  font-family: var(--cond); font-synthesis: none;
  font-weight: 900;
  font-size: clamp(1.9rem, 3.6vw, 3rem);
  line-height: 0.94; letter-spacing: -0.02em;
  color: var(--cream); text-align: center; text-wrap: balance;
}

/* caption: the project title, then the sub-copy beneath it
   (Gold Front structure — stacked, not side by side) */
.wtile-cap {
  margin-top: clamp(1rem, 1.8vw, 1.35rem);
  display: block;
}
.wtile-client {
  display: block;
  font-family: var(--cond); font-synthesis: none;
  font-weight: 900; font-size: clamp(1.3rem, 2vw, 1.7rem);
  line-height: 1; letter-spacing: -0.015em; color: var(--cream);
  transition: transform 0.4s var(--ease);
}
.wtile:hover .wtile-client { transform: translateX(6px); }
.wtile-idea {
  display: block;
  margin-top: clamp(0.45rem, 0.9vw, 0.7rem);
  font-family: var(--serif); font-synthesis: none; font-weight: 300;
  font-size: clamp(1rem, 1.3vw, 1.15rem);
  line-height: 1.4; color: var(--cream-55); text-wrap: pretty;
}

@media (max-width: 620px) {
  .work-grid { grid-template-columns: 1fr; gap: clamp(1.5rem, 5vw, 2.25rem); }
  .wtile:hover .wtile-client { transform: none; }
}
@media (prefers-reduced-motion: reduce) {
  .wtile-cover, .wtile-logo img, .wtile-client { transition: none; }
}

/* ============================================================
   WORK — the case study page (/work/<slug>)
   ============================================================ */
.case-nav { padding-top: clamp(1.5rem, 3vw, 2.5rem); }

.case-head { padding-top: clamp(1.5rem, 4vw, 3rem); }
.case-client {
  display: block;
  font-family: var(--cond); font-synthesis: none;
  font-size: 0.78rem; font-weight: 600;
  letter-spacing: 0.16em; text-transform: uppercase;
  color: var(--cream-55);
  margin-bottom: clamp(0.9rem, 2vw, 1.4rem);
}
.case-title {
  font-family: var(--cond); font-synthesis: none;
  font-weight: 900;
  font-size: clamp(2.6rem, 8vw, 6rem);
  line-height: 0.9; letter-spacing: -0.03em;
  color: var(--cream); text-wrap: balance;
  max-width: 16ch;
}

/* the hero panel — image-ready */
.case-hero {
  margin-top: clamp(2rem, 4vw, 3.25rem);
  aspect-ratio: 16 / 9;
  display: grid; place-items: center;
  background: var(--cream-12);
  overflow: hidden;
}
.case-hero .wtile-logo img { max-width: min(40%, 300px); max-height: 40%; opacity: 0.9; }
.case-hero-type {
  font-family: var(--cond); font-synthesis: none;
  font-weight: 900; font-size: clamp(2rem, 5vw, 4rem);
  letter-spacing: -0.02em; color: var(--cream); text-align: center;
  padding: 1.5rem;
}

/* "About the project" rule */
.case-about {
  margin-top: clamp(2.5rem, 5vw, 4rem);
  padding-bottom: 1rem;
  border-bottom: 1px solid var(--cream-12);
  font-family: var(--cond); font-synthesis: none;
  font-size: 0.72rem; font-weight: 600;
  letter-spacing: 0.18em; text-transform: uppercase;
  color: var(--cream-55);
}

/* What / How meta block */
.case-meta {
  margin-top: clamp(1.75rem, 3.5vw, 2.75rem);
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1.6fr);
  gap: clamp(1.5rem, 4vw, 3.5rem);
}
.case-meta-h {
  font-family: var(--cond); font-synthesis: none;
  font-size: 0.66rem; font-weight: 600;
  letter-spacing: 0.16em; text-transform: uppercase;
  color: var(--cream-28);
  margin-bottom: clamp(0.9rem, 1.8vw, 1.25rem);
}
.case-disc { display: grid; gap: 0.55rem; }
.case-disc li {
  font-family: var(--cond); font-synthesis: none;
  font-weight: 900; font-size: clamp(1.1rem, 1.7vw, 1.4rem);
  line-height: 1.1; letter-spacing: -0.01em; color: var(--cream);
}
.case-idea {
  font-family: var(--cond); font-synthesis: none;
  font-weight: 900; font-size: clamp(1.9rem, 3.6vw, 3rem);
  line-height: 0.98; letter-spacing: -0.02em; color: var(--cream);
  text-wrap: balance;
}
.case-idea-sub {
  margin-top: clamp(0.9rem, 1.8vw, 1.25rem);
  font-family: var(--serif); font-synthesis: none; font-weight: 300;
  font-size: clamp(1.05rem, 1.4vw, 1.25rem);
  line-height: 1.55; color: var(--cream-65); max-width: 40rem;
  text-wrap: pretty;
}

/* reading column — Challenge / Solution */
.case-body { max-width: 42rem; margin-top: clamp(2.5rem, 5vw, 4rem); }
.case-body + .case-body { margin-top: clamp(2rem, 4vw, 3rem); }
.case-body h2 {
  font-family: var(--cond); font-synthesis: none;
  font-weight: 900; font-size: clamp(1.4rem, 2.4vw, 1.9rem);
  line-height: 1.02; letter-spacing: -0.02em; color: var(--cream);
  margin-bottom: clamp(0.9rem, 1.8vw, 1.25rem);
}
.case-body p {
  font-size: clamp(1.05rem, 1.3vw, 1.18rem);
  line-height: 1.7; color: var(--cream-70); text-wrap: pretty;
}
.case-body p + p { margin-top: 1rem; }

/* full-bleed figure panels — image-ready */
.case-fig {
  margin-top: clamp(2rem, 4vw, 3.25rem);
  aspect-ratio: 16 / 10;
  display: grid; place-items: center;
  background: var(--cream-12);
  overflow: hidden;
}
.case-fig--tall { aspect-ratio: 4 / 3; }
.case-fig-note {
  font-family: var(--cond); font-synthesis: none;
  font-size: 0.66rem; font-weight: 600;
  letter-spacing: 0.16em; text-transform: uppercase;
  color: var(--cream-28);
}
.case-figs {
  margin-top: clamp(2rem, 4vw, 3.25rem);
  display: grid; grid-template-columns: repeat(2, 1fr);
  gap: clamp(1rem, 2.2vw, 1.75rem);
}
.case-figs .case-fig { margin-top: 0; aspect-ratio: 1 / 1; }

/* next project + back */
.case-next {
  margin-top: clamp(3rem, 6vw, 5rem);
  padding-top: clamp(2rem, 4vw, 3rem);
  border-top: 1px solid var(--cream-12);
  display: block;
}
.case-next .case-client { margin-bottom: 0.6rem; }
.case-next-title {
  display: block;
  font-family: var(--cond); font-synthesis: none;
  font-weight: 900; font-size: clamp(1.9rem, 4.5vw, 3.4rem);
  line-height: 0.96; letter-spacing: -0.025em; color: var(--cream);
  text-wrap: balance;
  transition: transform 0.45s var(--ease);
}
.case-next:hover .case-next-title { transform: translateX(clamp(6px, 1.2vw, 14px)); }

@media (max-width: 720px) {
  .case-meta { grid-template-columns: 1fr; gap: clamp(1.5rem, 5vw, 2.25rem); }
  .case-figs { grid-template-columns: 1fr; }
}
@media (prefers-reduced-motion: reduce) {
  .case-next-title { transition: none; }
}
