/* ==========================================================================
   scenes.css - no-scroll 4-scene layout for the English page (index.html).
   Self-contained: tokens copied from style.css, no @import. Linked ONLY from
   index.html. ko.html keeps style.css untouched.

   Progressive enhancement contract:
   - No JS: every .scene stacks in normal flow (min-height:100vh), page scrolls,
     the dock is hidden. Zero content loss.
   - html.js-scenes (added by scenes.js): scenes become fixed crossfading
     overlays and only the active one (body[data-scene="X"] #X) is visible.
   The splash sits above everything (z-index 9999); dock/chrome stay below 9000.
   ========================================================================== */

:root{
  --cream:#F9F3EB;
  --teal:#035F5C;
  --teal-deep:#023A38;
  --leaf:#7EC179;
  --pink:#EC9BAC;
  --ink:#0E2B29;
  --ink-soft:rgba(14,43,41,.62);
  --sage-top:#EAF2EC;
  --sage-mid:#E5EFE8;
  --sage-deep:#C6E0D2;
  --sage-ink:#2C5D33;
  /* Micro-typography and white-on-dark ladders (R30): every caps label, meta
     size, and translucent white in the scenes maps to one of these. */
  --track-wide:.3em;
  --track-meta:.22em;
  --fs-meta:13px;
  --fs-meta-sm:11px;
  --w88:rgba(255,255,255,.88);
  --w72:rgba(255,255,255,.72);
  --w60:rgba(255,255,255,.6);
  --w44:rgba(255,255,255,.44);
  --line:rgba(255,255,255,.5);
  --line-soft:rgba(255,255,255,.3);
  --line-strong:rgba(255,255,255,.75);
  --glass:rgba(255,255,255,.16);
  --glass-strong:rgba(255,255,255,.24);
  --maxw:1200px;
  --ease:cubic-bezier(.2,.7,.3,1);
}

*{box-sizing:border-box}

body{
  margin:0;
  background:var(--cream);
  color:var(--ink);
  /* Site-wide serif (user call: unify on the "Good habits" typeface). Weights
     stay 400/700 only - Georgia has no heavier cuts, faux-bold looks bad. */
  font-family:Georgia,"Times New Roman",serif;
  -webkit-font-smoothing:antialiased;
  text-rendering:optimizeLegibility;
  overflow-x:hidden;
  word-break:keep-all;
}

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

/* Text selection in the brand palette (default blue looks foreign on the dark scenes). */
::selection{background:var(--leaf);color:var(--ink)}

/* Keyboard focus: one white ring for every control (links, pills, buttons).
   :focus-visible only, so mouse clicks stay ring-free. */
:focus-visible{outline:2px solid rgba(255,255,255,.85);outline-offset:3px}

/* Serif italic accent (Georgia), echoing the splash counter's numeral. */
.acc{
  font-family:Georgia,"Times New Roman",serif;
  font-style:italic;
  font-weight:400;
}

/* Clean line breaking: accent phrases and compound terms (.nb) never split
   across lines; multi-line statements balance their line lengths; body copy
   avoids orphan last words. text-wrap is a progressive enhancement (ignored
   by older browsers); the longest nowrap phrase still fits a 320px viewport. */
.acc,.nb{white-space:nowrap}
.home-sub,.about-lead,.about-body,.product-sub{text-wrap:balance}
.product-body{text-wrap:pretty}
.team-strip .member{white-space:nowrap}

.kicker{
  font-size:var(--fs-meta);
  letter-spacing:var(--track-wide);
  text-transform:uppercase;
  color:var(--leaf);
  font-weight:400;
  margin:0 0 20px;
}

/* ---------------------------------------------------------------- chrome */
.chrome{
  position:fixed;
  top:0;left:0;
  z-index:2000;
  padding:clamp(20px,3vw,28px);
}
.brand{display:inline-flex;align-items:center}
.brand img{
  height:30px;width:auto;display:block;
  /* White over the dark scenes; drop-shadow keeps the mark legible on bright water. */
  filter:brightness(0) invert(1) drop-shadow(0 1px 6px rgba(2,58,56,.35));
}

