/* ============================================================================
   ARM B — Acqua Vida home page. CLEAN ROOM.
   Nothing here derives from the incumbent system: no tokens.css, no site.css,
   no band grammar. Written from zero on 2026-09-07.

   THE ONE MOVE: the page is one continuous night-to-night document with a
   single unbroken vertical rail running through it. Bands do not own their
   ground; the ground is one gradient across the whole document and the rail
   crosses band boundaries. That is only possible if sections are transparent.
   ========================================================================= */

/* ---------- 1. Fonts. Self-hosted, OFL, vendored at build time. ---------- */
@font-face {
  font-family: "Fraunces";
  src: url("./fonts/fraunces-latin.woff2") format("woff2-variations");
  font-weight: 100 900;
  font-stretch: normal;
  font-display: swap;
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA,
    U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212,
    U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: "Figtree";
  src: url("./fonts/figtree-latin.woff2") format("woff2-variations");
  font-weight: 300 900;
  font-display: swap;
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA,
    U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212,
    U+2215, U+FEFF, U+FFFD;
}

/* ---------- 2. The system ---------- */
:root {
  color-scheme: dark;

  /* Ground. Seven stops of one gradient. All measured: the lightest stop
     (#0d2632) still gives 13.8:1 against --paper. */
  --g0: #01101f;
  --g1: #02142c; /* the client's own navy, sampled from their renders */
  --g2: #06203a;
  --g3: #0d2632;
  --g4: #081f33;
  --g5: #04162a;
  --g6: #010b16;

  /* Ink */
  --paper:   #ecf3f7;
  --paper-2: #a9c0d0;
  --paper-3: #7f95a6;

  /* The one brand hue, sampled from their logo. 8.2:1 on the lightest ground,
     so here it can carry text. On white it is 1.91:1 and could not. */
  --cyan:   #3cd0cf; /* the VECTOR master (32.ai) says rgb(60,208,207). The
                        old #3ccfce came from sampling their logo PNG, a lossy
                        derivative. 8.1:1 on --paper, so it carries text here. */
  --cyan-2: #6ccdce;
  --cyan-d: #0b3f47;

  /* The day's colours are the machine's own panel icons: red mug, green tea
     mug, orange baby bottle, iced glass. Used as marks only, never as text. */
  --hr-0300: #f5a25d; /* warm / baby bottle */
  --hr-0645: #f2705b; /* hot */
  --hr-1000: #86c98e; /* tea */
  --hr-1530: #ff6b6b; /* the red lock */
  --hr-1900: #3ccfce; /* cold */
  --hr-2330: #93a9bc; /* night light */

  --line:  rgba(236, 243, 247, 0.14);
  --line-2:rgba(236, 243, 247, 0.07);
  --plate: rgba(1, 14, 27, 0.93);

  /* Type. Fluid 390 -> 1440. Ratio ~1.32 at desktop, ~1.25 at 390. */
  --f-xs:   clamp(0.8125rem, 0.789rem + 0.095vw, 0.875rem);   /* 13 -> 14 */
  --f-s:    clamp(0.9375rem, 0.914rem + 0.095vw, 1rem);       /* 15 -> 16 */
  --f-b:    clamp(1.094rem,  1.059rem + 0.143vw, 1.1875rem);  /* 17.5 -> 19 */
  --f-lead: clamp(1.25rem,   1.157rem + 0.381vw, 1.5rem);     /* 20 -> 24 */
  --f-h3:   clamp(1.375rem,  1.166rem + 0.857vw, 1.9375rem);  /* 22 -> 31 */
  --f-h2:   clamp(1.875rem,  1.411rem + 1.905vw, 3.125rem);   /* 30 -> 50 */
  --f-h1:   clamp(2.375rem,  1.4rem   + 4vw,     5rem);       /* 38 -> 80 */
  --f-mega: clamp(7.5rem,    4.25rem  + 13.333vw, 16.25rem);  /* 120 -> 260 */

  /* Space. 4px base, x1.5 at the top. */
  --s1: 4px;  --s2: 8px;  --s3: 12px; --s4: 16px; --s5: 24px;
  --s6: 32px; --s7: 48px; --s8: 64px; --s9: 96px; --s10: 128px; --s11: 176px;

  --pad: clamp(20px, 4vw, 56px);
  --band: clamp(72px, 9vw, 152px);
  --rail: 132px;      /* the time gutter: label, then the line */
  --rail-x: 132px;    /* the line sits on the gutter boundary */
  --measure: 62ch;
  --radius: 14px;
}

*, *::before, *::after { box-sizing: border-box; }

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

body {
  margin: 0;
  font-family: Figtree, ui-sans-serif, system-ui, -apple-system, "Segoe UI",
    Roboto, sans-serif;
  font-size: var(--f-b);
  line-height: 1.62;
  font-weight: 380;
  color: var(--paper);
  background-color: var(--g0);
  /* THE continuous ground. One gradient, whole document, no per-band colour. */
  background-image: linear-gradient(
    180deg,
    var(--g0)  0%,
    var(--g1)  9%,
    var(--g2) 26%,
    var(--g3) 44%,
    var(--g4) 63%,
    var(--g5) 82%,
    var(--g6) 100%
  );
  background-repeat: no-repeat;
  overflow-x: hidden;
  text-rendering: optimizeLegibility;
  -webkit-font-smoothing: antialiased;
}

img, video, svg { max-width: 100%; display: block; }
a { color: inherit; }

:where(a, button, summary, [tabindex]):focus-visible {
  outline: 2px solid var(--cyan);
  outline-offset: 3px;
  border-radius: 4px;
}

/* clip-based, not left:-9999px — an off-canvas element inflates
   scrollWidth and produces a phantom horizontal-overflow reading */
.skip {
  position: absolute; left: 0; top: 0; z-index: 99;
  background: var(--cyan); color: #04222a; padding: 10px 18px;
  font-weight: 600; border-radius: 0 0 8px 0;
  clip-path: inset(50%); white-space: nowrap;
}
.skip:focus { clip-path: none; }

.wrap {
  width: min(100% - (var(--pad) * 2), 1240px);
  margin-inline: auto;
}
.band { padding-block: var(--band); position: relative; }

/* ---------- 3. Type primitives ---------- */
.eyebrow {
  font-size: var(--f-xs);
  letter-spacing: 0.16em;
  text-transform: uppercase;
  font-weight: 620;
  color: var(--cyan);
  margin: 0 0 var(--s5);
  display: flex; align-items: center; gap: var(--s3);
}
.eyebrow::before {
  content: ""; width: 28px; height: 1px; background: var(--cyan); flex: none;
  opacity: 0.75;
}

h1, h2, h3, .mega {
  font-family: Fraunces, ui-serif, Georgia, serif;
  font-weight: 460;
  letter-spacing: -0.015em;
  line-height: 1.03;
  margin: 0;
  font-variation-settings: "opsz" 120, "SOFT" 40, "WONK" 1;
  text-wrap: balance;
}
h1 { font-size: var(--f-h1); line-height: 0.98; letter-spacing: -0.028em; }
h2 { font-size: var(--f-h2); line-height: 1.04; letter-spacing: -0.022em; }
h3 {
  font-size: var(--f-h3); line-height: 1.14; letter-spacing: -0.012em;
  font-variation-settings: "opsz" 40, "SOFT" 30, "WONK" 0;
  font-weight: 520;
}
em.hl {
  font-style: normal;
  color: var(--cyan);
  font-variation-settings: "opsz" 144, "SOFT" 90, "WONK" 1;
}
p { margin: 0 0 1.05em; max-width: var(--measure); }
p:last-child { margin-bottom: 0; }
.lead { font-size: var(--f-lead); line-height: 1.45; color: var(--paper); }
.muted { color: var(--paper-2); }
.small { font-size: var(--f-s); }

