/* ============================================================================
   AVANTI — 49 m charter yacht, Ligurian Sea.               (desktop-first demo)

   DESIGN BRIEF v3 — read before editing.

   The brief changed: STRIP IT. v2 was an engine-order telegraph in machined
   brass — an instrument, a plate, a dial, an ornament. v3 threw away every
   object. What is left is photography, air, hairlines and data.

   v4 — THE COPY. The engine-order narrative (AVANTI TUTTA … FINITO, a day
   told as a passage) is gone with it. The footage is one beautiful run and
   one move aboard, not a plot, and copy that narrated a story the pictures
   never told read as vague. Every line now carries a FACT — metres, guests,
   suites, crew, the chef, the toys, the coast, the rate — and the yacht's
   name does the rest. Elegance here is precision, not narration.

   RULES
     1. ONE typeface. Manrope, variable. Display sits at weight 200 with
        negative tracking; labels at 500 uppercase with +0.2em. Nothing else.
     2. NO accent colour. The only colour on this page is the photography.
        Hierarchy is made with contrast, scale and emptiness — never with hue.
     3. NO boxes, no cards, no borders except 1px hairlines. Buttons are
        underlined words.
     4. The page is DARK where the camera is (film, gallery, close) and
        PAPER where the reading is. That switch is the only "effect" in the
        layout, and the header inverts with it.

   PALETTE
     --ink    #0b1013  the sea after sunset
     --bone   #f3f2ee  gelcoat, type on ink
     --paper  #f3f2ee  the same white, now a surface
     --type   #101619  type on paper
     hairlines: rgba(bone,.16) on ink · rgba(type,.16) on paper

   SIGNATURE — THE HANDOVER. The pinned film does not end; its last frame is
   handed to the gallery below, which cross-fades the identical still over the
   still-pinned canvas and then swipes it left, one room per screen. See .pan
   (and LEAD in main.js — the -175svh pull-up is half of that mechanism).

   SECOND SIGNATURE — THE READOUT. The instrument survives as a line of data
   in the header: knots and position under way, ship's time at anchor, the
   room count through the gallery, her particulars over the editorial.
   ========================================================================== */

@font-face {
  font-family: "Manrope";
  src: url("fonts/manrope-latin.woff2") format("woff2");
  font-weight: 200 800;
  font-display: swap;
  font-style: normal;
}

:root {
  --ink: #0b1013;
  --ink-2: #151b1f;
  --bone: #f3f2ee;
  --bone-2: #99a1a4;
  --paper: #f3f2ee;
  --type: #101619;
  --mute: #6d7578;
  --line-d: rgba(243, 242, 238, 0.16);
  --line-l: rgba(16, 22, 25, 0.15);
  --f: "Manrope", "Segoe UI", system-ui, sans-serif;
  --ease: cubic-bezier(0.22, 1, 0.36, 1);
  /* The compass needle, cropped to its own bounding box and split the way a
     real one is: north half solid, south half a hairline outline. Filled whole
     it read as a plain rhombus; split, it reads as a needle at 17px. Same
     coordinates as .compass__needle in the header — one shape, two sizes. */
  --needle: url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='8.5 8.5 9 9'><path d='M17.1 8.9 L14.3 14.3 L11.7 11.7 Z' fill='black'/><path d='M8.9 17.1 L11.7 11.7 L14.3 14.3 Z' fill='none' stroke='black' stroke-width='0.5' stroke-linejoin='round'/></svg>");
  --wrap: 1340px;
  --pad: 3.2rem;
}

/* ---------------------------------------------------------------- base ---- */
*, *::before, *::after { box-sizing: border-box; }
html { scroll-behavior: auto; overflow-x: clip; }
body {
  margin: 0;
  background: var(--ink);
  color: var(--bone);
  font-family: var(--f);
  font-weight: 300;
  font-size: 1rem;
  line-height: 1.66;
  letter-spacing: 0.004em;
  -webkit-font-smoothing: antialiased;
}
h1, h2, h3 { margin: 0; font-weight: 200; line-height: 1.06; letter-spacing: -0.026em; }
p, dl, ol, ul, figure { margin: 0; }
a { color: inherit; text-decoration: none; }
img { display: block; max-width: 100%; height: auto; }
i, b { font-style: normal; }
.wrap { max-width: var(--wrap); margin: 0 auto; padding: 0 var(--pad); }
::selection { background: var(--bone); color: var(--ink); }
.paper ::selection { background: var(--type); color: var(--paper); }
:focus-visible { outline: 1px solid currentColor; outline-offset: 4px; }