/* ---------------------------------------------------------------- scenes */
/* No-JS default: normal-flow full-height panels that scroll. */
.scene{
  position:relative;
  min-height:100vh;
  min-height:100svh;
  display:flex;
  flex-direction:column;
  align-items:center;
  justify-content:center;
  padding:clamp(84px,12vh,140px) clamp(20px,4vw,44px);
  overflow:hidden;
}

/* JS mode: fixed crossfading overlays, only the active scene visible. */
html.js-scenes,
html.js-scenes body{height:100%;overflow:hidden}
html.js-scenes .scene{
  position:fixed;
  inset:0;
  min-height:0;
  opacity:0;
  visibility:hidden;
  pointer-events:none;
  transform:scale(1.02);
  transition:opacity .6s ease,transform .6s ease,visibility .6s ease;
  z-index:1;
}
html.js-scenes body[data-scene="home"] #home,
html.js-scenes body[data-scene="about"] #about,
html.js-scenes body[data-scene="product"] #product,
html.js-scenes body[data-scene="contact"] #contact{
  opacity:1;
  visibility:visible;
  pointer-events:auto;
  transform:scale(1);
  z-index:2;
}

/* ------------------------------------------------------------- home scene */
.scene-home{padding:0}
.home-media{position:absolute;inset:0;z-index:0}
.home-media video{width:100%;height:100%;object-fit:cover;display:block}
/* Local scrim recipe copied verbatim from style.css .hero-scrim (keeps white AA). */
.home-scrim{
  position:absolute;inset:0;
  background:
    radial-gradient(ellipse 76% 62% at 50% 49%,rgba(2,58,56,.64) 0%,rgba(2,58,56,.40) 50%,rgba(2,58,56,0) 78%),
    linear-gradient(180deg,rgba(2,58,56,.20) 0%,rgba(2,58,56,0) 32%,rgba(2,58,56,.40) 100%);
}
.home-copy{
  position:relative;z-index:2;
  text-align:center;
  color:#fff;
  padding:0 24px;
  max-width:900px;
}
.home-title{
  font-size:clamp(34px,5.2vw,64px);
  line-height:1.16;
  margin:0 0 18px;
  font-weight:400;
  letter-spacing:0;
  text-shadow:0 1px 24px rgba(2,58,56,.5);
}
.home-title .line{display:block}   /* original two-line balance of the hero */
.home-sub{
  font-size:clamp(15px,1.7vw,19px);
  line-height:1.6;
  color:var(--w88);
  font-weight:400;
  margin:0 auto;
  max-width:34em;
  text-shadow:0 1px 16px rgba(2,58,56,.45);
}

/* ------------------------------------------------------------ about scene */
/* Full-bleed water video like Home; the gradient stays as the loading/failure
   fallback behind it. The scrim keeps the white statement and team strip AA. */
