/* =========================================================================
   PRITHVI DEV — shared stylesheet
   This single file controls the look of the WHOLE site.
   Change a value here and every page updates at once.
   ========================================================================= */

/* ---- 1. Fonts ---------------------------------------------------------- */

/* ---- 2. Design tokens (the "knobs" you can tweak) ---------------------- */
:root {
  --ink:        #15130f;          /* main text — a soft near-black */
  --ink-soft:   #6b675f;          /* secondary text */
  --paper:      #fbfbf9;          /* background — a whisper off-white */
  --line:       rgba(21,19,15,.14); /* hairline rules */
  --overlay-ink:#ffffff;          /* nav text when sitting over a video */

  --sans: 'Hanken Grotesk', system-ui, sans-serif;  /* wordmark, nav, labels */
  --serif:'Newsreader', Georgia, serif;             /* headings + writeups   */

  --measure: 720px;               /* comfortable reading width */
  --wide:    1240px;              /* max page width */
  --gutter:  clamp(20px, 5vw, 64px);
}

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

html { -webkit-text-size-adjust: 100%; }

body {
  background: var(--paper);
  color: var(--ink);
  font-family: var(--serif);
  font-size: 18px;
  line-height: 1.5;
  font-weight: 400;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

img { display: block; max-width: 100%; height: auto; }
a { color: inherit; }

/* ---- 4. Header / navigation ------------------------------------------- */
.site-header {
  position: absolute;            /* sits over the hero; scrolls away */
  inset: 0 0 auto 0;
  z-index: 20;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 24px;
  padding: clamp(22px, 3vw, 38px) var(--gutter);
}

.wordmark {
  font-family: var(--sans);
  font-weight: 300;
  font-size: clamp(19px, 1.9vw, 23px);
  letter-spacing: .26em;
  text-transform: uppercase;
  text-decoration: none;
  white-space: nowrap;
}

.site-nav {
  display: flex;
  flex-wrap: wrap;
  gap: clamp(15px, 2vw, 32px);
  font-family: var(--sans);
  font-weight: 300;
  font-size: clamp(13px, 1.05vw, 14px);
  letter-spacing: .13em;
  text-transform: uppercase;
}
.site-nav a {
  text-decoration: none;
  position: relative;
  padding-bottom: 3px;
  opacity: .7;
  transition: opacity .25s ease;
}
.site-nav a::after {
  content: "";
  position: absolute;
  left: 0; bottom: 0;
  width: 100%; height: 1px;
  background: currentColor;
  transform: scaleX(0);
  transform-origin: left;
  transition: transform .35s cubic-bezier(.2,.7,.3,1);
}
.site-nav a:hover, .site-nav a[aria-current="page"] { opacity: 1; }
.site-nav a:hover::after,
.site-nav a[aria-current="page"]::after { transform: scaleX(1); }

/* light variant — when the header overlays a video */
.site-header--overlay .wordmark,
.site-header--overlay .site-nav { color: var(--overlay-ink); }
.site-header--overlay { mix-blend-mode: normal; }

/* solid variant — pages with no video behind the header */
.site-header--solid {
  position: relative;
  border-bottom: 1px solid var(--line);
}
.site-header--solid .wordmark,
.site-header--solid .site-nav { color: var(--ink); }

/* hamburger toggle — hidden on desktop, revealed on tablet/mobile */
.nav-toggle {
  display: none;
  appearance: none; -webkit-appearance: none;
  background: none; border: 0; margin: 0; padding: 10px 0;
  color: inherit; cursor: pointer; line-height: 0; z-index: 60;
}
.nav-toggle .bars { position: relative; display: block; width: 26px; height: 1.6px; background: currentColor; transition: background .2s ease; }
.nav-toggle .bars::before,
.nav-toggle .bars::after {
  content: ""; position: absolute; left: 0; width: 26px; height: 1.6px;
  background: currentColor; transition: transform .3s ease;
}
.nav-toggle .bars::before { top: -8px; }
.nav-toggle .bars::after  { top: 8px; }
.site-header.nav-open .nav-toggle .bars { background: transparent; }
.site-header.nav-open .nav-toggle .bars::before { transform: translateY(8px) rotate(45deg); }
.site-header.nav-open .nav-toggle .bars::after  { transform: translateY(-8px) rotate(-45deg); }

/* ---- 5. Hero video (cover-fills its frame) ---------------------------- */
.hero {
  position: relative;
  width: 100%;
  overflow: hidden;
  background: #000;
}
.hero--full  { height: 100svh; }   /* homepage: fills the screen */
.hero--tall  { height: 94svh; }    /* section pages: video fills most of the screen, curve near the bottom */

.hero__video {
  position: absolute;
  top: 50%; left: 50%;
  transform: translate(-50%, -50%);
  /* 16:9 cover: whichever dimension is larger wins */
  width: 100vw;  height: 56.25vw;
  min-height: 100%; min-width: 177.78svh;
  border: 0;
  pointer-events: none;           /* background videos aren't clickable */
}

/* On 94svh heroes the generic 177.78svh min-width (calibrated for 100svh)
   over-widens the box past 16:9, forcing the player to crop internally with
   an anchor we don't control. 94 x 16/9 = 167.11svh keeps the box exactly
   16:9, so the player and the poster have nothing left to disagree about. */
.hero--tall .hero__video, .hero--tall .hero__poster { min-width: 167.12svh; }

/* photo-background hero (section pages with a still image instead of video) */
.hero__img {
  position: absolute;
  inset: 0;
  width: 100%; height: 100%;
  object-fit: cover;
  object-position: center 25%;   /* bias toward the upper-middle of the drawing */
  display: block;
}

/* a faint darkening so white nav text stays legible over bright footage */
.hero::after {
  content: "";
  position: absolute; inset: 0;
  background: linear-gradient(to bottom, rgba(0,0,0,.28), rgba(0,0,0,0) 32%);
  pointer-events: none;
}
/* photo heroes are lighter than video, so the nav needs a touch more cover up top */
.hero--photo::after {
  background:
    linear-gradient(to bottom, rgba(0,0,0,.46), rgba(0,0,0,.08) 14%, rgba(0,0,0,0) 30%),
    rgba(0,0,0,.10);
}

/* ---- 6. Page content --------------------------------------------------- */
main { display: block; }

.section {
  padding: clamp(64px, 11vw, 150px) var(--gutter);
}
.section--tight { padding-top: clamp(48px, 7vw, 90px); }

/* ---- Hub pages: one uniform gap between every band (top banner, intro, grid,
   closing essay, bottom banner) so the vertical rhythm reads evenly top to bottom.
   Each section opens the gap with its top padding; the banner adds its own. ---- */
.hub .section { padding-top: clamp(80px, 11vw, 160px); padding-bottom: 0; }
.hub .full-bleed,
.hub .hero--end { margin-top: clamp(80px, 11vw, 160px); }

/* short centered hairline used as a section break */
.section-sep { border: 0; height: 1px; background: var(--line); width: clamp(56px, 9vw, 110px); margin: clamp(20px, 4vw, 48px) auto; }

.prose {
  max-width: var(--measure);
  margin: 0 auto;
  text-align: center;
}
.prose h1, .prose h2 {
  font-family: var(--serif);
  font-weight: 400;
  letter-spacing: -0.01em;
  line-height: 1.18;
}
.prose h1 { font-size: clamp(26px, 4.2vw, 40px); }
.prose h2 { font-size: clamp(22px, 3.2vw, 31px); }

.prose p {
  margin-top: 1.5em;
  font-size: clamp(17px, 1.45vw, 19.5px);
  line-height: 1.75;
  color: var(--ink);
}
.prose .lede { color: var(--ink-soft); }

.spacer { height: clamp(40px, 8vw, 100px); }

/* ---- 7. Subsection grid -----------------------------------------------
   Centred flex system. Tiles flow --grid-cols per row (3, dropping to 2 then
   1 at the breakpoints near the bottom of this section). justify-content:
   centre centres EACH wrapped line independently, so a short final row of 1
   or 2 tiles sits centred under the rows above instead of hugging the left.
   This is the default for every .grid on the site and needs no per-tile
   markup, so any tiles added to any grid — now or later — fall in line the
   same centred way. The flex grow+shrink keeps full rows flush edge-to-edge
   (shrink absorbs sub-pixel rounding so a full row never wraps early), while
   the max-width cap holds each tile to one column so a short row centres
   rather than stretching its tiles wide. ---- */
.grid {
  --grid-gap: clamp(10px, 1.4vw, 20px);
  --grid-cols: 3;
  max-width: var(--wide);
  margin: 0 auto;
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: var(--grid-gap);
}
/* Sizes the direct grid item, whatever it is: site.js wraps each .tile in a
   .cell (to carry the touch caption), so post-script the item is .cell; before
   the script runs it is the bare .tile. Targeting > * covers both — plus any
   future child — so tiles never collapse in the brief pre-script moment. */
.grid > * {
  flex: 1 1 calc((100% - (var(--grid-cols) - 1) * var(--grid-gap)) / var(--grid-cols));
  max-width: calc((100% - (var(--grid-cols) - 1) * var(--grid-gap)) / var(--grid-cols));
  min-width: 0;
}
.tile {
  position: relative;
  display: block;
  aspect-ratio: 1 / 1;
  background-color: #ecebe6;
  background-size: cover;
  background-position: center;
  text-decoration: none;
  overflow: hidden;
}
/* tasteful placeholder shown until a real image is dropped in */
.tile__ph {
  position: absolute; inset: 0;
  display: flex; flex-direction: column;
  align-items: center; justify-content: center;
  gap: 10px;
  font-family: var(--sans);
  color: var(--ink-soft);
}
.tile__ph .num {
  font-size: clamp(22px, 3vw, 34px);
  font-weight: 300;
  letter-spacing: .04em;
}
.tile__ph .lbl {
  font-size: 11px; letter-spacing: .28em; text-transform: uppercase;
}
.tile__cap {
  position: absolute; inset: 0; z-index: 2;
  display: flex; align-items: center; justify-content: center;
  padding: 18px; text-align: center;
  font-family: var(--sans);
  font-size: clamp(14px, 1.5vw, 18px); letter-spacing: .14em; text-transform: uppercase;
  color: #3f4650;
  background: rgba(251, 251, 249, .84);
  opacity: 0;
  transition: opacity .35s ease;
}
.tile:hover .tile__cap { opacity: 1; }
.tile__go {
  position: absolute; top: clamp(12px, 1.8vw, 18px); right: clamp(13px, 2vw, 19px); z-index: 3;
  width: 18px; height: 18px; color: var(--ink); opacity: 0;
  transition: opacity .3s ease; pointer-events: none;
}
.tile__go svg { width: 100%; height: 100%; display: block; }
.tile:hover .tile__go { opacity: .72; }
.tile--img .tile__ph { display: none; }

/* animated thumbnail: a live embed filling the tile (behind the hover caption) */
.tile--anim .tile__ph { display: none; }
.tile__anim {
  position: absolute; inset: 0; z-index: 1;
  width: 100%; height: 100%; border: 0;
  background: transparent; pointer-events: none;
}
/* Full-resolution still shown instantly beneath each animated tile. The live
   embed (.tile__anim) is loaded only as the tile nears the viewport, fades in
   over this poster, and fades back out — revealing the poster again — when its
   WebGL context is freed on scroll-away. So a tile is never blank, and only the
   few embeds near the viewport ever hold a GPU context. */
.tile__poster {
  position: absolute; inset: 0; z-index: 0;
  width: 100%; height: 100%;
  object-fit: cover; object-position: center;
  display: block; pointer-events: none;
  background: #ecebe6;
}
.tile--anim .tile__anim { opacity: 0; transition: opacity .55s ease; }
@media (prefers-reduced-motion: reduce) {
  .tile--anim .tile__anim { transition: opacity .12s linear; }
}
/* pre-rendered video thumbnail: a looping clip filling the tile, sitting over the
   poster (z-index 0) and beneath the hover caption (z-index 2). Shown instantly
   via its own poster frame, so the tile is never blank. */
.tile__vid {
  position: absolute; inset: 0; z-index: 1;
  width: 100%; height: 100%;
  object-fit: cover; object-position: center;
  display: block; pointer-events: none;
  background: transparent;
}

/* persistent caption under each tile — shown only where hover is unavailable (touch) */
.tile__label {
  display: none;
  margin-top: clamp(8px, 1.4vw, 12px);
  font-family: var(--sans);
  font-size: 12px;
  letter-spacing: .12em;
  text-transform: uppercase;
  color: var(--ink-soft);
  text-align: center;
  line-height: 1.3;
}@media (hover: none){ .tile__label { display: block; }}@media (max-width: 860px){ .grid { --grid-cols: 2; }}@media (max-width: 520px){ .grid { --grid-cols: 1; }}

/* ---- 7b. Interactive collections (text-forward cards) ----------------- */
.collection { max-width: var(--wide); margin: 0 auto; }

.group { margin-top: clamp(48px, 7vw, 96px); }
.group:first-child { margin-top: 0; }
.group__head { text-align: center; margin-bottom: clamp(22px, 3vw, 40px); }
.group__head h2 {
  font-family: var(--serif); font-weight: 400;
  font-size: clamp(21px, 2.8vw, 29px); letter-spacing: -0.01em;
}
.group__head p {
  font-family: var(--sans); font-size: 12px; letter-spacing: .26em;
  text-transform: uppercase; color: var(--ink-soft); margin-top: 10px;
}
.group__intro {
  max-width: var(--measure); margin: clamp(18px, 2.4vw, 30px) auto clamp(30px, 4vw, 52px);
  text-align: center;
}
.group__intro p { margin: 0 0 0.9em; }
.group__intro p:last-child { margin-bottom: 0; }

/* ---- 8. Footer --------------------------------------------------------- */
.site-footer {
  padding: clamp(40px, 6vw, 70px) var(--gutter) clamp(30px, 4vw, 46px);
}
.site-footer hr {
  border: 0;
  border-top: 1px solid var(--line);
  max-width: var(--wide);
  margin: 0 auto clamp(28px, 4vw, 44px);
}
.site-footer p {
  text-align: center;
  font-family: var(--serif);
  font-style: italic;
  font-size: 15px;
  color: var(--ink-soft);
}

/* ---- 9. Gentle motion -------------------------------------------------- */
.reveal {
  opacity: 0;
  transform: translateY(18px);
  transition: opacity 1s ease, transform 1s cubic-bezier(.2,.7,.3,1);
}
.reveal.is-in { opacity: 1; transform: none; }

/* Fail-open: hiding content behind .reveal is only safe while site.js is
   guaranteed to run. A tiny inline timer in each page's <head> adds
   .reveal-fallback to <html> if site.js hasn't executed shortly after load
   (offline cache miss, blocked request) — content then fades in through the
   normal transition instead of leaving the page blank below the hero. */
html.reveal-fallback .reveal { opacity: 1; transform: none; }

/* Browsers / readers with scripting off never run the timer either, so fail
   open for them directly. */
@media (scripting: none) {
  .reveal { opacity: 1; transform: none; transition: none; }
}

/* load-in for the hero header */
@keyframes fadeDown { from { opacity: 0; transform: translateY(-8px); } to { opacity: 1; transform: none; } }
.site-header--overlay .wordmark,
.site-header--overlay .site-nav { animation: fadeDown 1.1s ease both; }
.site-header--overlay .site-nav { animation-delay: .12s; }@media (prefers-reduced-motion: reduce){
  .reveal { opacity: 1; transform: none; transition: none; }
  .site-header--overlay .wordmark,
  .site-header--overlay .site-nav { animation: none; }}

/* ---- 10. Stub pages ("coming soon") ----------------------------------- */
.stub {
  min-height: 70svh;
  display: flex; flex-direction: column;
  align-items: center; justify-content: center;
  text-align: center; gap: 14px;
  padding: 80px var(--gutter);
}
.stub h1 { font-family: var(--serif); font-weight: 400; font-size: clamp(28px, 5vw, 44px); }
.stub p  { font-family: var(--sans); letter-spacing: .22em; text-transform: uppercase;
           font-size: 12px; color: var(--ink-soft); }

/* ---- 11. Umbrella dropdown nav ---------------------------------------- */
.nav-item.has-sub { position: relative; display: inline-flex; }
.nav-parent {
  font: inherit; color: inherit; background: none; border: 0; margin: 0;
  padding: 0 0 3px; cursor: pointer; letter-spacing: inherit; text-transform: inherit;
  display: inline-flex; align-items: center; gap: 7px; opacity: .7;
  transition: opacity .25s ease;
}
.nav-parent:hover { opacity: 1; }
.nav-parent .caret { font-size: .62em; opacity: .65; transition: transform .3s ease; }
.nav-item.has-sub.open .nav-parent .caret { transform: rotate(180deg); }
.nav-sub {
  position: absolute; top: 100%; left: 0; margin-top: 12px;
  display: flex; flex-direction: column; min-width: 200px; padding: 8px 0;
  opacity: 0; visibility: hidden; transform: translateY(-6px);
  transition: opacity .25s ease, transform .25s ease, visibility .25s; z-index: 40;
}
.nav-sub a {
  color: inherit; padding: 7px 0; font-size: 12.5px; letter-spacing: .1em;
  text-transform: uppercase; font-weight: 400;
  white-space: nowrap; opacity: .7; transition: opacity .2s ease;
}
.nav-sub a::after { content: none; }
.nav-sub a:hover, .nav-sub a[aria-current="page"] { opacity: 1; }
.nav-item.has-sub.open .nav-sub { opacity: 1; visibility: visible; transform: translateY(0); }@media (hover: hover){
  .nav-item.has-sub:hover .nav-sub { opacity: 1; visibility: visible; transform: translateY(0); }
  .nav-item.has-sub:hover .nav-parent { opacity: 1; }
  .nav-item.has-sub:hover .nav-parent .caret { transform: rotate(180deg); }}@media (max-width: 1120px){
  .nav-toggle { display: inline-flex; align-items: center; }

  /* the nav becomes a full-width slide-down panel below the header bar */
  .site-nav {
    position: absolute; top: 100%; left: 0; right: 0;
    flex-direction: column; flex-wrap: nowrap; align-items: stretch; gap: 0;
    background: var(--paper); color: var(--ink);
    border-top: 1px solid var(--line);
    box-shadow: 0 18px 44px rgba(0,0,0,.13);
    padding: 0 var(--gutter) 10px;
    font-size: 15px;
    max-height: 0; overflow: hidden;
    opacity: 0; visibility: hidden; transform: translateY(-8px);
    transition: max-height .4s ease, opacity .3s ease, transform .3s ease, visibility .3s;
  }
  .site-header.nav-open .site-nav {
    max-height: 82svh; overflow-y: auto;
    opacity: 1; visibility: visible; transform: translateY(0);
  }
  /* keep menu text readable even when the header overlays a video */
  .site-header--overlay .site-nav,
  .site-header--overlay .site-nav a,
  .site-header--overlay .nav-parent { color: var(--ink); }

  .site-nav > .nav-item,
  .site-nav > a { width: 100%; border-bottom: 1px solid var(--line); }
  .site-nav > *:last-child { border-bottom: 0; }
  .site-nav > a { display: block; padding: 15px 0; opacity: .9; }
  .site-nav a::after { content: none; }              /* drop the underline-grow on mobile */

  .nav-item.has-sub { display: block; position: static; }
  .nav-parent { width: 100%; justify-content: space-between; padding: 15px 0; opacity: 1; }

  .nav-sub {
    position: static; box-shadow: none; border: 0; background: none;
    margin: 0; min-width: 0; opacity: 1; transform: none; visibility: hidden;
    max-height: 0; overflow: hidden; padding: 0;
    transition: max-height .3s ease, visibility .3s;
  }
  .nav-item.has-sub.open .nav-sub { visibility: visible; max-height: 260px; padding: 0 0 12px; }
  .nav-sub a { display: block; padding: 10px 0 10px 16px; font-size: 15px; opacity: .78; }}

/* ---- 14. Section layout helper ---------------------------------------- */
.section { position: relative; }

/* ---- 15. Work / subsection pages (writeup + video stack) ------------- */
.prose .work-meta {
  font-family: var(--sans);
  font-size: 12px; letter-spacing: .24em; text-transform: uppercase;
  color: var(--ink-soft);
  margin-top: 1.1em;
}
.prose .work-materials {
  font-family: var(--sans);
  font-size: 13.5px; letter-spacing: .015em;
  color: var(--ink-soft);
  margin-top: .55em;
}
.video-stack { max-width: 960px; margin: 0 auto; }
.video-embed {
  position: relative;
  width: 100%;
  aspect-ratio: 16 / 9;
  background: #000;
  overflow: hidden;
}

/* ---- Lab detail pages: animation placeholder + open-interactive button ---- */
.lab-stage { max-width: 960px; margin: 0 auto; }
.lab-ph {
  position: relative; width: 100%; aspect-ratio: 16 / 9;
  background: #0b0b10;
  border: 1px solid var(--line);
  display: flex; align-items: center; justify-content: center;
  overflow: hidden;
}
.lab-ph__label {
  font-family: var(--sans); text-transform: uppercase;
  letter-spacing: .26em; font-size: 11px;
  color: rgba(255,255,255,0.4);
}
.lab-open-row { max-width: 960px; margin: clamp(18px,2.4vw,26px) auto 0; text-align: center; }
.lab-open {
  display: inline-flex; align-items: center; gap: .6em;
  font-family: var(--sans); text-transform: uppercase;
  letter-spacing: .18em; font-size: 12px; font-weight: 500;
  color: var(--ink); text-decoration: none;
  padding: 13px 22px; border: 1px solid var(--ink);
  transition: background .25s ease, color .25s ease;
}
.lab-open:hover { background: var(--ink); color: var(--paper); }
.lab-open .arrow { transition: transform .25s ease; }
.lab-open:hover .arrow { transform: translateX(3px); }

/* live animation embed inside a detail page (replaces the placeholder) */
.lab-embed {
  position: relative; width: 100%; aspect-ratio: 16 / 9;
  background: #0b0b10; border: 1px solid var(--line);
  overflow: hidden;
}
.lab-embed--light { background: #fff; }
.lab-embed iframe {
  position: absolute; inset: 0; width: 100%; height: 100%;
  border: 0; opacity: 0; transition: opacity 1s ease;
  pointer-events: none;            /* embeds are passive video screens — no orbit/zoom; page scroll passes through */
}
.lab-note {
  max-width: 720px; margin: clamp(16px,2.2vw,24px) auto 0;
  font-family: var(--sans); font-weight: 300;
  font-size: 13.5px; line-height: 1.7; color: var(--ink-soft);
  text-align: center;
}
.lab-note .lab-note__tag {
  display: block; font-size: 11px; letter-spacing: .24em;
  text-transform: uppercase; color: var(--ink-soft);
  margin-bottom: 8px; opacity: .8;
}
.lab-anim-title {
  max-width: 960px; margin: 0 auto clamp(10px,1.4vw,16px);
  font-family: var(--sans); font-size: 12px; font-weight: 500;
  letter-spacing: .22em; text-transform: uppercase; color: var(--ink);
}

/* inline links inside a writeup (e.g. the "interactive" link) */
.prose a {
  color: var(--ink);
  text-decoration: underline;
  text-underline-offset: 3px;
  text-decoration-thickness: 1px;
  text-decoration-color: var(--ink-soft);
  transition: text-decoration-color .2s ease;
}
.prose a:hover { text-decoration-color: var(--ink); }

/* ---- The Tu Identity studio — "mathematics, in plain terms" panel ----------
   This writeup sits in a .tu-math block outside .prose, so it carries its own
   typography. It mirrors the centred, serif reading column of .prose and reuses
   the sans uppercase kicker of the lab labels, so it reads as part of the page. */
.tu-math {
  max-width: var(--measure);
  margin: clamp(22px, 3vw, 38px) auto 0;
  text-align: center;
}
.tu-math p {
  margin-top: 1.5em;
  font-size: clamp(17px, 1.45vw, 19.5px);
  line-height: 1.75;
  color: var(--ink);
}
.tu-math .tu-lede { margin-top: 0; color: var(--ink-soft); }
.tu-divider {
  width: clamp(48px, 8vw, 72px); height: 0;
  border: 0; border-top: 1px solid var(--line);
  margin: clamp(28px, 4vw, 44px) auto 0;
}
.tu-part { margin-top: clamp(40px, 5.5vw, 68px); }
.tu-part .eyebrow {
  margin: 0;
  font-family: var(--sans); font-size: 12px; font-weight: 500;
  letter-spacing: .22em; text-transform: uppercase; color: var(--ink-soft);
}
.tu-part h3 {
  margin: clamp(7px, 1vw, 11px) 0 0;
  font-family: var(--serif); font-weight: 400;
  font-size: clamp(20px, 2.6vw, 26px); line-height: 1.2;
  letter-spacing: -0.01em; color: var(--ink);
}
/* the headline result, on its own centred line */
.tu-eq {
  display: block;
  margin: clamp(20px, 2.6vw, 30px) auto 0;
  font-family: var(--serif);
  font-size: clamp(19px, 2.2vw, 23px); line-height: 1.5;
  color: var(--ink);
}
/* the wider family of exact values */
.tu-fam {
  list-style: none; padding: 0;
  max-width: 30em;
  margin: clamp(18px, 2.4vw, 28px) auto 0;
  font-family: var(--serif);
  font-size: clamp(16px, 1.5vw, 18.5px); line-height: 2.1;
  color: var(--ink-soft);
}
.tu-fam li { text-align: center; }
.tu-fam .v { color: var(--ink); }

.video-embed + .video-embed { margin-top: clamp(16px, 2.4vw, 28px); }
.video-embed iframe { position: absolute; inset: 0; width: 100%; height: 100%; border: 0; pointer-events: none; }

/* ---- custom video controls (Vimeo chrome hidden; we drive via the API) ---- */
.vctrl {
  position: absolute; left: 0; right: 0; bottom: 0; z-index: 3;
  display: flex; align-items: center; gap: clamp(10px, 1.6vw, 16px);
  padding: clamp(11px, 1.8vw, 16px) clamp(13px, 2.4vw, 22px);
  font-family: var(--sans); color: var(--paper);
  background: linear-gradient(to top, rgba(10,9,7,.58) 0%, rgba(10,9,7,.12) 62%, rgba(10,9,7,0) 100%);
  opacity: 0; transition: opacity .3s ease;
  pointer-events: none;
}
.video-embed:hover .vctrl,
.video-embed.is-paused .vctrl,
.video-embed.show-controls .vctrl,
.vctrl:focus-within { opacity: 1; }
.vctrl > * { pointer-events: auto; }
.vctrl__btn {
  background: none; border: 0; padding: 0; margin: 0; cursor: pointer; flex: none;
  width: 19px; height: 19px; color: var(--paper); opacity: .85;
  display: inline-flex; transition: opacity .2s ease;
}
.vctrl__btn:hover { opacity: 1; }
.vctrl__btn svg { width: 100%; height: 100%; display: block; }
.vctrl__play.is-playing .i-play,
.vctrl__play:not(.is-playing) .i-pause { display: none; }
.vctrl__mute.is-muted .i-on,
.vctrl__mute:not(.is-muted) .i-off { display: none; }
.vctrl__track {
  position: relative; flex: 1 1 auto; height: 3px; border-radius: 2px;
  background: rgba(251,251,249,.30); cursor: pointer; touch-action: none;
}
.vctrl__track::before { content: ""; position: absolute; left: 0; right: 0; top: -8px; bottom: -8px; }
.vctrl__fill { position: absolute; left: 0; top: 0; bottom: 0; width: 0; background: var(--paper); border-radius: 2px; }
.vctrl__track:focus-visible { outline: 1px solid rgba(251,251,249,.7); outline-offset: 4px; }
.vctrl__time {
  flex: none; font-size: 12px; letter-spacing: .03em; opacity: .85;
  font-variant-numeric: tabular-nums;
}
/* fullscreen: let the container fill the screen and the player fill the container */
.video-embed:fullscreen,
.video-embed:-webkit-full-screen { width: 100vw; height: 100vh; aspect-ratio: auto; background: #000; }
.video-embed:fullscreen iframe,
.video-embed:-webkit-full-screen iframe { width: 100%; height: 100%; }

/* ---- subsection prev / collection / next nav ---- */
.work-nav {
  max-width: var(--wide);
  margin: 0 auto;
  display: grid;
  grid-template-columns: 1fr auto 1fr;
  align-items: baseline;
  gap: clamp(16px, 3vw, 48px);
  font-family: var(--sans);
  font-size: 12px; letter-spacing: .18em; text-transform: uppercase;
}
.work-nav a { color: var(--ink-soft); text-decoration: none; transition: color .2s ease; }
.work-nav a:hover { color: var(--ink); }
.work-nav .wn-prev { justify-self: start;  text-align: left; }
.work-nav .wn-home { justify-self: center; text-align: center; }
.work-nav .wn-next { justify-self: end;    text-align: right; }
.work-nav .wn-prev .wn-arrow { margin-right: .55em; }
.work-nav .wn-next .wn-arrow { margin-left: .55em; }@media (max-width: 600px){
  .work-nav { gap: 12px; font-size: 11px; letter-spacing: .1em; }
  .work-nav .wn-title { display: none; }   /* prev/next collapse to arrows; collection stays centered */
}
.video-embed--portrait { aspect-ratio: 9 / 16; max-width: 405px; margin-left: auto; margin-right: auto; }

/* ---- 16. Hero curved cutoff + photo-background closing banner --------- */
.hero__curve {
  position: absolute; left: 0; right: 0;
  /* The curve hangs below the section so its paper fill overlaps the edge.
     Tying that hang to viewport height (-5svh) let it outgrow the curve on
     tall-and-narrow screens — phones and portrait tablets — exposing a
     hairline of dark banner beneath the paper sweep. The hang is now capped
     so the fill always keeps at least 20px of full-width paper above the
     section's bottom edge (0.643 = 1 − 5/14, the path's deepest dip). The
     plain -14px line is the fallback for engines without max()/clamp(). */
  bottom: -14px;
  bottom: max(-5svh, calc(20px - 0.643 * clamp(70px, 10vw, 150px)));
  width: 100%; height: clamp(70px, 10vw, 150px);
  z-index: 3; display: block;
}
.hero__curve path { fill: var(--paper); }

/* ---- closing full-bleed image ---- */
.full-bleed { margin: 0; }
.full-bleed img { display: block; width: 100%; height: auto; }

/* ---- 18. Artworks — "plate" layout + deep-zoom viewer (Streams subsections) ---- */
.plates { max-width: var(--wide); margin: 0 auto; }

.plate {
  display: flex;
  flex-direction: column;
  gap: clamp(20px, 4vw, 30px);
  margin-bottom: clamp(80px, 13vw, 170px);
}
.plate:last-of-type { margin-bottom: 0; }

.plate__fig { margin: 0; line-height: 0; }
.plate__btn {
  display: block; width: 100%; padding: 0; border: 0; background: none;
  position: relative; cursor: zoom-in;
}
.plate__btn img {
  width: 100%; height: auto; display: block;
  border-radius: 3px;
  box-shadow: 0 10px 44px rgba(21, 19, 15, .13);
  transition: box-shadow .4s ease;
}
.plate__btn:hover img { box-shadow: 0 18px 60px rgba(21, 19, 15, .2); }
.plate__hint {
  position: absolute; left: 50%; bottom: clamp(12px, 1.6vw, 18px); transform: translateX(-50%) translateY(6px);
  display: inline-flex; align-items: center; gap: .5em;
  font-family: var(--sans); font-size: 11px; letter-spacing: .2em; text-transform: uppercase; line-height: 1;
  color: var(--ink); background: rgba(251, 251, 249, .92);
  padding: .7em 1.1em; border-radius: 999px;
  box-shadow: 0 3px 16px rgba(21, 19, 15, .14);
  opacity: 0; transition: opacity .3s ease, transform .3s ease; pointer-events: none;
}
.plate__btn:hover .plate__hint { opacity: 1; transform: translateX(-50%) translateY(0); }@media (hover: none){ .plate__hint { opacity: 1; transform: translateX(-50%) translateY(0); }}

.plate__meta { max-width: 33rem; }
.plate__idx {
  font-family: var(--sans); font-size: 12px; letter-spacing: .3em; text-transform: uppercase;
  color: var(--ink-soft);
}
.plate__title {
  font-family: var(--serif); font-weight: 400; letter-spacing: -.01em; line-height: 1.16;
  font-size: clamp(23px, 3vw, 33px); margin: .45em 0 0;
}
.plate__desc { margin-top: 1.05em; }
.plate__desc p { font-size: clamp(16px, 1.35vw, 18.5px); line-height: 1.75; color: var(--ink); }
.plate__desc p + p { margin-top: 1em; }
.plate__zoom {
  margin-top: 1.6em; display: inline-flex; align-items: center; gap: .55em;
  font-family: var(--sans); font-size: 13px; letter-spacing: .03em; color: var(--ink);
  background: none; border: 0; border-bottom: 1px solid var(--line); padding: 0 0 .4em; cursor: pointer;
  transition: gap .25s ease, border-color .25s ease;
}
.plate__zoom:hover { gap: .95em; border-color: var(--ink); }
.plate__zoom .ar { font-size: 1.05em; }

/* side-by-side on wider screens; image as large as fits, caption alongside */
@media (min-width: 900px) {
  .plate { flex-direction: row; align-items: center; gap: clamp(40px, 5.5vw, 84px); }
  .plate--flip { flex-direction: row-reverse; }
  .plate__fig { flex: 0 1 auto; min-width: 0; }
  .plate__btn img { max-height: 82vh; max-width: 100%; width: auto; }
  .plate__meta { flex: 1 1 24rem; min-width: 17rem; }
}

/* wide / landscape works: full-width image stacked above a centred caption */
.plate--wide .plate__meta { max-width: 42rem; margin: 0 auto; text-align: center; }
.plate--wide .plate__desc p { text-align: center; }@media (min-width: 900px){
  .plate--wide { flex-direction: column; align-items: center; gap: clamp(28px, 3.5vw, 46px); }
  .plate--wide .plate__fig { flex: none; width: 100%; display: flex; justify-content: center; }
  .plate--wide .plate__btn { width: auto; max-width: 100%; }
  .plate--wide .plate__btn img { width: auto; height: auto; max-width: 100%; max-height: 84vh; }
  .plate--wide .plate__meta { flex: none; }}

/* ---- deep-zoom overlay ---- */
.zoomer { position: fixed; inset: 0; z-index: 100; display: none; background: #0e0d0b; touch-action: none; }
.zoomer.is-open { display: block; }
.zoomer__stage { position: absolute; inset: 0; overflow: hidden; cursor: grab; touch-action: none; }
.zoomer.is-pan .zoomer__stage { cursor: grabbing; }
.zoomer__img { position: absolute; top: 0; left: 0; transform-origin: 0 0; will-change: transform; user-select: none; -webkit-user-drag: none; max-width: none; }
.zoomer__bar {
  position: absolute; top: 0; left: 0; right: 0; z-index: 2;
  display: flex; justify-content: space-between; align-items: center;
  padding: clamp(14px, 2vw, 22px) clamp(16px, 3vw, 32px);
  color: #f3f2ee; pointer-events: none;
}
.zoomer__bar > * { pointer-events: auto; }
.zoomer__title { font-family: var(--sans); font-size: 12.5px; letter-spacing: .18em; text-transform: uppercase; opacity: .82; max-width: 60%; }
.zoomer__controls { display: flex; gap: 8px; }
.zoomer__controls button {
  width: 42px; height: 42px; border-radius: 50%;
  border: 1px solid rgba(255, 255, 255, .26); background: rgba(255, 255, 255, .07);
  color: #f3f2ee; font-size: 19px; line-height: 1; cursor: pointer;
  display: grid; place-items: center; transition: background .2s ease, border-color .2s ease;
}
.zoomer__controls button:hover { background: rgba(255, 255, 255, .18); border-color: rgba(255,255,255,.5); }
.zoomer__hint {
  position: absolute; bottom: clamp(16px, 3vw, 28px); left: 50%; transform: translateX(-50%); z-index: 2;
  margin: 0; color: rgba(243, 242, 238, .72);
  font-family: var(--sans); font-size: 12px; letter-spacing: .12em;
  transition: opacity .6s ease; pointer-events: none;
}

/* ---- 21. Bottom infinite horizontal exhibit (no labels) ---- */
.exhibit { position: relative; }
.exhibit__rail {
  display: flex; align-items: center; gap: clamp(22px, 3vw, 52px);
  overflow-x: auto; overflow-y: hidden;
  padding: 8px clamp(20px, 5vw, 64px);
  scrollbar-width: none; -ms-overflow-style: none;
}
.exhibit__rail::-webkit-scrollbar { display: none; }
.exhibit__item { flex: 0 0 auto; line-height: 0; }
.exhibit__item button { border: 0; background: none; padding: 0; cursor: zoom-in; display: block; line-height: 0; }
.exhibit__item img {
  height: clamp(400px, 74vh, 800px); width: auto; display: block;
  border-radius: 3px; border: 1px solid var(--line);
  transition: transform .4s ease;
}
.exhibit__item button:hover img { transform: translateY(-4px); }
/* arrows — same circular aesthetic as the rest of the site */
/* arrows — fine frosted ring with a delicate elongated arrow, no shadow */
.exhibit__arrow {
  position: absolute; top: 50%; transform: translateY(-50%); z-index: 4;
  width: 60px; height: 60px; border-radius: 50%;
  border: 1px solid var(--line); background: rgba(251, 251, 249, .52);
  -webkit-backdrop-filter: blur(3px); backdrop-filter: blur(3px);
  color: var(--ink); cursor: pointer; display: grid; place-items: center;
  transition: background .3s ease, border-color .3s ease;
}
.exhibit__arrow svg { width: 30px; height: 18px; transition: transform .3s ease; }
.exhibit__arrow:hover { background: rgba(251, 251, 249, .96); border-color: var(--ink-soft); }
.exhibit__arrow--prev:hover svg { transform: translateX(-3px); }
.exhibit__arrow--next:hover svg { transform: translateX(3px); }
.exhibit__arrow--prev { left: clamp(14px, 3vw, 44px); }
.exhibit__arrow--next { right: clamp(14px, 3vw, 44px); }

/* ---- 22. Process sketches (secondary studies within a subsection) ---- */
.process { max-width: min(1500px, 95vw); margin: 0 auto; }
.process__intro { max-width: 40rem; margin: 0 auto clamp(26px, 4vw, 44px); text-align: center; }
.process__intro h2 { font-family: var(--serif); font-weight: 400; letter-spacing: -.01em; font-size: clamp(20px, 2.6vw, 28px); }
.process__intro p { margin-top: .7em; font-size: clamp(15px, 1.3vw, 17px); line-height: 1.7; color: var(--ink-soft); }
.process__row { display: flex; flex-wrap: wrap; justify-content: center; align-items: flex-start; gap: clamp(18px, 2.4vw, 38px); }
.process__item { margin: 0; }
.process__item button { display: block; padding: 0; border: 0; background: none; cursor: zoom-in; line-height: 0; }
.process__item img {
  height: clamp(300px, 42vh, 450px); width: auto; max-width: 100%; display: block;
  border-radius: 3px; border: 1px solid var(--line); box-shadow: 0 6px 26px rgba(21, 19, 15, .10);
  transition: box-shadow .35s ease, transform .35s ease;
}
.process__item button:hover img { box-shadow: 0 12px 40px rgba(21, 19, 15, .16); transform: translateY(-4px); }
.process__cap { margin-top: .85em; font-family: var(--sans); font-size: 12px; letter-spacing: .14em; text-transform: uppercase; color: var(--ink-soft); text-align: center; }@media (max-width: 700px){ .process__item { flex: 1 1 100%; max-width: 30rem; } .process__item img { height: auto; width: 100%; }}

/* ---- 23. Gallery grid (multi-image, untitled subsection) ---- */
.vlgrid { display: grid; grid-template-columns: repeat(3, 1fr); gap: clamp(14px, 1.8vw, 28px); max-width: var(--wide); margin: 0 auto; }
.vlgrid figure { margin: 0; }
.vlgrid button { display: block; width: 100%; padding: 0; border: 0; background: none; cursor: zoom-in; line-height: 0; }
.vlgrid img {
  width: 100%; height: auto; display: block; border-radius: 3px;
  border: 1px solid var(--line); box-shadow: 0 4px 18px rgba(21, 19, 15, .08);
  transition: box-shadow .35s ease, transform .35s ease;
}
.vlgrid button:hover img { box-shadow: 0 12px 36px rgba(21, 19, 15, .16); transform: translateY(-3px); }@media (max-width: 940px){ .vlgrid { grid-template-columns: repeat(2, 1fr); }}@media (max-width: 460px){ .vlgrid { gap: 12px; }}

/* two-up gallery: flex so the columns hug each drawing, giving an even gap in both
   directions instead of wide gaps between columns and tight gaps between rows */
.vlgrid--two { display: flex; flex-wrap: wrap; justify-content: center; align-items: flex-start;
  gap: clamp(34px, 4vw, 60px); }
.vlgrid--two figure { flex: 0 0 auto; margin: 0; }
/* cap each drawing to the viewport so a whole sheet stays visible at once (never taller than the screen) */
.vlgrid--two img { width: auto; height: auto; max-height: 80vh; max-width: min(46vw, 560px); display: block; }@media (max-width: 600px){
  .vlgrid--two { gap: 28px; }
  .vlgrid--two figure { flex: 0 0 100%; }
  .vlgrid--two img { width: 100%; max-width: 100%; max-height: none; }}

/* paper-cut images: the paper's rounded edge is baked into the alpha, so no rectangular frame */
.vlgrid--paper img { border: 0; border-radius: 0; box-shadow: none; filter: drop-shadow(0 4px 14px rgba(21, 19, 15, .13)); transition: filter .35s ease, transform .35s ease; }
.vlgrid--paper button:hover img { box-shadow: none; filter: drop-shadow(0 12px 28px rgba(21, 19, 15, .2)); transform: translateY(-3px); }
.exhibit--paper .exhibit__item img { border: 0; border-radius: 0; filter: none; }


/* ---- Golden Eagle main plate: larger, just shy of full screen ---- */
.plates--xl { max-width: min(1700px, 96vw); }
.plates--xl .plate--wide .plate__btn img { max-height: 90vh; }

/* ---- Indian Birds: a long series of solo + paired drawings ---- */
.series { max-width: min(1500px, 94vw); margin: 0 auto; }
.series__row { margin-bottom: clamp(34px, 4vw, 60px); display: flex; justify-content: center; align-items: center; }
.series__row:last-child { margin-bottom: 0; }
.series__row--duo { gap: clamp(28px, 3vw, 46px); align-items: center; }
.series__cell { flex: 1 1 0; min-width: 0; display: flex; justify-content: center; }
.series__row--duo .series__cell { flex: 0 0 auto; }
.series__btn { display: block; padding: 0; border: 0; background: none; position: relative; cursor: zoom-in; width: auto; max-width: 100%; }
.series__btn img { display: block; width: auto; height: auto; max-width: 100%; border-radius: 3px; box-shadow: 0 10px 44px rgba(21,19,15,.13); transition: box-shadow .4s ease; }
.series__btn:hover img { box-shadow: 0 18px 60px rgba(21,19,15,.2); }
.series__row--solo .series__btn img { max-height: 82vh; }
.series__row--duo  .series__btn img { width: min(40vw, 440px); height: auto; max-height: none; }@media (max-width: 720px){
  .series__row--duo { flex-direction: column; gap: clamp(34px, 6vw, 60px); }
  .series__row--duo .series__btn img { width: min(82vw, 440px); max-height: none; }}

/* ---- Closing image band (e.g. Bird Stipplings hub bottom header) ---- */
.hero--end { height: auto; max-height: 88vh; background: transparent; line-height: 0; overflow: hidden; display: flex; align-items: center; justify-content: center; }
.hero--end::after { display: none; }
.hero--end .hero__img { position: static; inset: auto; width: 100%; height: auto; object-fit: initial; object-position: initial; }

/* animated footer banner (live embed instead of a still image): dark band,
   fixed cinematic aspect, iframe fills it. Dark from first paint so the
   embed's own dark background never flashes white while loading. Carries its
   own top margin (this page's <main> isn't .hub) for separation from the prose. */
.hero--end-anim {
  display: block; width: 100%;
  margin-top: clamp(80px, 11vw, 160px);
  aspect-ratio: 2.044 / 1; height: auto; max-height: 88vh;
  background: #0b0b10; overflow: hidden;
}
.hero--end-anim .hero__embed {
  position: absolute; inset: 0;
  display: block; width: 100%; height: 100%;
  border: 0; opacity: 0; transition: opacity 1s ease;
}
/* Still fallback behind the animated footer banner: same 2.044:1 box, shown
   instantly and while the live embed boots (or if its WebGL context is ever
   lost). The embed fades in over it; the poster sits behind via DOM order
   (both are absolute, poster authored first). */
.hero__embed-poster {
  position: absolute; inset: 0;
  width: 100%; height: 100%;
  object-fit: cover; object-position: center;
  display: block; pointer-events: none;
  background: #0b0b10;
}

/* ===== Photography — featured carousel + justified gallery + lightbox ===== */
/* one photo at a time on the normal background, filling the width; circular arrows as elsewhere */
.photo-carousel { position: relative; max-width: var(--wide); margin: 0 auto; padding: 0 84px; }
.photo-carousel .exhibit__arrow--prev { left: 12px; }
.photo-carousel .exhibit__arrow--next { right: 12px; }
.photo-carousel__frame { display: flex; align-items: center; justify-content: center;
  height: clamp(440px, 84vh, 800px); }
.photo-carousel__img { display: block; width: auto; height: auto;
  max-width: 100%; max-height: 100%; object-fit: contain; cursor: zoom-in;
  opacity: 0; transition: opacity .35s ease; box-shadow: 0 14px 50px rgba(21,19,15,.16); }
.photo-carousel__count { text-align: center; font-family: var(--sans);
  font-size: 12px; letter-spacing: .22em; color: var(--ink-soft); margin: 18px 0 0; }

.gallery-wrap { max-width: min(1500px, 95vw); margin: 0 auto; }
.gallery { display: flex; flex-wrap: wrap; gap: 8px; }
.gallery__item { flex: 0 0 auto; margin: 0; position: relative; overflow: hidden;
  background: #ecebe6; cursor: zoom-in; }
.gallery__item img { display: block; width: 100%; height: 100%; object-fit: cover;
  transition: transform .5s cubic-bezier(.2,.7,.2,1); }
.gallery__item:hover img { transform: scale(1.035); }

/* full-screen lightbox */
.lightbox { position: fixed; inset: 0; z-index: 200; display: flex;
  align-items: center; justify-content: center; background: rgba(10,10,10,.94);
  opacity: 0; transition: opacity .22s ease; }
.lightbox.is-open { opacity: 1; }
.lightbox[hidden] { display: none; }
.lightbox img { max-width: 92vw; max-height: 90vh; object-fit: contain;
  box-shadow: 0 30px 80px rgba(0,0,0,.5); user-select: none; -webkit-user-drag: none; }
.lb-btn { position: absolute; background: none; border: 0; color: #fff; cursor: pointer;
  opacity: .65; transition: opacity .15s ease; -webkit-tap-highlight-color: transparent; }
.lb-btn:hover { opacity: 1; }
.lb-close { top: clamp(12px,2.4vw,26px); right: clamp(12px,2.4vw,26px);
  font-size: 30px; line-height: 1; width: 46px; height: 46px; }
.lb-prev, .lb-next { top: 50%; transform: translateY(-50%);
  font-size: clamp(34px,4vw,52px); line-height: 1; width: 58px; height: 84px; }
.lb-prev { left: clamp(6px,2vw,28px); }
.lb-next { right: clamp(6px,2vw,28px); }@media (hover: none){ .gallery__item:hover img { transform: none; }}@media (max-width: 640px){
  .photo-carousel { padding: 0 56px; }
  .photo-carousel__frame { height: clamp(360px, 64vh, 560px); }
  .photo-carousel .exhibit__arrow { width: 46px; height: 46px; }
  .photo-carousel .exhibit__arrow svg { width: 24px; height: 15px; }
  .photo-carousel .exhibit__arrow--prev { left: 5px; }
  .photo-carousel .exhibit__arrow--next { right: 5px; }}

/* =========================================================================
   19. About page — "the monograph with a geometric signature"
   Everything here is scoped to .about-* classes; the page uses its own
   bands (not .section) so none of this can disturb the rest of the site.
   ========================================================================= */

/* shared horizontal gutter for the statement / cv / contact bands */
.about-band { padding: 0 var(--gutter); }

/* ---- intro: portrait + name + opening line ---------------------------- */
.about-top { padding: clamp(40px, 7vw, 94px) var(--gutter) 0; }
.about-intro {
  max-width: 1000px;
  margin: 0 auto;
  display: grid;
  grid-template-columns: minmax(0, 0.85fr) minmax(0, 1.05fr);
  gap: clamp(28px, 5vw, 74px);
  align-items: center;
}
.about-portrait { line-height: 0; }
.about-portrait img { width: 100%; height: auto; border-radius: 8px; }
.about-intro-text { max-width: none; }
.about-name {
  font-family: var(--serif);
  font-weight: 400;
  letter-spacing: -0.015em;
  line-height: 1.04;
  font-size: clamp(26px, 4.2vw, 40px);
}
.about-lede {
  margin-top: clamp(16px, 2vw, 24px);
  font-family: var(--serif);
  font-size: clamp(16px, 1.4vw, 18.5px);
  line-height: 1.72;
  color: var(--ink);
}

/* bio body — left-aligned at reading measure (grounded, factual) */
.about-bio { max-width: var(--measure); margin: clamp(52px, 8vw, 96px) auto 0; }
.about-bio p {
  font-family: var(--serif);
  font-size: clamp(16px, 1.4vw, 18.5px);
  line-height: 1.78;
  color: var(--ink);
}
.about-bio p + p { margin-top: 1.25em; }

/* ---- geometric dividers (the signature: 3-, 4-, 5-gon glyphs) --------- */
.about-divider {
  display: flex;
  align-items: center;
  gap: clamp(14px, 2.2vw, 26px);
  width: 100%;
  max-width: 360px;
  margin: clamp(54px, 9vw, 116px) auto;
  padding: 0 20px;
}
.about-divider::before,
.about-divider::after { content: ""; flex: 1; height: 1px; background: var(--line); }
.about-divider svg { flex: 0 0 auto; width: 22px; height: 22px; display: block; overflow: visible; }
.about-divider polygon { fill: none; stroke: var(--ink-soft); stroke-width: 1; opacity: .55; }

/* ---- artist statement (lyrical centre + one floating specimen) -------- */
.about-statement-band { position: relative; }
.about-statement { max-width: 760px; margin: 0 auto; text-align: center; position: relative; z-index: 1; }
.about-eyebrow {
  font-family: var(--sans);
  font-weight: 400;
  font-size: 12.5px;
  letter-spacing: .26em;
  text-transform: uppercase;
  color: var(--ink-soft);
  margin-bottom: clamp(20px, 3vw, 34px);
}
.about-statement p {
  font-family: var(--serif);
  font-weight: 300;
  font-size: clamp(19px, 2vw, 24px);
  line-height: 1.46;
  letter-spacing: -0.01em;
  color: var(--ink);
}
.about-statement p + p { margin-top: 1em; }

/* ---- CV lists: exhibitions, workshops & talks ------------------------- */
.about-cv { max-width: 800px; margin: 0 auto; }
.cv-group + .cv-group { margin-top: clamp(46px, 7vw, 86px); }
.cv-head {
  font-family: var(--sans);
  font-weight: 400;
  font-size: 12.5px;
  letter-spacing: .26em;
  text-transform: uppercase;
  color: var(--ink-soft);
  padding-bottom: 14px;
  border-bottom: 1px solid var(--line);
}
.cv-row {
  display: grid;
  grid-template-columns: 4.5rem 1fr;
  gap: clamp(12px, 2vw, 30px);
  padding: clamp(15px, 1.8vw, 20px) 0;
  border-bottom: 1px solid var(--line);
  align-items: baseline;
}
.cv-row .yr {
  font-family: var(--sans);
  font-size: 13px;
  letter-spacing: .06em;
  color: var(--ink-soft);
  font-variant-numeric: tabular-nums;
}
.cv-entry { font-family: var(--sans); }
.cv-entry .ttl { font-size: clamp(15px, 1.3vw, 16.5px); line-height: 1.45; color: var(--ink); }
.cv-entry .ttl em { font-style: italic; }
.cv-entry .venue { display: block; margin-top: 3px; font-size: 13.5px; line-height: 1.5; color: var(--ink-soft); }
.cv-watch {
  display: inline-flex; align-items: center; gap: .4em; margin-top: 8px;
  font-family: var(--sans); font-size: 11.5px; letter-spacing: .16em; text-transform: uppercase;
  color: var(--ink-soft); text-decoration: none;
  border-bottom: 1px solid var(--line); padding-bottom: 2px;
  transition: color .2s ease, border-color .2s ease;
}
.cv-watch:hover { color: var(--ink); border-color: var(--ink); }
.cv-watch:focus-visible { outline: 2px solid var(--ink); outline-offset: 3px; }

/* ---- contact ---------------------------------------------------------- */
.about-contact { max-width: 560px; margin: 0 auto; text-align: center; }
.about-contact h2 { font-family: var(--serif); font-weight: 400; font-size: clamp(22px, 2.7vw, 29px); letter-spacing: -0.01em; }
.contact-intro { margin-top: .7em; font-family: var(--serif); font-size: clamp(16px, 1.4vw, 18.5px); color: var(--ink-soft); }
.contact-form { margin-top: clamp(28px, 4vw, 44px); text-align: left; }
.field { margin-bottom: clamp(20px, 2.6vw, 28px); }
.field label {
  display: block; font-family: var(--sans); font-size: 11.5px; letter-spacing: .2em;
  text-transform: uppercase; color: var(--ink-soft); margin-bottom: 9px;
}
.field input, .field textarea {
  width: 100%; appearance: none; -webkit-appearance: none;
  background: transparent; border: 0; border-bottom: 1px solid var(--line); border-radius: 0;
  padding: 8px 2px; font-family: var(--serif); font-size: 17px; color: var(--ink);
  transition: border-color .25s ease;
}
.field textarea { resize: vertical; min-height: 120px; line-height: 1.6; }
.field input:hover, .field textarea:hover { border-bottom-color: var(--ink-soft); }
.field input:focus, .field textarea:focus { outline: none; border-bottom-color: var(--ink); }
.field input:focus-visible, .field textarea:focus-visible { outline: 2px solid var(--ink); outline-offset: 4px; }
.field-row { display: grid; grid-template-columns: 1fr 1fr; gap: clamp(18px, 3vw, 34px); }
.contact-send {
  appearance: none; -webkit-appearance: none; cursor: pointer; margin: 8px auto 0;
  display: flex; width: fit-content; align-items: center; gap: .6em;
  background: transparent; color: var(--ink); border: 1px solid var(--ink);
  padding: 13px 30px; font-family: var(--sans); font-size: 12px; letter-spacing: .22em; text-transform: uppercase;
  transition: background .25s ease, color .25s ease;
}
.contact-send:hover { background: var(--ink); color: var(--paper); }
.contact-send:focus-visible { outline: 2px solid var(--ink); outline-offset: 3px; }
.contact-send .ar { font-size: 1.2em; line-height: 0; }
.contact-form .hp { position: absolute !important; left: -9999px !important; }
.about-contact-band { padding-bottom: clamp(70px, 11vw, 150px); }

/* ---- responsive ------------------------------------------------------- */
@media (max-width: 820px) {
  .about-intro { grid-template-columns: 1fr; gap: clamp(24px, 6vw, 40px); max-width: 460px; }
  .about-intro-text { max-width: none; }
  .about-statement p { font-size: clamp(18px, 4.2vw, 22px); }
}@media (max-width: 540px){
  .field-row { grid-template-columns: 1fr; }
  .cv-row { grid-template-columns: 3.2rem 1fr; gap: 14px; }}

/* social links under the About intro (About page only) */
.about-social { display: flex; gap: 10px; margin-top: clamp(17px, 2.2vw, 26px); margin-left: -10px; }
.about-social a {
  display: inline-flex; align-items: center; justify-content: center;
  width: 38px; height: 38px; color: var(--ink);
  transition: opacity .2s ease, transform .2s ease;
}
.about-social a:hover { opacity: .58; transform: translateY(-2px); }
.about-social a:focus-visible { outline: 2px solid var(--ink); outline-offset: 2px; border-radius: 6px; }
.about-social svg { width: 18px; height: 18px; display: block; fill: currentColor; }
.about-social a[aria-label="Vimeo"] svg { width: 17px; height: 17px; }@media (prefers-reduced-motion: reduce){ .about-social a:hover { transform: none; }}

/* ============================================================
   20 · RESEARCH — hub index + long-form article (Distill/Ciechanowski feel)
   ============================================================ */
:root{ --fig:#4f4a42; }

/* ---- Research hub ---- */
.research-head{ max-width:var(--measure); margin:clamp(40px,7vw,86px) auto clamp(26px,4vw,44px); padding:0 var(--gutter); }
.research-eyebrow{ font-family:var(--sans); text-transform:uppercase; letter-spacing:.2em; font-size:12.5px; font-weight:500; color:var(--ink-soft); margin:0 0 .9rem; }
.research-title{ font-family:var(--serif); font-weight:400; font-size:clamp(30px,5vw,46px); line-height:1.06; letter-spacing:-.01em; margin:0 0 1rem; }
.research-intro{ font-family:var(--serif); font-size:clamp(17px,2vw,19px); line-height:1.5; color:var(--ink-soft); max-width:56ch; margin:0; }

.research-index{ max-width:var(--measure); margin:0 auto clamp(60px,10vw,120px); padding:0 var(--gutter); border-top:1px solid var(--line); }
.research-entry{ display:grid; grid-template-columns:78px 1fr; gap:clamp(14px,3vw,40px); padding:clamp(26px,3.4vw,40px) 0; border-bottom:1px solid var(--line); text-decoration:none; color:inherit; align-items:start; }
a.research-entry{ transition:opacity .18s ease; }
a.research-entry:hover{ opacity:1; }
a.research-entry:hover .research-entry__title{ text-decoration:underline; text-underline-offset:3px; text-decoration-thickness:1px; }
.research-entry__year{ font-family:var(--sans); font-size:13px; letter-spacing:.04em; color:var(--ink-soft); padding-top:.45rem; }
.research-entry__title{ font-family:var(--serif); font-weight:400; font-size:clamp(21px,2.7vw,28px); line-height:1.12; margin:0 0 .5rem; }
.research-entry__abs{ font-family:var(--serif); font-size:clamp(15px,1.7vw,16.5px); line-height:1.5; color:var(--ink-soft); margin:0 0 .85rem; max-width:60ch; }
.research-entry__read{ font-family:var(--sans); font-size:12.5px; text-transform:uppercase; letter-spacing:.14em; color:var(--ink); }


/* ---- Article: hero ---- */
.paper{ padding:clamp(30px,5vw,68px) var(--gutter) 0; }
.paper-hero{ max-width:var(--measure); margin:0 auto clamp(26px,4vw,40px); }
.paper-eyebrow{ font-family:var(--sans); text-transform:uppercase; letter-spacing:.2em; font-size:12.5px; font-weight:500; margin:0 0 1.4rem; }
.paper-eyebrow a{ color:var(--ink-soft); text-decoration:none; }
.paper-eyebrow a:hover{ color:var(--ink); }
.paper-title{ font-family:var(--serif); font-weight:400; font-size:clamp(30px,5.4vw,52px); line-height:1.04; letter-spacing:-.015em; margin:0 0 1.1rem; }
.paper-sub{ font-family:var(--serif); font-style:italic; font-size:clamp(18px,2.3vw,23px); line-height:1.38; color:var(--ink-soft); margin:0 0 1.3rem; max-width:54ch; }
.paper-byline{ font-family:var(--sans); font-size:13.5px; letter-spacing:.03em; color:var(--ink-soft); margin:0; }

/* ---- Abstract ---- */
.paper-abstract{ max-width:var(--measure); margin:0 auto clamp(30px,5vw,52px); padding:clamp(20px,3vw,30px) 0 clamp(22px,3vw,32px); border-top:1px solid var(--line); border-bottom:1px solid var(--line); }
.paper-abstract__label{ font-family:var(--sans); text-transform:uppercase; letter-spacing:.18em; font-size:11.5px; font-weight:600; color:var(--ink-soft); margin:0 0 .8rem; }
.paper-abstract p{ font-family:var(--serif); font-size:clamp(16.5px,1.9vw,18.5px); line-height:1.6; margin:0; }

/* ---- Layout: sticky TOC + body ---- */
.paper-layout{ display:grid; grid-template-columns:minmax(0,1fr) minmax(0,var(--measure)) minmax(0,1fr); column-gap:clamp(16px,3vw,48px); align-items:start; }
.paper-toc{ grid-column:1; justify-self:end; position:sticky; top:104px; width:190px; max-height:calc(100vh - 140px); overflow:auto; padding-bottom:2rem; }
.paper-toc__h{ font-family:var(--sans); text-transform:uppercase; letter-spacing:.16em; font-size:11px; font-weight:600; color:var(--ink-soft); margin:0 0 1rem; }
.paper-toc ol{ list-style:none; margin:0; padding:0; }
.paper-toc li{ margin:0 0 .7rem; }
.paper-toc a{ display:grid; grid-template-columns:26px 1fr; gap:.3rem; font-family:var(--sans); font-size:13px; line-height:1.3; color:var(--ink-soft); text-decoration:none; transition:color .15s ease; }
.paper-toc a:hover{ color:var(--ink); }
.paper-toc a.is-current{ color:var(--ink); font-weight:500; }
.paper-toc__n{ font-size:11px; letter-spacing:.04em; opacity:.7; padding-top:.12em; }

.paper-body{ grid-column:2; min-width:0; }
.paper-body p{ font-family:var(--serif); font-size:clamp(16.5px,1.9vw,18.5px); line-height:1.66; margin:0 0 1.25em; }
.paper-sec{ margin:clamp(34px,5vw,58px) 0 0; scroll-margin-top:100px; }
.paper-h2{ font-family:var(--serif); font-weight:400; font-size:clamp(23px,3.2vw,32px); line-height:1.12; letter-spacing:-.01em; margin:0 0 1rem; padding-top:.6em; }
.paper-h2__n{ font-family:var(--sans); font-size:.46em; font-weight:600; letter-spacing:.1em; color:var(--ink-soft); vertical-align:middle; margin-right:.95em; position:relative; top:-.18em; }
.paper-h3{ font-family:var(--serif); font-style:italic; font-weight:400; font-size:clamp(17px,2vw,20px); color:var(--ink); margin:2em 0 .8em; }

/* ---- Figures ---- */
.paper-fig{ margin:clamp(28px,4vw,46px) 0; }
.paper-fig__art{ color:var(--fig); display:flex; justify-content:center; }
.paper-fig svg.gx{ display:block; height:auto; max-width:100%; }
.paper-fig--half .paper-fig__art{ max-width:500px; margin:0 auto; }
.paper-fig--half svg.gx{ width:100%; }
.paper-fig--wide{ width:100%; }
.paper-fig__img{ display:block; width:100%; height:auto; }
.paper-fig__pair{ display:flex; flex-wrap:wrap; gap:clamp(16px,3vw,44px); justify-content:center; align-items:flex-start; width:100%; }
.paper-fig__pair .paper-fig__img{ width:auto; max-width:calc(50% - 22px); height:auto; }
.paper-fig__stack{ display:flex; flex-direction:column; gap:clamp(14px,2.2vw,26px); align-items:center; width:100%; }
.paper-cap{ font-family:var(--sans); font-size:13px; line-height:1.5; color:var(--ink-soft); text-align:center; margin:1rem auto 0; max-width:60ch; }
.paper-cap__n{ font-weight:600; letter-spacing:.03em; color:var(--ink); }


.paper-back{ max-width:var(--measure); margin:clamp(34px,5vw,56px) auto clamp(50px,8vw,90px); }
.paper-back a{ font-family:var(--sans); font-size:13px; text-transform:uppercase; letter-spacing:.14em; color:var(--ink-soft); text-decoration:none; }
.paper-back a:hover{ color:var(--ink); }

/* ---- Responsive: collapse TOC into a contents block above the article ---- */
@media (max-width:1200px){
  .paper-layout{ grid-template-columns:minmax(0,1fr); }
  .paper-toc{ grid-column:1; position:static; width:100%; max-width:var(--measure); margin:0 auto clamp(20px,4vw,32px); max-height:none; justify-self:center; border:1px solid var(--line); border-radius:10px; padding:1.1rem 1.3rem; }
  .paper-toc ol{ columns:2; column-gap:1.6rem; }
  .paper-body{ grid-column:1; max-width:var(--measure); margin:0 auto; }
}@media (max-width:560px){
  .paper-toc ol{ columns:1; }
  .research-entry{ grid-template-columns:1fr; gap:.5rem; }
  .research-entry__year{ padding-top:0; }
  .paper-fig--wide{ width:100%; margin-left:0; transform:none; }}

/* paper body: lists & lead-in sublabels (added for full paper text) */
.paper-body .paper-ul{ margin:1.15em 0 1.4em; padding-left:1.3em; }
.paper-body .paper-ul li{ margin:.45em 0; line-height:1.55; color:var(--ink); }
.paper-body .paper-ul li::marker{ color:var(--ink-soft); }
.paper-lead{ margin:1.9em 0 .35em; font-size:1.02em; }
.paper-lead strong{ font-weight:600; letter-spacing:.01em; }

/* paper body: animated moire figures */
.paper-fig__art canvas.moire-anim{ display:block; width:100%; max-width:100%; height:auto; margin:0 auto; }

/* paper body: figure rows (multi-image sequences) */
.paper-fig__row{ display:flex; flex-wrap:wrap; gap:clamp(10px,1.8vw,18px); justify-content:center; align-items:center; width:100%; }
.paper-fig__row .paper-fig__img{ width:auto; flex:1 1 0; min-width:118px; max-width:calc(20% - 15px); height:auto; }

/* paper body: tall chart figures (sine-wave & symmetry diagrams) */
.paper-fig--tall .paper-fig__img{ width:auto; max-width:min(100%,520px); max-height:min(76vh,760px); }
.paper-fig--tall .paper-fig__pair .paper-fig__img{ max-width:calc(50% - 22px); }@media (max-width:560px){
  .paper-fig--tall .paper-fig__pair .paper-fig__img{ max-width:100%; max-height:none; }}

/* paper body: media figures (videos and live embeds) */
.paper-fig .video-embed{ width:100%; }
.paper-fig__vstack{ display:flex; flex-direction:column; gap:clamp(14px,2.4vw,26px); width:100%; }
.ref-mark{ text-decoration:none; border-bottom:none; }
.ref-mark sup{ font-size:0.68em; letter-spacing:0.02em; color:#6b675f; }
.ref-mark:hover sup{ color:inherit; }
.paper-refs{ list-style:none; counter-reset:ref; margin:0; padding:0; }
.paper-refs li{ counter-increment:ref; position:relative; padding-left:2.4em; margin:0 0 0.9em; font-size:0.95em; line-height:1.65; }
.paper-refs li::before{ content:"[" counter(ref) "]"; position:absolute; left:0; top:0; color:#6b675f; font-variant-numeric:tabular-nums; }
.paper-refs a{ word-break:break-word; }
.paper-fig__rows{ display:flex; flex-direction:column; gap:clamp(10px,1.6vw,16px); width:100%; }
.paper-fig__trio{ display:flex; gap:clamp(10px,1.6vw,16px); justify-content:center; }
.paper-fig__trio .paper-fig__img{ width:auto; max-width:calc(33.333% - clamp(7px,1.1vw,11px)); height:auto; }
.paper-fig__vstack .video-embed + .video-embed{ margin-top:0; }

/* ---- Research: Colour Perception (image-led visual study) ---- */
.cp-plates{ max-width:880px; margin:0 auto; }
.cp-plate{ margin:clamp(38px,6.5vw,78px) 0; }
.cp-plates .cp-plate:first-child{ margin-top:clamp(8px,1.5vw,14px); }
.cp-plate__btn{ display:flex; justify-content:center; width:100%; padding:0; margin:0; border:0; background:none; cursor:zoom-in; }
.cp-plate__btn:focus-visible{ outline:2px solid var(--ink-soft); outline-offset:5px; }
.cp-plate .paper-fig__img{ width:auto; max-width:100%; max-height:76vh; margin:0 auto; }
.cp-plate--edged .paper-fig__img{ border:1px solid var(--line); }
.paper-abstract p.cp-materials{ font-family:var(--sans); font-size:13px; letter-spacing:.02em; line-height:1.6; color:var(--ink-soft); margin-top:1.1rem; }
.paper-abstract p + p{ margin-top:1rem; }

/* chromacy subsection */
.cp-section{ max-width:var(--measure); margin:clamp(40px,7vw,86px) auto 0; padding-top:clamp(26px,4vw,44px); border-top:1px solid var(--line); }
.cp-h2{ font-family:var(--serif); font-weight:400; font-size:clamp(23px,3.2vw,32px); line-height:1.12; letter-spacing:-.01em; margin:0 0 1rem; }
.cp-text{ font-family:var(--serif); font-size:clamp(16.5px,1.9vw,18.5px); line-height:1.66; margin:0; }
.cp-species{ max-width:760px; margin:clamp(24px,4vw,40px) auto 0; display:grid; grid-template-columns:1fr 1fr; gap:clamp(20px,4vw,52px) clamp(20px,4vw,46px); }
.cp-creature{ margin:0; }
.cp-creature .paper-cap{ max-width:36ch; }@media (max-width:560px){
  .cp-species{ grid-template-columns:1fr; gap:clamp(30px,8vw,44px); }}

/* ---- Poetry (chapbook page) ---- */
.poems .poem{ text-align:center; padding:clamp(44px,7vw,80px) 0; border-bottom:1px solid var(--line); scroll-margin-top:84px; }
.poems .poem:first-child{ padding-top:clamp(6px,1.5vw,14px); }
.poems .poem:last-child{ border-bottom:0; }
.poem__title{ font-family:var(--serif); font-weight:400; font-size:clamp(24px,3.4vw,34px); line-height:1.1; letter-spacing:-.01em; margin:0 0 .4rem; }
.poem__year{ font-family:var(--sans); font-size:11.5px; letter-spacing:.18em; color:var(--ink-soft); margin:0 0 clamp(22px,3.6vw,38px); }
.poems .poem__verse p{ font-family:var(--serif); font-size:clamp(16.5px,1.9vw,18.5px); line-height:1.78; margin:0 0 1.5em; }
.poems .poem__verse p:last-child{ margin-bottom:0; }
.poem--prose .poem__verse p{ line-height:1.68; text-align:center; }
.paper-bib{ margin:clamp(40px,6vw,64px) 0 0; padding-top:clamp(26px,4vw,40px); border-top:1px solid var(--line); }
.paper-bib__h{ font-family:var(--sans); font-size:12.5px; font-weight:500; letter-spacing:.2em; text-transform:uppercase; margin:0 0 1.4rem; }
.paper-bib__list{ list-style:none; margin:0; padding:0; }
.paper-bib__list li{ font-family:var(--serif); font-size:clamp(15.5px,1.8vw,17.5px); line-height:1.65; margin:0 0 .95em; padding-left:1.35em; text-indent:-1.35em; }
.paper-bib__list a{ word-break:break-word; }

/* ===== Hero first-frame poster: same cover math as the video, so the
       still and the footage are pixel-registered by construction ===== */
.hero__poster{
  position:absolute;
  top:50%; left:50%;
  transform:translate(-50%,-50%);
  width:100vw; height:56.25vw;
  min-height:100%; min-width:177.78svh;
  object-fit:cover;
  pointer-events:none;
}
/* Homepage only: the poster sits 1px low against the video, so nudge it up 1px
   to line them up exactly. Other poster heroes (e.g. kinetic) keep the centred
   transform above. */
.hero--full .hero__poster{transform:translate(-50%,calc(-50% - 1px))}
.hero--poster .hero__video{opacity:0;transition:opacity .8s ease}
.hero--poster .hero__video.is-live{opacity:1}@media (prefers-reduced-motion: reduce){.hero--poster .hero__video{transition:none}}
/* --- Film embeds: offline/unreachable fallback -----------------------------
   The box keeps its original look: pure #000, player boots in place. The iframe
   is invisible until the Vimeo player document completes its handshake (site.js
   adds .is-live on p.ready()) — so a failed load can never paint the browser's
   error page. If no handshake arrives within the grace window, site.js adds
   .show-poster and the film's own still fades in, letterboxed (contain), never
   cropped. Online, the still never appears at all. html.reveal-fallback is the
   existing fail-open used when site.js itself never runs. ------------------ */
.video-embed > iframe.vid--vimeo { opacity: 0; transition: opacity .35s ease; }
.video-embed.is-live > iframe.vid--vimeo,
html.reveal-fallback .video-embed > iframe.vid--vimeo { opacity: 1; }
.video-embed:not(.is-live) .vctrl { opacity: 0; pointer-events: none; }
.video-embed.show-poster {
  background-image: var(--vposter);
  background-size: contain;
  background-repeat: no-repeat;
  background-position: center;
}
.video-embed.show-poster { transition: background-color .4s ease; }

/* ══ Animation fullscreen (mobile) — sibling of the .vctrl video controls ══
   A small circular expand button appears on animation surfaces (lab embeds,
   hub tiles, inline .embed-anim panes) on touch / narrow screens only, and
   opens the animation in a fullscreen overlay styled like the video player:
   the same bottom-gradient control bar, the same icon language. */
.afs-rel { position: relative; }
.afs-btn {
  position: absolute; right: 10px; bottom: 10px; z-index: 4;
  width: 34px; height: 34px; padding: 8px; border: 0; cursor: pointer;
  color: var(--paper); background: rgba(10,9,7,.45); border-radius: 999px;
  display: none; opacity: .85; -webkit-tap-highlight-color: transparent;
  transition: opacity .2s ease, background .2s ease;
}
.afs-btn svg { width: 100%; height: 100%; display: block; }
.afs-btn:hover, .afs-btn:focus-visible { opacity: 1; background: rgba(10,9,7,.62); }
@media (hover: none) and (pointer: coarse), (max-width: 900px) {
  .afs-btn { display: inline-flex; }
}
.afs-overlay {
  position: fixed; inset: 0; z-index: 2147483000; background: #000;
  display: flex; align-items: center; justify-content: center;
}
.afs-overlay video, .afs-overlay iframe {
  width: 100%; height: 100%; object-fit: contain; border: 0; background: #000;
}
.afs-overlay iframe { pointer-events: none; }   /* passive screen, like .lab-embed */
.afs-overlay .vctrl { opacity: 1; }             /* controls always visible here */
.afs-stage { position: relative; width: 100%; height: 100%; }

/* Synthetic landscape — portrait phones whose browser has no orientation
   lock (iOS). The stage turns 90° and takes the rotated viewport's size, so
   the 16:9 piece is presented landscape immediately; physically turning the
   phone completes it. Where the real lock succeeds (Android fullscreen) the
   viewport itself goes landscape and this class is never applied. */
.afs-overlay--rot .afs-stage {
  position: absolute;
  top: 50%; left: 50%;
  width: 100vh; height: 100vw;        /* older-iOS fallback */
  width: 100dvh; height: 100dvw;
  transform: translate(-50%, -50%) rotate(90deg);
}

/* ══ Mobile: banners show their full frame, uncropped ══
   On phones every section hero (hero--tall) drops the fixed 94svh cover-crop
   and renders at the banner's own aspect ratio, full width — the whole
   composition, exactly as it reads on desktop. Video heroes keep the poster
   and the loop overlaid (both are authored 16:9, so the pair stays in step).
   The homepage hero (hero--full) keeps its full-screen treatment. */
@media (max-width: 700px) {
  .hero--tall {
    height: auto;
    background: var(--paper); /* fractional-px rounding of the overlay can no
                                 longer expose the black hero backdrop as a
                                 thin line under the banner animation */
  }
  .hero--tall .hero__img,
  .hero--tall .hero__poster {
    position: static !important; inset: auto !important;
    top: auto !important; left: auto !important;
    transform: none !important;
    width: 100% !important; height: auto !important;
    min-width: 0 !important; min-height: 0 !important;
    object-fit: initial !important;
    display: block;
  }
  .hero--tall .hero__video {
    position: absolute !important; inset: 0 !important;
    top: 0 !important; left: 0 !important;
    transform: none !important;
    width: 100% !important; height: 100% !important;
    min-width: 0 !important; min-height: 0 !important;
    object-fit: cover;          /* same 16:9 as its poster — overlay, no crop */
  }
}

/* ══ Mobile: lab embeds keep their desktop framing ══
   The panes are small on a phone, and the pieces frame their scenes for a
   desktop-width canvas. Instead of re-framing forty programs, each embedded
   pane renders internally at 2.5× its on-screen width — a desktop-class
   viewport — and is scaled down to fit. The framing is therefore identical
   to desktop, miniaturized; the fullscreen button gives the full-size view. */
@media (max-width: 700px) {
  .lab-embed iframe,
  iframe.embed-anim {
    width: 250% !important; height: 250% !important;
    transform: scale(0.4);
    transform-origin: 0 0;
  }
}


/* ══ Keyboard: a consistent visible focus ring site-wide ══ */
a:focus-visible, button:focus-visible, [role="button"]:focus-visible, summary:focus-visible {
  outline: 2px solid var(--ink);
  outline-offset: 3px;
  border-radius: 2px;
}

/* ══ Artwork media: no drag-out, no long-press save sheet, no text-selection ══ */
img, video, canvas, picture, svg {
  -webkit-user-drag: none;
  user-select: none;
  -webkit-user-select: none;
  -webkit-touch-callout: none;
}


/* ══ Reduced-motion play badge ══ */
.rm-play {
  position: absolute; z-index: 4; top: 50%; left: 50%;
  width: 54px; height: 54px; margin: -27px 0 0 -27px; padding: 15px;
  border: 0; cursor: pointer; color: var(--paper);
  background: rgba(10,9,7,.5); border-radius: 999px;
  display: inline-flex; -webkit-tap-highlight-color: transparent;
  transition: background .2s ease;
}
.rm-play:hover, .rm-play:focus-visible { background: rgba(10,9,7,.68); }
.rm-play svg { width: 100%; height: 100%; display: block; }

/* ══ Streams: portrait-source banner sits at section-banner height ══ */
@media (max-width: 700px) {
  .hero--tall { background: transparent; line-height: 0; }
  .hero--portrait-src { height: 57vw; }
  .hero--portrait-src .hero__img {
    position: absolute !important; inset: 0 !important;
    width: 100% !important; height: 100% !important;
    object-fit: cover !important;   /* object-position: the page's own tuned value governs */
  }
}

/* ══ Essay index: title + actions become the links (card is a plain grid) ══ */
.research-entry__title a { color: inherit; text-decoration: none; }
.research-entry__title a:hover { text-decoration: underline; text-underline-offset: 3px; text-decoration-thickness: 1px; }
.research-entry__actions { display: flex; gap: 22px; align-items: baseline; flex-wrap: wrap; }
a.research-entry__read { text-decoration: none; }
a.research-entry__read:hover { text-decoration: underline; text-underline-offset: 3px; }

/* figure pairs: invisible on screen, two-up in print */
.fig-pair { display: contents; }

/* ══ Print: the essays as considered documents ══
   A proper reading measure (~70 characters), clearly separated paragraphs,
   figures set as plates with air around them, and paired plates at equal
   height — image bottoms on one line, captions starting on one line. */
@media print {
  .site-header, .nav-toggle, .work-nav, .paper-toc, footer,
  .afs-btn, .mg-pill, .rm-play,
  .paper-eyebrow, .paper-back { display: none !important; }
  img:not([src]) { display: none !important; }
  .reveal { opacity: 1 !important; visibility: visible !important; transform: none !important; transition: none !important; }
  html, body { background: #fff; }
  a { color: inherit; text-decoration: none; }
  .paper { padding: 0; }
  .paper-layout { display: block; }

  /* reading column */
  .paper-hero { max-width: 400pt; margin: 0 auto 14pt; text-align: center; }
  .paper-abstract, .paper-body { max-width: 362pt; margin-left: auto; margin-right: auto; }
  .paper-body { counter-reset: fig; }

  .paper-title { font-size: 19pt; line-height: 1.16; letter-spacing: -.008em; margin: 0 0 7pt; }
  .paper-sub { font-size: 11pt; line-height: 1.4; margin: 0 auto 8pt; max-width: 88%; }
  .paper-byline { font-size: 9pt; letter-spacing: .06em; padding-bottom: 9pt; border-bottom: 1px solid #c9c6bf; }

  .paper-abstract { margin-top: 12pt; margin-bottom: 16pt; padding: 8pt 0 10pt; }
  .paper-abstract__label { font-size: 7.5pt; letter-spacing: .22em; text-align: center; margin: 0 0 5pt; }
  .paper-abstract p { font-size: 9.5pt; line-height: 1.5; text-align: justify;
                      hyphens: auto; -webkit-hyphens: auto; margin: 0; }

  /* body: clearly separated paragraphs */
  .paper-body p { font-size: 10.5pt; line-height: 1.5; margin: 0 0 6pt; text-indent: 0;
                  text-align: justify; hyphens: auto; -webkit-hyphens: auto; orphans: 3; widows: 3; }
  .paper-sec { margin: 14pt 0 0; }
  .paper-h2 { font-size: 12.5pt; font-weight: 600; line-height: 1.25; margin: 16pt 0 7pt;
              padding-top: 0; break-after: avoid; page-break-after: avoid; }
  blockquote { margin: 8pt 1.5em 10pt; font-size: 9.75pt; line-height: 1.45; }
  .paper-body ul, .paper-body ol { padding-left: 1.15em; margin: 4pt 0 6pt; }
  .paper-body li { font-size: 8.5pt; line-height: 1.38; margin: 0 0 2pt; }
  .paper-bib__h { font-size: 11.5pt; font-weight: 600; margin: 14pt 0 5pt; break-after: avoid; }
  blockquote, figure, .fig-pair { break-inside: avoid; page-break-inside: avoid; }

  /* figures: plates with air */
  .paper-fig { margin: 12pt auto 14pt; width: auto; max-width: 100%; }
  .paper-fig--wide { width: auto; max-width: 100%; }
  .paper-fig__art { display: flex; justify-content: center; align-items: flex-end; background: none; }
  .paper-fig__art img { width: auto; height: auto; max-width: 74%; max-height: 190pt; }
  .paper-fig--wide .paper-fig__art img { max-width: 92%; }
  .paper-fig--tall .paper-fig__art img,
  .paper-fig--tall .paper-fig__img { width: auto; max-width: 74%; max-height: 190pt; }
  .paper-cap { font-size: 8pt; color: #59564f; text-align: center; margin: 6pt auto 0;
               line-height: 1.35; max-width: 90%; }
  .paper-cap::before { counter-increment: fig; content: "Fig. " counter(fig) ".\2002";
                       font-weight: 600; letter-spacing: .02em; }

  /* paired plates — print-safe inline-blocks: fixed-height wells, images
     seated on the well floor, captions starting on one shared line */
  .fig-pair { text-align: center; margin: 12pt 0 14pt;
              break-inside: avoid; page-break-inside: avoid; }
  .fig-pair .paper-fig, .fig-pair .paper-fig--tall, .fig-pair .paper-fig--wide {
    display: inline-block; vertical-align: top; width: 46%; margin: 0 1.5%;
    max-width: 46%; text-align: center; }
  .fig-pair .paper-fig__art { display: block; position: relative; height: 140pt; }
  .fig-pair .paper-fig__art img,
  .fig-pair .paper-fig--tall .paper-fig__art img,
  .fig-pair .paper-fig--tall .paper-fig__img {
    position: absolute; bottom: 0; left: 50%; transform: translateX(-50%);
    width: auto; height: auto; max-width: 100%; max-height: 100%; }
  .fig-pair .paper-cap { margin-top: 6pt; }
}

/* ---- About: CV download (below the lede, above social links) ------------ */
.cv-download { margin-top: clamp(22px, 2.7vw, 31px); }
.cv-download a {
  font-family: var(--sans);
  font-size: 12.5px;
  letter-spacing: .22em;
  text-transform: uppercase;
  color: var(--ink);
  text-decoration: none;
  border-bottom: 1px solid transparent;
  padding-bottom: 3px;
  transition: border-color .2s ease;
}
.cv-download a:hover,
.cv-download a:focus-visible { border-bottom-color: var(--ink); }