.sr-only {
  position: absolute;
  width: 1px; height: 1px;
  margin: -1px; padding: 0;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

/* the one repeated label form: the needle, then small tracked caps.
   The mark is the SAME path as the needle inside the header compass (see
   .compass__needle) — one shape, twice: once in its ring at the top of the
   screen, once small in front of every label. A hairline rule would have been
   generic; the needle makes the label form this ship's and no one else's. */
.eyebrow {
  display: flex;
  align-items: center;
  /* the needle needs MORE air than the hairline did, not less: a glyph next to
     tracked caps reads as a word otherwise. */
  gap: 1.15rem;
  font-size: 0.65rem;
  font-weight: 500;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  opacity: 0.62;
}
/* masked rather than inlined: the mark has to take currentColor so it inverts
   with the ink/paper switch exactly like the hairline it replaced. */
.eyebrow__mark {
  width: 1.05rem;
  height: 1.05rem;
  flex: none;
  background: currentColor;
  opacity: 0.9;
  -webkit-mask: var(--needle) center / contain no-repeat;
  mask: var(--needle) center / contain no-repeat;
}

/* ============================================================ INTRO ======= */
.intro {
  position: fixed;
  inset: 0;
  z-index: 1000;
  display: grid;
  place-items: center;
  background: var(--ink);
  animation: introFail 1s var(--ease) 2.8s forwards; /* self-healing without JS */
}
.intro__brand {
  font-size: clamp(2.4rem, 9vw, 6rem);
  font-weight: 200;
  letter-spacing: 0.42em;
  text-indent: 0.42em;
  color: var(--bone);
  will-change: transform;
}
.intro.is-done { opacity: 0; pointer-events: none; transition: opacity 0.9s var(--ease); animation: none; }
@keyframes introFail { to { opacity: 0; visibility: hidden; } }
html:not(.js) .intro { display: none; }
html.intro-on .hdr__readout,
html.intro-on .compass { animation: navReveal 0.8s var(--ease) 1.7s both; }
@keyframes navReveal {
  from { opacity: 0; transform: translateY(-5px); }
  to   { opacity: 1; transform: none; }
}

/* ============================================================ HEADER ======
   Brand + live readout lock up hard left; navigation sits hard right. The bar
   inverts to ink-on-paper over the editorial sections (.is-light) and carries
   the page's scroll progress on its bottom hairline. */
.hdr {
  position: fixed;
  inset: 0 0 auto 0;
  z-index: 950;                        /* above .menu (940): the bar stays put */
  display: flex;
  align-items: center;
  gap: 1.5rem;
  /* the bar's height is the compass' height — the padding only keeps it off
     the edges, so the rose can grow without the plate growing with it */
  padding: 0.72rem 2.2rem;
  color: var(--bone);
  transition: transform 0.5s var(--ease), background 0.5s var(--ease), color 0.5s var(--ease);
}
/* over footage the bar is NOT a bar: a scrim that dissolves downwards, no
   edge, no plate. Over paper it becomes a proper bar — wash and hairline. */
.hdr::before {
  content: "";
  position: absolute;
  inset: 0 0 -2.8rem 0;
  z-index: -1;
  pointer-events: none;
  background: linear-gradient(to bottom, rgba(6, 11, 14, 0.72) 0%, rgba(6, 11, 14, 0.32) 52%, rgba(6, 11, 14, 0) 100%);
  transition: opacity 0.5s var(--ease);
}
.hdr::after {
  content: "";
  position: absolute;
  inset: auto 0 0 0;
  height: 1px;
  background: currentColor;
  opacity: 0;
  transition: opacity 0.5s var(--ease);
}
.hdr:not(.is-light) { text-shadow: 0 1px 14px rgba(6, 11, 14, 0.5); }
.hdr.is-light { color: var(--type); }
.hdr.is-light::before { opacity: 0; }
.hdr.is-light.is-stuck { background: rgba(243, 242, 238, 0.86); backdrop-filter: blur(18px) saturate(1.05); }
.hdr.is-light.is-stuck::after { opacity: 0.16; }
.hdr.is-hidden { transform: translateY(-102%); }
.hdr__brand {
  font-size: 0.94rem;
  font-weight: 500;
  letter-spacing: 0.3em;
  text-indent: 0.3em;
  flex: none;
}
.hdr__readout {
  position: relative;
  padding-left: 1.5rem;
  font-size: 0.62rem;
  font-weight: 450;
  letter-spacing: 0.16em;
  white-space: nowrap;
  font-variant-numeric: tabular-nums;
  opacity: 0.6;
}
.hdr__readout::before {
  content: "";
  position: absolute;
  left: 0;
  top: 50%;
  width: 1px;
  height: 13px;
  margin-top: -6.5px;
  background: currentColor;
  opacity: 0.35;
}
/* ---- the compass: the only icon on the page, and the whole navigation ---- */
.compass {
  all: unset;
  margin-left: auto;
  flex: none;
  width: 5.1rem;
  height: 5.1rem;
  display: grid;
  place-items: center;
  color: inherit;
  cursor: pointer;
}
/* the rose is the page's only icon, so it is allowed to be the size of one.
   Stroke scales DOWN as the glyph grows (1 at 33px → 0.7 at 54px): the ring
   must stay the same hairline as the header rules, not thicken with it. */
.compass svg {
  width: 54px;
  height: 54px;
  overflow: visible;
  fill: none;
  stroke: currentColor;
  stroke-width: 0.7;
  stroke-linejoin: round;
  transition: transform 0.9s var(--ease);
}
.compass__ring { opacity: 0.5; }
.compass__north { opacity: 0.75; }
.compass__pin { fill: currentColor; stroke: none; }
.compass:hover svg { transform: rotate(24deg); }
.compass[aria-expanded="true"] svg { transform: rotate(135deg); }

.hdr__bar { position: absolute; inset: auto 0 0 0; height: 1px; overflow: hidden; }
.hdr__bar i {
  display: block;
  height: 100%;
  background: currentColor;
  opacity: 0.55;
  transform: scaleX(0);
  transform-origin: 0 50%;
}

/* ---- what the compass opens: no panel, no drawer — the page simply gives
   itself over to the list. The bar stays on top of it and goes light again. -- */
.menu {
  position: fixed;
  inset: 0;
  z-index: 940;
  display: grid;
  grid-template-rows: 1fr auto;
  padding: 21vh var(--pad) 3rem;
  color: var(--bone);
  /* Opaque, and NO backdrop-filter. Translucency was the wrong instinct: over
     the paper sections the spec figures ghosted straight through, and a
     full-viewport backdrop root would sit live behind the pinned film for the
     entire page. The menu is a takeover, not a scrim. */
  background: #080c0f;
  opacity: 0;
  visibility: hidden;
  transition: opacity 0.55s var(--ease), visibility 0.55s var(--ease);
}
.menu.is-open { opacity: 1; visibility: visible; }
.menu__list { align-self: start; width: 100%; max-width: var(--wrap); margin: 0 auto; }
.menu__link {
  position: relative;
  display: flex;
  align-items: baseline;
  gap: 2.2rem;
  padding: 1.3rem 0;
  border-top: 1px solid rgba(243, 242, 238, 0.13);
  font-size: clamp(1.7rem, 4.2vw, 3.3rem);
  font-weight: 200;
  letter-spacing: -0.03em;
  line-height: 1.1;
  opacity: 0;
  transform: translateY(16px);
}
.menu__link:last-child { border-bottom: 1px solid rgba(243, 242, 238, 0.13); }
.menu.is-open .menu__link {
  opacity: 1;
  transform: none;
  transition: opacity 0.7s var(--ease), transform 0.7s var(--ease);
}
.menu.is-open .menu__link:nth-child(1) { transition-delay: 0.06s; }
.menu.is-open .menu__link:nth-child(2) { transition-delay: 0.12s; }
.menu.is-open .menu__link:nth-child(3) { transition-delay: 0.18s; }
.menu.is-open .menu__link:nth-child(4) { transition-delay: 0.24s; }
.menu.is-open .menu__link:nth-child(5) { transition-delay: 0.30s; }
.menu__link i {
  flex: none;
  font-size: 0.62rem;
  font-weight: 500;
  letter-spacing: 0.2em;
  opacity: 0.4;
  font-variant-numeric: tabular-nums;
}
.menu__link span { transition: transform 0.5s var(--ease); }
.menu__link:hover span { transform: translateX(0.7rem); }
.menu__foot {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: 2rem;
  width: 100%;
  max-width: var(--wrap);
  margin: 0 auto;
  padding-top: 1.8rem;
  font-size: 0.63rem;
  font-weight: 500;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  opacity: 0;
  transition: opacity 0.6s var(--ease) 0.34s;
}
.menu.is-open .menu__foot { opacity: 1; }
.menu__meta { opacity: 0.42; }
.menu__lang { display: flex; align-items: center; gap: 0.45rem; }
.menu__lang i { opacity: 0.3; }
.menu__lang button {
  all: unset;
  cursor: pointer;
  font: inherit;
  letter-spacing: inherit;
  opacity: 0.42;
  transition: opacity 0.3s var(--ease);
}
.menu__lang button:hover { opacity: 0.8; }
.menu__lang button.is-active { opacity: 1; }

/* with the menu open the bar rides on top of it — always light, never plated */
html.menu-open .hdr { color: var(--bone); }
html.menu-open .hdr::before,
html.menu-open .hdr::after,
html.menu-open .hdr__bar { opacity: 0; }
/* both need to out-specify .hdr.is-light.is-stuck, which is (0,3,0) */
html.menu-open .hdr.is-light.is-stuck { background: transparent; backdrop-filter: none; }
html.menu-open .hdr.is-light.is-stuck::after { opacity: 0; }

/* ============================================================ FILM ======== */
.story { position: relative; height: var(--story-length, 900vh); }
.story__viewport {
  position: sticky;
  top: 0;
  height: 100svh;
  overflow: hidden;
  background: var(--ink);
}
.story__poster,
.story__canvas { position: absolute; inset: 0; width: 100%; height: 100%; }
.story__poster { object-fit: cover; transition: opacity 0.5s var(--ease); }
.story.is-ready .story__poster { opacity: 0; }
/* idle loop: rides above the canvas, below grade/grain; yields to the scrub */
.story__idle {
  position: absolute;
  inset: 0;
  z-index: 1;
  width: 100%;
  height: 100%;
  object-fit: cover;
  opacity: 0;
  transition: opacity 0.5s var(--ease);
  pointer-events: none;
}
.story.is-idle .story__idle.is-ready { opacity: 1; }
@media (prefers-reduced-motion: reduce) { .story__idle { display: none; } }

/* shared filmic finish — used by the film AND the gallery, so the handover
   between them carries no change of treatment whatsoever */
.grade {
  position: absolute;
  inset: 0;
  z-index: 2;
  pointer-events: none;
  background:
    linear-gradient(to bottom, rgba(6, 11, 14, 0.3) 0%, rgba(6, 11, 14, 0) 16%),
    /* an even bottom weighting now — nothing is written in a corner any more,
       so the old corner wash would only have biased the pictures */
    linear-gradient(to top, rgba(6, 11, 14, 0.5) 0%, rgba(6, 11, 14, 0.18) 26%, rgba(6, 11, 14, 0) 54%),
    radial-gradient(130% 105% at 50% 44%, rgba(6, 11, 14, 0) 55%, rgba(6, 11, 14, 0.32) 100%);
}
.grain {
  position: absolute;
  inset: -50%;
  z-index: 2;
  pointer-events: none;
  opacity: 0.07;
  mix-blend-mode: overlay;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='160' height='160'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='2' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");
  background-size: 180px 180px;
  will-change: transform;
  animation: grainshift 0.6s steps(2) infinite;
}
@keyframes grainshift {
  0%   { transform: translate(0, 0); }
  25%  { transform: translate(-6%, 3%); }
  50%  { transform: translate(4%, -5%); }
  75%  { transform: translate(-3%, -2%); }
  100% { transform: translate(5%, 4%); }
}

/* type set over footage: a wide, soft shadow only — never a plate */
.pan__cap { text-shadow: 0 1px 26px rgba(6, 11, 14, 0.7), 0 1px 4px rgba(6, 11, 14, 0.3); }

/* the film carries no running copy at all any more — only the three strikes */

/* ---- idle affordance ---- */
.hint {
  position: absolute;
  z-index: 3;
  left: 50%;
  bottom: 4.4vh;
  transform: translateX(-50%);
  white-space: nowrap;
  font-size: 0.61rem;
  font-weight: 500;
  letter-spacing: 0.34em;
  text-indent: 0.34em;
  text-transform: uppercase;
  opacity: 0;
  transition: opacity 1s var(--ease);
  pointer-events: none;
}
.story.is-idle .hint { opacity: 0.62; }

/* ---- THE STRIKES — the three cards over the film: a fact set large, with
   its particulars in a line underneath. Tracking closes and weight locks
   across the window (driven in main.js); a hairline ring opens behind it. ---- */
.strike {
  position: absolute;
  inset: 0;
  z-index: 4;
  display: grid;
  place-content: center;
  justify-items: center;
  pointer-events: none;
  text-align: center;
}
.js .strike { opacity: 0; visibility: hidden; }
.strike__word {
  position: relative;
  display: grid;
  justify-items: center;
  font-size: clamp(3.4rem, 8.4vw, 8rem);
  line-height: 1.02;
  color: var(--bone);
  text-shadow: 0 4px 40px rgba(6, 11, 14, 0.55);
  letter-spacing: var(--track, 0.5em);
  text-indent: var(--track, 0.5em);     /* recentre tracked caps */
  font-variation-settings: "wght" var(--wght, 200);
}
.strike__line { display: block; white-space: nowrap; }
/* a nine-character line needs its own step: at the strike's opening tracking
   (0.5em, before it locks) it would run off both edges at the size the
   six-letter cards are set in — on a phone by 120px. */
.strike--long .strike__word { font-size: clamp(1.9rem, 7.4vw, 7rem); }
/* the caption under the card carries the facts now, so it has to survive a
   sunlit hull behind it: same bone, its own shadow, a touch more size */
.strike__sub {
  position: relative;
  margin-top: 2rem;
  font-size: 0.72rem;
  font-weight: 500;
  letter-spacing: 0.34em;
  text-indent: 0.34em;
  text-transform: uppercase;
  color: var(--bone);
  text-shadow: 0 1px 20px rgba(6, 11, 14, 0.9), 0 0 6px rgba(6, 11, 14, 0.7);
  opacity: var(--subop, 0);
}
.strike__ring {
  position: absolute;
  left: 50%;
  top: 50%;
  width: 48vmin;
  height: 48vmin;
  margin: -24vmin 0 0 -24vmin;
  border: 1px solid rgba(243, 242, 238, 0.7);
  border-radius: 50%;
  opacity: 0;
  transform: scale(0.3);
}
.strike.is-struck .strike__ring { animation: ringout 1.4s var(--ease) forwards; }
@keyframes ringout {
  0%   { opacity: 0.7; transform: scale(0.3); }
  100% { opacity: 0;   transform: scale(1.25); }
}

/* ============================================================ THE GALLERY =
   The handover. `margin-top: -175svh` pulls this section up over the film so its
   sticky stage is already pinned while the film's canvas is still pinned
   underneath; main.js cross-fades this stage in across that overlap (LEAD).
   Panel 1 is the film's own last frame, so nothing appears to change — then
   the track swipes left, one room per screen. */
.pan {
  position: relative;
  height: var(--pan-length, 900vh);
  /* pulled up far enough that the WHOLE cross-fade happens while the film is
     still pinned — if this is only -100svh the film unpins halfway through and
     its viewport slides up out from under a half-transparent still. */
  margin-top: -175svh;
}
.pan__stage {
  position: sticky;
  top: 0;
  height: 100svh;
  overflow: hidden;
  background: var(--ink);
  opacity: 0;
  visibility: hidden;
}
html:not(.js) .pan { margin-top: 0; }
html:not(.js) .pan__stage { opacity: 1; visibility: visible; }
/* The frame. main.js drives its box from full-bleed (handover) down to the
   contained size, so the film contracts into a picture on a plain ground
   instead of cutting to one. Its inline left/top/width/height ARE the
   animation — a transform cannot do it, because the frame's aspect ratio
   changes and the stills must stay cover-fitted throughout. */
.pan__frame {
  position: absolute;
  left: 0;
  top: 0;
  width: 100%;
  height: 100%;
  overflow: hidden;
}
.pan__frame::after {                   /* the container edge, drawn as it arrives */
  content: "";
  position: absolute;
  inset: 0;
  border: 1px solid rgba(243, 242, 238, 0.16);
  opacity: var(--edge, 0);
  pointer-events: none;
}
.pan__track {
  display: flex;
  width: calc(var(--n) * 100%);
  height: 100%;
  will-change: transform;
}
.pan__panel {
  position: relative;
  flex: 0 0 calc(100% / var(--n));
  height: 100%;
  overflow: hidden;
}
.pan__media { position: absolute; inset: 0; overflow: hidden; }
.pan__media img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  will-change: transform;
  /* NO base scale: a centred panel must sit at scale 1 so panel 1 matches the
     film canvas pixel for pixel at the handover. main.js scales each still
     only as far as its own drift needs. */
}
/* once the picture is framed it no longer carries type, so the cinematic
   vignette steps back — main.js eases --grade-op from 1 to 0.24 */