.scene-about{
  justify-content:space-between;
  background:linear-gradient(180deg,
    #7FB49A 0%,
    #3C8271 20%,
    #10655C 46%,
    #045650 72%,
    #023A38 100%);
  color:#fff;
}
.about-media{position:absolute;inset:0;z-index:0;overflow:hidden}
.about-media video{width:100%;height:100%;object-fit:cover;display:block}
.about-scrim{
  position:absolute;inset:0;
  background:
    radial-gradient(ellipse 76% 62% at 50% 49%,rgba(2,58,56,.64) 0%,rgba(2,58,56,.40) 50%,rgba(2,58,56,0) 78%),
    linear-gradient(180deg,rgba(2,58,56,.20) 0%,rgba(2,58,56,0) 32%,rgba(2,58,56,.48) 100%);
}
.about-inner{
  position:relative;
  z-index:2;
  flex:1;
  display:flex;
  flex-direction:column;
  align-items:center;
  justify-content:center;
  text-align:center;
  max-width:var(--maxw);
  margin:0 auto;
}
/* Width caps live on each line in ITS OWN em so the lead breaks into two
   balanced lines (a single 20em cap measured in the base font squeezed
   everything to ~320px and forced 4-5 awkward wraps). */
.about-lead{
  display:block;
  font-size:clamp(28px,4.2vw,50px);
  line-height:1.22;
  font-weight:400;
  letter-spacing:0;
  max-width:16em;
  margin:0 auto clamp(16px,2.4vh,26px);
}
.about-body{
  display:block;
  font-size:clamp(16px,1.9vw,22px);
  line-height:1.62;
  font-weight:400;
  color:var(--w88);
  max-width:30em;
  margin:0 auto;
}
.about-values{
  list-style:none;
  margin:clamp(30px,5vh,52px) 0 0;
  padding:0;
  display:flex;
  flex-wrap:wrap;
  justify-content:center;
  gap:clamp(20px,5vw,64px);
}
.about-values li{
  font-size:var(--fs-meta-sm);
  letter-spacing:var(--track-meta);
  text-transform:uppercase;
  font-weight:400;
  color:var(--w88);
}
/* Team strip along the bottom; bios live in each member's hover/tap popover. */
.team-strip{
  position:relative;
  z-index:2;
  list-style:none;
  margin:clamp(28px,5vh,48px) 0 0;
  padding:0;
  display:flex;
  flex-wrap:wrap;
  justify-content:center;
  gap:10px clamp(16px,3vw,34px);
}
.team-strip .member{
  font-size:var(--fs-meta);
  letter-spacing:.02em;
  color:var(--w72);
  cursor:default;
}
.team-strip li{position:relative}
/* Bio popover: pure CSS on hover AND focus, so touch (tap focuses the tabindex
   span) and keyboard both get what desktop hover gets. Dark glass card above
   the name; :focus (not :focus-visible) because a tap must open it. */
.member::after{
  content:attr(data-bio);
  position:absolute;
  left:50%;
  bottom:calc(100% + 10px);
  transform:translateX(-50%) translateY(4px);
  width:max-content;
  max-width:min(520px,90vw);   /* wide enough that each career line stays unwrapped */
  white-space:pre-line;   /* newlines in data-bio become line breaks (career items) */
  text-align:center;
  font-size:var(--fs-meta-sm);
  line-height:1.6;
  letter-spacing:.01em;
  padding:10px 14px;
  border-radius:12px;
  color:var(--w88);
  background:rgba(2,58,56,.55);
  border:1px solid var(--line-soft);
  -webkit-backdrop-filter:blur(10px) saturate(1.2);
  backdrop-filter:blur(10px) saturate(1.2);
  opacity:0;
  pointer-events:none;
  z-index:5;
  transition:opacity .3s var(--ease),transform .3s var(--ease);
}
.member:hover::after,
.member:focus::after{opacity:1;transform:translateX(-50%) translateY(0)}
/* Below wide desktop: the anchored popover (wide enough for unwrapped career
   lines) would clip at the strip edges, so it becomes a fixed glass bar above
   the dock instead (the scene's transform makes fixed resolve against the
   scene box, which is viewport-sized here). */
@media (max-width:1024px){
  .member::after{
    position:fixed;
    left:16px;
    right:16px;
    bottom:112px;
    width:auto;
    max-width:none;
    transform:translateY(4px);
  }
  .member:hover::after,
  .member:focus::after{transform:translateY(0)}
}

/* ---------------------------------------------------------- product scene */
/* Full-bleed water video like About/Contact; the gradient stays as the
   loading/failure fallback behind it. The scrim keeps the white teaser copy
   AA. The cream Mayu world lives on the separate Mayu landing page behind the CTA. */
.scene-product{
  background:
    radial-gradient(ellipse 52% 44% at 50% 46%,rgba(127,180,154,.16) 0%,rgba(127,180,154,0) 72%),
    linear-gradient(180deg,#10655C 0%,#045650 55%,#023A38 100%);
  color:#fff;
}
.product-media{position:absolute;inset:0;z-index:0;overflow:hidden}
.product-media video{width:100%;height:100%;object-fit:cover;display:block}
.product-scrim{
  position:absolute;inset:0;
  background:
    radial-gradient(ellipse 76% 62% at 50% 49%,rgba(2,58,56,.64) 0%,rgba(2,58,56,.40) 50%,rgba(2,58,56,0) 78%),
    linear-gradient(180deg,rgba(2,58,56,.20) 0%,rgba(2,58,56,0) 32%,rgba(2,58,56,.48) 100%);
}
.product-inner{
  position:relative;
  z-index:2;
  max-width:var(--maxw);
  margin:0 auto;
  width:100%;
  text-align:center;
}
.product-copy .kicker{color:var(--leaf)}
.product-title{
  font-size:clamp(42px,5.4vw,68px);
  line-height:1.08;
  margin:0 0 12px;
  font-weight:400;
  letter-spacing:0;
}
.product-sub{
  margin:0 0 18px;
  font-size:clamp(16px,1.9vw,21px);
  font-weight:400;
  font-style:italic;                       /* serif italic subtitle, accent-style */
  color:var(--w88);
  letter-spacing:.005em;
}
.product-body{
  margin:0 auto 34px;
  font-size:clamp(15px,1.6vw,17px);
  line-height:1.8;
  color:var(--w72);
  max-width:30em;
}
.cta-mayu{
  display:inline-block;
  background:var(--glass);
  color:#fff;
  border:1px solid var(--line);
  border-radius:999px;
  padding:14px 30px;
  font-size:14px;
  font-weight:400;
  letter-spacing:.04em;
  text-decoration:none;
  -webkit-backdrop-filter:blur(10px) saturate(1.2);
  backdrop-filter:blur(10px) saturate(1.2);
  transition:transform .3s var(--ease),background .3s var(--ease),border-color .3s var(--ease),box-shadow .3s var(--ease);
}
.cta-mayu:hover{
  background:var(--glass-strong);
  border-color:var(--line-strong);
  transform:translateY(-2px);
  box-shadow:0 12px 30px rgba(2,58,56,.3);
}
.cta-mayu:hover .roll > span{ transform:translateY(-100%); }

/* ---------------------------------------------------------- contact scene */
/* Full-bleed water video like About; the gradient stays as the loading/failure
   fallback behind it. The scrim keeps the white contact copy and small print AA. */
.scene-contact{
  background:linear-gradient(180deg,
    #7FB49A 0%,
    #3C8271 20%,
    #10655C 46%,
    #045650 72%,
    #023A38 100%);
  color:#fff;
}
.contact-media{position:absolute;inset:0;z-index:0;overflow:hidden}
.contact-media video{width:100%;height:100%;object-fit:cover;display:block}
/* Same recipe as .about-scrim; the bottom linear is a touch deeper (.52 vs .48)
   since the legal small print sits low-center over the brightest water sparkle. */
.contact-scrim{
  position:absolute;inset:0;
  background:
    radial-gradient(ellipse 76% 62% at 50% 49%,rgba(2,58,56,.64) 0%,rgba(2,58,56,.40) 50%,rgba(2,58,56,0) 78%),
    linear-gradient(180deg,rgba(2,58,56,.20) 0%,rgba(2,58,56,0) 32%,rgba(2,58,56,.52) 100%);
}
.contact-inner{
  position:relative;
  z-index:2;
  max-width:var(--maxw);
  margin:0 auto;
  text-align:center;
}
.contact-kicker{margin:0 0 clamp(30px,5vh,52px)}
/* Two channels, the hero of the scene. */
.contact-emails{
  margin:0 auto;
}
.contact-row{margin:0}
.contact-row + .contact-row{margin-top:clamp(18px,3.2vh,30px)}
.contact-label{
  display:block;
  font-size:var(--fs-meta-sm);
  letter-spacing:var(--track-meta);
  text-transform:uppercase;
  font-weight:400;
  color:var(--w60);
  margin:0 0 12px;
}
.contact-mail{
  display:inline-block;
  font-size:clamp(20px,2.4vw,29px);
  font-weight:400;
  letter-spacing:.005em;
  color:#fff;
  text-decoration:none;
  /* Resting underline removed; hover reveals the hairline (border keeps its slot). */
  border-bottom:1px solid transparent;
  padding-bottom:3px;
  text-shadow:0 1px 16px rgba(2,58,56,.45);
  transition:color .3s var(--ease),border-color .3s var(--ease);
}
.contact-mail:hover{border-color:var(--line-strong)}
/* Hairline rule separating the emails from the corporate block. */
.contact-rule{
  width:54px;
  height:1px;
  margin:clamp(36px,6vh,58px) auto;
  background:var(--line-soft);
}
.contact-fine{font-size:var(--fs-meta);color:var(--w60)}
/* Legal document links, quiet row above the copyright line. */
.contact-legal{
  margin:14px 0 0;
  font-size:var(--fs-meta-sm);
  letter-spacing:.04em;
  color:var(--w60);
}
.contact-legal a{
  text-decoration:none;
  transition:color .3s var(--ease);
}
.contact-legal a:hover{color:#fff}
.contact-copy{
  margin:clamp(22px,3.6vh,34px) 0 0;
  font-size:var(--fs-meta-sm);
  letter-spacing:.06em;
  color:var(--w44);
}

/* ------------------------------------------------ scene entrance choreography */
/* Each active scene's key lines rise and fade in. Kept entirely inside
   no-preference so reduced-motion users get the content with zero animation.
   The rules match on body[data-scene="X"], so switching scenes (and the splash
   replay hook) re-triggers them. Base styles never set opacity:0, so no-JS and
   unsupported browsers keep every element; the "both" fill handles the pre-delay
   frame while active. */
@media (prefers-reduced-motion: no-preference){
  @keyframes sceneRise{
    from{opacity:0;transform:translateY(18px)}
    to{opacity:1;transform:translateY(0)}
  }
  @keyframes sceneRule{
    from{opacity:0;transform:scaleX(0)}
    to{opacity:1;transform:scaleX(1)}
  }
  html.js-scenes body[data-scene="home"] #home .home-title .line:first-child{animation:sceneRise .8s var(--ease) .08s both}
  html.js-scenes body[data-scene="home"] #home .home-title .line:last-child{animation:sceneRise .8s var(--ease) .2s both}
  html.js-scenes body[data-scene="home"] #home .home-sub{animation:sceneRise .8s var(--ease) .36s both}

  html.js-scenes body[data-scene="about"] #about .kicker{animation:sceneRise .8s var(--ease) .06s both}
  html.js-scenes body[data-scene="about"] #about .about-lead{animation:sceneRise .8s var(--ease) .16s both}
  html.js-scenes body[data-scene="about"] #about .about-body{animation:sceneRise .8s var(--ease) .3s both}
  html.js-scenes body[data-scene="about"] #about .about-values{animation:sceneRise .8s var(--ease) .44s both}
  html.js-scenes body[data-scene="about"] #about .team-strip{animation:sceneRise .8s var(--ease) .56s both}

  html.js-scenes body[data-scene="product"] #product .product-copy .kicker{animation:sceneRise .8s var(--ease) .06s both}
  html.js-scenes body[data-scene="product"] #product .product-title{animation:sceneRise .8s var(--ease) .16s both}
  html.js-scenes body[data-scene="product"] #product .product-sub{animation:sceneRise .8s var(--ease) .3s both}
  html.js-scenes body[data-scene="product"] #product .product-body{animation:sceneRise .8s var(--ease) .42s both}
  html.js-scenes body[data-scene="product"] #product .cta-mayu{animation:sceneRise .8s var(--ease) .54s both}

  html.js-scenes body[data-scene="contact"] #contact .contact-kicker{animation:sceneRise .8s var(--ease) .06s both}
  html.js-scenes body[data-scene="contact"] #contact .contact-emails{animation:sceneRise .8s var(--ease) .18s both}
  html.js-scenes body[data-scene="contact"] #contact .contact-rule{animation:sceneRule .7s var(--ease) .32s both}
  html.js-scenes body[data-scene="contact"] #contact .contact-fine{animation:sceneRise .8s var(--ease) .46s both}

  /* End-scene rubber-band: a gesture pushing past the first/last scene (scenes.js
     toggles .nudge-prev/.nudge-next on the active scene) gives a 6px bounce so a
     dead input still reads as received. No fill: transform returns to 0 (the
     active scene's own scale(1)); reduced-motion users are cut off by this block. */
  @keyframes sceneNudgeNext{0%{transform:translateY(0)}35%{transform:translateY(-6px)}100%{transform:translateY(0)}}
  @keyframes sceneNudgePrev{0%{transform:translateY(0)}35%{transform:translateY(6px)}100%{transform:translateY(0)}}
  html.js-scenes .scene.nudge-next{animation:sceneNudgeNext .4s var(--ease)}
  html.js-scenes .scene.nudge-prev{animation:sceneNudgePrev .4s var(--ease)}
}

/* -------------------------------------------------------------- dock */
.dock{
  display:none; /* hidden without JS */
  position:fixed;
  left:50%;
  bottom:clamp(18px,4vh,34px);
  transform:translateX(-50%);
  z-index:2000;
  /* Single dark palette now: white glass over every scene. */
  --dock-fg:#fff;
  --dock-bg:var(--glass);
  --dock-bd:var(--line);
  --dock-active-bg:#fff;
  --dock-active-fg:var(--ink);
}
html.js-scenes .dock{display:block}

.dock-toggle{
  display:flex;
  flex-direction:column;
  align-items:center;
  gap:7px;
  background:none;
  border:0;
  padding:0;
  font-family:inherit;   /* buttons do not inherit the body font by default */
  cursor:pointer;
  color:var(--dock-fg);
  transition:opacity .3s var(--ease),transform .3s var(--ease);
}
/* Brand H symbol in a transparent liquid-glass circle (matches the Welcome
   pill): no fill, hairline border, backdrop blur. The symbol is white over
   every scene, mirroring the top-left brand mark. */
.dock-badge{
  position:relative;
  width:44px;height:44px;
  border-radius:50%;
  display:flex;align-items:center;justify-content:center;
  background:transparent;
  border:1px solid var(--dock-bd);
  -webkit-backdrop-filter:blur(10px) saturate(1.2);
  backdrop-filter:blur(10px) saturate(1.2);
  box-shadow:0 6px 20px rgba(2,58,56,.14);
}
/* Inviting water ripples: two rings breathe out of the badge on a loop,
   scene-toned via the dock border token. Hidden with the badge when open. */
.dock-badge::before,
.dock-badge::after{
  content:"";
  position:absolute;
  inset:-1px;                    /* start on the badge border */
  border-radius:50%;
  border:1px solid var(--dock-bd);
  pointer-events:none;
  opacity:0;
  animation:dockRipple 3.2s cubic-bezier(.25,.6,.4,1) infinite;
}
.dock-badge::after{ animation-delay:1.6s; }
@keyframes dockRipple{
  0%{ transform:scale(1); opacity:.75; }
  70%{ opacity:.22; }
  100%{ transform:scale(2.15); opacity:0; }
}
.dock-badge img{
  height:21px;
  width:auto;
  filter:brightness(0) invert(1);
}
.dock-explore{
  font-size:var(--fs-meta-sm);
  letter-spacing:var(--track-meta);
  color:var(--dock-fg);
}

.dock-pills{
  position:absolute;
  left:50%;
  bottom:0;
  transform:translateX(-50%) scale(.96);
  display:flex;
  align-items:center;
  gap:8px;
  opacity:0;
  visibility:hidden;
  pointer-events:none;
  transition:opacity .3s var(--ease),transform .3s var(--ease),visibility .3s var(--ease);
}
.dock.is-open .dock-toggle{
  opacity:0;
  visibility:hidden;
  pointer-events:none;
  transform:scale(.96);
}
.dock.is-open .dock-pills{
  opacity:1;
  visibility:visible;
  pointer-events:auto;
  transform:translateX(-50%) scale(1);
}
.pill{
  font-size:var(--fs-meta);
  padding:9px 22px;
  border-radius:999px;
  text-decoration:none;
  white-space:nowrap;
  color:var(--dock-fg);
  background:var(--dock-bg);
  border:1px solid var(--dock-bd);
  -webkit-backdrop-filter:blur(10px) saturate(1.2);
  backdrop-filter:blur(10px) saturate(1.2);
  transition:background .3s var(--ease),color .3s var(--ease),border-color .3s var(--ease),transform .2s var(--ease);
}
.pill:hover{transform:translateY(-2px)}
/* Hover text roll (same recipe as the splash Welcome): per-letter spans; the
   duplicate row is each glyph's own text-shadow 1em below (currentColor, so it
   follows the scene tones and the active pill); hover lifts the letters -100%
   with a small stagger and the shadow copy rolls up into view. */
.roll{
  display:inline-flex;
  overflow:hidden;
  text-shadow:0 1em 0 currentColor;
}
.roll > span{
  display:block;
  line-height:1em;
  white-space:pre;
  -webkit-backface-visibility:hidden;
          backface-visibility:hidden;
  transform:translateY(0);
  transition:transform .5s cubic-bezier(.76,0,.24,1);
}
.pill:hover .roll > span,
.dock-toggle:hover .roll > span{ transform:translateY(-100%); }
.roll > span:nth-child(1){transition-delay:0ms}
.roll > span:nth-child(2){transition-delay:26ms}
.roll > span:nth-child(3){transition-delay:52ms}
.roll > span:nth-child(4){transition-delay:78ms}
.roll > span:nth-child(5){transition-delay:104ms}
.roll > span:nth-child(6){transition-delay:130ms}
.roll > span:nth-child(7){transition-delay:156ms}
.roll > span:nth-child(8){transition-delay:182ms}
.roll > span:nth-child(9){transition-delay:208ms}
.roll > span:nth-child(10){transition-delay:234ms}
.roll > span:nth-child(11){transition-delay:260ms}
.roll > span:nth-child(12){transition-delay:286ms}
.roll > span:nth-child(13){transition-delay:312ms}
.roll > span:nth-child(14){transition-delay:338ms}
.roll > span:nth-child(15){transition-delay:364ms}
.roll > span:nth-child(16){transition-delay:390ms}
/* flex items ignore letter-spacing, so the explore label's tracking becomes gap.
   text-shadow overrides .roll here, so the hover-roll clone glyph row (0 1em 0
   currentColor) must stay the first term; the second term is a glow for bright water. */
.dock-explore.roll{gap:var(--track-meta);text-shadow:0 1em 0 currentColor,0 1px 8px rgba(2,58,56,.45)}
.pill[aria-current="page"]{
  background:var(--dock-active-bg);
  color:var(--dock-active-fg);
  border-color:transparent;
}
.dock-close{
  width:34px;height:34px;
  border-radius:50%;
  display:inline-flex;align-items:center;justify-content:center;
  flex:0 0 auto;
  font-family:inherit;
  cursor:pointer;
  color:var(--dock-fg);
  background:var(--dock-bg);
  border:1px solid var(--dock-bd);
  -webkit-backdrop-filter:blur(10px) saturate(1.2);
  backdrop-filter:blur(10px) saturate(1.2);
  font-size:17px;
  line-height:1;
}

/* Dock pills stagger: on open, each control rises with a small per-item delay.
   Fill MUST be backwards (never forwards/both): a forwards fill would freeze the
   100% transform and kill the .pill:hover translateY(-2px). backwards applies the
   from-frame only during the pre-delay, then releases to the natural state, so
   hover stays alive. Own no-preference block; reduced-motion users get no stagger. */
@media (prefers-reduced-motion: no-preference){
  @keyframes pillRise{from{opacity:0;transform:translateY(8px)}to{opacity:1;transform:translateY(0)}}
  .dock.is-open .dock-pills > *{animation:pillRise .35s var(--ease) backwards}
  .dock.is-open .dock-pills > :nth-child(1){animation-delay:0ms}
  .dock.is-open .dock-pills > :nth-child(2){animation-delay:30ms}
  .dock.is-open .dock-pills > :nth-child(3){animation-delay:60ms}
  .dock.is-open .dock-pills > :nth-child(4){animation-delay:90ms}
  .dock.is-open .dock-pills > :nth-child(5){animation-delay:120ms}
}

/* -------------------------------------------------------- scene index */
/* Bottom-right counter (italic serif, echoing the splash 0-100). JS only, so it
   stays hidden without the fixed-scene layout; it fades out while the dock is
   open (the general sibling selector needs it to follow .dock in the markup). */
.scene-index{display:none}
html.js-scenes .scene-index{
  display:block;
  position:fixed;
  right:clamp(24px,4vw,48px);
  bottom:clamp(22px,4vh,40px);
  z-index:2000;
  font-style:italic;
  font-size:15px;
  letter-spacing:.08em;
  color:var(--w60);
  text-shadow:0 1px 12px rgba(2,58,56,.35);
  transition:opacity .3s var(--ease);
}
.dock.is-open ~ .scene-index{opacity:0}
.si-cur{display:inline-block}
@media (prefers-reduced-motion: no-preference){
  @keyframes siSwap{
    from{opacity:0;transform:translateY(.35em)}
    to{opacity:1;transform:translateY(0)}
  }
  .si-cur.swap{animation:siSwap .45s var(--ease)}
}

/* -------------------------------------------------------- film grain */
/* Fixed monochrome noise over every scene (z 1500: above the scenes, below the
   chrome/dock/index at 2000 and the splash at 9999). Inline SVG feTurbulence
   data URI, so it fetches nothing and is file:// safe. Always on, no-JS too:
   adds tooth at 100% and dithers banding on the flat Product gradient. */
body::after{
  content:"";
  position:fixed;
  inset:0;
  z-index:1500;
  pointer-events:none;
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='240' height='240'%3E%3Cfilter id='g'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='3' stitchTiles='stitch'/%3E%3CfeColorMatrix type='saturate' values='0'/%3E%3C/filter%3E%3Crect width='240' height='240' filter='url(%23g)'/%3E%3C/svg%3E");
  opacity:.05;
}

/* -------------------------------------------------------- reduced motion */
@media (prefers-reduced-motion:reduce){
  html.js-scenes .scene{transition:none;transform:none}
  html.js-scenes body[data-scene="home"] #home,
  html.js-scenes body[data-scene="about"] #about,
  html.js-scenes body[data-scene="product"] #product,
  html.js-scenes body[data-scene="contact"] #contact{transform:none}
  .dock-toggle,.dock-pills,.pill,.dock-close,.contact-mail,.cta-mayu,.member::after{transition:none}
  .roll > span{transition:none}
  .pill:hover .roll > span,.dock-toggle:hover .roll > span,.cta-mayu:hover .roll > span{transform:none}   /* no text roll */
  .dock-badge::before,.dock-badge::after{animation:none;opacity:0}   /* no ripple pulse */
}

/* -------------------------------------------------------------- responsive */
@media (max-width:720px){
  .brand img{height:24px}
  .home-title{font-size:clamp(30px,8vw,44px)}
  .home-sub{font-size:15px}
}

@media (max-width:480px){
  .pill{font-size:12px;padding:8px 14px}
  .dock-pills{gap:6px}
  .dock-close{width:30px;height:30px;font-size:16px}
}
