/* The instrument's columns: the front row at scale. 8 note columns on a 20 mm pitch, a 10 mm gap,
   then 4 pad columns on a 30 mm pitch, 290 mm in all. Headlines sit in the note columns, body copy
   in the pad columns, 16 px inside a column line. */
:root{
  --cols: repeat(8, minmax(0, 20fr)) minmax(0, 10fr) repeat(4, minmax(0, 30fr));
  --col-inset: 16px;
}
.cols{ position: relative; }
.cols::before{
  content: ""; position: absolute; top: 0; bottom: 0; left: var(--safe-l); right: var(--safe-r);
  pointer-events: none;
  background-image:
    linear-gradient(var(--hair), var(--hair)), linear-gradient(var(--hair), var(--hair)),
    linear-gradient(var(--hair), var(--hair)), linear-gradient(var(--hair), var(--hair)),
    linear-gradient(var(--hair), var(--hair)), linear-gradient(var(--hair), var(--hair)),
    linear-gradient(var(--hair), var(--hair)), linear-gradient(var(--hair), var(--hair)),
    linear-gradient(var(--hair), var(--hair)), linear-gradient(var(--hair), var(--hair)),
    linear-gradient(var(--hair), var(--hair)), linear-gradient(var(--hair), var(--hair)),
    linear-gradient(var(--hair), var(--hair)), linear-gradient(var(--hair), var(--hair));
  background-size: 1px 100%;
  background-repeat: no-repeat;
  background-position:
    calc(0 / 290 * 100%) 0, calc(20 / 290 * 100%) 0, calc(40 / 290 * 100%) 0, calc(60 / 290 * 100%) 0,
    calc(80 / 290 * 100%) 0, calc(100 / 290 * 100%) 0, calc(120 / 290 * 100%) 0, calc(140 / 290 * 100%) 0,
    calc(160 / 290 * 100%) 0, calc(170 / 290 * 100%) 0, calc(200 / 290 * 100%) 0, calc(230 / 290 * 100%) 0,
    calc(260 / 290 * 100%) 0, calc(290 / 290 * 100%) 0;
}
.cols-grid{ position: relative; display: grid; grid-template-columns: var(--cols); align-items: end; }
.in-notes{ grid-column: 1 / 9; padding-inline: var(--col-inset); }
.in-pads{ grid-column: 10 / 14; padding-inline: var(--col-inset); }
.across{ grid-column: 1 / -1; }
.cols-grid > .across{ margin-top: clamp(48px, 6vw, 80px); }

/* Films: full bleed, nothing on them but the Replay control once they stop */
.film-sec{ position: relative; height: 100vh; height: 100svh; overflow: hidden; background: var(--ground); }
.film, .film-sec .frame{ position: absolute; inset: 0; }
.film-sec .frame{ overflow: hidden; }

/* Chapter films are stops. The page comes to rest with each one full screen (js/film-player.js catches a swipe on
   it and glides a scroll that stops near it), the film plays through, and nothing moves until the visitor scrolls
   again; then the words slide up over its last frame for one screen, and both move on together. */
@media (prefers-reduced-motion: no-preference){
  .film-sec.chapter{ overflow: visible; height: 200vh; height: 200svh; }
  .film-sec.chapter > .frame{ position: sticky; inset: auto; top: 0; height: 100vh; height: 100svh; }
  .film-sec.chapter + .words{ position: relative; z-index: 1; margin-top: -100vh; margin-top: -100svh; }
  /* the frame stays pinned to the end of its track, which reaches past a words section shorter than a screen:
     everything after a film is drawn over it, so none of it shows below those words */
  .film-sec.chapter ~ .words, .foot{ position: relative; z-index: 1; background: var(--ground); }
}
.film:focus-visible{ outline-offset: -6px; }
.film video, .film img{
  position: absolute; inset: 0; width: 100%; height: 100%; display: block;
  object-fit: cover; object-position: var(--pos, 50% 50%);
}
/* Replay is the icon alone, 24 px. The 44 px button reaches 10 px past it on every side, so the icon itself sits on
   the margins and the target stays thumb-sized. */