.pan .grade { opacity: var(--grade-op, 1); }

/* ---- the plate: the caption sits UNDER the picture on the plain ground,
   never on top of it. main.js lifts the captions out of their panels. ---- */
.pan__plate {
  position: absolute;
  left: var(--fx, 0px);
  width: var(--fw, 100%);
  top: calc(var(--ft, 0px) + var(--fh, 100%) + var(--gap, 2rem));
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 2.5rem;
  opacity: 0;
  pointer-events: none;
}
.pan__caps { display: grid; flex: 1 1 auto; }
.pan__cap { grid-area: 1 / 1; max-width: 34rem; opacity: 0; }
.pan__cap .eyebrow { margin-bottom: 0.9rem; opacity: 0.55; }
.pan__cap h2 {
  font-size: clamp(1.35rem, 2.3vw, 2.1rem);
  font-weight: 200;
  letter-spacing: -0.028em;
  text-wrap: balance;
}
.pan__sub {
  margin-top: 0.7rem;
  max-width: 30rem;
  font-size: 0.92rem;
  font-weight: 300;
  opacity: 0.5;
}
.pan__hud {
  flex: none;
  display: flex;
  align-items: center;
  gap: 1.1rem;
  padding-top: 0.35rem;
  font-size: 0.64rem;
  font-weight: 500;
  letter-spacing: 0.2em;
  font-variant-numeric: tabular-nums;
}
.pan__tot { opacity: 0.4; }
.pan__rail { width: 6.5rem; height: 1px; background: rgba(243, 242, 238, 0.2); overflow: hidden; }
.pan__rail i { display: block; height: 100%; background: var(--bone); transform: scaleX(0); transform-origin: 0 50%; }