/* ---------- 4. Buttons ---------- */
.btn {
  display: inline-flex; align-items: center; gap: 10px;
  font-family: inherit; font-size: var(--f-s); font-weight: 640;
  letter-spacing: 0.005em;
  padding: 15px 26px; border-radius: 999px; text-decoration: none;
  border: 1px solid transparent; cursor: pointer;
  transition: transform 0.18s ease, background-color 0.18s ease,
    border-color 0.18s ease;
}
.btn--go { background: var(--cyan); color: #032027; }
@media (hover: hover) and (pointer: fine) { .btn--go:hover { background: var(--cyan-2); transform: translateY(-2px); } }
.btn--ghost { border-color: var(--line); color: var(--paper); }
@media (hover: hover) and (pointer: fine) { .btn--ghost:hover { border-color: var(--cyan); color: var(--cyan); transform: translateY(-2px); } }
.btn--big { font-size: var(--f-lead); padding: 20px 36px; font-weight: 600; }
.btn svg { width: 16px; height: 16px; flex: none; }

/* ---------- 5. Header ---------- */
.top {
  position: sticky; top: 0; z-index: 40;
  background: rgba(1, 14, 27, 0.82);
  backdrop-filter: blur(14px) saturate(1.3);
  border-bottom: 1px solid var(--line-2);
}
.top__in {
  display: flex; align-items: center; gap: var(--s5);
  height: 64px;
}
.brand {
  font-family: Fraunces, serif; font-size: 1.0625rem; font-weight: 600;
  letter-spacing: 0.13em; text-transform: uppercase; text-decoration: none;
  font-variation-settings: "opsz" 20, "SOFT" 0, "WONK" 0;
  margin-right: auto; white-space: nowrap;
}
/* ---------- 5b. THE MARK -------------------------------------------------
   Their mark is a rounded triangle whose counter is a CLOSED region, so the
   logo can hold water instead of merely suggesting it. The counter is a
   clip path; two offset sine surfaces sit inside it.

   FREQUENCY RULE: the header mark is on screen constantly, so it does NOT
   loop. It fills once on first paint, the surface drifts for two cycles
   while it settles, and then it rests. A perpetual wave up here would be
   motion at 100+ exposures a day, which is the one tier that gets no
   animation at all. Hover is the only re-trigger, and only on a real
   pointer. The expressive version belongs in a rare band, not the chrome.
   -------------------------------------------------------------------- */
.brand { display: inline-flex; align-items: center; gap: 9px; }
.brand__mark { flex: none; width: 27px; display: block; }
.brand__mark svg { display: block; width: 100%; height: auto; }
.brand__word { display: block; height: 15px; width: auto; }
@media (min-width: 860px) {
  .brand__mark { width: 31px; }
  .brand__word { height: 17px; }
}
.brand--foot .brand__word { height: 22px; }
.top nav { display: none; gap: var(--s6); font-size: var(--f-s); }
.top nav a { text-decoration: none; color: var(--paper-2); }
@media (hover: hover) and (pointer: fine) { .top nav a:hover { color: var(--paper); } }
.top .btn { padding: 10px 20px; }
@media (min-width: 860px) { .top nav { display: flex; } }

/* ---------- 6. Hero ------------------------------------------------------
   The product is shown WHERE IT LIVES. This replaced a knockout PNG of the
   machine floating on the page ground — a black silhouette on a dark field,
   about 1.6:1, which is why it read as feathered and weightless. The client
   photographed the thing on a real counter with the panel lit; the knockout
   had thrown that away. Text never sits on bare photographic pixels: the
   scrim below is opaque brand navy across the whole column the copy uses.
   -------------------------------------------------------------------- */
.hero { position: relative; display: grid; isolation: isolate; overflow: hidden; }
.hero__shot { position: relative; grid-area: 1 / 1; overflow: hidden; }
.hero__shot img {
  display: block; width: 100%; height: 100%;
  object-fit: cover; object-position: 58% 52%;
}
.hero__shot::after { content: ""; position: absolute; inset: 0; }
.hero__in {
  grid-area: 2 / 1; position: relative; z-index: 1;
  padding-block: clamp(28px, 5vw, 46px) 0;
}
.hero__copy { max-width: 40rem; }
.hero h1 { margin-bottom: var(--s5); }
.hero .lead { max-width: 46ch; color: var(--paper-2); }
.hero__cta { display: flex; flex-wrap: wrap; gap: var(--s4); margin-top: var(--s7); }
.hero__note {
  margin-top: var(--s5); font-size: var(--f-s); color: var(--paper-3);
  max-width: 44ch;
}
/* mobile: photo on top, copy on solid ground beneath it — no text on pixels.
   The band stays short ON PURPOSE. A taller one frames the machine better but
   costs ~60px, and that is exactly the margin that decides whether the primary
   door is above the fold at 844 — which it was not, twice before. The whole
   machine is shown at full height three bands down; here the crop is a slice.
   Both CTAs land inside the fold at 390x844 with the tightened rhythm below. */
.hero__shot { height: clamp(220px, 31vh, 310px); }
@media (max-width: 899px) {
  .hero__cta { margin-top: var(--s6); }
  .hero h1 { margin-bottom: var(--s4); }
}
.hero__shot::after {
  background: linear-gradient(180deg,
    rgba(2, 20, 44, 0.34) 0%, rgba(2, 20, 44, 0) 24%,
    rgba(2, 20, 44, 0.30) 62%, var(--g1) 100%);
}
@media (min-width: 900px) {
  /* The photo is taken OUT OF FLOW so it can never drive the hero's height —
     only the copy can. A grid row that sized itself from a height:100% image
     resolved circularly to the file's own 2561px: the fold showed nothing but
     wall and the CTA sat 744px under it. The copy sets the height; the photo
     fills whatever that turns out to be.

     It occupies the RIGHT COLUMN, not the whole hero. Full-bleeding a 1012x1800
     PORTRAIT into a 1440x1001 landscape box cost two things at once: cover threw
     away 61% of the frame — everything below the panel head, which is the entire
     reason to use a photograph of the thing on a counter — and it stretched a
     1012px source to 1440 CSS px, 1.42x at DPR1 and 2.85x at DPR2, which is what
     read as soft. A column near the source's own aspect fixes both: the box is
     ~760px wide, so the file DOWNSCALES, and the crop keeps the machine whole. */
  .hero { display: block; position: relative; min-height: min(88vh, 860px); }
  .hero__shot {
    position: absolute; inset: 0 0 0 auto; height: auto;
    width: clamp(420px, 52%, 780px);
  }
  .hero__shot img { object-position: 52% 58%; }
  .hero__in {
    display: flex; align-items: center;
    min-height: min(88vh, 860px);
    padding-block: clamp(48px, 6vw, 84px);
  }
  .hero__copy { max-width: 30rem; }
  .hero h1 { font-size: clamp(2.375rem, 1.9rem + 2.6vw, 4.25rem); text-wrap: balance; }
  /* The photo no longer runs under the copy, so the scrim's job changes: it is
     a FEATHER at the seam, not a blanket over the left half. Vertical stops stay
     — they seat the frame against the ground above and below. */
  .hero__shot::after {
    background:
      linear-gradient(90deg,
        var(--g1) 0%, rgba(2, 20, 44, 0.72) 9%, rgba(2, 20, 44, 0.22) 22%,
        rgba(2, 20, 44, 0) 38%),
      linear-gradient(180deg,
        rgba(2, 20, 44, 0.52) 0%, rgba(2, 20, 44, 0) 26%,
        rgba(2, 20, 44, 0) 62%, rgba(2, 20, 44, 0.55) 88%, var(--g1) 100%);
  }
}

/* ---------- 7. THE RAIL — the spine of the document ---------- */
.day { position: relative; }
.day__head { margin-bottom: clamp(40px, 5vw, 76px); }
.day__head .lead { color: var(--paper-2); }

.moments { list-style: none; margin: 0; padding: 0; position: relative; }

/* the line itself: one element, drawn once, crossing every moment */
.moments::before {
  content: ""; position: absolute; z-index: 0;
  left: 7px; top: 10px; bottom: 10px; width: 1px;
  background: linear-gradient(180deg,
    transparent, var(--line) 6%, var(--line) 94%, transparent);
}
.moment {
  position: relative; z-index: 1;
  padding: 0 0 clamp(38px, 4.4vw, 62px) 40px;
}
.moment:last-child { padding-bottom: 0; }
.moment__time {
  font-size: var(--f-s); font-weight: 620; letter-spacing: 0.04em;
  font-variant-numeric: tabular-nums lining-nums;
  color: var(--paper-2); margin: 0 0 var(--s2);
  display: block; white-space: nowrap;
}
.mer {
  font-size: 0.72em; font-weight: 600; letter-spacing: 0.1em;
  text-transform: uppercase; color: var(--paper-3); margin-left: 0.32em;
}
.moment::before { /* the dot, in that hour's colour */
  content: ""; position: absolute; left: 0; top: 7px;
  width: 15px; height: 15px; border-radius: 50%;
  background: var(--dot, var(--cyan));
  box-shadow: 0 0 0 5px var(--g1), 0 0 22px -2px var(--dot, var(--cyan));
}
.moment h3 { margin-bottom: var(--s3); }
.moment p { color: var(--paper-2); max-width: 52ch; }

@media (min-width: 780px) {
  .moments::before { left: var(--rail-x); }
  .moment {
    display: grid;
    grid-template-columns: var(--rail) minmax(0, 1fr);
    gap: 0 clamp(28px, 3.4vw, 52px);
    padding-left: 0;
  }
  .moment::before { left: calc(var(--rail-x) - 7.5px); top: 7px; }
  .moment__time {
    grid-column: 1; text-align: right; padding-right: 30px;
    margin: 0; padding-top: 1px;
    font-size: 1.25rem; color: var(--paper);
    letter-spacing: 0.005em; white-space: nowrap;
  }
  .moment__body { grid-column: 2; }
}

/* A figure the brochure states, set as a readout rather than typed into the
   sentence. Only ever 150 ML and 6° here — the numbers that are published. */
.moment__val {
  font-weight: 700; font-style: normal; color: var(--cyan);
  font-variant-numeric: tabular-nums; letter-spacing: 0.02em;
  white-space: nowrap;
}

/* --- THE HORIZONTAL DAY --------------------------------------------------
   Default state is the vertical rail above: .day__scroll and .day__pin are
   inert wrappers, the sky and the marker are not rendered. The horizontal
   day is switched on only where all three conditions hold — room for it,
   scroll-driven animation to scrub it, and a reader who has not asked for
   less motion. A pan that cannot be scrubbed would land on its end state,
   which is a track shoved off-screen: that is why this is gated on @supports
   and not merely allowed to fall back.
   --------------------------------------------------------------------- */
.day__scroll { width: min(100% - (var(--pad) * 2), 1240px); margin-inline: auto; }
.day__sky, .day__now { display: none; }

@supports (animation-timeline: view()) {
  @media (min-width: 900px) and (prefers-reduced-motion: no-preference) {
    :root:not(.nosdt) .day__scroll {
      width: auto; margin-inline: 0;
      height: 320vh;                    /* the pan's runway */
      view-timeline-name: --day; view-timeline-axis: block;
    }
    :root:not(.nosdt) .day__pin {
      position: sticky; top: 0; height: 100vh;
      display: grid; align-content: center;
      /* The track is max-content wide (3,520px at 1440). Without an explicit
         column the grid sizes to IT, and everything else — the heading —
         centres inside a column three screens wide and lands off to the
         right. One declaration; it cost a render to see. */
      grid-template-columns: minmax(0, 1fr);
      overflow: hidden;
    }
    :root:not(.nosdt) .day__head {
      position: relative; z-index: 2;
      width: min(100% - (var(--pad) * 2), 1240px); margin-inline: auto;
      margin-bottom: clamp(36px, 6vh, 84px);
    }
    :root:not(.nosdt) .day__head h2 { max-width: 20ch; }
    :root:not(.nosdt) .day__head .lead { max-width: 44ch; }

    /* The ground behind the day. Wider than the viewport and panned at a
       third of the track's rate, so the hours pass over a sky that is
       moving with them: 3am, dawn, the middle of the day, dusk, midnight. */
    :root:not(.nosdt) .day__sky {
      display: block; position: absolute; z-index: 0;
      /* 160vw panned 60vw against a track that moves ~119vw: the ground goes
         SLOWER than the hours crossing it, which is the only way round that
         reads as depth. The first version was wider than the track and moved
         faster — parallax backwards. */
      top: 0; bottom: 0; left: 0; width: 160vw;
      background: linear-gradient(90deg,
        #01060f 0%, #041229 14%, #0a2740 32%, #123b52 48%,
        #0d2a44 64%, #05182e 82%, #01060f 100%);
      animation: day-sky linear both;
      animation-timeline: --day; animation-range: entry 100% exit 0%;
    }
    @keyframes day-sky { to { transform: translateX(calc(-160vw + 100vw)); } }

    /* The hour marker. It does not move; the day moves past it. */
    :root:not(.nosdt) .day__now {
      /* Only over the track. Run full-height and it draws a line through the
         heading, which is a rule nobody asked for. */
      display: block; position: absolute; z-index: 2;
      left: 28%; top: 52%; bottom: 12%; width: 1px;
      background: linear-gradient(180deg,
        transparent, rgba(60, 208, 207, 0.5) 22%,
        rgba(60, 208, 207, 0.5) 78%, transparent);
    }

    :root:not(.nosdt) .moments {
      position: relative; z-index: 1;
      display: flex; width: max-content; align-items: start;
      gap: clamp(56px, 7vw, 132px);
      padding-inline: 28% 12vw;
      /* Per-cent translate resolves against the track's own width, so the
         pan lands exactly at its end with nothing measured in JS. */
      animation: day-pan linear both;
      animation-timeline: --day; animation-range: entry 100% exit 0%;
    }
    @keyframes day-pan { to { transform: translateX(calc(-100% + 100vw)); } }

    /* the rail is now horizontal, and it is the line the dots sit on */
    :root:not(.nosdt) .moments::before {
      left: 0; right: 0; top: 12px; bottom: auto; width: auto; height: 1px;
      background: linear-gradient(90deg,
        transparent, var(--line) 4%, var(--line) 96%, transparent);
    }
    :root:not(.nosdt) .moment {
      display: block; width: clamp(280px, 24vw, 360px); flex: none;
      padding: 42px 0 0; grid-template-columns: none;
    }
    :root:not(.nosdt) .moment::before { left: 0; top: 5px; }        /* the dot, back on the line */
    :root:not(.nosdt) .moment__time {
      grid-column: auto; text-align: left; padding: 0; margin: 0 0 var(--s4);
      font-family: Fraunces, ui-serif, Georgia, serif;
      font-size: clamp(2.25rem, 3.4vw, 3.25rem); line-height: 1;
      font-weight: 300; color: var(--paper); letter-spacing: -0.02em;
    }
    :root:not(.nosdt) .mer { font-family: Figtree, sans-serif; font-size: 0.3em; }
    :root:not(.nosdt) .moment h3 { font-size: var(--f-lead); }
    :root:not(.nosdt) .moment p { font-size: var(--f-s); max-width: 34ch; }
    /* the rail is the reveal; a second one per card would be noise */
    :root:not(.nosdt) .moment.rise { animation: none; }
  }
}

/* ---------- 8. The 180mm display ----------------------------------------
   The number is set at display size beside the object, not underneath it as
   a caption. NOT claimed: that the silhouette is life size. A CSS pixel is
   not a millimetre on anybody's display, so the dimension line states the
   MACHINE's width, never the screen's.
   ---------------------------------------------------------------------- */
.size__grid {
  display: grid; gap: clamp(40px, 6vw, 96px); align-items: center;
  grid-template-columns: 1fr;
}
@media (min-width: 900px) {
  .size__grid { grid-template-columns: minmax(0, 1.05fr) minmax(0, 0.95fr); }
}
.size__mega {
  font-family: Fraunces, ui-serif, Georgia, serif;
  font-size: var(--f-mega); line-height: 0.82; letter-spacing: -0.05em;
  font-weight: 300;
  font-variation-settings: "opsz" 144, "SOFT" 0, "WONK" 0;
  font-variant-numeric: lining-nums tabular-nums;
  color: var(--paper);
  margin: 0 0 var(--s6); max-width: none;
  display: flex; align-items: baseline; gap: 0.1em;
}
.size__mega span {
  font-family: Figtree, sans-serif; font-size: 0.16em; font-weight: 560;
  letter-spacing: 0.08em; color: var(--cyan); text-transform: none;
}
.size__copy p { color: var(--paper-2); }
.size__copy .lead { color: var(--paper); }
.size__spec {
  margin-top: var(--s6) !important; font-size: var(--f-s);
  color: var(--paper-3); letter-spacing: 0.03em;
}
.size__fig { position: relative; }
.size__shot {
  position: relative; overflow: hidden;
  border-radius: var(--radius); border: 1px solid var(--line-2);
}
.size__shot img { display: block; width: 100%; height: auto; }
.size__fig figcaption {
  margin-top: var(--s4); font-size: var(--f-xs); color: var(--paper-3);
  line-height: 1.6;
}
/* Geometry read off luna-counter-front.jpg (1012x1350, cropped once from
   luna-kitchen-front.jpg y120..1470 so these percentages never move): the
   panel housing is the machine's widest point and spans x 148->812
   (14.6%..80.2%); its top edge is at 7.0%. The rule is laid just above it. */
.size__dim {
  position: absolute; left: 14.6%; width: 65.6%; top: 3.4%; z-index: 2;
  display: flex; align-items: center; gap: 8px;
}
.size__cap { width: 1.5px; height: 17px; background: var(--cyan); flex: none;
  box-shadow: 0 0 10px -1px rgba(60, 208, 207, 0.9); }
.size__rule { height: 1.5px; background: var(--cyan); flex: 1 1 auto;
  box-shadow: 0 0 10px -1px rgba(60, 208, 207, 0.9); }
.size__val {
  font-size: var(--f-xs); font-weight: 700; letter-spacing: 0.06em;
  color: var(--cyan); flex: none; font-variant-numeric: tabular-nums;
  font-style: normal; white-space: nowrap;
  background: var(--plate); border: 1px solid var(--cyan-d);
  padding: 4px 10px; border-radius: 999px;
}

/* ---------- 9. Annotated media (panel + cutaway) ------------------------
   SYSTEM RULE: text is NEVER set on photographic pixels. Every annotation
   sits on an opaque plate, so its contrast is a fixed measurable number
   and not a function of what happens to be behind it.
   -------------------------------------------------------------------- */
.figc { position: relative; border-radius: var(--radius); overflow: visible; }
.figc__img {
  position: relative;
  border-radius: var(--radius); overflow: hidden;
  border: 1px solid var(--line-2);
  background: #000;
}
.figc__img img { width: 100%; height: auto; }

/* Ring markers. A solid pin covers the very icon it points at; a ring
   encircles it and leaves it readable. This is why there are no filled
   pins anywhere on this page. */
.ring {
  position: absolute; width: 48px; height: 48px;
  transform: translate(-50%, -50%);
  border-radius: 50%; border: 1.5px solid var(--cyan);
  background: rgba(60, 207, 206, 0.05);
  box-shadow: 0 0 0 1px rgba(1, 16, 31, 0.5), 0 0 18px -4px rgba(60, 207, 206, 0.7);
  z-index: 3; transition: transform 0.2s ease, background-color 0.2s ease;
}
.ring b {
  position: absolute; right: -9px; top: -9px;
  width: 21px; height: 21px; border-radius: 50%;
  display: grid; place-items: center;
  font-family: Figtree, sans-serif; font-size: 11px; font-weight: 700;
  font-style: normal; color: #032027; background: var(--cyan);
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.6);
}
/* marker 4 encircles nothing on purpose — dashed says "not a part" */
.ring--none { border-style: dashed; background: none; }
/* the readout is a wide element, so its marker is a wide one */
.ring--wide { width: 44%; height: 24%; border-radius: 999px; }
.ring--wide b { right: -8px; top: -10px; }

/* --- the panel band: the photograph IS the interface --------------------
   The old treatment was a photograph beside a seven-item list — the machine
   described in prose next to a picture of itself. Here the icons are the
   controls: a real <button> over each one, the rest of the panel dimmed by a
   masked scrim while you read, and one plate at a time.

   Text still never sits on photographic pixels. The one element that overlays
   the photograph, .pui__read, carries its own opaque plate, so its contrast
   is a fixed number rather than a function of what the LCD is doing.
   -------------------------------------------------------------------- */
@property --hx { syntax: "<percentage>"; inherits: true; initial-value: 50%; }
@property --hy { syntax: "<percentage>"; inherits: true; initial-value: 50%; }

.pui {
  display: grid; gap: clamp(24px, 3.4vw, 44px); align-items: start;
  grid-template-columns: 1fr; --hx: 50%; --hy: 40%; --hr: 9%;
}
@media (min-width: 980px) {
  .pui { grid-template-columns: minmax(0, 1.08fr) minmax(0, 0.92fr); gap: clamp(32px, 4vw, 60px); }
  .pui__stage { position: sticky; top: 96px; }
  /* one plate at a time leaves this column short; centring it against the
     photograph is what stops the pair reading as top-heavy */
  .pui.is-live .pui__facts { align-self: center; }
  .pui__facts { padding-top: clamp(8px, 3vw, 48px); }
}
.pui__stage { margin: 0; }
.pui__img { background: #000; }

/* One element, one moving hole. The mask centre follows the pressed icon;
   --hx/--hy are registered above so the hole travels instead of jumping. */
.pui__scrim {
  position: absolute; inset: 0; z-index: 2; pointer-events: none;
  background: rgba(1, 10, 22, 0.74);
  opacity: 0;
  transition: opacity 0.34s ease, --hx 0.42s ease, --hy 0.42s ease;
  -webkit-mask-image: radial-gradient(circle at var(--hx) var(--hy),
      rgba(0, 0, 0, 0) 0 var(--hr), #000 calc(var(--hr) + 8%));
  mask-image: radial-gradient(circle at var(--hx) var(--hy),
      rgba(0, 0, 0, 0) 0 var(--hr), #000 calc(var(--hr) + 8%));
}
.pui.is-on .pui__scrim { opacity: 1; }

/* The machine's own readout, overlaid with the figure for the setting being
   read. Only ever a number the brochure states. */
.pui__read {
  position: absolute; left: 50%; top: 40%; z-index: 4;
  transform: translate(-50%, -50%) scale(0.96);
  opacity: 0; visibility: hidden;
  padding: 6px clamp(14px, 2.4vw, 26px);
  border-radius: 10px;
  background: rgba(0, 6, 13, 0.94);
  border: 1px solid var(--cyan-d);
  transition: opacity 0.28s ease, transform 0.28s ease, visibility 0.28s;
}
.pui__read b {
  display: block;
  font-family: Figtree, sans-serif; font-weight: 800;
  font-size: clamp(1.5rem, 3.6vw, 2.75rem); line-height: 1;
  letter-spacing: 0.01em; color: var(--cyan);
  font-variant-numeric: tabular-nums;
}
.pui.has-read .pui__read { opacity: 1; visibility: visible; transform: translate(-50%, -50%) scale(1); }

/* The hotspots. Sized in per-cent of the photograph, so they stay over their
   icons at every render width. */
.pui__hot {
  position: absolute; transform: translate(-50%, -50%);
  width: 12.5%; aspect-ratio: 1; border-radius: 50%;
  /* 12.5% of the photograph is 43.75px at a 390 viewport — under the 44px
     touch minimum by a quarter of a pixel, which is exactly the kind of miss
     a percentage layout hides. Floored. */
  min-width: 44px; min-height: 44px;
  padding: 0; z-index: 3; cursor: pointer;
  border: 1px solid rgba(60, 208, 207, 0.34);
  background: rgba(60, 208, 207, 0.05);
  transition: border-color 0.2s ease, background-color 0.2s ease,
              box-shadow 0.2s ease, transform 0.2s ease;
}
.pui__hot--wide { width: 44%; aspect-ratio: auto; height: 24%; border-radius: 999px; }
@media (hover: hover) and (pointer: fine) {
  .pui__hot:hover { border-color: var(--cyan); background: rgba(60, 208, 207, 0.16); }
}
.pui__hot:focus-visible { outline: 2px solid var(--cyan); outline-offset: 4px; }
.pui__hot.is-on {
  border-color: var(--cyan); border-width: 2px;
  background: rgba(60, 208, 207, 0.14);
  box-shadow: 0 0 24px -4px rgba(60, 208, 207, 0.8);
  transform: translate(-50%, -50%) scale(1.06); z-index: 5;
}
.pui__hot--wide.is-on { transform: translate(-50%, -50%) scale(1.02); }
/* The badges are the key to the no-JS list. With JS on there is no list to
   key, so they go. */
.pui__hot b {
  position: absolute; right: -9px; top: -9px;
  width: 21px; height: 21px; border-radius: 50%;
  display: grid; place-items: center;
  font-size: 11px; font-weight: 700; font-style: normal;
  color: #032027; background: var(--cyan);
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.6);
}
.pui.is-live .pui__hot b { display: none; }
.pui__sr {
  position: absolute; width: 1px; height: 1px; overflow: hidden;
  clip-path: inset(50%); white-space: nowrap;
}
.pui__hint {
  margin: var(--s4) 0 0; font-size: var(--f-xs); letter-spacing: 0.08em;
  text-transform: uppercase; color: var(--paper-3); display: none;
}
.pui.is-live .pui__hint { display: block; }

/* The facts. JS off: all ten, numbered, the panel's reading order.
   JS on: the same ten stacked in one grid cell, one visible. Stacking in a
   grid cell means the block is as tall as its TALLEST member at every width,
   so switching plates never moves the page — no magic min-height. */
.pui__facts { list-style: none; margin: 0; padding: 0; counter-reset: n; }
.pui__facts li {
  display: grid; grid-template-columns: 30px minmax(0, 1fr); gap: var(--s4);
  padding: var(--s5) 0; border-top: 1px solid var(--line-2);
}
.pui__facts li:first-child { border-top: 0; padding-top: 0; }
.pui__facts li::before {
  counter-increment: n; content: counter(n);
  font-size: 12px; font-weight: 700; color: var(--cyan);
  width: 26px; height: 26px; border-radius: 50%;
  border: 1px solid var(--cyan-d);
  background: rgba(60, 208, 207, 0.08);
  display: grid; place-items: center; margin-top: 3px;
}
.pui__facts h3 { font-size: var(--f-lead); margin-bottom: 6px; font-weight: 560; }
.pui__facts p { color: var(--paper-2); font-size: var(--f-s); line-height: 1.55; }

.pui.is-live .pui__facts { display: grid; }
.pui.is-live .pui__facts li {
  grid-area: 1 / 1; grid-template-columns: minmax(0, 1fr);
  border-top: 0; padding: var(--s5) 0 0;
  border-left: 2px solid var(--cyan-d); padding-left: var(--s5);
  opacity: 0; visibility: hidden; transform: translateY(12px);
  /* Leaving is fast and has no delay; arriving waits for it. Crossfading two
     plates in the same grid cell renders both sentences on top of each other
     for a quarter of a second — invisible in a screenshot, unmissable in the
     usage recording, which is why the recording is part of shipping. */
  transition: opacity 0.14s ease, transform 0.14s ease, visibility 0.14s;
}
.pui.is-live .pui__facts li::before { display: none; }
.pui.is-live .pui__facts li.is-on {
  opacity: 1; visibility: visible; transform: none;
  transition: opacity 0.24s ease 0.15s, transform 0.24s ease 0.15s,
              visibility 0.24s 0.15s;
}
.pui.is-live .pui__facts h3 { color: var(--cyan); }

/* --- the cutaway band ---------------------------------------------------
   The cards sit BELOW the image in a 4-up row rather than floating over it.
   The photograph has no empty region wide enough to hold a readable card
   without covering a part, and covering the part to label the part is the
   failure mode this treatment exists to avoid. -------------------------- */
.cut { position: relative; }
.cut__cards {
  display: grid; gap: var(--s4); margin-top: var(--s5);
  grid-template-columns: 1fr;
}
@media (min-width: 620px)  { .cut__cards { grid-template-columns: 1fr 1fr; } }
@media (min-width: 1040px) { .cut__cards { grid-template-columns: repeat(4, 1fr); } }
.card {
  background: rgba(3, 20, 36, 0.72);
  border: 1px solid var(--line-2);
  border-radius: 12px;
  padding: var(--s5);
  position: relative;
  padding-left: calc(var(--s5) + 34px);
}
.card::before {
  content: attr(data-c);
  position: absolute; left: var(--s5); top: var(--s5);
  width: 24px; height: 24px; border-radius: 50%;
  display: grid; place-items: center;
  font-size: 12px; font-weight: 700; color: #032027; background: var(--cyan);
}
.card h3 { font-size: var(--f-lead); margin-bottom: 6px; font-weight: 560; }
.card p { color: var(--paper-2); font-size: var(--f-s); line-height: 1.5; margin: 0; }
.card strong { color: var(--paper); font-weight: 620; }

/* --- THE SCAN -----------------------------------------------------------
   A line crosses the render and the machine lights behind it, part by part.
   NOT a shell dissolving off the product: that needs two frames from one
   camera and the client's house shot these from two. This reveals the
   photograph we hold, in the order the water goes.

   Every value here ENDS where an un-scrubbed browser starts it — full
   brightness, line drawn, all four cards up, which is the page as it was.
   That is why there is no @supports gate: the fallback is the old design,
   not a broken one.
   --------------------------------------------------------------------- */
.xray__stage { position: relative; }
.xray__veil {
  position: absolute; inset: 0; z-index: 2; pointer-events: none;
  background: linear-gradient(90deg,
    rgba(1, 10, 22, 0.66) 0 60%, rgba(1, 10, 22, 0.84) 100%);
  border-left: 2px solid var(--cyan);
  box-shadow: -2px 0 30px -2px rgba(60, 208, 207, 0.8);
  /* The veil SLIDES off to the right; it is not clipped from the left.
     Clipping ate the very border that was supposed to be the scan line —
     the edge was there, the line was not, and only the render showed it.
     Sliding also keeps this on the compositor: transform, not layout. */
  transform: translateX(100%);          /* end state: gone, nothing dimmed */
}
.xray__flow {
  position: absolute; inset: 0; z-index: 1; width: 100%; height: 100%;
  pointer-events: none;
}
.xray__flow path {
  stroke: var(--cyan); stroke-width: 5; stroke-linecap: round;
  stroke-linejoin: round; vector-effect: non-scaling-stroke;
  filter: drop-shadow(0 0 6px rgba(60, 208, 207, 0.65));
  stroke-dasharray: 1; stroke-dashoffset: 0;   /* end state: fully drawn */
}
.xray .ring { transition: none; }

@media (prefers-reduced-motion: no-preference) {
  /* The scan is timed against the PHOTOGRAPH, not the whole block. Timed
     against the block, most of the progress happened while only the cards
     were on screen: at 390 the image is 234px tall, and it had left the
     viewport with the scan 60% done — the reveal was never seen on a phone.
     timeline-scope hoists the name so the cards, which are its siblings,
     can read it too. */
  .xray { timeline-scope: --xray; }
  .xray__stage { view-timeline-name: --xray; view-timeline-axis: block; }
  .xray__veil, .xray__flow path,
  .xray .ring, .cut__cards .card {
    animation-timeline: --xray;
    animation-range: cover 20% cover 76%;
    animation-fill-mode: both;
    animation-timing-function: linear;
  }
  .xray__veil { animation-name: xray-wipe; }
  .xray__flow path { animation-name: xray-draw; }
  @keyframes xray-wipe {
    from { transform: translateX(0); }
    to   { transform: translateX(100%); }
  }
  @keyframes xray-draw { from { stroke-dashoffset: 1; } to { stroke-dashoffset: 0; } }

  /* Each part lights as the edge reaches it. One timeline, four keyframe
     blocks whose offsets are the part's own x position in the frame:
     cartridge 37.5%, coil 56%, tank 66%, and the UV last because it is the
     one you cannot see and it should arrive after the frame is open. */
  .xray .ring { opacity: 0.18; }
  .xr1 { animation-name: lit-1; }
  .xr2 { animation-name: lit-2; }
  .xr3 { animation-name: lit-3; }
  .xr4 { animation-name: lit-4; }
  @keyframes lit-1 { 0%, 33% { opacity: 0.18; } 40%, 100% { opacity: 1; } }
  @keyframes lit-2 { 0%, 52% { opacity: 0.18; } 59%, 100% { opacity: 1; } }
  @keyframes lit-3 { 0%, 62% { opacity: 0.18; } 69%, 100% { opacity: 1; } }
  @keyframes lit-4 { 0%, 88% { opacity: 0.18; } 96%, 100% { opacity: 1; } }

  /* The cards stay a four-up row and all four end readable. They rise as
     their part lights; they never take turns, because a row where three
     cards are invisible is a row that reads as broken the moment the
     scrubbing stops. The dim floor is 0.55, not 0.34: a reader whose scroll
     stops mid-scan still has to be able to READ the two cards that have not
     lit yet, and the contrast walk measures them where they sit. */
  .xc1 { animation-name: card-1; }
  .xc2 { animation-name: card-2; }
  .xc3 { animation-name: card-3; }
  .xc4 { animation-name: card-4; }
  @keyframes card-1 {
    0%, 33% { opacity: 0.55; transform: translateY(14px); }
    44%, 100% { opacity: 1; transform: none; }
  }
  @keyframes card-2 {
    0%, 52% { opacity: 0.55; transform: translateY(14px); }
    63%, 100% { opacity: 1; transform: none; }
  }
  @keyframes card-3 {
    0%, 62% { opacity: 0.55; transform: translateY(14px); }
    73%, 100% { opacity: 1; transform: none; }
  }
  @keyframes card-4 {
    0%, 88% { opacity: 0.55; transform: translateY(14px); }
    99%, 100% { opacity: 1; transform: none; }
  }
}

.frames {
  display: grid; gap: var(--s5); margin-top: clamp(40px, 5vw, 72px);
  grid-template-columns: 1fr;
}
@media (min-width: 760px) { .frames { grid-template-columns: 1fr 1fr; } }
.frame figcaption {
  margin-top: var(--s4); font-size: var(--f-s); color: var(--paper-2);
  max-width: 44ch;
}
.frame__m {
  border-radius: var(--radius); overflow: hidden; border: 1px solid var(--line-2);
  background: #000; aspect-ratio: 16 / 9;
}
.frame__m > * { width: 100%; height: 100%; object-fit: cover; }
/* the tray sits in the upper third of a 900x1600 portrait */
.frame__m img[src*="drip-tray"] { object-position: 50% 46%; }

/* ---------- 10. The argument (the one silent band) ---------- */
.argue { text-align: left; }
.argue__in { max-width: 720px; margin-inline: auto; }
.argue h2 { margin-bottom: var(--s7); font-size: clamp(2.125rem, 1.3rem + 3.4vw, 4rem); }
.argue p { font-size: var(--f-lead); line-height: 1.5; color: var(--paper-2); max-width: none; }
.argue p:first-of-type { color: var(--paper); }

/* ---------- 11. Showroom ---------- */
.show__grid {
  display: grid; gap: clamp(28px, 4vw, 64px); align-items: center;
  grid-template-columns: 1fr;
}
@media (min-width: 940px) {
  /* the photograph bleeds off the left edge — the one asymmetry on the page,
     and it is here because this band is the page's actual offer */
  .show > .wrap { width: 100%; max-width: none; }
  .show__grid {
    grid-template-columns: minmax(0, 0.44fr) minmax(0, 0.56fr);
    gap: clamp(40px, 5vw, 84px);
  }
  .show__ph { border-radius: 0 var(--radius) var(--radius) 0; aspect-ratio: 1012 / 1330; }
  .show__body { padding-right: max(var(--pad), calc((100vw - 1240px) / 2 + var(--pad))); }
}
.show__ph {
  border-radius: var(--radius); overflow: hidden;
  border: 1px solid var(--line-2);
  aspect-ratio: 1012 / 1440;
}
.show__ph img { width: 100%; height: 100%; object-fit: cover; }
.show p { color: var(--paper-2); }
.show .btn { margin-top: var(--s6); }

/* ---------- 12. Origin + safety mark ---------- */
.origin__grid {
  display: grid; gap: clamp(28px, 4vw, 64px); align-items: center;
  grid-template-columns: 1fr;
}
@media (min-width: 900px) {
  .origin__grid { grid-template-columns: minmax(0, 1.2fr) minmax(0, 0.8fr); }
}
.origin p { color: var(--paper-2); }
.markbox {
  background: rgba(236, 243, 247, 0.96);
  border-radius: var(--radius); padding: var(--s7) var(--s6);
  display: grid; place-items: center; gap: var(--s4);
}
.markbox img { width: min(300px, 80%); height: auto; }
.markbox figcaption {
  font-size: var(--f-s); color: #21384a; text-align: center; max-width: 34ch;
}

/* ---------- 13. Also ---------- */
.also__row {
  display: grid; gap: var(--s4); margin-top: var(--s6);
  grid-template-columns: 1fr;
}
@media (min-width: 640px) { .also__row { grid-template-columns: 1fr 1fr; } }
.also__row a {
  display: flex; align-items: center; justify-content: space-between;
  gap: var(--s4); text-decoration: none;
  padding: var(--s5) var(--s6); border: 1px solid var(--line-2);
  border-radius: 12px; font-size: var(--f-lead);
  font-family: Fraunces, serif; font-weight: 480;
  font-variation-settings: "opsz" 30, "SOFT" 30, "WONK" 0;
  transition: border-color 0.18s ease, transform 0.18s ease;
}
@media (hover: hover) and (pointer: fine) { .also__row a:hover { border-color: var(--cyan); transform: translateY(-2px); } }
.also__row span { color: var(--cyan); font-family: Figtree, sans-serif; font-size: 1.25rem; }

/* ---------- 14. Close ---------- */
.close { text-align: center; padding-block: clamp(88px, 11vw, 190px); }
.close h2 { max-width: 18ch; margin-inline: auto; margin-bottom: var(--s7); }
.close .btn { margin-bottom: var(--s6); }
.close__alt { font-size: var(--f-s); color: var(--paper-2);
  max-width: 48ch; margin-inline: auto; }
.close__alt a { color: var(--cyan); text-underline-offset: 4px; }

/* ---------- 15. Footer ---------- */
.foot { border-top: 1px solid var(--line-2); padding-block: var(--s8) var(--s7); }
.foot__grid {
  display: grid; gap: var(--s6); grid-template-columns: 1fr;
  font-size: var(--f-s); color: var(--paper-2);
}
@media (min-width: 760px) { .foot__grid { grid-template-columns: 1.4fr 1fr 1fr; } }
.foot h2 { font-size: var(--f-s); font-family: Figtree, sans-serif;
  text-transform: uppercase; letter-spacing: 0.14em; font-weight: 640;
  color: var(--paper-3); margin-bottom: var(--s4); }
.foot ul { list-style: none; margin: 0; padding: 0; display: grid; gap: 10px; }
.foot a { color: var(--paper-2); text-decoration: none; }
@media (hover: hover) and (pointer: fine) { .foot a:hover { color: var(--cyan); } }
.foot__legal {
  margin-top: var(--s8); padding-top: var(--s5); border-top: 1px solid var(--line-2);
  font-size: var(--f-xs); color: var(--paper-3); line-height: 1.7;
}

/* ---------- 16. Motion.
   Deliberate rule for this arm: NOTHING on this page animates opacity from
   zero, and no reveal is gated on script. Every element is at full opacity
   in its resting state; motion is transform-only and additive. A screenshot,
   a link preview, a reader landing mid-page and a browser with JS off all
   see identical, complete content.
   ---------------------------------------------------------------------- */
@supports (animation-timeline: view()) {
  @media (prefers-reduced-motion: no-preference) {
    .rise {
      animation: rise linear both;
      animation-timeline: view();
      animation-range: entry 5% entry 46%;
    }
    /* 20px of travel on an 80px headline is a move you can measure and
       cannot see, which is why the answer to "the motion is missing" was
       never "add more animations". 48px, still transform-only. */
    @keyframes rise {
      from { transform: translateY(48px); }
      to   { transform: translateY(0); }
    }
    /* the rail fills as the day passes — scroll-driven, no JS */
    .moments::after {
      content: ""; position: absolute; z-index: 0;
      left: 7px; top: 10px; width: 1px; height: calc(100% - 20px);
      background: linear-gradient(180deg, var(--cyan), rgba(60,207,206,0.15));
      transform-origin: top;
      animation: fill linear both;
      animation-timeline: view();
      animation-range: entry 90% exit 10%;
    }
    @keyframes fill { from { transform: scaleY(0); } to { transform: scaleY(1); } }

    /* the measurement draws out from its own centre as the band arrives */
    .size__dim {
      animation: dimdraw linear both;
      animation-timeline: view();
      animation-range: entry 28% entry 78%;
    }
    @keyframes dimdraw {
      from { clip-path: inset(0 50% 0 50%); }
      to   { clip-path: inset(0 0 0 0); }
    }
  }
}
@media (min-width: 780px) { .moments::after { left: var(--rail-x); } }

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after {
    animation: none !important;
    transition: none !important;
  }
  .moments::after { display: none; }
}

/* ======================================================================
   17. SITE-WIDE CHROME + SUB-PAGES (2026-09-17). The home page above was
   the clean room; these are the nine pages that make it a site. Same
   ground, same rail, same two faces. Nothing here introduces a colour the
   product does not emit or a component the home page would not recognise.
   ====================================================================== */

/* ---- 17a. Header: the folded menu below 860px ------------------------ */
.menu__box { position: absolute; opacity: 0; width: 0; height: 0; pointer-events: none; }
.menu__btn {
  display: inline-flex; flex-direction: column; justify-content: center; gap: 5px;
  width: 44px; height: 44px; padding: 10px; margin-right: -10px;
  border-radius: 8px; cursor: pointer; flex: none;
}
.menu__btn span { display: block; height: 2px; background: var(--paper); border-radius: 2px; transition: transform 240ms, opacity 240ms; }
.menu__box:checked ~ .menu__btn span:nth-child(1) { transform: translateY(7px) rotate(45deg); }
.menu__box:checked ~ .menu__btn span:nth-child(2) { opacity: 0; }
.menu__box:checked ~ .menu__btn span:nth-child(3) { transform: translateY(-7px) rotate(-45deg); }
.top nav a[aria-current="page"] { color: var(--cyan); }
@media (max-width: 859.98px) {
  .top .top__cta { display: none; }
  .top nav {
    display: flex; flex-direction: column; gap: 0;
    position: absolute; left: 0; right: 0; top: 64px;
    background: rgba(1, 14, 27, 0.97); border-bottom: 1px solid var(--line);
    padding: var(--s3) var(--pad) var(--s5);
    /* clip, not display:none, so the transition can run; and inset(0 0 100% 0)
       so nothing off-canvas inflates scrollWidth. */
    clip-path: inset(0 0 100% 0); visibility: hidden;
    transition: clip-path 260ms cubic-bezier(0.23, 1, 0.32, 1), visibility 0s 260ms;
  }
  .top nav a { display: block; padding: 14px 0; font-size: var(--f-b); border-bottom: 1px solid var(--line-2); }
  .top nav a:last-of-type { border-bottom: 0; }
  .menu__box:checked ~ nav { clip-path: inset(0); visibility: visible; transition-delay: 0s, 0s; }
  .top nav .menu__cta { display: block; margin-top: var(--s4); text-align: center; padding: 14px 20px; border-radius: 999px; border: 0; background: var(--cyan); color: #032027; font-weight: 600; text-decoration: none; }
}
@media (min-width: 860px) {
  .menu__btn, .menu__only, .menu__cta { display: none; }
}

/* ---- 17b. Page head: every sub-page opens the same way ---------------- */
.ph { padding-block: clamp(56px, 8vw, 120px) clamp(40px, 5vw, 72px); }
.ph h1 { font-family: Fraunces, serif; font-weight: 340; font-size: var(--f-h2); line-height: 1.04; letter-spacing: -0.015em; margin: var(--s4) 0 0; max-width: 20ch;
  font-variation-settings: "opsz" 144, "SOFT" 30, "WONK" 0; }
.ph h1 .hl { color: var(--cyan); font-style: normal; }
.ph .lead { margin-top: var(--s5); max-width: var(--measure); color: var(--paper-2); }
.ph--shot { display: grid; gap: var(--s7); align-items: end; }
.ph--shot figure { margin: 0; border-radius: var(--radius); overflow: hidden; }
.ph--shot img { width: 100%; height: auto; }
@media (min-width: 900px) {
  .ph--shot { grid-template-columns: 1.1fr 0.9fr; }
}
.ph--big h1 { font-size: var(--f-h1); font-weight: 300; max-width: 14ch; }

/* ---- 17c. Prose + spec ------------------------------------------------ */
.sec { padding-block: clamp(40px, 5.5vw, 88px); border-top: 1px solid var(--line-2); }
.sec h2 { font-family: Fraunces, serif; font-weight: 380; font-size: var(--f-h3); line-height: 1.15; margin: 0 0 var(--s5); letter-spacing: -0.01em;
  font-variation-settings: "opsz" 72, "SOFT" 20; }
.sec h2 b { font-weight: 700; }
.sec p, .sec li { max-width: var(--measure); }
.sec p { margin: 0 0 var(--s4); color: var(--paper-2); }
.sec p:last-child { margin-bottom: 0; }
.sec p strong { color: var(--paper); font-weight: 600; }
.two { display: grid; gap: var(--s6); align-items: start; }
@media (min-width: 900px) { .two { grid-template-columns: minmax(0, 0.42fr) minmax(0, 0.58fr); gap: var(--s9); } .two > h2 { margin-bottom: 0; } }
.two--flip > figure { order: -1; }
@media (min-width: 900px) { .two--pic { grid-template-columns: minmax(0,1fr) minmax(0,1fr); align-items: center; } }
.two figure { margin: 0; }
.two figure img { width: 100%; height: auto; border-radius: var(--radius); }
.two figcaption { font-size: var(--f-s); color: var(--paper-3); margin-top: var(--s3); }

.spec { display: grid; margin: 0; border-top: 1px solid var(--line); }
.spec > div { display: grid; grid-template-columns: minmax(0, 11rem) minmax(0, 1fr); gap: var(--s4); padding: var(--s4) 0; border-bottom: 1px solid var(--line-2); }
.spec dt { color: var(--paper); font-weight: 600; font-size: var(--f-s); }
.spec dd { margin: 0; color: var(--paper-2); }
@media (max-width: 560px) { .spec > div { grid-template-columns: 1fr; gap: var(--s1); } }
.spec--icons dt { display: flex; align-items: center; gap: 10px; }
.spec--icons dt i { width: 10px; height: 10px; border-radius: 50%; background: var(--dot, var(--cyan)); flex: none; }

/* ---- 17d. Numbers, route, steps, cards -------------------------------- */
.nums { display: grid; grid-template-columns: 1fr 1fr; gap: var(--s5); }
@media (min-width: 760px) { .nums { grid-template-columns: repeat(4, 1fr); } }
.nums > div { border-top: 1px solid var(--line); padding-top: var(--s4); }
.nums b { display: block; font-family: Fraunces, serif; font-weight: 300; font-size: var(--f-h1); line-height: 1; letter-spacing: -0.03em; color: var(--paper);
  font-variation-settings: "opsz" 144, "SOFT" 40; }
.nums b small { font-size: 0.4em; color: var(--cyan); margin-left: 2px; font-weight: 400; }
.nums span { display: block; margin-top: var(--s2); color: var(--paper-2); font-size: var(--f-s); }

.route { list-style: none; margin: 0; padding: 0; position: relative; counter-reset: st; }
.route li { position: relative; padding: 0 0 var(--s6) 56px; counter-increment: st; }
.route li::before { content: counter(st, decimal-leading-zero); position: absolute; left: 0; top: 2px; width: 36px; height: 36px; border-radius: 50%; border: 1px solid var(--cyan); color: var(--cyan); display: grid; place-items: center; font-size: var(--f-xs); font-weight: 600; letter-spacing: 0.06em; background: var(--g1); z-index: 1; }
.route li::after { content: ""; position: absolute; left: 18px; top: 40px; bottom: 0; width: 1px; background: linear-gradient(180deg, var(--cyan), rgba(60,208,207,0.12)); }
.route li:last-child::after { display: none; }
.route li:last-child { padding-bottom: 0; }
.route h3 { margin: 0 0 var(--s1); font-size: var(--f-b); font-weight: 600; font-family: Figtree, sans-serif; color: var(--paper); }
.route p { margin: 0; color: var(--paper-2); }
@supports (animation-timeline: view()) {
  @media (prefers-reduced-motion: no-preference) {
    .route li::after { transform-origin: top; animation: fill linear both; animation-timeline: view(); animation-range: entry 30% entry 90%; }
  }
}

.steps { display: grid; gap: var(--s5); counter-reset: s; list-style: none; margin: 0; padding: 0; }
@media (min-width: 760px) { .steps { grid-template-columns: repeat(3, 1fr); } }
.steps li { counter-increment: s; border-top: 1px solid var(--line); padding-top: var(--s4); }
.steps li::before { content: counter(s); display: block; font-family: Fraunces, serif; font-size: var(--f-h2); font-weight: 300; color: var(--cyan); line-height: 1; margin-bottom: var(--s3); font-variation-settings: "opsz" 144; }
.steps h3 { margin: 0 0 var(--s2); font-size: var(--f-b); font-weight: 600; font-family: Figtree, sans-serif; }
.steps p { margin: 0; color: var(--paper-2); }

.trio { display: grid; gap: var(--s4); list-style: none; margin: 0; padding: 0; }
@media (min-width: 640px) { .trio { grid-template-columns: repeat(3, 1fr); } }
.trio li { border: 1px solid var(--line); border-radius: var(--radius); padding: var(--s5); background: rgba(236,243,247,0.02); }
.trio li i { display: block; width: 28px; height: 28px; border-radius: 50%; background: var(--dot, var(--cyan)); margin-bottom: var(--s4); box-shadow: 0 0 0 6px color-mix(in srgb, var(--dot, var(--cyan)) 18%, transparent); }
.trio h3 { margin: 0 0 var(--s1); font-family: Fraunces, serif; font-weight: 400; font-size: var(--f-h3); font-variation-settings: "opsz" 72; }
.trio p { margin: 0; color: var(--paper-2); }
.trio--photo li i { display: none; }
.trio__img { display: block; width: 100%; height: auto; aspect-ratio: 1 / 1; object-fit: cover; border-radius: calc(var(--radius) - 4px); margin-bottom: var(--s4); background: #fff; }
/* Phone: a full-width square per scent made the trio three screens tall.
   Photo left, name right, so all three fit in about one screen. */
@media (max-width: 639px) {
  .trio--photo li { display: grid; grid-template-columns: 112px 1fr; column-gap: var(--s4); align-items: center; padding: var(--s3); }
  .trio--photo .trio__img { grid-row: span 2; margin: 0; }
  .trio--photo h3 { align-self: end; }
  .trio--photo p { align-self: start; }
}

/* ---- 17e. FAQ: <details>, no script ----------------------------------- */
.faq { border-top: 1px solid var(--line); }
.faq details { border-bottom: 1px solid var(--line-2); }
.faq summary { list-style: none; cursor: pointer; display: flex; justify-content: space-between; gap: var(--s4); align-items: baseline; padding: var(--s4) 0; font-weight: 600; color: var(--paper); }
.faq summary::-webkit-details-marker { display: none; }
.faq summary::after { content: "+"; color: var(--cyan); font-family: Figtree, sans-serif; font-size: 1.4rem; line-height: 1; flex: none; transition: transform 200ms; }
.faq details[open] summary::after { transform: rotate(45deg); }
.faq details > p { margin: 0 0 var(--s5); color: var(--paper-2); max-width: var(--measure); }

/* ---- 17f. Forms: booking + contact ------------------------------------ */
.form { max-width: 640px; }
.form fieldset { border: 0; padding: 0; margin: 0 0 var(--s7); min-width: 0; }
.form legend { font-family: Fraunces, serif; font-size: var(--f-h3); font-weight: 380; padding: 0; margin-bottom: var(--s4); font-variation-settings: "opsz" 72; }
.chips { display: flex; flex-wrap: wrap; gap: var(--s2); }
.chips label { position: relative; }
.chips input { position: absolute; inset: 0; opacity: 0; margin: 0; }
.chips span { display: inline-flex; align-items: center; min-height: 44px; padding: 8px 18px; border-radius: 999px; border: 1px solid var(--line); color: var(--paper-2); cursor: pointer; transition: border-color 160ms, color 160ms, background 160ms; }
.chips input:checked + span { border-color: var(--cyan); color: var(--cyan); background: rgba(60,208,207,0.08); }
.chips input:focus-visible + span { outline: 2px solid var(--cyan); outline-offset: 3px; }
.fields { display: grid; gap: var(--s4); }
@media (min-width: 620px) { .fields { grid-template-columns: 1fr 1fr; } .fields .full { grid-column: 1 / -1; } }
.form label.f { display: block; font-size: var(--f-s); color: var(--paper-2); }
.form input[type="text"], .form input[type="tel"], .form input[type="email"], .form textarea {
  display: block; width: 100%; margin-top: var(--s2); min-height: 48px; padding: 12px 14px;
  background: rgba(236,243,247,0.04); border: 1px solid var(--line); border-radius: 10px;
  color: var(--paper); font: inherit; font-size: var(--f-b);
}
.form textarea { resize: vertical; min-height: 110px; }
.form input:focus, .form textarea:focus { outline: 2px solid var(--cyan); outline-offset: 0; border-color: transparent; }
.form .note { font-size: var(--f-s); color: var(--paper-3); margin: var(--s3) 0 0; }
.hp { position: absolute; clip-path: inset(50%); width: 1px; height: 1px; overflow: hidden; white-space: nowrap; }
.form__msg { display: none; margin-top: var(--s5); padding: var(--s5); border-radius: var(--radius); border: 1px solid var(--line); }
.form__msg.is-on { display: block; }
.form__msg--ok { border-color: var(--cyan); }
.form__msg--err { border-color: var(--hr-1530); }
.form__msg p { margin: 0 0 var(--s2); }
.form__msg b { font-family: Fraunces, serif; font-size: var(--f-lead); font-weight: 400; }

/* ---- 17g. Contact dials ------------------------------------------------ */
.dials { display: grid; gap: var(--s4); list-style: none; padding: 0; margin: 0; }
@media (min-width: 760px) { .dials { grid-template-columns: repeat(3, 1fr); } }
.dials li { border: 1px solid var(--line); border-radius: var(--radius); padding: var(--s5); }
.dials small { display: block; font-size: var(--f-xs); letter-spacing: 0.12em; text-transform: uppercase; color: var(--paper-3); margin-bottom: var(--s2); }
.dials a, .dials span.v { display: inline-block; min-height: 44px; font-family: Fraunces, serif; font-size: var(--f-h3); font-weight: 400; color: var(--paper); text-decoration: none; line-height: 1.25; }
.dials a { text-decoration: underline; text-decoration-color: rgba(60,208,207,0.5); text-underline-offset: 6px; }
@media (hover: hover) and (pointer: fine) { .dials a:hover { color: var(--cyan); } }

/* ---- 17h. Next step + the Luna sheet ---------------------------------- */
.next { border-top: 1px solid var(--line-2); padding-block: clamp(56px, 8vw, 128px); }
.next .lead { max-width: 30ch; }
.next .btn { margin-top: var(--s6); }

.sheet {
  position: fixed; z-index: 50; left: var(--pad); right: var(--pad); bottom: var(--pad);
  max-width: 440px; margin-left: auto;
  background: var(--plate); border: 1px solid var(--line); border-radius: var(--radius);
  padding: var(--s5); box-shadow: 0 30px 60px rgba(0,0,0,0.45);
  transform: translateY(calc(100% + var(--pad) + 10px));
  transition: transform 520ms cubic-bezier(0.23, 1, 0.32, 1);
  visibility: hidden;
}
.sheet.is-on { transform: none; visibility: visible; }
.sheet h2 { font-family: Fraunces, serif; font-weight: 400; font-size: var(--f-h3); margin: 0 var(--s7) var(--s3) 0; line-height: 1.15; font-variation-settings: "opsz" 72; }
.sheet p { margin: 0 0 var(--s4); color: var(--paper-2); font-size: var(--f-s); }
.sheet .btn { width: 100%; justify-content: center; }
.sheet__x { position: absolute; top: 10px; right: 10px; width: 44px; height: 44px; border: 0; background: transparent; color: var(--paper-2); font-size: 1.5rem; cursor: pointer; border-radius: 8px; line-height: 1; }
@media (prefers-reduced-motion: reduce) { .sheet { transition: none; } }

.thin { border: 1px dashed var(--line); border-radius: var(--radius); padding: var(--s5); color: var(--paper-2); max-width: var(--measure); }
.thin b { color: var(--paper); }
.video { border-radius: var(--radius); overflow: hidden; background: #000; }
.video video { width: 100%; height: auto; display: block; }

/* ---- 17i. Legal prose: the client's own text, set to be read ---------- */
.legal h2 { margin-top: var(--s7); }
.legal h2:first-child { margin-top: 0; }
.legal ul { padding-left: 1.2em; color: var(--paper-2); margin: 0 0 var(--s4); }
.legal li { margin-bottom: var(--s2); }
.legal .spec { margin-bottom: var(--s6); }
.form__msg .lede { margin: 0 0 var(--s3); color: var(--paper-2); }

/* ---- 17j. Hit boxes. Every link in a list or the chrome gets a 44px box
   without moving the type: padding grows the target, the negative margin
   hands the space back. Measured on the full site walk, 2026-09-17. ---- */
.top nav a, .foot li a, .foot__legal a, .close__alt a, .route h3 a, .sec p a, .brand {
  display: inline-block; padding: 12px 0; margin: -12px 0;
}
.brand { display: inline-flex; padding: 6px 0; margin: -6px auto -6px 0; min-height: 44px; }
.brand--foot { min-height: 44px; }
@media (min-width: 860px) { .top nav a { padding: 11px 0; margin: -11px 0; } }
@media (max-width: 859.98px) { .top nav a { display: block; padding: 14px 0; margin: 0; } }
/* the safety-mark plate is light; its caption must be ink, not paper */
.two .markbox figcaption, .markbox figcaption { color: #24333d; }
.two .markbox figcaption strong { color: #0b1a24; }
/* small sources are shown small: no image is stretched past 1.5x at DPR2 */
img[src$="replacement.jpg"] { max-width: 420px; }
img[src$="install-new.jpg"] { max-width: 500px; }
@media (min-width: 860px) { .top nav a { padding: 11px 6px; margin: -11px -6px; } }
@media (min-width: 860px) { .top nav a.menu__cta, .top nav a.menu__only { display: none; } }
.ph--shot { align-items: center; }
@media (max-width: 859.98px) { .top nav { background: var(--g0); } }

/* ======================================================================
   18. PROFESSIONAL IMAGES ONLY + THE CAMERA (2026-09-17, Marxk).
   The phone photographs and the pastel drawings are gone. What remains is
   the client's render set: two studio renders (floor lifted, shadow kept),
   the cutaway, the coil macro, the cartridge render, the panel graphic and
   the safety mark. Rules below override sections 6, 8, 9 and 11 where the
   asset changed; the earlier rules stay as history of why.
   ====================================================================== */

/* ---- 18a. Hero: object on the ground, no photograph, no scrim -------- */
.hero__shot { display: none; }
.hero { display: block; min-height: 0; }
.hero__in {
  display: grid; gap: var(--s6); align-items: center;
  padding-block: clamp(28px, 5vw, 64px) clamp(24px, 4vw, 56px);
  min-height: 0;
}
.hero__obj { position: relative; isolation: isolate; }
.hero__obj::before {
  /* the machine's own spout glow, widened into a floor light. Colour is
     the client's cyan; nothing introduced. */
  content: ""; position: absolute; z-index: -1; left: 10%; right: 10%; bottom: 4%; height: 46%;
  background: radial-gradient(ellipse at 50% 100%, rgba(60, 208, 207, 0.22), rgba(60, 208, 207, 0.06) 45%, transparent 72%);
  filter: blur(6px);
}
.hero__obj img { width: 100%; height: auto; display: block; }
@media (max-width: 899px) {
  .hero__in { grid-template-rows: auto auto; }
  .hero__obj { order: -1; margin-inline: -4%; }
  .hero__cta { margin-top: var(--s6); }
}
@media (min-width: 900px) {
  .hero__in {
    grid-template-columns: minmax(0, 0.44fr) minmax(0, 0.56fr);
    gap: clamp(32px, 4vw, 72px);
    min-height: min(84vh, 800px);
    padding-block: clamp(40px, 5vw, 72px);
  }
  .hero__copy { max-width: 32rem; }
  .hero__obj { margin-right: -6%; }
}
@supports (animation-timeline: view()) {
  @media (prefers-reduced-motion: no-preference) {
    /* the object settles as the page opens: transform only, ends at rest */
    .hero__obj img { animation: obj-in 1100ms cubic-bezier(0.23, 1, 0.32, 1) 80ms backwards; }
    @keyframes obj-in { from { transform: translateY(28px) scale(0.985); } }
  }
}

/* ---- 18b. 180mm on the render ------------------------------------------ */
.size__shot--obj { border: 0; border-radius: 0; overflow: visible; background: none; }
.size__shot--obj img { width: 100%; height: auto; }
.size__shot--obj .size__dim { left: 31.0%; width: 37.6%; top: -0.6%; }

/* ---- 18c. Objects and plates on sub-pages ----------------------------- */
.ph--shot figure { overflow: visible; }
img.obj { border-radius: 0; }
.ph--shot figure:has(img.obj) { position: relative; isolation: isolate; }
.ph--shot figure:has(img.obj)::before {
  content: ""; position: absolute; z-index: -1; left: 12%; right: 12%; bottom: 6%; height: 40%;
  background: radial-gradient(ellipse at 50% 100%, rgba(60, 208, 207, 0.2), transparent 70%);
  filter: blur(6px);
}
img.plate { background: #f4f1ea; border-radius: var(--radius); padding: var(--s4); }

/* ---- 18d. Showroom: three steps instead of a photograph we don't have - */
.show__grid { grid-template-columns: 1fr; }
@media (min-width: 940px) {
  .show > .wrap { width: min(100% - 2 * var(--pad), 1240px); max-width: 1240px; }
  .show__grid { grid-template-columns: minmax(0, 0.56fr) minmax(0, 0.44fr); }
  .show__body { padding-right: 0; }
}
.show__steps { margin-top: var(--s2); }
.show__steps li { padding-left: 64px; }
.show__steps li::before { width: 44px; height: 44px; font-size: var(--f-s); }
.show__steps li::after { left: 22px; top: 48px; }
.show__steps h3 { font-family: Fraunces, serif; font-weight: 400; font-size: var(--f-h3); font-variation-settings: "opsz" 72; }

/* ---- 18e. THE CAMERA ---------------------------------------------------
   A tall scroller (.cam) with a sticky stage inside it. The stage holds a
   3:2 view of the cutaway inside a frame that the scroll position drives:
   scale + translate, transform only, so it stays on the compositor. The
   coil macro is a second image that takes the frame during beat two. Four
   text beats stack in one cell and cross-fade by the same timeline.

   The fallback IS the design when it cannot scrub: no pin, no height,
   view then four cards. Same words, same picture, no motion.
   --------------------------------------------------------------------- */
.cam__stage { display: grid; gap: var(--s6); align-items: center; }
.cam__view {
  position: relative; overflow: hidden; border-radius: var(--radius);
  border: 1px solid var(--line-2); background: #061423; aspect-ratio: 3 / 2;
}
.cam__frame { position: absolute; inset: 0; transform-origin: 0 0; }
.cam__frame img { width: 100%; height: 100%; object-fit: cover; display: block; }
.cam__coil { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; opacity: 0; }
.cam__dark { position: absolute; inset: 0; background: rgba(1, 10, 22, 0.72); opacity: 0; pointer-events: none; }
.cam__dots { position: absolute; left: var(--s4); bottom: var(--s4); display: flex; gap: 8px; margin: 0; padding: 0; list-style: none; }
.cam__dots li { width: 8px; height: 8px; border-radius: 50%; background: rgba(236,243,247,0.25); }
.cam__text { position: relative; }
.cam__beat { }
.cam__k { font-size: var(--f-xs); letter-spacing: 0.14em; text-transform: uppercase; color: var(--cyan); font-weight: 600; margin: 0 0 var(--s3); }
.cam__beat h3 { font-family: Fraunces, serif; font-weight: 380; font-size: var(--f-h3); line-height: 1.12; margin: 0 0 var(--s3); font-variation-settings: "opsz" 72, "SOFT" 20; }
.cam__beat p:last-child { margin: 0; color: var(--paper-2); }
.cam__after { margin-top: var(--s5); }
/* the rings from section 9 stay full-opacity in the fallback */
.cam .ring { opacity: 1; }

/* fallback layout: view on top, four cards under it */
.cam__text { display: grid; gap: var(--s4); }
.cam__beat { border: 1px solid var(--line-2); border-radius: 12px; padding: var(--s5); background: rgba(3, 20, 36, 0.6); }
@media (min-width: 620px) { .cam__text { grid-template-columns: 1fr 1fr; } }

@supports (animation-timeline: view()) {
  @media (prefers-reduced-motion: no-preference) and (min-width: 700px) {
    .cam { height: 420vh; view-timeline-name: --cam; view-timeline-axis: block; }
    .cam__stage {
      position: sticky; top: 0; height: 100vh; box-sizing: border-box;
      padding-block: calc(64px + var(--s5)) var(--s6);
      grid-template-columns: minmax(0, 0.36fr) minmax(0, 0.64fr);
      gap: clamp(28px, 4vw, 64px);
    }
    .cam__view { max-height: calc(100vh - 64px - var(--s5) - var(--s6)); width: 100%; }
    .cam__text { display: grid; grid-template-columns: 1fr; }
    .cam__beat { grid-area: 1 / 1; border: 0; padding: 0; background: none; opacity: 0; transform: translateY(18px); }
    .cam__after { display: none; }

    .cam__frame, .cam__coil, .cam__dark, .cam__beat, .cam .ring, .cam__dots li {
      animation-timeline: --cam;
      animation-range: contain 0% contain 100%;
      animation-fill-mode: both;
      animation-timing-function: linear;
    }
    /* THE CAMERA MOVE. To centre point p at scale s the frame translates
       50% - p*s*100% of its own size. Cartridge (0.37, 0.46) @1.9, coil
       (0.57, 0.50) @2.2, tank (0.66, 0.52) @2.0, then wide. */
    .cam__frame { animation-name: cam-move; }
    @keyframes cam-move {
      0%        { transform: translate(0, 0) scale(1); }
      14%, 30%  { transform: translate(-20.3%, -37.4%) scale(1.9); }
      42%, 56%  { transform: translate(-75.4%, -60%) scale(2.2); }
      66%, 80%  { transform: translate(-82%, -54%) scale(2); }
      92%, 100% { transform: translate(0, 0) scale(1); }
    }
    .cam__coil { animation-name: cam-coil; }
    @keyframes cam-coil { 0%, 44% { opacity: 0; } 50%, 54% { opacity: 1; } 60%, 100% { opacity: 0; } }
    .cam__dark { animation-name: cam-dark; }
    @keyframes cam-dark { 0%, 90% { opacity: 0; } 97%, 100% { opacity: 1; } }
    .cam .ring { opacity: 0.15; }
    .cr1 { animation-name: cr-1; } .cr2 { animation-name: cr-2; } .cr3 { animation-name: cr-3; } .cr4 { animation-name: cr-4; }
    @keyframes cr-1 { 0%, 10% { opacity: 0.15; } 16%, 30% { opacity: 1; } 38%, 100% { opacity: 0.15; } }
    @keyframes cr-2 { 0%, 38% { opacity: 0.15; } 44%, 46% { opacity: 1; } 50%, 100% { opacity: 0.15; } }
    @keyframes cr-3 { 0%, 62% { opacity: 0.15; } 68%, 80% { opacity: 1; } 88%, 100% { opacity: 0.15; } }
    @keyframes cr-4 { 0%, 90% { opacity: 0.15; } 97%, 100% { opacity: 1; } }
    .cb1 { animation-name: cb-1; } .cb2 { animation-name: cb-2; } .cb3 { animation-name: cb-3; } .cb4 { animation-name: cb-4; }
    @keyframes cb-1 { 0%, 4% { opacity: 0; transform: translateY(18px); } 10%, 30% { opacity: 1; transform: none; } 36%, 100% { opacity: 0; transform: translateY(-18px); } }
    @keyframes cb-2 { 0%, 36% { opacity: 0; transform: translateY(18px); } 42%, 56% { opacity: 1; transform: none; } 62%, 100% { opacity: 0; transform: translateY(-18px); } }
    @keyframes cb-3 { 0%, 62% { opacity: 0; transform: translateY(18px); } 68%, 82% { opacity: 1; transform: none; } 88%, 100% { opacity: 0; transform: translateY(-18px); } }
    @keyframes cb-4 { 0%, 88% { opacity: 0; transform: translateY(18px); } 94%, 100% { opacity: 1; transform: none; } }
    .cd1 { animation-name: cd-1; } .cd2 { animation-name: cd-2; } .cd3 { animation-name: cd-3; } .cd4 { animation-name: cd-4; }
    @keyframes cd-1 { 0%, 4% { background: rgba(236,243,247,0.25); } 10%, 30% { background: var(--cyan); } 36%, 100% { background: rgba(236,243,247,0.25); } }
    @keyframes cd-2 { 0%, 36% { background: rgba(236,243,247,0.25); } 42%, 56% { background: var(--cyan); } 62%, 100% { background: rgba(236,243,247,0.25); } }
    @keyframes cd-3 { 0%, 62% { background: rgba(236,243,247,0.25); } 68%, 82% { background: var(--cyan); } 88%, 100% { background: rgba(236,243,247,0.25); } }
    @keyframes cd-4 { 0%, 88% { background: rgba(236,243,247,0.25); } 94%, 100% { background: var(--cyan); } }
  }
}

/* glow: a soft radial with no blur filter, so it never shows a box edge */
.hero__obj::before, .ph--shot figure:has(img.obj)::before {
  filter: none; left: -10%; right: -10%; bottom: -12%; height: 70%;
  background: radial-gradient(ellipse 50% 50% at 50% 75%, rgba(60, 208, 207, 0.20), rgba(60, 208, 207, 0.05) 45%, transparent 68%);
}
.hero__obj img, img.obj { position: relative; z-index: 1; }
.hero__obj::before, .ph--shot figure:has(img.obj)::before { left: 0; right: 0; bottom: 0; height: 60%; }
.hero__obj, .ph--shot figure:has(img.obj) { overflow: hidden; }
@media (max-width: 899px) { .hero__obj { margin-inline: 0; } }
@supports (animation-timeline: view()) {
  @media (prefers-reduced-motion: no-preference) and (min-width: 700px) {
    /* the picture takes the wide column, the words the narrow one */
    .cam__stage { grid-template-columns: minmax(0, 0.34fr) minmax(0, 0.66fr); }
    .cam__view { order: 2; }
    .cam__text { order: 1; }
    @keyframes cam-move {
      0%        { transform: translate(0, 0) scale(1); }
      14%, 30%  { transform: translate(-20.3%, -37.4%) scale(1.9); }
      42%, 56%  { transform: translate(-75.4%, -60%) scale(2.2); }
      66%, 80%  { transform: translate(-97.2%, -69.6%) scale(2.3); }
      92%, 100% { transform: translate(0, 0) scale(1); }
    }
  }
}

/* ---- 18g. THE PANEL'S OWN ICONS, with light touches (Marxk, 09-17:
   "play with the icons from the device so it becomes fun and interactive",
   "hot water can also steam", "light touches"). The icons are the client's
   vector masters (Lcd Panel & Icon/*.ai), rendered once at 240px. Each
   moment on the day rail carries its hour's icon; a hover on a real
   pointer plays one small thing that the icon would do: steam rises off
   the hot mug, drops run down the cold glass, the bottle tips, the lock
   glows, the tea leaf settles, the night drop falls in. Nothing loops
   unattended; where the vertical rail scrolls, the same touch is scrubbed
   by the moment's own arrival. ------------------------------------------ */
.moment__body { position: relative; padding-left: 64px; min-height: 52px; }
.moment__icon { position: absolute; left: 0; top: -4px; width: 48px; height: 48px; }
.moment__icon img { width: 100%; height: 100%; display: block; position: relative; z-index: 1;
  filter: drop-shadow(0 4px 10px rgba(0, 0, 0, 0.5)); }
.moment__icon::before, .moment__icon::after { content: ""; position: absolute; opacity: 0; pointer-events: none; }
/* steam: two wisps above the hot and tea mugs */
.moment__icon--hot::before, .moment__icon--hot::after,
.moment__icon--tea::before, .moment__icon--tea::after {
  left: 18px; top: -2px; width: 3px; height: 12px; border-radius: 3px;
  background: linear-gradient(180deg, rgba(236,243,247,0.9), rgba(236,243,247,0));
  filter: blur(0.6px);
}
.moment__icon--hot::after, .moment__icon--tea::after { left: 27px; top: -6px; height: 10px; }
/* condensation: two drops on the cold glass */
.moment__icon--cold::before, .moment__icon--cold::after {
  left: 10px; top: 14px; width: 4px; height: 6px; border-radius: 50% 50% 60% 60%;
  background: rgba(200, 240, 255, 0.95); z-index: 2;
}
.moment__icon--cold::after { left: 34px; top: 10px; }
/* lock: its own glow */
.moment__icon--lock::before { inset: 4px; border-radius: 50%; background: radial-gradient(circle, rgba(255,140,60,0.55), transparent 65%); z-index: 0; }

@media (prefers-reduced-motion: no-preference) {
  .moment__icon img { transition: transform 420ms cubic-bezier(0.22, 1, 0.36, 1); }
  @keyframes steam-a { 0% { opacity: 0; transform: translateY(6px) scaleY(0.6); } 35% { opacity: 0.9; } 100% { opacity: 0; transform: translateY(-16px) scaleY(1.2); } }
  @keyframes steam-b { 0% { opacity: 0; transform: translateY(6px) scaleY(0.6); } 45% { opacity: 0.7; } 100% { opacity: 0; transform: translateY(-14px) scaleY(1.1) translateX(2px); } }
  @keyframes drip { 0% { opacity: 0; transform: translateY(-4px); } 25% { opacity: 1; } 100% { opacity: 0; transform: translateY(20px); } }
  @keyframes tip  { 0% { transform: rotate(0); } 40% { transform: rotate(-12deg) translateY(-2px); } 100% { transform: rotate(0); } }
  @keyframes glow { 0% { opacity: 0; } 50% { opacity: 1; } 100% { opacity: 0.35; } }
  @keyframes fall { 0% { transform: translateY(-10px); opacity: 0.4; } 60% { transform: translateY(2px); opacity: 1; } 100% { transform: translateY(0); } }
  @keyframes settle { 0% { transform: rotate(0); } 30% { transform: rotate(6deg); } 70% { transform: rotate(-4deg); } 100% { transform: rotate(0); } }
  @media (hover: hover) and (pointer: fine) {
    .moment:hover .moment__icon img { transform: translateY(-3px) scale(1.06); }
    .moment:hover .moment__icon--hot::before, .moment:hover .moment__icon--tea::before { animation: steam-a 1500ms ease-out 2; }
    .moment:hover .moment__icon--hot::after,  .moment:hover .moment__icon--tea::after  { animation: steam-b 1500ms ease-out 250ms 2; }
    .moment:hover .moment__icon--cold::before { animation: drip 1300ms ease-in 2; }
    .moment:hover .moment__icon--cold::after  { animation: drip 1300ms ease-in 400ms 2; }
    .moment:hover .moment__icon--warm img { animation: tip 900ms ease-in-out 1; }
    .moment:hover .moment__icon--lock::before { animation: glow 1200ms ease-in-out 1 forwards; }
    .moment:hover .moment__icon--drop img { animation: fall 700ms cubic-bezier(0.22, 1, 0.36, 1) 1; }
    .moment:hover .moment__icon--tea img  { animation: settle 1100ms ease-in-out 1; }
  }
  /* vertical rail: the touch plays once as the moment arrives, driven by scroll */
  @supports (animation-timeline: view()) {
    @media (max-width: 899px) {
      .moment__icon--hot::before, .moment__icon--tea::before { animation: steam-a linear both; animation-timeline: view(); animation-range: entry 30% entry 100%; }
      .moment__icon--hot::after,  .moment__icon--tea::after  { animation: steam-b linear both; animation-timeline: view(); animation-range: entry 45% cover 15%; }
      .moment__icon--cold::before { animation: drip linear both; animation-timeline: view(); animation-range: entry 30% entry 100%; }
      .moment__icon--cold::after  { animation: drip linear both; animation-timeline: view(); animation-range: entry 50% cover 20%; }
      .moment__icon--lock::before { animation: glow linear both; animation-timeline: view(); animation-range: entry 20% cover 40%; }
      .moment__icon--warm img { animation: tip linear both; animation-timeline: view(); animation-range: entry 20% cover 30%; }
      .moment__icon--drop img { animation: fall linear both; animation-timeline: view(); animation-range: entry 10% entry 90%; }
    }
  }
}
/* the Luna page icon table uses the same masters instead of coloured dots */
.spec--icons dt img { width: 36px; height: 36px; flex: none; filter: drop-shadow(0 2px 6px rgba(0,0,0,0.5)); }
/* the masters carry the panel's own black plate; keep it and let it read as
   a tile of the screen, not a broken image: panel corners, a hairline edge */
.moment__icon img, .spec--icons dt img { border-radius: 10px; box-shadow: inset 0 0 0 1px rgba(255,255,255,0.08); }
.spec--icons dt img { border-radius: 8px; }

/* ======================================================================
   19. IMAGERY + WATER PASS (2026-09-23). Specs: docs/team/imagery-pass/
   (BUILD-PLAN, mei-shotlist, rex-review, mei-motion). Overrides above.
   ====================================================================== */

/* ---- 19a. Hero stack + the phone cap (Rex blocking #3) ----------------
   The stack IS the image box (aspect-ratio 1400/1426). It was originally
   here so the POUR's per-cent geometry would land on the render's own
   spout at every width — the pour is gone now (19c deleted 2026-10-18),
   but the hero itself is unchanged and still wants this box: it is the
   shape of luna-angle-hero.webp. At < 900 it is capped at 250px tall so
   the CTA sits above the fold. */
.hero__stack { position: relative; aspect-ratio: 1400 / 1426; }
.hero__stack > img { width: 100%; height: 100%; display: block; }
@media (max-width: 899px) {
  .hero__stack { height: 250px; width: auto; margin-inline: auto; }
  .hero__in { gap: var(--s5); }
}

/* short phones (360x740 class): the fold is 100px higher, so the cap is too */
@media (max-width: 899px) and (max-height: 780px) { .hero__stack { height: 196px; } }

/* ---- 19d. W3 THE TIDE (mei-motion §3) ---------------------------------
   Sits UNDER everything in #day and the hero (z 0), rises -60vh over the
   first viewport of #day's travel (surface on screen ~1.9x page speed),
   fades at 80-100%. The sticky pin is its own stacking context, so the
   body grades to --g1 and meets the pin's top edge without a seam; the
   tide has faded before the pin engages. Default = still waterline. */
.hero { z-index: 1; }
.day__scroll { position: relative; z-index: 1; }
#day { view-timeline-name: --tide; view-timeline-axis: block; }
.tide { position: absolute; left: 0; right: 0; top: -22px; height: 48px; z-index: 0; pointer-events: none; overflow: hidden; }
.tide > span, .tide > i { position: absolute; display: block; }
.tide__front, .tide__back { left: 0; right: 0; top: 0; height: 48px; }
.tide__back { top: 10px; opacity: 0.35; display: none; }
.tide__front i, .tide__back i { position: absolute; top: 0; bottom: 0; left: 0; width: calc(100% + 640px); display: block; }
.tide__front i { background: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='480' height='48' viewBox='0 0 480 48'%3E%3Cdefs%3E%3ClinearGradient id='h' x1='0' y1='0' x2='0' y2='1'%3E%3Cstop offset='0' stop-color='rgb%2860%2C208%2C207%29' stop-opacity='.18'/%3E%3Cstop offset='.6' stop-color='rgb%2860%2C208%2C207%29' stop-opacity='0'/%3E%3C/linearGradient%3E%3C/defs%3E%3Cpath d='M0 20.0 L8 18.5 L16 17.1 L24 15.7 L32 14.3 L40 13.0 L48 11.8 L56 10.6 L64 9.6 L72 8.7 L80 7.9 L88 7.2 L96 6.7 L104 6.3 L112 6.1 L120 6.0 L128 6.1 L136 6.3 L144 6.7 L152 7.2 L160 7.9 L168 8.7 L176 9.6 L184 10.6 L192 11.8 L200 13.0 L208 14.3 L216 15.7 L224 17.1 L232 18.5 L240 20.0 L248 21.5 L256 22.9 L264 24.3 L272 25.7 L280 27.0 L288 28.2 L296 29.4 L304 30.4 L312 31.3 L320 32.1 L328 32.8 L336 33.3 L344 33.7 L352 33.9 L360 34.0 L368 33.9 L376 33.7 L384 33.3 L392 32.8 L400 32.1 L408 31.3 L416 30.4 L424 29.4 L432 28.2 L440 27.0 L448 25.7 L456 24.3 L464 22.9 L472 21.5 L480 20.0 L480 48 L0 48Z' fill='rgba%2810%2C55%2C80%2C.62%29'/%3E%3Cpath d='M0 20.0 L8 18.5 L16 17.1 L24 15.7 L32 14.3 L40 13.0 L48 11.8 L56 10.6 L64 9.6 L72 8.7 L80 7.9 L88 7.2 L96 6.7 L104 6.3 L112 6.1 L120 6.0 L128 6.1 L136 6.3 L144 6.7 L152 7.2 L160 7.9 L168 8.7 L176 9.6 L184 10.6 L192 11.8 L200 13.0 L208 14.3 L216 15.7 L224 17.1 L232 18.5 L240 20.0 L248 21.5 L256 22.9 L264 24.3 L272 25.7 L280 27.0 L288 28.2 L296 29.4 L304 30.4 L312 31.3 L320 32.1 L328 32.8 L336 33.3 L344 33.7 L352 33.9 L360 34.0 L368 33.9 L376 33.7 L384 33.3 L392 32.8 L400 32.1 L408 31.3 L416 30.4 L424 29.4 L432 28.2 L440 27.0 L448 25.7 L456 24.3 L464 22.9 L472 21.5 L480 20.0 L480 48 L0 48Z' fill='url%28%23h%29'/%3E%3Cpath d='M0 20.0 L8 18.5 L16 17.1 L24 15.7 L32 14.3 L40 13.0 L48 11.8 L56 10.6 L64 9.6 L72 8.7 L80 7.9 L88 7.2 L96 6.7 L104 6.3 L112 6.1 L120 6.0 L128 6.1 L136 6.3 L144 6.7 L152 7.2 L160 7.9 L168 8.7 L176 9.6 L184 10.6 L192 11.8 L200 13.0 L208 14.3 L216 15.7 L224 17.1 L232 18.5 L240 20.0 L248 21.5 L256 22.9 L264 24.3 L272 25.7 L280 27.0 L288 28.2 L296 29.4 L304 30.4 L312 31.3 L320 32.1 L328 32.8 L336 33.3 L344 33.7 L352 33.9 L360 34.0 L368 33.9 L376 33.7 L384 33.3 L392 32.8 L400 32.1 L408 31.3 L416 30.4 L424 29.4 L432 28.2 L440 27.0 L448 25.7 L456 24.3 L464 22.9 L472 21.5 L480 20.0' fill='none' stroke='rgba%28108%2C205%2C206%2C.85%29' stroke-width='2'/%3E%3C/svg%3E") repeat-x 0 0 / 480px 48px; }
.tide__back i { background: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='640' height='48' viewBox='0 0 640 48'%3E%3Cdefs%3E%3ClinearGradient id='h' x1='0' y1='0' x2='0' y2='1'%3E%3Cstop offset='0' stop-color='rgb%2860%2C208%2C207%29' stop-opacity='.18'/%3E%3Cstop offset='.6' stop-color='rgb%2860%2C208%2C207%29' stop-opacity='0'/%3E%3C/linearGradient%3E%3C/defs%3E%3Cpath d='M0 20.0 L8 19.2 L16 18.4 L24 17.7 L32 16.9 L40 16.2 L48 15.5 L56 14.8 L64 14.1 L72 13.5 L80 12.9 L88 12.4 L96 11.9 L104 11.5 L112 11.1 L120 10.8 L128 10.5 L136 10.3 L144 10.1 L152 10.0 L160 10.0 L168 10.0 L176 10.1 L184 10.3 L192 10.5 L200 10.8 L208 11.1 L216 11.5 L224 11.9 L232 12.4 L240 12.9 L248 13.5 L256 14.1 L264 14.8 L272 15.5 L280 16.2 L288 16.9 L296 17.7 L304 18.4 L312 19.2 L320 20.0 L328 20.8 L336 21.6 L344 22.3 L352 23.1 L360 23.8 L368 24.5 L376 25.2 L384 25.9 L392 26.5 L400 27.1 L408 27.6 L416 28.1 L424 28.5 L432 28.9 L440 29.2 L448 29.5 L456 29.7 L464 29.9 L472 30.0 L480 30.0 L488 30.0 L496 29.9 L504 29.7 L512 29.5 L520 29.2 L528 28.9 L536 28.5 L544 28.1 L552 27.6 L560 27.1 L568 26.5 L576 25.9 L584 25.2 L592 24.5 L600 23.8 L608 23.1 L616 22.3 L624 21.6 L632 20.8 L640 20.0 L640 48 L0 48Z' fill='rgba%2810%2C55%2C80%2C.62%29'/%3E%3Cpath d='M0 20.0 L8 19.2 L16 18.4 L24 17.7 L32 16.9 L40 16.2 L48 15.5 L56 14.8 L64 14.1 L72 13.5 L80 12.9 L88 12.4 L96 11.9 L104 11.5 L112 11.1 L120 10.8 L128 10.5 L136 10.3 L144 10.1 L152 10.0 L160 10.0 L168 10.0 L176 10.1 L184 10.3 L192 10.5 L200 10.8 L208 11.1 L216 11.5 L224 11.9 L232 12.4 L240 12.9 L248 13.5 L256 14.1 L264 14.8 L272 15.5 L280 16.2 L288 16.9 L296 17.7 L304 18.4 L312 19.2 L320 20.0 L328 20.8 L336 21.6 L344 22.3 L352 23.1 L360 23.8 L368 24.5 L376 25.2 L384 25.9 L392 26.5 L400 27.1 L408 27.6 L416 28.1 L424 28.5 L432 28.9 L440 29.2 L448 29.5 L456 29.7 L464 29.9 L472 30.0 L480 30.0 L488 30.0 L496 29.9 L504 29.7 L512 29.5 L520 29.2 L528 28.9 L536 28.5 L544 28.1 L552 27.6 L560 27.1 L568 26.5 L576 25.9 L584 25.2 L592 24.5 L600 23.8 L608 23.1 L616 22.3 L624 21.6 L632 20.8 L640 20.0 L640 48 L0 48Z' fill='url%28%23h%29'/%3E%3C/svg%3E") repeat-x 0 0 / 640px 48px; left: -640px; }
.tide__body { display: none; left: 0; right: 0; top: 47px; bottom: 0;
  background: linear-gradient(180deg, rgba(10,55,80,0.62) 0, #041229 30vh, var(--g1) 46vh); }
.tide__caustic { display: none; inset: -64px; top: 30px; opacity: 0.10;
  background: url(/assets/img/caustic.webp) repeat 0 0 / 512px 512px; }
.tide__caustic--b { background-size: 704px 704px; }
@media (max-width: 899px) {
  .tide__front i { background: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='320' height='40' viewBox='0 0 320 40'%3E%3Cdefs%3E%3ClinearGradient id='h' x1='0' y1='0' x2='0' y2='1'%3E%3Cstop offset='0' stop-color='rgb%2860%2C208%2C207%29' stop-opacity='.18'/%3E%3Cstop offset='.6' stop-color='rgb%2860%2C208%2C207%29' stop-opacity='0'/%3E%3C/linearGradient%3E%3C/defs%3E%3Cpath d='M0 16.0 L8 14.6 L16 13.2 L24 11.9 L32 10.7 L40 9.6 L48 8.7 L56 8.0 L64 7.4 L72 7.1 L80 7.0 L88 7.1 L96 7.4 L104 8.0 L112 8.7 L120 9.6 L128 10.7 L136 11.9 L144 13.2 L152 14.6 L160 16.0 L168 17.4 L176 18.8 L184 20.1 L192 21.3 L200 22.4 L208 23.3 L216 24.0 L224 24.6 L232 24.9 L240 25.0 L248 24.9 L256 24.6 L264 24.0 L272 23.3 L280 22.4 L288 21.3 L296 20.1 L304 18.8 L312 17.4 L320 16.0 L320 40 L0 40Z' fill='rgba%2810%2C55%2C80%2C.62%29'/%3E%3Cpath d='M0 16.0 L8 14.6 L16 13.2 L24 11.9 L32 10.7 L40 9.6 L48 8.7 L56 8.0 L64 7.4 L72 7.1 L80 7.0 L88 7.1 L96 7.4 L104 8.0 L112 8.7 L120 9.6 L128 10.7 L136 11.9 L144 13.2 L152 14.6 L160 16.0 L168 17.4 L176 18.8 L184 20.1 L192 21.3 L200 22.4 L208 23.3 L216 24.0 L224 24.6 L232 24.9 L240 25.0 L248 24.9 L256 24.6 L264 24.0 L272 23.3 L280 22.4 L288 21.3 L296 20.1 L304 18.8 L312 17.4 L320 16.0 L320 40 L0 40Z' fill='url%28%23h%29'/%3E%3Cpath d='M0 16.0 L8 14.6 L16 13.2 L24 11.9 L32 10.7 L40 9.6 L48 8.7 L56 8.0 L64 7.4 L72 7.1 L80 7.0 L88 7.1 L96 7.4 L104 8.0 L112 8.7 L120 9.6 L128 10.7 L136 11.9 L144 13.2 L152 14.6 L160 16.0 L168 17.4 L176 18.8 L184 20.1 L192 21.3 L200 22.4 L208 23.3 L216 24.0 L224 24.6 L232 24.9 L240 25.0 L248 24.9 L256 24.6 L264 24.0 L272 23.3 L280 22.4 L288 21.3 L296 20.1 L304 18.8 L312 17.4 L320 16.0' fill='none' stroke='rgba%28108%2C205%2C206%2C.85%29' stroke-width='2'/%3E%3C/svg%3E") repeat-x 0 0 / 320px 40px; }
  .tide__front { height: 40px; }
  .tide__back { display: none !important; }
  .tide__caustic { background-size: 320px 320px; }
  .tide__caustic--b { display: none !important; }
}
html.lite .tide__back, html.lite .tide__caustic { display: none !important; }
@keyframes tide-rise { 0% { transform: translateY(0); opacity: 1; } 80% { opacity: 1; } 100% { transform: translateY(-60vh); opacity: 0; } }
@keyframes tide-chop { from { transform: scaleY(1.6); } to { transform: scaleY(0.6); } }
@keyframes tide-drift { to { transform: translateX(-480px); } }
@keyframes tide-drift-b { to { transform: translateX(640px); } }
@keyframes tide-c1 { to { transform: translate(64px, 40px); } }
@keyframes tide-c2 { to { transform: translate(-48px, 56px); } }
@supports (animation-timeline: view()) {
  @media (prefers-reduced-motion: no-preference) {
:root:not(.nosdt) .tide { top: 0; height: 70vh; transform: translateY(0);
  -webkit-mask-image: linear-gradient(180deg, #000 calc(100% - 20vh), transparent);
          mask-image: linear-gradient(180deg, #000 calc(100% - 20vh), transparent); }
:root:not(.nosdt) .tide__body, :root:not(.nosdt) .tide__back { display: block; }
:root:not(.nosdt) .tide__front { top: 0; transform-origin: 50% 100%; }
:root:not(.nosdt) .tide--on .tide__caustic { display: block; }

:root:not(.nosdt) .tide { animation: tide-rise linear both; animation-timeline: --tide; animation-range: cover 25vh cover 90vh; }
:root:not(.nosdt) .tide__front { animation: tide-chop linear both; animation-timeline: --tide; animation-range: cover 25vh cover 90vh; }
  }
}
@media (prefers-reduced-motion: no-preference) {
html.wj .tide { top: 0; height: 70vh; transform: translateY(0);
  -webkit-mask-image: linear-gradient(180deg, #000 calc(100% - 20vh), transparent);
          mask-image: linear-gradient(180deg, #000 calc(100% - 20vh), transparent); }
html.wj .tide__body, html.wj .tide__back { display: block; }
html.wj .tide__front { top: 0; transform-origin: 50% 100%; }
html.wj .tide--on .tide__caustic { display: block; }

html.wj .tide { animation: tide-rise 1000ms linear both paused; }
html.wj .tide__front { animation: tide-chop 1000ms linear both paused; }

  .tide__front i { animation: tide-drift 6s linear infinite; }
  .tide__back i { animation: tide-drift-b 9s linear infinite; }
  .tide__caustic { animation: tide-c1 7s ease-in-out infinite alternate; }
  .tide__caustic--b { animation: tide-c2 11s ease-in-out infinite alternate; }
  @media (max-width: 899px) { .tide__front i { animation-name: tide-drift-m; } }
  @keyframes tide-drift-m { to { transform: translateX(-320px); } }
}
/* the header goes solid while the tide or the film is on screen: a backdrop
   blur over moving full-bleed pixels re-samples every frame */
html.top-solid .top { -webkit-backdrop-filter: none; backdrop-filter: none; background: rgba(1, 14, 27, 0.94); }
/* time loops pause offscreen and on a hidden tab (water.js toggles the
   classes). Scroll-driven animations are never paused: they would freeze. */
:is(.is-off, html.is-hidden) :is(.tide__front i, .tide__back i, .tide__caustic) { animation-play-state: paused; }
/* the pin's ground fades in over its top 30vh, so the tide rising behind it
   shows through instead of being cut by a hard edge (the pin is its own
   stacking context; the tide cannot sit between its ground and its text) */
.day__sky { -webkit-mask-image: linear-gradient(180deg, transparent 0, #000 30vh); mask-image: linear-gradient(180deg, transparent 0, #000 30vh); }

/* ---- 19e. THE DAY FILM (mei-shotlist §4.3-4.4; Rex blocking 1, 4) -----
   Geometry fix (pre-mortem 3): the pan is ranged to the PIN (contain) and
   the track's right padding is sized so the LAST card lands on the 28%
   marker at 92% of the pin. At 1440 that is 2232px of pan over 1980px of
   pin: 364px of scroll per moment (>= 300). */
@supports (animation-timeline: view()) {
  @media (min-width: 900px) and (prefers-reduced-motion: no-preference) {
    :root:not(.nosdt) .moments {
      padding-inline: 28vw calc(72vw - clamp(280px, 24vw, 360px));
      animation-range: contain 0% contain 100%;
    }
    @keyframes day-pan { 0% { transform: none; } 92%, 100% { transform: translateX(calc(-100% + 100vw)); } }
    :root:not(.nosdt) .day__sky { animation-range: contain 0% contain 100%; }
  }
}

/* M0 (JS off / reduced motion): each moment carries its own still */
.moment__scene { margin: var(--s4) 0 0; aspect-ratio: 16 / 9; overflow: hidden; border-radius: 10px; background: var(--g2); }
.moment__scene img { width: 100%; height: 100%; object-fit: cover; object-position: 35% 45%; display: block; }
@media (min-width: 780px) { .moment__scene { grid-column: 2; max-width: 460px; } }
.day--film .moment__scene { display: none; }

/* the film layers (created by film.js) */
.day__film { display: none; }
.day--film .day__film { display: block; position: relative; overflow: hidden;
  background: linear-gradient(90deg, #01060f 0%, #041229 40%, #0a2740 100%); }
.day__film .scene { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; object-position: 50% 40%;
  opacity: 0; z-index: 0; transform: scale(1.035); }
.day__film .scene.is-under { opacity: 1; z-index: 1; transform: none; }
.day__film .scene.is-in { opacity: 1; z-index: 2; transform: scale(1); will-change: opacity, transform;
  transition: opacity 700ms cubic-bezier(0.4, 0, 0.2, 1), transform 7000ms linear; }
.day__film .day__scrim { position: absolute; inset: 0; z-index: 3; pointer-events: none; }
.day__film .scene { max-width: none; }

/* M2: >= 900 with timelines. Film full-bleed behind the pinned pan; the
   head top-left over the left scrim, the track in the bottom band. */
:root:not(.nosdt) .day--m2 .day__sky { display: none; }
:root:not(.nosdt) .day--m2 .day__film { position: absolute; inset: 0; z-index: 0; }
:root:not(.nosdt) .day--m2 .day__scrim { background:
  linear-gradient(90deg, rgba(1,11,22,0.92) 0, rgba(1,11,22,0.70) 26%, rgba(1,11,22,0.12) 50%, rgba(1,11,22,0.30) 100%),
  linear-gradient(0deg, rgba(1,11,22,0.95) 0, rgba(1,11,22,0.88) 27%, rgba(1,11,22,0) 44%),
  linear-gradient(180deg, var(--g1) 0, transparent 9%); }
@media (min-aspect-ratio: 21/10) { :root:not(.nosdt) .day--m2 .day__film .scene { object-position: 50% 35%; } }
@supports (animation-timeline: view()) {
  @media (min-width: 900px) and (prefers-reduced-motion: no-preference) {
    :root:not(.nosdt) .day--m2 .day__pin { display: block; }
    :root:not(.nosdt) .day--m2 .day__head { position: absolute; left: 0; right: 0; top: calc(64px + 4vh); margin: 0 auto; z-index: 2; }
    :root:not(.nosdt) .day--m2 .day__head .lead { margin-top: var(--s4) !important; }
    :root:not(.nosdt) .day--m2 .moments { position: absolute; left: 0; bottom: 4vh; z-index: 2; }
    :root:not(.nosdt) .day--m2 .day__now { top: 68%; bottom: 4%; }
    /* the film fades up as the pin arrives, so the tide rising behind the
       pin is never cut by an opaque edge; fully up before the pin engages */
    :root:not(.nosdt) .day--m2 .day__film { animation: film-up linear both; animation-timeline: --day; animation-range: entry 40% entry 100%; }
    @keyframes film-up { from { opacity: 0; } }
  }
}

/* M1 phones: a sticky stage above the moments; text never over a photo.
   Rex blocking 1: render at 58% of the stage, action in the scene's left
   half (the -m squares are cut with the action at x ~32%). */
@media (max-width: 899px) {
  .day--m1 .day__film { position: sticky; top: 64px; z-index: 2; height: 46svh; margin: 0 calc(var(--pad) * -1) var(--s6);
    background: var(--g1); }
  .day--m1 .day__film .scene { object-position: 30% 45%; }
  .day--m1 .day__scrim { background: linear-gradient(0deg, var(--g1) 0, rgba(2,20,44,0) 22%); }
}
/* M1 wide without timelines (Firefox, Safari < 26, ?nosdt): two columns,
   the rail left, a sticky 100vh stage right. */
@media (min-width: 900px) {
  .day--m1 .day__pin { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: 0 var(--s8); align-items: start; }
  .day--m1 .day__head, .day--m1 .moments { grid-column: 1; }
  .day--m1 .day__film { grid-column: 2; grid-row: 1 / span 2; position: sticky; top: 64px; height: calc(100vh - 64px); border-radius: var(--radius); }
  .day--m1 .day__film .scene { object-position: 45% 50%; }
  .day--m1 .day__scrim { background: linear-gradient(0deg, rgba(1,11,22,0.55) 0, rgba(1,11,22,0) 30%); }
  .day--m1 .moment { min-height: 46vh; }
}
/* JS on + motion allowed: the film replaces the per-moment stills. Set by
   the head script before first style, so the lazy stills are never fetched. */
html.js.motion .moment__scene { display: none; }
/* legibility gate (build/legibility.js, p95 <= 0.02): the generated scenes
   put people inside Mei's heading safe zone (S2, S5 at x 30-45%), so the
   scrim carries a dark ellipse under the head block. Darker scrim, never
   lighter text (Mei §4.3). The lead is narrowed so the ellipse stays small. */
:root:not(.nosdt) .day--m2 .day__scrim { background:
  radial-gradient(ellipse 50% 46% at 14% 14%, rgba(1,11,22,0.95) 0, rgba(1,11,22,0.94) 66%, rgba(1,11,22,0) 100%),
  linear-gradient(90deg, rgba(1,11,22,0.80) 0, rgba(1,11,22,0.40) 20%, rgba(1,11,22,0.06) 46%, rgba(1,11,22,0.26) 100%),
  linear-gradient(0deg, rgba(1,11,22,0.96) 0, rgba(1,11,22,0.90) 27%, rgba(1,11,22,0) 44%),
  linear-gradient(180deg, var(--g1) 0, transparent 9%); }
:root:not(.nosdt) .day--m2 .day__head .lead { max-width: 32ch; }
:root:not(.nosdt) .day--m2 .day__head h2 { max-width: 14ch; }
/* living loops (film.js): a <video class="scene live"> over its still, same
   box and classes, so it dissolves and pushes in with the scene; hidden until
   it is actually playing (its first frame is the still, so no pop). */
.day__film .scene.live { visibility: hidden; }
.day__film .scene.live.is-playing { visibility: visible; }

/* ---- 19f. SCENE BANDS (Task 6) -----------------------------------------
   One <picture> per band. Phones: a 780x440 strip where the DOM puts it
   (before the text, or after a CTA). >= 900: the band's background, with
   a navy scrim under the text and the top/bottom feathered into the page
   ground (a mask, so the band never shows a rectangle edge). */
.pic { position: relative; }
.pic__img { display: block; aspect-ratio: 780 / 440; overflow: hidden; margin: 0 0 var(--s6); }
.pic__img img { display: block; width: 100%; height: 100%; object-fit: cover; }
.pic--taste .pic__img, .pic--shower .pic__img { margin: var(--s6) 0 0; }
@media (max-width: 899px) { .pic--argue .pic__img { margin-top: calc(var(--band) * -0.5); } }
@media (min-width: 900px) {
  .pic { overflow: hidden; isolation: isolate; }
  .pic__img { position: absolute; inset: 0; margin: 0 !important; aspect-ratio: auto; z-index: -1;
    -webkit-mask-image: linear-gradient(180deg, transparent 0, #000 14%, #000 86%, transparent 100%);
            mask-image: linear-gradient(180deg, transparent 0, #000 14%, #000 86%, transparent 100%); }
  .pic__img::after { content: ""; position: absolute; inset: 0; background: var(--pic-scrim); }
  .pic__img img { object-position: var(--pic-pos, 70% 50%); }
}
/* home argue: the H2 large over the pour; lead; the two paragraphs as a pair */
.argue__pair { display: grid; gap: var(--s6); margin-top: var(--s6); }
.argue__pair .eyebrow { margin-bottom: var(--s3); }
.argue__pair p:not(.eyebrow) { font-size: var(--f-b); }
.pic--argue .lead { color: var(--paper); }
@media (min-width: 900px) {
  .pic--argue { --pic-pos: 62% 50%; --pic-scrim: linear-gradient(90deg, rgba(1,11,22,0.95) 0, rgba(1,11,22,0.93) 50%, rgba(1,11,22,0.4) 62%, rgba(1,11,22,0) 74%);
    padding-block: clamp(120px, 12vw, 200px); }
  .pic--argue .argue__in { max-width: min(640px, 48%); margin-inline: 0; }
  .pic--argue h2 { font-size: clamp(2.75rem, 1.6rem + 3.6vw, 5.25rem); max-width: 11ch; }
  .argue__pair { grid-template-columns: 1fr 1fr; }
}
/* LUNA taste door: hand lifting a glass, right half */
@media (min-width: 900px) {
  .pic--taste { --pic-pos: 80% 50%; --pic-scrim: linear-gradient(90deg, rgba(1,11,22,0.95) 0, rgba(1,11,22,0.93) 52%, rgba(1,11,22,0.3) 66%, rgba(1,11,22,0.05) 82%); }
  .pic--taste .argue__in { max-width: min(640px, 50%); margin-inline: max(var(--pad), calc((100vw - 1240px) / 2)) 0; }
}
/* shower head: S9 behind the head on desktop, a strip under it on phones */
@media (min-width: 900px) {
  .pic--shower { --pic-pos: 70% 55%; --pic-scrim: linear-gradient(90deg, rgba(1,11,22,0.93) 0, rgba(1,11,22,0.92) 52%, rgba(1,11,22,0.55) 64%, rgba(1,11,22,0.38) 100%); }
}
/* book head: desktop only, right half */
.pic--book .pic__img { display: none; }
@media (min-width: 900px) {
  .pic--book .pic__img { display: block; }
  .pic--book { --pic-pos: 70% 50%; --pic-scrim: linear-gradient(90deg, rgba(1,11,22,0.95) 0, rgba(1,11,22,0.93) 60%, rgba(1,11,22,0.5) 76%, rgba(1,11,22,0.42) 100%); }
}
/* home showroom: the REAL photograph Kenneth took in the van, 2026-10-18.
   The compositing layer (.show__luna — the front render positioned onto a
   generated counter's counter plane) is deleted with it: a photograph that
   already contains the machine has nothing left to composite. */
.show__scene { position: relative; margin: 0; border-radius: var(--radius); overflow: hidden; aspect-ratio: 780 / 440; }
.show__bg, .show__bg img { display: block; width: 100%; height: 100%; }
.show__bg img { object-fit: cover; object-position: 52% 50%; }
@media (max-width: 939px) { .show__scene { margin-block: var(--s6); } }
@media (min-width: 940px) {
  .show__grid { grid-template-columns: minmax(0, 0.9fr) minmax(0, 1.1fr) !important; align-items: center; }
  .show__scene { aspect-ratio: 4 / 3; }
  /* the machine sits centre-left in the frame; a 4/3 crop off a 16:9 photo
     takes the width, so bias left of centre to keep the panel whole */
  .show__bg img { object-position: 54% 50%; }
  .show__steps { grid-column: 1 / -1; display: grid; grid-template-columns: repeat(3, 1fr); gap: var(--s6); }
  .show__steps li { padding-bottom: 0; }
  .show__steps li::after { display: none; }
}
/* about: object figure + counter card */
.obj-fig { margin: 0; }
.obj-fig img { width: 100%; height: auto; display: block; }
.pic-card { margin: 0; border-radius: var(--radius); overflow: hidden; aspect-ratio: 4 / 3; }
.pic-card picture, .pic-card img { display: block; width: 100%; height: 100%; object-fit: cover; object-position: 60% 50%; }
@media (max-width: 899px) { .pic-card { aspect-ratio: 780 / 440; } }

/* ---- 19g. RHYTHM FIXES THAT COST NOTHING (mei-shotlist §7) ------------- */
.trio--num li { position: relative; }
.trio__n { display: block; font-family: Fraunces, serif; font-weight: 300; font-size: clamp(2.75rem, 2rem + 2.4vw, 4rem); line-height: 1; color: var(--cyan); margin-bottom: var(--s4); letter-spacing: -0.02em; }
.trio--num h3 { font-size: var(--f-lead); }
.trio__or::before { content: "or"; position: absolute; top: 50%; left: 0; transform: translate(-50%, -50%); z-index: 1;
  font-size: var(--f-xs); font-weight: 650; letter-spacing: 0.08em; text-transform: uppercase; color: var(--cyan);
  background: var(--g1); border: 1px solid var(--line); border-radius: 999px; padding: 6px 10px; }
@media (max-width: 639px) { .trio__or::before { top: 0; left: 50%; } }
.mega-fig { font-family: Fraunces, serif; font-weight: 300; font-size: clamp(4.25rem, 2.4rem + 6vw, 8rem); line-height: 0.95; letter-spacing: -0.04em;
  color: var(--paper); margin: var(--s6) 0 0 !important; font-variant-numeric: lining-nums; }
.mega-fig span { display: block; font-family: Figtree, sans-serif; font-size: var(--f-b); font-weight: 600; letter-spacing: 0.02em; color: var(--cyan); margin-top: var(--s3); }
.check { list-style: none; margin: var(--s4) 0; padding: 0; display: grid; gap: var(--s3); }
.check li { position: relative; padding-left: 34px; color: var(--paper); }
.check li::before { content: ""; position: absolute; left: 0; top: 0.18em; width: 20px; height: 20px; border-radius: 50%; border: 1.5px solid var(--cyan); }
.toc { display: none; }
@media (min-width: 900px) {
  .toc { display: block; position: sticky; top: 96px; max-height: calc(100vh - 128px); overflow: auto; }
  .toc ol { list-style: none; margin: var(--s4) 0 0; padding: 0; display: grid; gap: 2px; border-left: 1px solid var(--line); }
  .toc a { display: block; padding: 11px 0 11px 16px; color: var(--paper-2); text-decoration: none; font-size: var(--f-s); line-height: 1.3; }
  .toc a:hover { color: var(--cyan); }
}
.legal h2[id] { scroll-margin-top: 88px; }
/* LUNA footprint beside the numbers */
.nums-fig { display: grid; gap: var(--s7); align-items: center; }
@media (min-width: 760px) { .nums-fig { grid-template-columns: 240px minmax(0, 1fr); } .nums-fig .nums { grid-template-columns: 1fr 1fr; } }
.fprint { margin: 0 auto; width: min(240px, 60vw); }
.fprint__tile { position: relative; background: var(--g2); border-radius: 18px; padding: 44px 44px 28px 22px; }
.fprint__tile img { display: block; width: 100%; height: auto; }
.fprint__w, .fprint__d { position: absolute; display: flex; align-items: center; justify-content: center; }
.fprint__w { left: calc(22px + (100% - 66px) * 0.053); right: calc(44px + (100% - 66px) * 0.054); top: 16px; height: 16px; border-inline: 1.5px solid var(--cyan); }
.fprint__w::before { content: ""; position: absolute; left: 0; right: 0; top: 50%; border-top: 1.5px solid var(--cyan); }
.fprint__d { right: 14px; width: 16px; top: calc(44px + (100% - 72px) * 0.027); bottom: calc(28px + (100% - 72px) * 0.029); border-block: 1.5px solid var(--cyan); }
.fprint__d::before { content: ""; position: absolute; top: 0; bottom: 0; left: 50%; border-left: 1.5px solid var(--cyan); }
.fprint b { position: relative; background: var(--g2); color: var(--cyan); font-size: var(--f-xs); font-weight: 650; letter-spacing: 0.04em; padding: 0 6px; white-space: nowrap; }
.fprint__d b { writing-mode: vertical-rl; padding: 6px 0; }
.fprint figcaption { margin-top: var(--s3); font-size: var(--f-xs); color: var(--paper-3); text-align: center; }
@media (min-width: 900px) { .pic--book .lead { max-width: 44ch; } }
/* phones: the card row must not be taller than the list it replaced (Rex
   L4b), or the taste door's CTA drops. Numeral inline, tighter card. */
@media (max-width: 639px) {
  .trio--num { gap: var(--s3); }
  .trio--num li { padding: var(--s4); display: grid; grid-template-columns: auto 1fr; column-gap: var(--s4); align-items: baseline; }
  .trio--num .trio__n { font-size: 2rem; margin: 0; grid-row: 1 / span 2; }
  .trio--num h3 { font-size: var(--f-b); margin-bottom: 2px; }
  .trio--num p { font-size: var(--f-s); grid-column: 2; }
  .trio__or::before { top: 0; left: auto; right: var(--s4); transform: translateY(-50%); }
}
.toc a { min-height: 44px; box-sizing: border-box; display: flex; align-items: center; }

/* ---- 19h. W2 WATER THROUGH THE STAGES (mei-motion §2) ------------------
   LUNA route: resting state = full (pipe, nodes, one fork lane, glass), so
   JS off / reduced motion is complete. water.js builds the scrubbed
   keyframes from the nodes' real offsets (they depend on text wrap) and
   attaches them to a ViewTimeline, or seeks them where there is none. */
.route--flow { padding-bottom: 60px; }
.route--flow li::after { display: none !important; }
.route__pipe { position: absolute; left: 15px; width: 6px; top: 20px; bottom: 40px; z-index: 0; border-radius: 3px;
  background: rgba(236,243,247,0.10); box-shadow: inset 0 0 0 1px rgba(60,208,207,0.35); }
.route__water { position: absolute; left: 1px; right: 1px; top: 0; bottom: 0; border-radius: 2px; overflow: hidden;
  background: rgba(60,208,207,0.85); transform-origin: 50% 0; }
.route__water b { position: absolute; left: 0; right: 0; top: 0; height: 300%;
  background: repeating-linear-gradient(180deg, transparent 0 4%, rgba(236,250,255,0.7) 5%, transparent 6.5%); }
.route__front { position: absolute; left: -11px; right: -11px; top: 0; bottom: 0; opacity: 0; pointer-events: none; }
.route__front::before { content: ""; position: absolute; left: 50%; bottom: -14px; width: 28px; height: 28px; margin-left: -14px; border-radius: 50%;
  background: radial-gradient(circle, rgba(60,208,207,0.55), rgba(60,208,207,0) 70%); }
.route__front::after { content: ""; position: absolute; left: 50%; bottom: -5px; width: 10px; height: 10px; margin-left: -5px; border-radius: 50%;
  background: rgba(236,250,255,0.95); }
.route__node { position: absolute; left: 0; top: 2px; width: 36px; height: 36px; border-radius: 50%; overflow: hidden; z-index: 2; }
.route__node > i { position: absolute; inset: 0; background: var(--cyan); }
.route__node::after { content: attr(data-n); position: absolute; inset: 0; display: grid; place-items: center; z-index: 1;
  font-size: var(--f-xs); font-weight: 650; letter-spacing: 0.06em; color: #032027; }
.route__pulse { position: absolute; left: 0; top: 2px; width: 36px; height: 36px; border-radius: 50%; border: 1.5px solid var(--cyan); opacity: 0; z-index: 1; }
/* the fork: between Filter 1 and "Filter 2 or 3" a second lane runs beside
   the pipe, dashed and EMPTY: a machine runs one of the two, never both */
.route__lane { position: absolute; left: 27px; top: 20px; bottom: -20px; width: 6px; border: 1.5px dashed rgba(60,208,207,0.55); border-radius: 3px; z-index: 0; }
.route__glass { position: absolute; left: 4px; bottom: 0; width: 28px; height: 36px; }
.route__glass svg { position: absolute; inset: 0; width: 100%; height: 100%; overflow: visible; }
.route__glass path { fill: rgba(236,243,247,0.05); stroke: rgba(236,243,247,0.6); stroke-width: 1.5; }
.route__gw { position: absolute; left: 3px; right: 3px; top: 2px; bottom: 2px; overflow: hidden; clip-path: polygon(0 0, 100% 0, 88% 100%, 12% 100%); }
.route__gw i { position: absolute; inset: 0; background: rgba(60,208,207,0.75); transform: translateY(22%); }
@media (max-width: 899px) { .route__front::before { width: 18px; height: 18px; margin-left: -9px; bottom: -9px; } }
@media (prefers-reduced-motion: no-preference) {
  .route__water b { animation: route-run 600ms linear infinite; }
  @keyframes route-run { from { transform: translateY(-33.333%); } to { transform: translateY(0); } }
  html.lite .route__water b { animation: none; }
  html.lite .route__front::before { display: none; }
}
:is(.is-off, html.is-hidden) .route__water b { animation-play-state: paused; }

/* home #inside: four stations under the view, filling on the camera's beats */
.cam__dots { display: none; }
.cam__rail { position: absolute; left: 8%; right: 8%; bottom: 14px; height: 18px; margin: 0; padding: 0; list-style: none; z-index: 3; }
.cam__rail .st { position: absolute; top: 0; width: 18px; height: 18px; margin-left: -9px; border-radius: 50%; overflow: hidden;
  border: 1.5px solid rgba(60,208,207,0.8); background: rgba(1,11,22,0.55); }
.cam__rail .st1 { left: 12.5%; } .cam__rail .st2 { left: 37.5%; } .cam__rail .st3 { left: 62.5%; } .cam__rail .st4 { left: 87.5%; }
.cam__rail .st i { position: absolute; inset: 0; background: var(--cyan); }
@supports (animation-timeline: view()) {
  @media (prefers-reduced-motion: no-preference) and (min-width: 700px) {
    .cam__rail .st i { animation-timeline: --cam; animation-range: contain 0% contain 100%; animation-fill-mode: both; animation-timing-function: linear; }
    .cam__rail .st1 i { animation-name: st-1; } .cam__rail .st2 i { animation-name: st-2; } .cam__rail .st3 i { animation-name: st-3; } .cam__rail .st4 i { animation-name: st-4; }
    @keyframes st-1 { 0%, 4% { transform: translateY(100%); } 10%, 30% { transform: none; } 36%, 100% { transform: translateY(100%); } }
    @keyframes st-2 { 0%, 36% { transform: translateY(100%); } 42%, 56% { transform: none; } 62%, 100% { transform: translateY(100%); } }
    @keyframes st-3 { 0%, 62% { transform: translateY(100%); } 68%, 82% { transform: none; } 88%, 100% { transform: translateY(100%); } }
    @keyframes st-4 { 0%, 88% { transform: translateY(100%); } 94%, 100% { transform: none; } }
  }
  @media (prefers-reduced-motion: no-preference) and (max-width: 699px) {
    /* not pinned: the rail fills left to right as the view crosses the screen */
    .cam__view { view-timeline-name: --camv; }
    .cam__rail .st i { animation: st-m linear both; animation-timeline: --camv; }
    .cam__rail .st1 i { animation-range: cover 20% cover 32%; } .cam__rail .st2 i { animation-range: cover 32% cover 45%; }
    .cam__rail .st3 i { animation-range: cover 45% cover 57%; } .cam__rail .st4 i { animation-range: cover 57% cover 70%; }
    @keyframes st-m { from { transform: translateY(100%); } to { transform: none; } }
  }
}
.route--flow::before { content: ""; position: absolute; left: 16px; width: 4px; top: 20px; bottom: 40px; border-radius: 2px; background: rgba(60,208,207,0.85); }
.route--flow.is-live::before { display: none; }
.route--flow li .route__glass { bottom: -52px; }


/* ---- 19i. W4 TEMPERATURE CUES (mei-motion §4) --------------------------
   Replaces §18g's 3px wisps / 4px drops (never seen at arm's length). Each
   cue says only what the copy says: hot ~95 (steam), tea gentler (fewer,
   fainter wisps), warm = the bottle (a warm halo, no steam), cold ~6
   (beads + frost), night drop (a breathing light). Triggers:
   >= 900 film modes: plays while its moment is the active scene;
   < 900 / LUNA table / LUNA numbers: scrubbed by the icon's own view();
   JS off on desktop: pointer hover; reduced motion: still marks. */
.moment__icon::before, .moment__icon::after { display: none !important; }
.moment__icon img { animation: none !important; }
.ico { position: relative; display: inline-block; flex: none; line-height: 0; }
.nums b { position: relative; }
.cue { position: absolute; inset: 0; z-index: 2; pointer-events: none; }
.cue b { position: absolute; display: block; opacity: 0; }
/* steam: hot 3 wisps, tea 2 */
.cue--hot b, .cue--tea b { top: -58%; width: 20.8%; height: 75%; background: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 10 36'%3E%3Cdefs%3E%3ClinearGradient id='g' x1='0' y1='1' x2='0' y2='0'%3E%3Cstop offset='0' stop-color='%23ecf3f7' stop-opacity='.95'/%3E%3Cstop offset='1' stop-color='%23ecf3f7' stop-opacity='0'/%3E%3C/linearGradient%3E%3C/defs%3E%3Cpath d='M5 35c-4-6 4-10 0-17S1 6 5 1' fill='none' stroke='url%28%23g%29' stroke-width='2.6' stroke-linecap='round'/%3E%3C/svg%3E") center / 100% 100% no-repeat; transform-origin: 50% 100%; }
.cue--hot b:nth-child(1), .cue--tea b:nth-child(1) { left: 24%; }
.cue--hot b:nth-child(2), .cue--tea b:nth-child(2) { left: 42%; }
.cue--hot b:nth-child(3) { left: 60%; }
.cue--tea b:nth-child(n+3), .cue--hot b:nth-child(n+4) { display: none; }
/* warm: a halo in the bottle's own colour */
.cue--warm b:nth-child(1) { inset: -30%; border-radius: 50%; background: radial-gradient(circle, rgba(245,162,93,0.55), rgba(245,162,93,0) 68%); z-index: -1; }
.cue--warm b:nth-child(n+2) { display: none; }
/* cold: five beads, a frost rim, a cool halo */
.cue--cold b { width: 4px; height: 4px; border-radius: 50%; background: rgba(236,250,255,0.95); }
.cue--cold b:nth-child(1) { left: 28%; top: 36%; width: 5px; height: 5px; }
.cue--cold b:nth-child(2) { left: 56%; top: 30%; }
.cue--cold b:nth-child(3) { left: 40%; top: 58%; width: 3px; height: 3px; }
.cue--cold b:nth-child(4) { left: 64%; top: 52%; width: 5px; height: 5px; }
.cue--cold b:nth-child(5) { left: 34%; top: 46%; }
.cue--cold::before { content: ""; position: absolute; inset: -3px; border-radius: 12px; border: 1.5px solid rgba(236,250,255,0.75); opacity: 0; }
.cue--cold::after { content: ""; position: absolute; inset: -35%; border-radius: 50%; z-index: -1; background: radial-gradient(circle, rgba(60,208,207,0.4), rgba(60,208,207,0) 66%); opacity: 0; }
/* night drop: a soft cyan light that breathes */
.cue--drop b:nth-child(1) { inset: -35%; border-radius: 50%; z-index: -1; background: radial-gradient(circle, rgba(108,205,206,0.6), rgba(108,205,206,0) 66%); }
.cue--drop b:nth-child(n+2) { display: none; }
.cue--lock b { display: none; }
.cue--lock b:nth-child(1) { display: block; inset: -25%; border-radius: 50%; z-index: -1; background: radial-gradient(circle, rgba(255,120,80,0.55), rgba(255,120,80,0) 66%); }
/* the LUNA #numbers cues sit over the figure, bigger */
.cue--big { inset: -10% auto auto 0; width: 2.2em; height: 1.2em; }
.cue--big.cue--hot b { top: -40%; height: 60px; width: 16px; }
.cue--big.cue--cold b { width: 7px; height: 7px; }

@keyframes cue-steam { 0% { opacity: 0; transform: translateY(0) scaleX(1); } 30% { opacity: var(--pk, 0.8); } 100% { opacity: 0; transform: translateY(var(--rise, -83%)) scaleX(1.4); } }
@keyframes cue-halo { 0% { opacity: 0.25; transform: scale(0.9); } 50% { opacity: 1; transform: scale(1.15); } 100% { opacity: 0.25; transform: scale(0.9); } }
@keyframes cue-bead { from { opacity: 0; scale: 0.4; } to { opacity: 0.95; scale: 1; } }
@keyframes cue-run { from { translate: 0 0; } to { translate: 0 var(--run, 18px); } }
@keyframes cue-frost { from { opacity: 0; } to { opacity: 0.6; } }
@keyframes cue-breath { 0%, 100% { opacity: 0.35; } 50% { opacity: 1; } }
.cue--tea { --pk: 0.6; --rise: -86%; }
.cue--big { --rise: -67%; --run: 26px; }

@media (prefers-reduced-motion: no-preference) {
  /* TIME: plays while active (film modes >= 900, and the panel photo) */
  @media (min-width: 900px) {
    :is(.day--film[data-scene="0"] .moment[data-scene="0"], .day--film[data-scene="1"] .moment[data-scene="1"], .day--film[data-scene="2"] .moment[data-scene="2"], .day--film[data-scene="3"] .moment[data-scene="3"], .day--film[data-scene="4"] .moment[data-scene="4"], .day--film[data-scene="5"] .moment[data-scene="5"]) .cue--hot b { animation: cue-steam 2400ms ease-out var(--n, 4) both; }
    :is(.day--film[data-scene="0"] .moment[data-scene="0"], .day--film[data-scene="1"] .moment[data-scene="1"], .day--film[data-scene="2"] .moment[data-scene="2"], .day--film[data-scene="3"] .moment[data-scene="3"], .day--film[data-scene="4"] .moment[data-scene="4"], .day--film[data-scene="5"] .moment[data-scene="5"]) .cue--hot b:nth-child(2) { animation-delay: 800ms; }
    :is(.day--film[data-scene="0"] .moment[data-scene="0"], .day--film[data-scene="1"] .moment[data-scene="1"], .day--film[data-scene="2"] .moment[data-scene="2"], .day--film[data-scene="3"] .moment[data-scene="3"], .day--film[data-scene="4"] .moment[data-scene="4"], .day--film[data-scene="5"] .moment[data-scene="5"]) .cue--hot b:nth-child(3) { animation-delay: 1600ms; }
    :is(.day--film[data-scene="0"] .moment[data-scene="0"], .day--film[data-scene="1"] .moment[data-scene="1"], .day--film[data-scene="2"] .moment[data-scene="2"], .day--film[data-scene="3"] .moment[data-scene="3"], .day--film[data-scene="4"] .moment[data-scene="4"], .day--film[data-scene="5"] .moment[data-scene="5"]) .cue--tea b { animation: cue-steam 2800ms ease-out 3 both; }
    :is(.day--film[data-scene="0"] .moment[data-scene="0"], .day--film[data-scene="1"] .moment[data-scene="1"], .day--film[data-scene="2"] .moment[data-scene="2"], .day--film[data-scene="3"] .moment[data-scene="3"], .day--film[data-scene="4"] .moment[data-scene="4"], .day--film[data-scene="5"] .moment[data-scene="5"]) .cue--tea b:nth-child(2) { animation-delay: 1100ms; }
    :is(.day--film[data-scene="0"] .moment[data-scene="0"], .day--film[data-scene="1"] .moment[data-scene="1"], .day--film[data-scene="2"] .moment[data-scene="2"], .day--film[data-scene="3"] .moment[data-scene="3"], .day--film[data-scene="4"] .moment[data-scene="4"], .day--film[data-scene="5"] .moment[data-scene="5"]) .cue--warm b { animation: cue-halo 2800ms ease-in-out 2 both; }
    :is(.day--film[data-scene="0"] .moment[data-scene="0"], .day--film[data-scene="1"] .moment[data-scene="1"], .day--film[data-scene="2"] .moment[data-scene="2"], .day--film[data-scene="3"] .moment[data-scene="3"], .day--film[data-scene="4"] .moment[data-scene="4"], .day--film[data-scene="5"] .moment[data-scene="5"]) .cue--cold b { animation: cue-bead 500ms cubic-bezier(0.23, 1, 0.32, 1) both; }
    :is(.day--film[data-scene="0"] .moment[data-scene="0"], .day--film[data-scene="1"] .moment[data-scene="1"], .day--film[data-scene="2"] .moment[data-scene="2"], .day--film[data-scene="3"] .moment[data-scene="3"], .day--film[data-scene="4"] .moment[data-scene="4"], .day--film[data-scene="5"] .moment[data-scene="5"]) .cue--cold b:nth-child(2) { animation: cue-bead 500ms cubic-bezier(0.23, 1, 0.32, 1) 90ms both, cue-run 1400ms ease-in 700ms both; }
    :is(.day--film[data-scene="0"] .moment[data-scene="0"], .day--film[data-scene="1"] .moment[data-scene="1"], .day--film[data-scene="2"] .moment[data-scene="2"], .day--film[data-scene="3"] .moment[data-scene="3"], .day--film[data-scene="4"] .moment[data-scene="4"], .day--film[data-scene="5"] .moment[data-scene="5"]) .cue--cold b:nth-child(3) { animation-delay: 180ms; }
    :is(.day--film[data-scene="0"] .moment[data-scene="0"], .day--film[data-scene="1"] .moment[data-scene="1"], .day--film[data-scene="2"] .moment[data-scene="2"], .day--film[data-scene="3"] .moment[data-scene="3"], .day--film[data-scene="4"] .moment[data-scene="4"], .day--film[data-scene="5"] .moment[data-scene="5"]) .cue--cold b:nth-child(4) { animation: cue-bead 500ms cubic-bezier(0.23, 1, 0.32, 1) 270ms both, cue-run 1400ms ease-in 800ms both; }
    :is(.day--film[data-scene="0"] .moment[data-scene="0"], .day--film[data-scene="1"] .moment[data-scene="1"], .day--film[data-scene="2"] .moment[data-scene="2"], .day--film[data-scene="3"] .moment[data-scene="3"], .day--film[data-scene="4"] .moment[data-scene="4"], .day--film[data-scene="5"] .moment[data-scene="5"]) .cue--cold b:nth-child(5) { animation-delay: 360ms; }
    :is(.day--film[data-scene="0"] .moment[data-scene="0"], .day--film[data-scene="1"] .moment[data-scene="1"], .day--film[data-scene="2"] .moment[data-scene="2"], .day--film[data-scene="3"] .moment[data-scene="3"], .day--film[data-scene="4"] .moment[data-scene="4"], .day--film[data-scene="5"] .moment[data-scene="5"]) .cue--cold::before, :is(.day--film[data-scene="0"] .moment[data-scene="0"], .day--film[data-scene="1"] .moment[data-scene="1"], .day--film[data-scene="2"] .moment[data-scene="2"], .day--film[data-scene="3"] .moment[data-scene="3"], .day--film[data-scene="4"] .moment[data-scene="4"], .day--film[data-scene="5"] .moment[data-scene="5"]) .cue--cold::after { animation: cue-frost 700ms ease-out 200ms both; }
    :is(.day--film[data-scene="0"] .moment[data-scene="0"], .day--film[data-scene="1"] .moment[data-scene="1"], .day--film[data-scene="2"] .moment[data-scene="2"], .day--film[data-scene="3"] .moment[data-scene="3"], .day--film[data-scene="4"] .moment[data-scene="4"], .day--film[data-scene="5"] .moment[data-scene="5"]) .cue--drop b { animation: cue-breath 4000ms ease-in-out 3 both; }
    :is(.day--film[data-scene="0"] .moment[data-scene="0"], .day--film[data-scene="1"] .moment[data-scene="1"], .day--film[data-scene="2"] .moment[data-scene="2"], .day--film[data-scene="3"] .moment[data-scene="3"], .day--film[data-scene="4"] .moment[data-scene="4"], .day--film[data-scene="5"] .moment[data-scene="5"]) .cue--lock b { animation: cue-breath 1600ms ease-in-out 1 both; }
    /* while the S2 steam loop plays, the scene owns the steam: 1 cycle */
    .day--m2 .cue--hot { --n: 1; }
  }
  /* JS off, desktop pointer: the cue plays on hover */
  @media (hover: hover) and (pointer: fine) and (min-width: 900px) {
    html:not(.js) .moment:hover .cue--hot b, html:not(.js) .moment:hover .cue--tea b { animation: cue-steam 2400ms ease-out 2 both; }
    html:not(.js) .moment:hover .cue--hot b:nth-child(2) { animation-delay: 800ms; }
    html:not(.js) .moment:hover .cue--cold b { animation: cue-bead 500ms ease-out both; }
    html:not(.js) .moment:hover .cue--cold::before, html:not(.js) .moment:hover .cue--cold::after { animation: cue-frost 500ms ease-out both; }
    html:not(.js) .moment:hover :is(.cue--warm, .cue--drop, .cue--lock) b { animation: cue-halo 2000ms ease-in-out 1 both; }
  }
  /* SCRUB: phones' day rail, the LUNA icon table, the LUNA numbers */
  @supports (animation-timeline: view()) {
    @media (max-width: 899px) {
      .moment .cue b, .moment .cue::before, .moment .cue::after { animation-timeline: view(); animation-range: entry 30% cover 45%; animation-fill-mode: both; animation-timing-function: linear; }
    }
    .spec--icons .cue b, .spec--icons .cue::before, .spec--icons .cue::after { animation-timeline: view(); animation-range: entry 20% cover 40%; animation-fill-mode: both; animation-timing-function: linear; }
    .nums .cue b, .nums .cue::before, .nums .cue::after { animation-timeline: view(); animation-range: entry 40% cover 60%; animation-fill-mode: both; animation-timing-function: linear; }
    @media (max-width: 899px) {
      .moment .cue--hot b, .moment .cue--tea b { animation-name: cue-steam-s; }
      .moment .cue--hot b:nth-child(2) { animation-range: entry 38% cover 50%; }
      .moment .cue--hot b:nth-child(3) { animation-range: entry 46% cover 55%; }
      .moment .cue--tea b:nth-child(2) { animation-range: entry 40% cover 52%; }
      .moment :is(.cue--warm, .cue--drop, .cue--lock) b { animation-name: cue-glow-s; }
      .moment .cue--cold b { animation-name: cue-bead-s; }
      .moment .cue--cold b:nth-child(2), .moment .cue--cold b:nth-child(4) { animation-name: cue-bead-run-s; }
      .moment .cue--cold::before, .moment .cue--cold::after { animation-name: cue-frost; }
    }
    .spec--icons .cue--hot b, .spec--icons .cue--tea b, .nums .cue--hot b { animation-name: cue-steam-s; }
    .spec--icons .cue--hot b:nth-child(2), .nums .cue--hot b:nth-child(2) { animation-range: entry 28% cover 46%; }
    .spec--icons .cue--hot b:nth-child(3), .nums .cue--hot b:nth-child(3) { animation-range: entry 36% cover 52%; }
    .spec--icons .cue--warm b { animation-name: cue-glow-s; }
    .spec--icons .cue--cold b, .nums .cue--cold b { animation-name: cue-bead-s; }
    .spec--icons .cue--cold b:nth-child(2), .spec--icons .cue--cold b:nth-child(4),
    .nums .cue--cold b:nth-child(2), .nums .cue--cold b:nth-child(4) { animation-name: cue-bead-run-s; }
    .spec--icons .cue--cold::before, .spec--icons .cue--cold::after, .nums .cue--cold::before, .nums .cue--cold::after { animation-name: cue-frost; }
  }
  @keyframes cue-steam-s { 0% { opacity: 0; transform: translateY(0) scaleX(1); } 35% { opacity: var(--pk, 0.8); } 100% { opacity: 0.1; transform: translateY(var(--rise, -83%)) scaleX(1.4); } }
  @keyframes cue-glow-s { 0% { opacity: 0; transform: scale(0.9); } 60% { opacity: 1; transform: scale(1.15); } 100% { opacity: 0.5; transform: scale(1); } }
  @keyframes cue-bead-s { 0% { opacity: 0; scale: 0.4; } 40%, 100% { opacity: 0.95; scale: 1; } }
  @keyframes cue-bead-run-s { 0% { opacity: 0; scale: 0.4; translate: 0 0; } 35% { opacity: 0.95; scale: 1; translate: 0 0; } 100% { opacity: 0.95; scale: 1; translate: 0 var(--run, 18px); } }
}
/* the panel photo, every width: the pressed icon's cue plays once. The cue
   classes sit on .pui__cue itself, so these are compound, not descendant. */
@media (prefers-reduced-motion: no-preference) {
  .pui__cue.is-play.cue--hot b { animation: cue-steam 2400ms ease-out both; }
  .pui__cue.is-play.cue--hot b:nth-child(2) { animation-delay: 500ms; }
  .pui__cue.is-play.cue--hot b:nth-child(3) { animation-delay: 1000ms; }
  .pui__cue.is-play.cue--tea b { animation: cue-steam 2800ms ease-out both; }
  .pui__cue.is-play.cue--tea b:nth-child(2) { animation-delay: 700ms; }
  .pui__cue.is-play.cue--warm b { animation: cue-halo 2800ms ease-in-out both; }
  .pui__cue.is-play.cue--cold b { animation: cue-bead 500ms cubic-bezier(0.23, 1, 0.32, 1) both; }
  .pui__cue.is-play.cue--cold b:nth-child(3) { animation-delay: 180ms; }
  .pui__cue.is-play.cue--cold b:nth-child(5) { animation-delay: 360ms; }
  .pui__cue.is-play.cue--cold b:nth-child(2) { animation: cue-bead 500ms cubic-bezier(0.23, 1, 0.32, 1) 90ms both, cue-run 1400ms ease-in 700ms both; }
  .pui__cue.is-play.cue--cold b:nth-child(4) { animation: cue-bead 500ms cubic-bezier(0.23, 1, 0.32, 1) 270ms both, cue-run 1400ms ease-in 800ms both; }
  .pui__cue.is-play.cue--cold::before, .pui__cue.is-play.cue--cold::after { animation: cue-frost 700ms ease-out 200ms both; }
}
/* reduced motion: still marks, complete */
@media (prefers-reduced-motion: reduce) {
  .cue--hot b:nth-child(-n+2), .cue--tea b:nth-child(-n+2) { opacity: 0.5; transform: translateY(-30%); }
  .cue--cold b { opacity: 0.9; }
  .cue--warm b { opacity: 0.25; }
}
:is(.is-off, html.is-hidden) .cue b { animation-play-state: paused; }
html.lite .cue--hot b:nth-child(3) { display: none; }
html.lite .cue--cold b:nth-child(2), html.lite .cue--cold b:nth-child(4) { animation-name: cue-bead !important; }
/* the panel photo: the cue plays once over the icon that was pressed, 1.6x */
.pui__cue { position: absolute; inset: auto; left: var(--hx, 50%); top: var(--hy, 50%); width: 7%; aspect-ratio: 1; transform: translate(-50%, -50%) scale(1.6); z-index: 4; }

/* ---- 19j. W5 MICRO: the droplet press + the WhatsApp water hover ------ */
.btn { position: relative; overflow: hidden; isolation: isolate; }
.btn .ripple { position: absolute; z-index: -1; border-radius: 50%; pointer-events: none; transform: scale(0.08); opacity: 0.38;
  background: rgba(60,208,207,0.30);
  /* size on Mei's ease-out, fade LINEAR: on the ease-out the fade was gone by 60ms (Task 9 pixel check) */
  animation: btn-ripple 280ms cubic-bezier(0.23, 1, 0.32, 1) forwards, btn-ripple-o 280ms linear forwards; }
.btn--go .ripple { background: rgba(255,255,255,0.45); }
@keyframes btn-ripple { to { transform: scale(1); } }
@keyframes btn-ripple-o { to { opacity: 0; } }
.btn .wet { position: absolute; inset: 0; z-index: -1; display: block; background: var(--cyan-2); transform: translateY(101%); pointer-events: none; }
.btn .wet i { position: absolute; left: 0; top: -5px; width: 200%; height: 6px; display: block;
  background: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='6' viewBox='0 0 24 6'%3E%3Cpath d='M0 3Q6 0 12 3T24 3V6H0Z' fill='%236ccdce'/%3E%3C/svg%3E") repeat-x 0 0 / 24px 6px; }
@media (prefers-reduced-motion: no-preference) {
  .btn:active { transform: scale(0.97); transition: transform 120ms ease-out; }
  @media (hover: hover) and (pointer: fine) {
    .btn--go:hover { background: var(--cyan); transform: none; }
    .btn .wet { transition: transform 200ms cubic-bezier(0.23, 1, 0.32, 1); }
    .btn:hover .wet { transform: translateY(0); transition-duration: 260ms; }
    .btn:hover .wet i { animation: wet-drift 900ms linear infinite; }
    @keyframes wet-drift { to { transform: translateX(-50%); } }
  }
}
@media (prefers-reduced-motion: reduce) {
  .btn .ripple, .btn .wet { display: none; }
  .btn--go:active { background: #2fb9b8; }
  .btn--go:hover { transform: none; }
}
.spec--icons .ico { display: inline-block; width: 36px; height: 36px; }
.spec--icons dt .cue { width: auto; height: auto; border-radius: 0; background: none; }

/* ---- 20. 180mm as a picture (2026-09-23, Marxk: "this section is not good enough") ----
   Head, then the counter full-bleed with the rule drawn on the real machine,
   then the details. No text on bare ground beside a lone object. */
.size__head { max-width: 58rem; }
.size__head .size__mega { margin-bottom: var(--s5); }
.size__scene { position: relative; margin: clamp(28px, 4vw, 56px) 0 0; }
.size__scene img { display: block; width: 100%; height: auto; }
/* fade into whatever ground is behind it (the page ground is a gradient, so a
   painted colour would seam) */
.size__scene img {
  -webkit-mask-image: linear-gradient(180deg, transparent 0, #000 13%, #000 86%, transparent 100%);
          mask-image: linear-gradient(180deg, transparent 0, #000 13%, #000 86%, transparent 100%);
}
.size__dim--scene { left: 39.00%; width: 9.82%; top: calc(32.59% - 14px); z-index: 2; gap: 0; }
/* the span-level clip-path draw would clip the label above the rule: draw the
   rules instead, from the centre out, as the picture scrolls in */
.size__dim--scene { clip-path: none !important; animation: none !important; }
@supports (animation-timeline: view()) {
  @media (prefers-reduced-motion: no-preference) {
    .size__dim--scene .size__rule, .size__dim--scene .size__cap { animation: sz-draw linear both; animation-timeline: --sz; animation-range: entry 55% cover 50%; }
    .size__dim--scene .size__rule:first-of-type { transform-origin: 100% 50%; }
    .size__dim--scene .size__rule:last-of-type { transform-origin: 0 50%; }
    .size__dim--scene .size__val { animation: sz-val linear both; animation-timeline: --sz; animation-range: entry 70% cover 50%; }
    .size__scene { view-timeline: --sz block; }
    @keyframes sz-draw { from { transform: scaleX(0); opacity: 0; } }
    @keyframes sz-val { from { opacity: 0; transform: translate(-50%, 10px); } }
  }
}
.size__dim--scene .size__val {
  position: absolute; left: 50%; bottom: calc(100% + 8px); transform: translateX(-50%); white-space: nowrap;
}
.size__foot {
  display: grid; gap: var(--s5); margin-top: clamp(24px, 3vw, 40px);
}
.size__foot p { margin: 0; color: var(--paper-2); max-width: 46ch; }
@media (min-width: 900px) {
  .size__foot { grid-template-columns: minmax(0, 1fr) auto; align-items: end; }
}
@media (max-width: 899px) {
  .size__dim--scene { left: 45.04%; width: 12.28%; top: calc(32.97% - 12px); }
}

/* ---- 21. Hero ground: the same home at blue hour (2026-09-23, Marxk: "the
   hero background is a bit boring"). Generated plate, graded to the page
   navy, softly out of focus so the real render stays the only sharp thing.
   The counter runs behind the machine; the left is scrimmed for the words. */
.hero::before {
  content: ""; position: absolute; inset: 0; z-index: -2;
  background: url("/assets/img/scenes/herobg-d.webp") 62% 58% / cover no-repeat;
}
.hero::after {
  content: ""; position: absolute; inset: 0; z-index: -1; pointer-events: none;
  background:
    linear-gradient(90deg, rgba(2,16,34,.96) 0, rgba(2,16,34,.90) 34%, rgba(2,16,34,.34) 60%, rgba(2,16,34,.18) 100%),
    linear-gradient(0deg, var(--g1) 0, rgba(2,20,44,0) 22%);
}
@media (max-width: 899px) {
  /* phones: the plate lives behind the machine only; the words sit on navy */
  .hero::before { background-image: url("/assets/img/scenes/herobg-m.webp"); background-position: 50% 0; background-size: 100% auto; bottom: auto; height: 420px; }
  .hero::after { background: linear-gradient(180deg, rgba(2,16,34,.20) 0, rgba(2,16,34,.30) 200px, var(--g1) 400px); }
}

/* ---- 22. The panel as the page's one LIGHT band (2026-09-23, Marxk: the
   panel "probably needs a different segment style"). Every other band is
   navy with a head top-left; a change of ground is the beat the scroll was
   missing, and the dark panel reads as a real object on a pale table.
   Tokens are re-pointed locally so every existing rule inverts with them;
   the photograph keeps the bright set, since its hotspots sit on black. */
.band.panel {
  --paper: #06203a; --paper-2: #2e475b; --paper-3: #4d6477;
  --cyan: #0a6a6e; --cyan-d: #9fcfd0;
  --line: rgba(6, 32, 58, 0.16); --line-2: rgba(6, 32, 58, 0.10);
  background: #e8f0f3 linear-gradient(180deg, #e3edf0 0, #eef4f5 40%, #e6eff2 100%);
  color: var(--paper);
}
.band.panel h2, .band.panel h3 { color: var(--paper); }
.band.panel .pui__stage {
  --paper: #ecf3f7; --paper-2: #a9c0d0; --paper-3: #7f95a6;
  --cyan: #3cd0cf; --cyan-d: #0b3f47;
  --line: rgba(236, 243, 247, 0.14); --line-2: rgba(236, 243, 247, 0.07);
}
.band.panel .pui__img {
  border-radius: 22px; overflow: hidden;
  box-shadow: 0 2px 0 rgba(255,255,255,.6) inset, 0 40px 80px -30px rgba(2, 20, 44, 0.55), 0 12px 24px -12px rgba(2, 20, 44, 0.35);
}
.band.panel .pui__hint { color: #4d6477; }

/* ---- 23. Panel: quiet at rest, ONE animated cue (2026-09-23) ------------
   Rings on all ten icons read as a diagram. At rest the hotspots are
   invisible; a fine pointer gets a faint ring on hover; the pressed one
   lights as before. Until the first press, only Warm pulses. */
.pui.is-live .pui__hot { border-color: transparent; background: transparent; }
@media (hover: hover) and (pointer: fine) {
  .pui.is-live .pui__hot:hover { border-color: rgba(60, 208, 207, 0.55); background: rgba(60, 208, 207, 0.08); }
}
.pui.is-live .pui__hot.is-on { border-color: var(--cyan); background: rgba(60, 208, 207, 0.14); }
.pui.is-idle .pui__scrim { opacity: 0; }
.pui.is-idle .pui__hot.is-on { border-color: transparent; background: transparent; box-shadow: none; transform: translate(-50%, -50%); }
.pui.is-idle .pui__read { opacity: 0; visibility: hidden; }
.pui__hot.is-cue { border-color: var(--cyan) !important; border-width: 2px; }
.pui__hot.is-cue::before, .pui__hot.is-cue::after {
  content: ""; position: absolute; inset: -2px; border-radius: 50%;
  border: 2px solid var(--cyan); pointer-events: none;
}
@media (prefers-reduced-motion: no-preference) {
  .pui__hot.is-cue { animation: cue-breathe 1.8s ease-in-out infinite; }
  .pui__hot.is-cue::before, .pui__hot.is-cue::after { animation: cue-ring 1.8s cubic-bezier(0.2, 0.6, 0.3, 1) infinite; }
  .pui__hot.is-cue::after { animation-delay: 0.6s; }
  @keyframes cue-breathe {
    0%, 100% { box-shadow: 0 0 0 0 rgba(60, 208, 207, 0.0), 0 0 18px -4px rgba(60, 208, 207, 0.6); }
    50%      { box-shadow: 0 0 0 0 rgba(60, 208, 207, 0.0), 0 0 34px 2px rgba(60, 208, 207, 0.9); }
  }
  @keyframes cue-ring { from { transform: scale(1); opacity: 0.9; } to { transform: scale(1.9); opacity: 0; } }
}

/* ---- 24. No drawn circles on the device (Marxk 2026-09-23: "the circles are
   not part of the device"). The real panel is backlit icons on black, so the
   cue is the ICON lighting up in its own colour: a feathered glow screened
   over it, no border, no ring, no edge. Supersedes the ring rules in 23. */
.pui.is-live .pui__hot,
.pui.is-live .pui__hot:hover,
.pui.is-live .pui__hot.is-on,
.pui__hot.is-cue {
  border-color: transparent !important; background: transparent !important;
  box-shadow: none !important; animation: none !important;
}
.pui__hot { --glow: 60, 208, 207; }
.pui__hot[data-k="lock"] { --glow: 255, 70, 70; }
.pui__hot[data-k="hot"]  { --glow: 255, 72, 60; }
.pui__hot[data-k="tea"]  { --glow: 120, 220, 90; }
.pui__hot[data-k="warm"] { --glow: 255, 150, 60; }
.pui__hot[data-k="cold"] { --glow: 70, 170, 255; }
.pui__hot[data-k="vol"]  { --glow: 200, 205, 210; }
.pui__hot::before, .pui__hot::after { content: none; }
.pui__hot.is-cue::before {
  content: ""; position: absolute; inset: -22%; border: 0 !important; border-radius: 50%;
  pointer-events: none; mix-blend-mode: screen;
  background: radial-gradient(closest-side, rgba(var(--glow), 0.55), rgba(var(--glow), 0.18) 55%, rgba(var(--glow), 0) 100%);
  opacity: 0.9; transform: none;
}
.pui__hot.is-cue::after { content: none !important; }
@media (prefers-reduced-motion: no-preference) {
  .pui__hot.is-cue::before { animation: glow-breathe 1.6s ease-in-out infinite !important; }
  @keyframes glow-breathe { 0%, 100% { opacity: 0.35; transform: scale(0.9); } 50% { opacity: 1; transform: scale(1.08); } }
}
@media (hover: hover) and (pointer: fine) {
  .pui.is-live .pui__hot:hover::before {
    content: ""; position: absolute; inset: -18%; border-radius: 50%; pointer-events: none; mix-blend-mode: screen;
    background: radial-gradient(closest-side, rgba(var(--glow), 0.35), rgba(var(--glow), 0) 100%);
  }
}
/* keyboard users still need a visible focus: a soft glow, not a ring */
.pui__hot:focus-visible { outline: none; }
.pui__hot:focus-visible::before {
  content: ""; position: absolute; inset: -18%; border-radius: 50%; pointer-events: none; mix-blend-mode: screen;
  background: radial-gradient(closest-side, rgba(var(--glow), 0.6), rgba(var(--glow), 0) 100%);
}
/* the readout plate reads as the device's own display: no drawn border */
.pui__read { border-color: transparent; background: rgba(0, 4, 8, 0.96); }
/* the frost cue's drawn outline is a shape the device does not have: on the
   panel photograph, keep only the beads and the glow */
.pui__cue.cue--cold::before { content: none; }

/* ---- 25. Panel section reorganised (Marxk 2026-09-23: the instruction was
   "floating unnaturally"). The instruction is the label of the card it
   drives. Desktop: head + card left, the device large on the right.
   Phone: head, device, card. */
.pui__head h2 { max-width: 16ch; }
.pui__head { margin: 0; }
.pui__card {
  background: #fff; border-radius: 20px; padding: clamp(20px, 2.4vw, 32px);
  box-shadow: 0 1px 0 rgba(6,32,58,.06), 0 24px 48px -28px rgba(2,20,44,.35);
}
.pui__label {
  display: none; align-items: center; gap: 10px; margin: 0 0 var(--s4);
  font-size: var(--f-xs); letter-spacing: 0.12em; text-transform: uppercase; font-weight: 620; color: #0a6a6e;
}
.pui.is-live .pui__label { display: flex; }
.pui__dot { width: 8px; height: 8px; border-radius: 50%; background: #0a6a6e; flex: none; }
@media (prefers-reduced-motion: no-preference) {
  .pui.is-idle .pui__dot { animation: dot-breathe 1.6s ease-in-out infinite; }
  @keyframes dot-breathe { 0%,100% { box-shadow: 0 0 0 0 rgba(10,106,110,.45); } 50% { box-shadow: 0 0 0 7px rgba(10,106,110,0); } }
}
.pui__card .pui__facts { padding-top: 0 !important; align-self: auto !important; }
.pui.is-live .pui__card .pui__facts li.is-on { border-left: 0; padding-left: 0; padding-top: 0; }
@media (min-width: 980px) {
  .pui {
    grid-template-columns: minmax(0, 0.82fr) minmax(0, 1.18fr);
    grid-template-areas: "head stage" "card stage";
    grid-template-rows: auto 1fr; column-gap: clamp(40px, 5vw, 80px); row-gap: clamp(28px, 3vw, 40px);
    align-items: start;
  }
  .pui__head { grid-area: head; }
  .pui__stage { grid-area: stage; position: sticky; top: 96px; }
  .pui__card { grid-area: card; }
}
.pui__card .pui__facts h3 { margin: 0 0 10px; }
.pui__card .pui__facts li { row-gap: 0; align-content: start; }
.pui__card .pui__facts p { margin: 0; }

/* ---- 26. Hero plate x tide (Marxk 2026-09-23: the water transition "seems
   boxy and out of place" once the hero got its photograph). The plate was
   opaque to a hard bottom edge, so the tide rising behind it only showed
   below that line as a rectangle. The plate now dissolves over its lower
   third, and the caustic light fades in under the wave instead of starting
   on a straight line. */
.hero::before {
  -webkit-mask-image: linear-gradient(180deg, #000 0, #000 58%, transparent 100%);
          mask-image: linear-gradient(180deg, #000 0, #000 58%, transparent 100%);
}
.hero::after { background:
    linear-gradient(90deg, rgba(2,16,34,.96) 0, rgba(2,16,34,.90) 34%, rgba(2,16,34,.34) 60%, rgba(2,16,34,.18) 100%);
  -webkit-mask-image: linear-gradient(180deg, #000 0, #000 58%, transparent 100%);
          mask-image: linear-gradient(180deg, #000 0, #000 58%, transparent 100%); }
.tide__caustic {
  -webkit-mask-image: linear-gradient(180deg, transparent 0, rgba(0,0,0,.6) 90px, #000 220px);
          mask-image: linear-gradient(180deg, transparent 0, rgba(0,0,0,.6) 90px, #000 220px);
}
.tide__body { background: linear-gradient(180deg, rgba(10,55,80,0.0) 0, rgba(10,55,80,0.55) 40px, #041229 30vh, var(--g1) 46vh); }
@media (max-width: 899px) {
  .hero::before { -webkit-mask-image: linear-gradient(180deg, #000 0, #000 70%, transparent 100%); mask-image: linear-gradient(180deg, #000 0, #000 70%, transparent 100%); }
  .hero::after { background: linear-gradient(180deg, rgba(2,16,34,.20) 0, rgba(2,16,34,.30) 200px, var(--g1) 400px); -webkit-mask-image: none; mask-image: none; }
}
/* the tide hands over to the film without a line: the film's top edge
   feathers into the ground */
.day--film .day__film {
  -webkit-mask-image: linear-gradient(180deg, transparent 0, #000 16%);
          mask-image: linear-gradient(180deg, transparent 0, #000 16%);
}

/* ---- 27. LUNA trim (2026-09-23) -------------------------------------------
   Energy + day to day as a two-up quick-info block. */
@media (min-width: 640px) { .trio--two { grid-template-columns: repeat(2, 1fr); } }
.trio--two h3 { font-size: var(--f-lead); margin-bottom: var(--s3); }

/* ---- 28. ABOUT (rebuilt 2026-09-23) --------------------------------------
   Real client photographs only. Hero = copy + a tall photo; the story as
   three numbered steps; a strip of three photos that bleeds on phones as a
   swipe row; company facts as a quick-info grid; the van copy in the close. */
.ab-hero { display: grid; gap: var(--s6); align-items: center; padding-block: clamp(40px, 6vw, 96px) clamp(32px, 4vw, 64px); }
.ab-hero h1 { font-family: Fraunces, serif; font-weight: 340; font-size: var(--f-h1, var(--f-h2)); line-height: 1.02; letter-spacing: -0.02em; margin: var(--s4) 0 var(--s5); max-width: 12ch; font-variation-settings: "opsz" 144; }
.ab-hero h1 .hl { color: var(--cyan); font-style: normal; }
.ab-hero__pic { margin: 0; border-radius: var(--radius); overflow: hidden; aspect-ratio: 4 / 5; box-shadow: 0 30px 80px -30px rgba(0,0,0,0.7); }
.ab-hero__pic img { display: block; width: 100%; height: 100%; object-fit: cover; }
@media (max-width: 899px) { .ab-hero__pic { aspect-ratio: 4 / 3.4; } .ab-hero__pic img { object-position: 50% 45%; } }
@media (min-width: 900px) { .ab-hero { grid-template-columns: minmax(0, 1.1fr) minmax(0, 0.9fr); gap: clamp(40px, 6vw, 110px); } }
.ab-steps h3 { font-size: var(--f-lead); margin-bottom: var(--s3); }
.ab-strip { padding-block: var(--s6) var(--s8); }
.ab-strip__row { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: var(--s4); max-width: var(--maxw, 1240px); margin: 0 auto; padding-inline: var(--pad); }
.ab-strip__row img { display: block; width: 100%; height: auto; aspect-ratio: 3 / 4; object-fit: cover; border-radius: var(--radius); }
.ab-strip__row img:nth-child(2) { transform: translateY(clamp(16px, 3vw, 48px)); }
.ab-strip__cap { margin-top: clamp(28px, 4vw, 64px); text-align: center; }
@media (max-width: 899px) {
  .ab-strip__row { grid-auto-flow: column; grid-template-columns: none; grid-auto-columns: 70%; overflow-x: auto; scroll-snap-type: x mandatory; padding-bottom: var(--s3); scrollbar-width: none; }
  .ab-strip__row::-webkit-scrollbar { display: none; }
  .ab-strip__row img { scroll-snap-align: center; }
  .ab-strip__row img:nth-child(2) { transform: none; }
}
.ab-facts { display: grid; gap: var(--s4); margin: 0; }
@media (min-width: 640px) { .ab-facts { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (min-width: 1000px) { .ab-facts { grid-template-columns: repeat(4, minmax(0, 1fr)); } }
.ab-facts div { border-top: 1px solid var(--line-2); padding-top: var(--s4); }
.ab-facts dt { font-size: var(--f-xs); letter-spacing: 0.14em; text-transform: uppercase; color: var(--cyan); font-weight: 600; margin-bottom: var(--s2); }
.ab-facts dd { margin: 0; color: var(--paper); }
.close__lead { max-width: 58ch; margin: calc(var(--s5) * -1) auto var(--s7); color: var(--paper-2); }
.close .eyebrow { justify-content: center; text-align: center; }

/* ---- 29. INSIDE, re-set (2026-09-23, Marxk: "improve this section, UI/UX").
   Was: a heading alone on an empty band, then a 420vh pin where three of
   four text beats sat at ~0 opacity at any moment, a dots rail and an
   internal footnote. Now: the heading lives in the stage, all four parts
   are always readable (the active one lit, a cyan bar beside it), the pin
   is 300vh, the rail and the footnote are gone. Phones: heading, the
   render, then the four parts as a swipe row. ----------------------------- */
.cam__rail { display: none; }
.cam__head { margin-bottom: var(--s5); }
.cam__head h2 { margin: var(--s3) 0 0; }
.cam__beat h3 { font-size: var(--f-lead); }
@media (max-width: 699px) {
  .cam__text { grid-auto-flow: column; grid-template-columns: none; grid-auto-columns: 82%; overflow-x: auto;
    scroll-snap-type: x mandatory; margin-inline: calc(var(--pad) * -1); padding: 0 var(--pad) var(--s3);
    scroll-padding-inline: var(--pad); scrollbar-width: none; }
  .cam__text::-webkit-scrollbar { display: none; }
  .cam__beat { scroll-snap-align: start; }
}
@supports (animation-timeline: view()) {
  @media (prefers-reduced-motion: no-preference) and (min-width: 700px) {
    .cam { height: 300vh; }
    .cam__stage { grid-template-areas: "head view" "text view"; grid-template-rows: auto 1fr; align-items: start; align-content: center; row-gap: 0; }
    .cam__head { grid-area: head; margin-bottom: var(--s6); }
    .cam__head h2 { font-size: var(--f-h3); }
    .cam__view { grid-area: view; align-self: center; }
    .cam__text { grid-area: text; display: flex; flex-direction: column; gap: var(--s4); }
    .cam__beat { position: relative; padding-left: var(--s5); transform: none; }
    .cam__beat::before { content: ""; position: absolute; left: 0; top: 2px; bottom: 2px; width: 2px; border-radius: 2px; background: var(--cyan); opacity: 0;
      animation: inherit; animation-timeline: --cam; animation-range: contain 0% contain 100%; animation-fill-mode: both; animation-timing-function: linear; }
    .cam__beat .cam__k { margin-bottom: var(--s2); }
    .cam__beat h3 { margin-bottom: var(--s2); }
    .cam__beat p:last-child { font-size: var(--f-s); }
    .cb1 { animation-name: ib-1; } .cb2 { animation-name: ib-2; } .cb3 { animation-name: ib-3; } .cb4 { animation-name: ib-4; }
    .cb1::before { animation-name: ibar-1; } .cb2::before { animation-name: ibar-2; } .cb3::before { animation-name: ibar-3; } .cb4::before { animation-name: ibar-4; }
    @keyframes ib-1 { 0%, 4% { opacity: .5; } 10%, 30% { opacity: 1; } 36%, 100% { opacity: .5; } }
    @keyframes ib-2 { 0%, 36% { opacity: .5; } 42%, 56% { opacity: 1; } 62%, 100% { opacity: .5; } }
    @keyframes ib-3 { 0%, 62% { opacity: .5; } 68%, 82% { opacity: 1; } 88%, 100% { opacity: .5; } }
    @keyframes ib-4 { 0%, 88% { opacity: .5; } 94%, 100% { opacity: 1; } }
    @keyframes ibar-1 { 0%, 4% { opacity: 0; } 10%, 30% { opacity: 1; } 36%, 100% { opacity: 0; } }
    @keyframes ibar-2 { 0%, 36% { opacity: 0; } 42%, 56% { opacity: 1; } 62%, 100% { opacity: 0; } }
    @keyframes ibar-3 { 0%, 62% { opacity: 0; } 68%, 82% { opacity: 1; } 88%, 100% { opacity: 0; } }
    @keyframes ibar-4 { 0%, 88% { opacity: 0; } 94%, 100% { opacity: 1; } }
    .cam .ring { opacity: .35; }
  }
}
/* the menu button always sits at the right edge (Marxk 09-23) */
.menu__btn { margin-left: auto; }
/* phones: the big closing button stays on one line (it wrapped to two at 390) */
@media (max-width: 480px) { .btn--big { font-size: var(--f-b); padding: 16px 26px; white-space: nowrap; } }

/* ---- 20. Hero = the mobile showroom (Kenneth, 2026-10-23) -------------
   Kenneth's own photo of the van, cut out (windscreen rebuilt: the cutout
   took it for background). It drives in from the right (it faces left, so
   nose first), brakes, dips its nose once and rests. No spinning hubcaps:
   on a phone they strobed and looked fake (Kenneth, 24 Oct). Transform/
   opacity only. Reduced motion or no JS: the van is simply parked.
   The old LUNA hero is section 2 (#luna); its headline is an h2. */
.vhero { position: relative; overflow: hidden; isolation: isolate; }
.vhero__in { display: grid; gap: var(--s5); align-items: center; padding-block: clamp(20px, 4vw, 56px) clamp(32px, 5vw, 72px); }
.vhero__copy { max-width: 34rem; }
.vhero h1 { font-size: clamp(2.375rem, 1.9rem + 2.6vw, 4.25rem); text-wrap: balance; margin-bottom: var(--s5); }
.vhero .lead { max-width: 46ch; color: var(--paper-2); }
.vhero__van { position: relative; margin: 0; }
.vhero__car { position: relative; }
.vhero__body { position: relative; z-index: 1; transform-origin: 90% 72%; }
.vhero__body > img { display: block; width: 100%; height: auto; }
/* ground: one long shadow along the line from the front tyre to the rear
   tyre (the photo is three-quarter, so that line climbs ~12deg), a tight
   contact shadow under each tyre, and a cyan floor light behind */
.vhero__car::before {
  content: ""; position: absolute; z-index: 0; left: 6%; width: 92%; top: 80%; height: 15%;
  background: radial-gradient(ellipse 50% 50% at 50% 50%, rgba(0, 0, 0, 0.6), rgba(0, 0, 0, 0.25) 55%, transparent 72%);
  transform: rotate(-12deg); transform-origin: 50% 50%;
}
.vhero__body::after {
  content: ""; position: absolute; z-index: -1; inset: 0;
  background:
    radial-gradient(ellipse 9% 2.6% at 31.5% 98.6%, rgba(0, 0, 0, 0.75), transparent),
    radial-gradient(ellipse 5% 1.8% at 91.2% 72%, rgba(0, 0, 0, 0.7), transparent);
}
.vhero__van::after {
  content: ""; position: absolute; z-index: -1; left: -10%; right: -10%; bottom: -10%; height: 60%;
  background: radial-gradient(ellipse 50% 50% at 50% 70%, rgba(60, 208, 207, 0.16), rgba(60, 208, 207, 0.04) 45%, transparent 70%);
}
@media (max-width: 899px) {
  .vhero__van { order: -1; margin-inline: -8px -12px; }
  .vhero h1 { margin-bottom: var(--s4); }
}
@media (min-width: 900px) {
  .vhero__in { grid-template-columns: minmax(0, 0.42fr) minmax(0, 0.58fr); gap: clamp(24px, 3vw, 56px); min-height: min(80vh, 760px); }
  .vhero__van { margin-right: -8%; }
}
.hero h2 { font-size: clamp(2rem, 1.6rem + 2vw, 3.5rem); text-wrap: balance; margin-bottom: var(--s5); }
@media (prefers-reduced-motion: no-preference) {
  /* a long, even deceleration, the way a driver brakes to a kerb */
  .motion .vhero__car { animation: van-in 1900ms cubic-bezier(0.22, 0.61, 0.36, 1) 150ms backwards; }
  .motion .vhero__body { animation: van-brake 650ms cubic-bezier(0.33, 1, 0.68, 1) 1850ms; }
  /* road streaks behind the van while it is moving, gone before it stops */
  .motion .vhero__car::after {
    content: ""; position: absolute; z-index: 0; left: 88%; width: 70%; top: 52%; height: 40%; pointer-events: none;
    background:
      linear-gradient(90deg, rgba(222, 246, 247, 0.5), transparent) 0 18% / 70% 2px no-repeat,
      linear-gradient(90deg, rgba(60, 208, 207, 0.55), transparent) 10% 46% / 95% 2px no-repeat,
      linear-gradient(90deg, rgba(222, 246, 247, 0.35), transparent) 4% 74% / 55% 1px no-repeat,
      linear-gradient(90deg, rgba(60, 208, 207, 0.4), transparent) 0 96% / 80% 2px no-repeat;
    opacity: 0; animation: van-streak 1500ms linear 150ms;
  }
  .motion .vhero__copy > * { animation: vcopy-in 700ms cubic-bezier(0.23, 1, 0.32, 1) backwards; }
  .motion .vhero__copy > :nth-child(2) { animation-delay: 80ms; }
  .motion .vhero__copy > :nth-child(3) { animation-delay: 160ms; }
  .motion .vhero__copy > :nth-child(4) { animation-delay: 240ms; }
  .motion .vhero__copy > :nth-child(5) { animation-delay: 320ms; }
  @keyframes van-in { from { transform: translateX(110vw); } }
  @keyframes van-streak { 0% { opacity: 0.9; } 55% { opacity: 0.6; } 100% { opacity: 0; } }
  /* the nose (left) dips as it brakes, then the springs lift it back once */
  @keyframes van-brake { 0%, 100% { transform: none; } 35% { transform: rotate(-0.7deg); } 70% { transform: rotate(0.2deg); } }
  @keyframes vcopy-in { from { opacity: 0; transform: translateY(16px); } }
}