.replay{
  position: absolute; right: calc(var(--safe-r) - 10px); bottom: calc(var(--gut) - 10px + env(safe-area-inset-bottom, 0px));
  display: grid; place-items: center;
  width: 44px; height: 44px; padding: 0;
  background: transparent; border: 0; cursor: pointer;
}
.replay[hidden]{ display: none; }
.replay:focus-visible{ outline-color: currentColor; outline-offset: -4px; } /* the focus ring takes the icon's ink */
/* Legends on a film are set in --ink: the films' grey ground is too dark for --ink-2 (1.7:1) */
.film-sec .legend{ color: var(--ink); }
.replay svg{ width: 24px; height: 24px; transition: transform 200ms var(--ease-return); }
/* Replay sits on each film's last frame, and some end on a dark corner, where --ink falls to 1.3-2.4:1. There it takes
   --ink-light, by film and by the film's shape (measured on the last frames at five screen sizes, 8 Nov 2026: every pick is 3.7:1 or more, past the 3:1 a control needs).
   The 4:3 films end light in that corner, like their 16:9 versions of top and rear34. */
.film-sec:is([data-film="knobs"], [data-film="pads"], [data-film="rear"], [data-film="macro"])[data-orient="landscape"] .replay,
.film-sec:is([data-film="pads"], [data-film="top"], [data-film="rear"], [data-film="rear34"])[data-orient="portrait"] .replay{ color: var(--ink-light); }

/* The opening. The hero film holds the wordmark above the instrument; js/hero-layout.js fits it to the
   visible film (the fallbacks are the 16:9 values). Past 2:1 the section grows so the film keeps its framing. */
.hero.film-sec{ height: max(100vh, 50vw); height: max(100svh, 50vw); background: var(--landscape-band); }
.hero .film video, .hero .film img{ object-position: var(--hero-pos, var(--pos, 50% 50%)); }
.wordmark{
  position: absolute; left: max(var(--wm-left, 3.3vw), env(safe-area-inset-left, 0px)); top: var(--wm-top, 2.6vw);
  margin: 0 0 0 -0.04em;
  font-weight: 600; font-stretch: 125%; letter-spacing: -0.05em; line-height: 0.8;
  font-size: var(--wm-size, 11.6vw); color: var(--ink-light);
  white-space: nowrap;
}
.hero .dev{ position: absolute; right: max(var(--wm-left, 3.3vw), env(safe-area-inset-right, 0px)); top: var(--legend-top, 2.6vw); }

/* Phones (the portrait film): the wordmark in light ink above the instrument, and IN DEVELOPMENT at the
   film's foot. The claim follows on the next screen, as on desktop. The frame holds from the first paint,
   before any script: it follows the screen's orientation, and the film player marks the hero
   data-orient="landscape" only when it falls back to the landscape film. The hero's ground is the portrait
   film's top band, so the light type reads before the poster arrives. */
@media (orientation: portrait){
  .hero:not([data-orient="landscape"]){ background: var(--portrait-band); }
  .hero:not([data-orient="landscape"]) .wordmark{
    color: var(--ink-light);
    font-size: var(--wm-size, 16.4vw); top: var(--wm-top, 9svh);
    left: max(var(--wm-left, 6vw), env(safe-area-inset-left, 0px));
  }
  .hero:not([data-orient="landscape"]) .dev{
    top: auto; right: auto;
    left: max(var(--wm-left, 6vw), env(safe-area-inset-left, 0px));
    bottom: calc(var(--foot-bottom, 6svh) + env(safe-area-inset-bottom, 0px));
    font-size: var(--legend-size, 3.1vw); color: var(--ink-light);
  }
  .hero:not([data-orient="landscape"]) .replay{ color: var(--ink-light); }
}

/* The claim screen: one viewport on the columns, the claim in the note columns, the lede in the pad
   columns, and the dot row playing the films' loop above the column names */
.claim-sec .cols-grid{
  min-height: 100vh; min-height: 100svh;
  grid-template-rows: auto 1fr auto auto;
  align-items: start;
  padding-block: clamp(72px, 11vh, 132px) clamp(36px, 5vh, 60px);
}
/* Sized to the grid, not the screen: the agreed mockup sets the claim at 7.93% of the grid's width, which
   keeps it to two lines in the note columns (7.4vw of a full-width frame, where the grid filled the frame). */