/* ============================================================ PAPER ======= */
.paper {
  position: relative;
  background: var(--paper);
  color: var(--type);
  padding: 9.5rem 0;
}
.paper--flush { padding-top: 0; }
.head { margin-bottom: 4.5rem; }
.head .eyebrow { margin-bottom: 1.6rem; }
.h-sec {
  font-size: clamp(1.9rem, 3.4vw, 3rem);
  font-weight: 200;
  letter-spacing: -0.03em;
}

/* ---- the claim ---- */
#claim .eyebrow { margin-bottom: 2.4rem; }
.statement {
  font-size: clamp(2rem, 4.4vw, 4rem);
  font-weight: 200;
  letter-spacing: -0.032em;
  line-height: 1.12;
  max-width: 26ch;
}
/* the line settles word by word once the block is in */
.js .statement .w { display: inline-block; opacity: 0; transform: translateY(0.28em); }
.js .statement.is-in .w {
  opacity: 1;
  transform: none;
  transition: opacity 0.8s var(--ease), transform 0.8s var(--ease);
  transition-delay: calc(0.1s + var(--wi, 0) * 0.055s);
}
.figures {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 2.4rem;
  margin-top: 6rem;
  border-top: 1px solid var(--line-l);
  padding-top: 2.1rem;
}
.figures__item { display: flex; flex-direction: column-reverse; align-items: start; }
.figures dd {
  margin: 0;
  font-size: clamp(1.7rem, 2.7vw, 2.5rem);
  font-weight: 200;
  letter-spacing: -0.02em;
  font-variant-numeric: tabular-nums;
}
.figures dt {
  margin-top: 0.85rem;
  font-size: 0.63rem;
  font-weight: 500;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--mute);
}