.claim{
  font-size: clamp(56px, calc((min(100vw, var(--wrap)) - 2 * var(--gut)) * 0.0793), 128px); font-weight: 600;
  letter-spacing: -0.032em; line-height: 0.98; text-wrap: balance;
}
.claim-sec .lede{ font-size: clamp(18px, 1.46vw, 21px); line-height: 1.45; color: var(--ink-2); padding-top: 0.3em; }
.claim-sec .cols-grid > .across{ margin-top: 0; }
.claim-sec .dots{ grid-row: 3; display: block; width: 100%; height: clamp(48px, 8vh, 96px); }
.dot-legends{ grid-row: 4; display: grid; grid-template-columns: var(--cols); padding-top: 14px; }
.dot-legends span{ padding-inline: var(--col-inset); }
.dot-legends span:nth-child(9){ grid-column: 10; }

/* Parallax on the hero: it moves at 70% of the scroll speed inside its frame while the claim screen scrolls at
   full speed and slides over it. Everything on it (wordmark, legend, Replay) rides with it, so type never drifts
   onto the instrument. Scroll-driven, so it runs on the compositor with no script; the layer's offset is
   -0.3 x the section's distance from the top of the screen, which never opens a gap at its edges. The chapter
   films are stops instead. Off under reduced motion, and absent where scroll-driven animations aren't supported. */
.film-sec{ --plx-k: 0.3; --plx-h: 100svh; }
.hero.film-sec{ --plx-h: max(100svh, 50vw); }
@keyframes film-parallax{
  from{ transform: translate3d(0, calc(var(--plx-k) * -100vh), 0); }
  to{ transform: translate3d(0, calc(var(--plx-k) * var(--plx-h)), 0); }
}
@media (prefers-reduced-motion: no-preference){
  @supports (animation-timeline: view()){
    .film-sec:not(.chapter){ view-timeline: --film block; }
    .film-sec:not(.chapter) > *{ animation: film-parallax linear both; animation-timeline: --film; }
  }
}

/* Words: the draft's sections, on the columns. Opaque, so they can slide over a pinned film. The headline and
   the body share one top line, measured to their capitals: Archivo's capitals start 0.125em into a 0.98
   headline line and 6.65 px into an 18 px / 1.55 body line. A track label sits above the headline. */
.words{ background: var(--ground); --part-block: 54px; /* the label's 26 px chip and its 28 px gap */ }
.words .cols-grid{ align-items: start; }
.words .head + .copy{ padding-top: calc(var(--h2) * 0.125 - 6.65px); }
.words .head:has(.part) + .copy{ padding-top: calc(var(--part-block) + var(--h2) * 0.125 - 6.65px); }
.words > .cols{ padding-block: clamp(110px, 16vh, 200px); }
.copy p.aside{ margin-top: 40px; padding-top: 20px; border-top: 1px solid var(--rule); font-size: 16px; }

/* Talk: a held drone drawn as thirteen pen lines. What you ask to keep stays pinned. */
.field{
  background: var(--surface);
  border-radius: 28px;
  padding: clamp(20px, 3vw, 40px);
  color: var(--ink);
}
.said{
  display:flex; gap: 14px; align-items:flex-start;
  font-size: clamp(22px, 2.5vw, 34px); font-weight: 500;
  letter-spacing: -0.018em; line-height: 1.18;
  min-height: 2.4em;
}
.said svg{ flex: none; width: 0.9em; height: 0.9em; margin-top: 0.14em; }
.said q{ transition: opacity 250ms var(--ease-return); }
.said.orig q{ opacity: 0.45; }
.stage{ position:relative; height: clamp(220px, 27vw, 380px); margin-top: clamp(16px, 2vw, 28px); }
.stage canvas{ position:absolute; inset:0; width:100%; height:100%; display:block; }
.pin{
  position:absolute; display:flex; align-items:center; gap: 6px;
  font-size: 14px; line-height: 1; color: var(--ink-2); white-space: nowrap;
}
.pin svg{ width: 11px; height: 13px; }
.pin.attack{ padding-bottom: 10px; border-bottom: 1px solid var(--ink-2); }
.pin.pitch{ right: 0; padding: 4px 0 4px 10px; background: var(--surface); }
.controls{ display:flex; flex-wrap:wrap; justify-content:space-between; align-items:center; gap: 16px 24px; margin-top: clamp(16px, 2vw, 28px); }
.chips{ display:flex; flex-wrap:wrap; gap: 8px; align-items:center; }
.chips .lab{ font-size: 14px; color: var(--ink-2); margin-right: 6px; }
.chip{
  font: 500 15px/1 var(--sans);
  min-height: 44px; padding: 0 18px;
  border-radius: 999px; border: 1px solid var(--ink-2);
  background: transparent; color: var(--ink); cursor: pointer;
  transition: background-color 200ms var(--ease-return), color 200ms var(--ease-return);
}
.chip[aria-pressed="true"]{ background: var(--ink); color: var(--ground); border-color: var(--ink); }
.ab{
  display:grid; grid-template-columns: 1fr 1fr; gap: 4px;
  padding: 4px; min-width: 260px;
  border-radius: 999px; background: var(--ground);
}
.ab button{
  font: 500 15px/1 var(--sans);
  min-height: 44px; border:0; border-radius: 999px;
  background: transparent; color: var(--ink-2); cursor: pointer;
  transition: background-color 200ms var(--ease-return), color 200ms var(--ease-return);
}
.ab button[aria-pressed="true"]{ background: var(--ink); color: var(--ground); }
.field + figcaption{ margin-top: 16px; font-size: 14px; color: var(--ink-2); max-width: 40em; }
figure{ margin: 0; }

/* Pad layouts on the instrument's columns. The two-row layouts stack in the note columns, one pad to a 20 mm
   column; feed/back's four rows sit on the four pad columns, one pad to a 30 mm column, as on the instrument.
   The layout is a 29-cell grid of 10 mm (the module every column line falls on), so no line crosses a pad. A pad
   fills 85% of its cell's width, with the draft's proportions (25.5 x 32.9 on a 30 x 37.4 pitch). */
.layouts{ display: grid; grid-template-columns: repeat(29, minmax(0, 1fr)); grid-template-rows: 1fr auto auto; row-gap: clamp(36px, 4vw, 56px); }
.layouts figure{ margin: 0; }
/* the two-row layouts stack at the foot of feed/back's 4x4; the space above them takes up the difference */
.layouts .l8{ grid-column: 1 / span 8; grid-row: 2; align-self: end; }
.layouts .l16{ grid-column: 1 / span 16; grid-row: 3; align-self: end; }
.layouts .ours{ grid-column: 18 / span 12; grid-row: 1 / span 3; align-self: end; }
.pads{ display: grid; grid-template-columns: repeat(var(--c), minmax(0, 1fr)); }
.pads i{ position: relative; aspect-ratio: 30 / 37.4; }
.pads i::before{ content: ""; position: absolute; inset: 12% 7.5% 0; border-radius: 9% / 7%; } /* the row gap sits above each pad, so every layout's last row ends on the figure's foot */
.pads.other i::before{ border: 1.5px solid var(--ink-2); }
.pads.ours i::before{ background: var(--ink); }
.layouts figcaption{ margin-top: 16px; font-size: 15px; color: var(--ink-2); }
/* each caption starts where its pads do: 7.5% into a cell, as a share of the figure's width */
.layouts .l8 figcaption, .layouts .ours figcaption{ padding-left: 1.875%; }
.layouts .l16 figcaption{ padding-left: 0.9375%; }
.layouts figure.ours figcaption{ color: var(--ink); }
.layouts figcaption b{ display:block; font-weight: 600; }

/* Two hands: the callouts span the note columns and the pad columns */
.co-row{ display: grid; grid-template-columns: var(--cols); }
.co{
  position: relative;
  border-top: 1px solid var(--ink);
  padding-top: 14px;
  display:flex; align-items:center; gap: 10px;
  font-size: 15px; color: var(--ink);
}
.co::before, .co::after{ content:""; position:absolute; top:-7px; width:1px; height:7px; background: var(--ink); }
.co::before{ left:0; } .co::after{ right:0; }
.co.keys{ grid-column: 1 / 9; }
.co.pads{ grid-column: 10 / 14; }
.co .hand{ color: var(--ink-2); }