/* ---- the day ---- */
.day { list-style: none; margin: 0; padding: 0; border-top: 1px solid var(--line-l); }
.day__row {
  position: relative;
  display: grid;
  grid-template-columns: 6rem 14rem 1fr;
  gap: 3.2rem;
  align-items: start;
  padding: 2.7rem 0;
  border-bottom: 1px solid var(--line-l);
}
/* the hairline draws itself in under each row as it arrives */
.day__row::after {
  content: "";
  position: absolute;
  left: 0; right: 0; bottom: -1px;
  height: 1px;
  background: var(--type);
  opacity: 0.3;
  transform: scaleX(0);
  transform-origin: 0 50%;
}
.js .day__row.is-in::after { transform: scaleX(1); transition: transform 1.2s var(--ease) 0.15s; }
.day__time {
  font-size: 0.86rem;
  font-weight: 400;
  letter-spacing: 0.1em;
  font-variant-numeric: tabular-nums;
  color: var(--mute);
  padding-top: 0.28rem;
}
.day__name h3 {
  font-size: 0.92rem;
  font-weight: 500;
  letter-spacing: 0.14em;
  line-height: 1.4;
}
.day__name p {
  margin-top: 0.35rem;
  font-size: 0.63rem;
  font-weight: 500;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--mute);
}
.day__copy { max-width: 38rem; color: var(--mute); font-weight: 300; }

/* ---- the breath: one letterbox of open sea between the readings ---- */
.strip { position: relative; aspect-ratio: 21 / 6; overflow: hidden; background: var(--ink); }
.strip img {
  position: absolute;
  inset: -9% 0;
  width: 100%;
  height: 118%;
  object-fit: cover;
  object-position: 50% 56%;
  will-change: transform;
}

/* ---- specification ---- */
.spec { columns: 2; column-gap: 5.5rem; border-top: 1px solid var(--line-l); padding-top: 1.2rem; }
.spec__row {
  display: flex;
  align-items: baseline;
  gap: 1rem;
  padding: 0.72rem 0;
  border-bottom: 1px solid rgba(16, 22, 25, 0.08);
  break-inside: avoid;
}
.spec dt {
  flex: 0 0 auto;
  font-size: 0.63rem;
  font-weight: 500;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--mute);
}
.spec__row::after {                    /* hairline leader */
  content: "";
  order: 1;
  flex: 1;
  border-bottom: 1px solid rgba(16, 22, 25, 0.14);
  transform: translateY(-4px);
}
.spec dd {
  order: 2;
  margin: 0;
  font-size: 0.94rem;
  font-weight: 400;
  font-variant-numeric: tabular-nums;
}

/* ============================================================ CLOSE ======= */
.close { background: var(--ink); color: var(--bone); padding: 12rem 0 10rem; text-align: center; }
.close__mark {
  font-size: clamp(2.4rem, 12vw, 9rem);
  font-weight: 200;
  line-height: 1;
  letter-spacing: 0.4em;
  text-indent: 0.4em;
}
/* the earned motion of the whole page: the wordmark settles its tracking.
   (specificity deliberately above .js .reveal.is-in, which lands later in
   this file and would otherwise drop the letter-spacing from the transition) */