/* Finishes: the two studies, as stills */
.finishes{ display:grid; grid-template-columns: 1fr 1fr; gap: clamp(16px, 2vw, 28px); }
.finishes picture{ display:block; }
.finishes img{ display:block; width:100%; height:auto; aspect-ratio: 2400 / 1500; } /* renders, square-cornered like the films */
.finishes .name{ margin-top: 22px; font-size: 16px; color: var(--ink-2); }

/* Current design */
.spec-head{ grid-column: 1 / 5; padding-inline: var(--col-inset); align-self: start; }
.spec-head p{ margin-top: 10px; font-size: 15px; color: var(--ink-2); max-width: 22em; }
.spec-list{ grid-column: 6 / 14; margin:0; padding-inline: var(--col-inset); align-self: start; }
.spec-list .row{ display:grid; grid-template-columns: minmax(110px, 1fr) 2.2fr; gap: 16px; padding: 15px 0; border-top: 1px solid var(--rule); font-size: 16px; }
.spec-list .row:last-child{ border-bottom: 1px solid var(--rule); }
.spec-list dt{ color: var(--ink-2); }
.spec-list dd{ margin:0; }

/* Where it stands */
.status-list{ align-self: start; margin-top: clamp(48px, 6vw, 80px); }
.status-list ul, .status-list ol{ margin: 16px 0 0; padding:0; list-style:none; }
.status-list li{ padding: 14px 0; border-top: 1px solid var(--rule); font-size: 16px; color: var(--ink-2); display:flex; gap: 14px; }
.status-list ol{ counter-reset: step; }
.status-list ol li::before{ counter-increment: step; content: counter(step); font-family: var(--lcd); font-weight:600; color: var(--ink); min-width: 1ch; }

/* Closing frame */
.foot{ padding-block: clamp(140px, 20vh, 240px) calc(clamp(48px, 8vh, 96px) + env(safe-area-inset-bottom, 0px)); }
.foot .sign{ display:flex; flex-wrap:wrap; justify-content:space-between; align-items:baseline; gap: 16px 40px; }
.foot .mark{ font-weight: 600; font-stretch: 125%; font-size: clamp(36px, 5vw, 64px); letter-spacing: -0.045em; line-height: 1; }
.foot .sign p:not(.mark){ font-size: 15px; color: var(--ink-2); }

/* Hover: a little more contrast on anything you can press */
@media (hover: hover){
  .chip:hover{ border-color: var(--ink); }
  .ab button:hover{ color: var(--ink); }
  .replay:hover svg{ transform: rotate(-45deg); } /* turns back, the way the arrow points */
}

/* Narrow screens: the words stack across all columns; the lines stay */
@media (max-width: 900px){
  .in-notes, .in-pads, .spec-head, .spec-list{ grid-column: 1 / -1; }
  /* the claim spans the whole grid here, so it grows to keep the desktop's two lines: large claim, small lede */
  .claim-sec .claim{ font-size: calc((100vw - var(--safe-l) - var(--safe-r) - 2 * var(--col-inset)) / 7.2); }
  .cols-grid > .in-pads:not(.status-list){ margin-top: 28px; }
  .words .head + .copy, .words .head:has(.part) + .copy{ padding-top: 0; } /* stacked: no shared top line */
  .spec-list{ margin-top: 28px; }
  .status-list + .status-list{ margin-top: 40px; }
}
@media (max-width: 700px){
  .co{ font-size: 13px; flex-wrap: wrap; gap: 6px; }
  .dot-legends span{ padding-inline: 0; text-align: center; white-space: nowrap; font-size: 11px; letter-spacing: 0.04em; }
  .ab{ min-width: 0; width: 100%; }
  .layouts figcaption{ font-size: 13px; }
}
@media (max-width: 560px){
  body{ font-size: 17px; }
  .finishes{ grid-template-columns: 1fr; }
  .spec-list .row{ grid-template-columns: 1fr; gap: 4px; }
}