.js .close .close__mark.is-in {
  letter-spacing: 0.2em;
  text-indent: 0.2em;
  transition: letter-spacing 1.8s var(--ease) 0.1s, text-indent 1.8s var(--ease) 0.1s,
              opacity 1.2s var(--ease), transform 1.2s var(--ease);
}
.close__line {
  margin: 2.6rem auto 0;
  max-width: 30rem;
  font-size: 1.02rem;
  font-weight: 300;
  opacity: 0.7;
}
.close__cta {
  display: inline-block;
  position: relative;
  margin-top: 3.2rem;
  padding-bottom: 0.7rem;
  font-size: 0.72rem;
  font-weight: 500;
  letter-spacing: 0.24em;
  text-indent: 0.24em;
  text-transform: uppercase;
}
.close__cta::after {
  content: "";
  position: absolute;
  left: 0; right: 0; bottom: 0;
  height: 1px;
  background: currentColor;
  opacity: 0.4;
  transform-origin: 0 50%;
  transition: opacity 0.4s var(--ease), transform 0.5s var(--ease);
}
.close__cta:hover::after { opacity: 1; }
.close__rate {
  margin-top: 2.4rem;
  font-size: 0.63rem;
  font-weight: 500;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  opacity: 0.45;
}

/* ============================================================ FOOTER ====== */
.foot { background: var(--ink); border-top: 1px solid var(--line-d); padding: 2.2rem 0 2.6rem; }
.foot__grid {
  display: flex;
  justify-content: space-between;
  gap: 2rem;
  font-size: 0.68rem;
  font-weight: 400;
  letter-spacing: 0.09em;
  color: var(--bone-2);
}

/* ============================================================ REVEAL ====== */
.js .reveal { opacity: 0; transform: translateY(20px); }
.js .reveal.is-in {
  opacity: 1;
  transform: none;
  transition: opacity 0.95s var(--ease), transform 0.95s var(--ease);
}
.js .reveal[data-delay="1"].is-in { transition-delay: 0.1s; }
.js .reveal[data-delay="2"].is-in { transition-delay: 0.2s; }
.js .reveal[data-delay="3"].is-in { transition-delay: 0.3s; }

/* ============================================================ CURSOR ====== */
/* BRANDED CURSOR — one pair for the whole page: bone fill, ink hairline, so it
   reads on open footage and on paper alike. */
@media (hover: hover) and (pointer: fine) {
  html { cursor: url("img/cursor-arrow.svg") 3 2, auto; }
  a, button, label, summary, select,
  [role="button"], [data-cursor] { cursor: url("img/cursor-dot.svg") 9 9, pointer; }
  input, textarea { cursor: text; }
}

/* ============================================================ RESPONSIVE == */
@media (max-width: 1080px) {
  :root { --pad: 2rem; }
  .hdr { padding: 0.7rem 1.3rem; gap: 1.1rem; }
  .day__row { grid-template-columns: 5rem 11rem 1fr; gap: 2rem; }
}
@media (max-width: 780px) {
  body { font-size: 0.96rem; }
  .hdr__readout { display: none; }
  .compass { width: 3.8rem; height: 3.8rem; }
  .compass svg { width: 40px; height: 40px; stroke-width: 0.85; }
  .menu { padding: 17vh var(--pad) 2.4rem; }
  .menu__foot { flex-direction: column; align-items: flex-start; gap: 0.8rem; }
  .paper { padding: 6.5rem 0; }
  .paper--flush { padding-top: 0; }
  .pan { --pan-length: 620vh; }
  .pan__plate { flex-direction: column; gap: 1.1rem; }
  .pan__cap { max-width: none; }
  .pan__rail { width: 4.5rem; }
  .figures { grid-template-columns: 1fr; gap: 1.8rem; }
  .figures__item { flex-direction: row; align-items: baseline; gap: 1rem; justify-content: space-between; }
  .figures dt { margin-top: 0; }
  .day__row { grid-template-columns: 1fr; gap: 0.9rem; padding: 2rem 0; }
  .day__time { padding-top: 0; }
  .spec { columns: 1; }
  .strip { aspect-ratio: 16 / 9; }
  .close { padding: 7.5rem 0 6.5rem; }
  .foot__grid { flex-direction: column; gap: 0.6rem; }
}

/* ============================================================ MOTION OFF == */
@media (prefers-reduced-motion: reduce) {
  .intro { display: none; }
  html.intro-on .hdr__readout, html.intro-on .compass { animation: none; }
  .grain { animation: none; }
  .hint { display: none; }
  .compass svg { transition: none; }
  .menu__link, .menu__foot { opacity: 1; transform: none; transition: none; }
  .menu { transition: none; }
  /* the film unpins into one still plus the copy as a plain column — without
     this the overlays keep their absolute corner and pile onto each other */
  .story { height: auto; }
  .story__viewport { position: static; height: auto; overflow: visible; padding-bottom: 5rem; }
  .story__poster { display: none; }
  .story__canvas { position: relative; display: block; width: 100%; height: 64svh; }
  .story .grade, .story .grain { display: none; }
  .js .strike {
    opacity: 1; visibility: visible; position: relative;
    inset: auto; left: auto; bottom: auto; max-width: none;
    padding: 3rem 7vw 0; transform: none; text-shadow: none;
  }
  /* justify-items must be reset too: Chrome now honours block-level alignment,
     so the base `justify-items: center` would keep centring the word box */
  .strike { --track: 0.2em; --wght: 300; --subop: 1; display: block; text-align: left; justify-items: start; }
  .strike__word { font-size: clamp(2.2rem, 6vw, 4rem); justify-items: start; text-shadow: none; }
  .strike__sub { margin-top: 1rem; }
  .strike__ring { display: none; }
  /* the gallery unrolls into a plain stack: each still with its own caption
     underneath (main.js leaves the captions inside their panels here) */
  .pan { height: auto; margin-top: 0; }
  .pan__stage { position: static; height: auto; overflow: visible; opacity: 1; visibility: visible; }
  .pan__frame { position: static; width: auto; height: auto; overflow: visible; }
  .pan__frame::after { display: none; }
  .pan__track { display: block; width: 100%; transform: none !important; }
  .pan__panel { height: auto; }
  .pan__media { position: relative; inset: auto; height: 58svh; }
  .pan__media img { transform: none !important; }
  .pan__cap { display: block; opacity: 1 !important; transform: none !important; padding: 1.4rem 7vw 3.5rem; max-width: none; }
  .pan__plate, .pan .grain, .pan .grade { display: none; }
  .js .reveal { opacity: 1; transform: none; }
  .js .statement .w { opacity: 1; transform: none; transition: none; }
  .js .day__row.is-in::after { transform: scaleX(1); transition: none; }
  .js .close .close__mark.is-in { transition: none; letter-spacing: 0.2em; text-indent: 0.2em; }
  .strip img { transform: none !important; }
}
