/* =============================================================================
   BOBA TEA — "the only colour is inside the cup"
   Every value here is a measured number from design-spec.md (klimt-wine capture).
   Type ratio 150/14 = 10.7:1 · inset 20px · radius {0,999px} · shadow {none}
   Motion: one-shot entrance chain, then ZERO ambient motion. No `infinite`,
   no resident rAF, no scroll-linked transform. Every transition routes through
   a var(--dur*) + var(--ease*) token.
   ========================================================================== */

@import url('https://fonts.googleapis.com/css2?family=Instrument+Serif:ital@0;1&family=Instrument+Sans:wght@400;500&display=swap');
@import url('https://fonts.googleapis.com/css2?family=Noto+Serif+SC:wght@400&family=Noto+Sans+SC:wght@400;500&display=swap');

/* ---------------------------------------------------------------- tokens -- */
:root{
  /* faces — matched on measured letterform characteristics, not on a name */
  --font-display:'Instrument Serif','Noto Serif SC','Times New Roman',serif;
  --font-body:'Instrument Sans','Noto Sans SC','Helvetica Neue',Arial,sans-serif;

  /* type scale — display cap-height 105px ÷ 0.70 = 150px @1440 */
  --fs-display-mult:1;
  --fs-display:calc(clamp(3.75rem, 2.86rem + 7.24vw, 10.5rem) * var(--fs-display-mult));
  --fs-h2:calc(clamp(2.5rem, 1.7rem + 4.35vw, 6.25rem) * var(--fs-display-mult));
  --fs-h3:clamp(1.5rem, 1.221rem + 1.143vw, 2.25rem);
  --fs-lead:14px; --fs-body:16px; --fs-ui:14px; --fs-micro:11px;
  --lh-display:.933; --lh-h2:.95; --lh-h3:1.12;
  --lh-lead:1.36; --lh-body:1.55; --lh-ui:1.71;
  /* The measured reference face (a Canela/Ogg-class serif) needed −0.022em to
     bring adjacent lowercase ink gaps to 4–8px at 150px. Instrument Serif ships
     ~0.02em tighter by default, so the SAME measured ink-gap target lands at
     −0.005em here; the acceptance test is the gap, not the number. Word space
     is pulled back to the measured ≈16px, which the face sets far wider. */
  --tr-display:-.005em; --ws-display:-.11em;
  --tr-h2:-.004em; --tr-h3:-.010em; --tr-micro:.22em;

  /* grounds — eyedropped at x=1425 */
  --ground:#191714; --plate:#CEC6BE; --pill:#FFFFFF; --chip:#EFEAE2;
  --ink:#F3F0EB; --ink-dim:rgba(243,240,235,.40);
  --rule:rgba(243,240,235,.14); --lift:rgba(243,240,235,.045);
  --ink-stage:#171512;            /* ground used as ink below 70% of a stage */

  /* nine series hues — measured out of each series' own photographs.
     NEVER promoted to :root usage; a section sets --series, one at a time. */
  --s-milk:#CD9765; --s-brownsugar:#864A36; --s-chizu:#E6CCB9; --s-fruit:#EDB102;
  --s-latte:#91A552; --s-tea:#C1A414; --s-viet:#DC9CD4; --s-mochi:#CE96A5;
  --s-limited:#DE530D;
  --series:var(--s-milk);

  /* space — 4px ramp: 4 8 12 16 20 24 32 40 48 64 80 96 120 140 160 200 240 */
  --inset:20px; --col-gap:20px; --content:1400px;
  --edge:max(var(--inset), calc((100% - var(--content)) / 2));
  --switch-gap:96px;
  /* COMPOSED (see design-spec §4.5) — the seam between two sections is ONE
     band of --pad-section, and 140px is the measured display leading: a seam
     is exactly one line of the biggest type on the page. After a LIT stage the
     seam drops to --pad-after-stage, because the floor's bright bottom edge is
     already the hardest edge in the system. */
  --pad-section:clamp(96px, 9.7vw, 140px);
  --pad-after-stage:clamp(48px, 4.4vw, 64px);
  --measure:62ch;

  /* motion — see §6. Absolute ms constrained by the MEASURED ratio 0.10 */
  --ease-out:cubic-bezier(.16,1,.3,1);
  --ease-wipe:cubic-bezier(.87,0,.13,1);
  --ease-micro:cubic-bezier(.33,1,.68,1);
  --dur-glyph:380ms;  --stagger-char:38ms;
  --dur-h2glyph:340ms;
  --dur-stage:900ms;  --stagger-item:120ms;
  --dur-lift:620ms;   --stagger-line:55ms;
  --dur-row:520ms;    --stagger-row:40ms;
  --dur-draw:420ms;   --dur-retract:300ms;
  --dur-wipe:500ms;   --dur-count:660ms;
  --dur-micro:180ms;  --dur-floor:1200ms; --dur-panel:1000ms;
  --dur-spring:500ms;
}

/* Chinese is the original language of this concept — optical corrections,
   not a font swap. Latin caps fill .70em, SC glyphs ~.86em. */
html[data-lang="zh"]{
  --fs-display-mult:.80; --lh-display:1.02; --tr-display:-.04em; --ws-display:0;
  --tr-h2:-.04em; --lh-body:1.8; --tr-micro:.28em; --stagger-char:76ms;
}
html[data-lang="es"]{ --fs-display-mult:.88 }

/* ------------------------------------------------------------------ base -- */
*,*::before,*::after{box-sizing:border-box}
html{-webkit-text-size-adjust:100%;color-scheme:dark}
body{margin:0;background:var(--ground);color:var(--ink);
  font:400 var(--fs-body)/var(--lh-body) var(--font-body);
  font-synthesis-weight:none;-webkit-font-smoothing:antialiased;overflow-x:hidden}
::selection{background:var(--series);color:var(--ground)}
img{display:block;max-width:100%}
a{color:inherit;text-decoration:none}
h1,h2,h3,p,figure,ul,table{margin:0;padding:0}
ul{list-style:none}
button{font:inherit;color:inherit;background:none;border:0;padding:0;cursor:pointer}
:focus-visible{outline:1px solid var(--ink);outline-offset:3px}

.dsp{font-family:var(--font-display);font-weight:400;
  font-size:var(--fs-display);line-height:var(--lh-display);
  letter-spacing:var(--tr-display);word-spacing:var(--ws-display)}
.h2{font-family:var(--font-display);font-weight:400;
  font-size:var(--fs-h2);line-height:var(--lh-h2);
  letter-spacing:var(--tr-h2);word-spacing:var(--ws-display)}
.h3{font-family:var(--font-display);font-weight:400;
  font-size:var(--fs-h3);line-height:var(--lh-h3);letter-spacing:var(--tr-h3)}
.lead{font-size:var(--fs-lead);line-height:var(--lh-lead);max-width:44ch}
.body{font-size:var(--fs-body);line-height:var(--lh-body);max-width:var(--measure)}
.dim{color:var(--ink-dim)}
.klab{display:block;font-size:var(--fs-micro);font-weight:500;line-height:1.3;
  letter-spacing:var(--tr-micro);text-transform:uppercase;color:var(--ink-dim)}
html[data-lang="zh"] .klab{text-transform:none}
.num{font-variant-numeric:tabular-nums}

.wrap{width:100%;max-width:calc(var(--content) + 2 * var(--inset));
  margin-inline:auto;padding-inline:var(--inset)}
.g12{display:grid;grid-template-columns:repeat(12,1fr);gap:var(--col-gap)}
.c1-5{grid-column:1/6} .c1-6{grid-column:1/7} .c1-7{grid-column:1/8} .c1-8{grid-column:1/9}
.c6-13{grid-column:6/13} .c7-13{grid-column:7/13} .c8-13{grid-column:8/13} .c9-13{grid-column:9/13}
.c1-13{grid-column:1/13}

.skip{position:absolute;left:-9999px;top:0;z-index:9600;padding:12px 20px;
  background:var(--ink);color:var(--ground);font-size:var(--fs-ui)}
.skip:focus{left:var(--inset);top:var(--inset)}

/* --------------------------------------------------------------- the nav -- */
.nav{position:absolute;top:var(--inset);left:0;right:0;z-index:6;
  padding-inline:var(--edge);
  display:grid;grid-template-columns:1fr auto 1fr;align-items:start;gap:24px}
.nav--flat{position:relative;top:0;padding-top:var(--inset)}
.nav__set{display:flex;flex-direction:column;gap:0}
.nav__set a{font-size:var(--fs-ui);line-height:var(--lh-ui);width:max-content}
.nav__mark{justify-self:center;text-align:center;display:block}
.nav__mark b{display:block;font-family:var(--font-display);font-weight:400;
  font-size:24px;line-height:1;letter-spacing:-.01em}
.nav__mark .klab{margin-top:8px}
.nav__end{justify-self:end;display:flex;align-items:baseline;gap:24px;
  font-size:var(--fs-ui);line-height:var(--lh-ui)}
.lang{display:flex;gap:8px;align-items:baseline}
.lang button{font-size:var(--fs-ui);line-height:var(--lh-ui);opacity:.4;
  position:relative;transition:opacity var(--dur-micro) var(--ease-micro)}
.lang button.is-on{opacity:1}
.lang button.is-on::after{content:"";position:absolute;left:0;right:0;bottom:-3px;
  height:1px;background:var(--ink)}
.nav__end .nav__mobile{display:none}

/* underline that DRAWS from the entry side and RETRACTS toward the exit side */
.ln{position:relative;display:inline-block}
.ln::after{content:"";position:absolute;left:0;right:0;bottom:-2px;height:1px;
  background:var(--ink);transform:scaleX(0);transform-origin:var(--o,left) center;
  transition:transform var(--dur-retract) var(--ease-out);pointer-events:none}
.ln[aria-current="page"]::after{transform:scaleX(1);background:var(--ink-dim)}
@media (hover:hover) and (pointer:fine){
  .ln:hover::after{transform:scaleX(1);transition-duration:var(--dur-draw)}
}
.ln:focus-visible::after{transform:scaleX(1);transition-duration:var(--dur-draw)}

/* -------------------------------------------------------------- the room -- */
.stage{position:relative;isolation:isolate;background:var(--ground)}
.stage__floor{position:absolute;left:0;right:0;bottom:0;height:56%;z-index:0;
  pointer-events:none;transform-origin:50% 100%;
  background:linear-gradient(180deg,
    #191714 0%, #1D1B18 5.4%, #211F1B 8.9%, #272421 14.3%, #2D2A26 21.4%,
    #34312D 28.6%, #3C3834 35.7%, #43403B 44.6%, #514C48 51.8%, #5F5A55 60.7%,
    #6D6862 67.9%, #7B756F 76.8%, #89837C 83.9%, #98918A 92.9%, #A69E97 100%);
  transition:transform var(--dur-floor) var(--ease-out)}
/* the floor is PAINTED without JS; only the rise is scoped to html.js */
.js .stage__floor{transform:scaleY(0)}
.js .stage.is-in .stage__floor{transform:none}
.stage > .wrap{position:relative;z-index:1}

/* the one blurred ellipse in the system — never a box-shadow */
.cut{position:relative;display:block}
.cut__shadow{position:absolute;left:50%;bottom:0;translate:-50% 40%;
  width:58%;height:22px;border-radius:999px;pointer-events:none;
  background:radial-gradient(closest-side,rgba(0,0,0,.62),transparent 72%);
  filter:blur(10px);opacity:0;transform:scaleX(.7);
  transition:opacity var(--dur-lift) var(--ease-out),
             transform var(--dur-lift) var(--ease-out),
             filter var(--dur-row) var(--ease-out)}
.cut__glow{position:absolute;inset:0;pointer-events:none;z-index:-1;
  background:radial-gradient(closest-side at 50% 58%,var(--series),transparent 70%);
  opacity:0;transition:opacity var(--dur-row) var(--ease-out)}

/* The account's photographs are 1600×1600 room shots, not knocked-out cups, so
   the floating-object language is kept by cropping the photograph to the circle
   the shadow underneath already implies. Same object, same glow, same landing —
   only the silhouette is now a circle instead of a cup. */
.cut--ph img{border-radius:50%;object-fit:cover;aspect-ratio:1}
.cut--ph .cut__glow{border-radius:50%}
.pill__chip--ph img{object-fit:cover;padding:0;border-radius:50%}
/* the account's own second-language name for a dish, where it keeps one */
.tile__l2{display:block;margin-top:6px;font-size:var(--fs-ui);color:var(--ink-dim)}

/* ------------------------------------------------------------- the hero  -- */
.hero{min-height:100svh;overflow:hidden}
.hero__type{padding:132px var(--edge) 0;position:relative;z-index:3}
.hero__type h1{max-width:min(690px,100%)}
.hero__cup{position:absolute;left:50%;translate:-50% 0;bottom:104px;z-index:2;
  height:min(52svh,470px);margin:0}
.hero__cup img{height:100%;width:auto;object-fit:contain}
.hero__note{position:absolute;left:var(--edge);bottom:168px;z-index:3;
  width:min(300px,52%);color:var(--ink);
  font-size:var(--fs-lead);line-height:var(--lh-lead)}
.hero__cue{position:absolute;right:var(--edge);bottom:24px;z-index:3;
  color:var(--ink-stage);font-size:var(--fs-ui);line-height:var(--lh-ui)}
.hero__cta{position:absolute;left:50%;translate:-50% 0;bottom:20px;z-index:4}

/* the one white surface, the only curved object: 212×48, radius = h/2 */
.pill{display:inline-flex;align-items:center;gap:12px;height:48px;
  min-width:212px;padding:0 8px 0 8px;border-radius:999px;
  background:var(--pill);color:var(--ground);
  font-size:var(--fs-ui);line-height:1;
  transform:translate(var(--mx,0px),var(--my,0px));
  transition:transform var(--dur-spring) var(--ease-out),
             background-color var(--dur-micro) var(--ease-micro),
             border-color var(--dur-micro) var(--ease-micro),
             color var(--dur-micro) var(--ease-micro)}
.pill__chip{display:grid;place-items:center;width:32px;height:32px;flex:0 0 32px;
  border-radius:999px;background:var(--chip);overflow:hidden}
.pill__chip img{width:100%;height:100%;object-fit:contain;padding:3px 3px 0}
.pill__lbl{flex:1 1 auto;text-align:center;padding-inline:4px;white-space:nowrap}
.pill__chev{display:grid;place-items:center;width:32px;height:32px;flex:0 0 32px;
  border-radius:999px;background:var(--chip);
  transition:transform var(--dur-draw) var(--ease-out),
             background-color var(--dur-micro) var(--ease-micro)}
.pill__chev svg{width:12px;height:12px;stroke:var(--ground);stroke-width:1.5;fill:none;
  transition:stroke var(--dur-micro) var(--ease-micro)}
@media (hover:hover) and (pointer:fine){
  .pill:hover{background:var(--ground);color:var(--ink)}
  .pill:hover .pill__chev{transform:rotate(180deg);background:rgba(243,240,235,.14)}
  .pill:hover .pill__chev svg{stroke:var(--ink)}
}
.pill--ghost{background:transparent;color:var(--ink);border:1px solid var(--rule);
  min-width:0;padding:0 24px}
.pill--ghost .pill__lbl{padding-inline:0}
@media (hover:hover) and (pointer:fine){
  .pill--ghost:hover{background:var(--ink);color:var(--ground);border-color:var(--ink)}
}

/* ---------------------------------------------------------- the sections -- */
/* Vertical space belongs to the section BELOW it: a section ends on its last
   element and never pays a second exit toll, so a seam is one band, not two
   stacked paddings plus a gap. [COMPOSED — §4.5] */
.sec{padding-block:var(--pad-section) 0}
.sec--tight{padding-top:calc(var(--pad-section) * .6)}
.stage + .sec,.stage + .sec--tight{padding-top:var(--pad-after-stage)}
main:has(> .stage:last-child) + .foot{padding-top:var(--pad-after-stage)}
.shead{display:grid;gap:24px;align-items:end;
  grid-template-columns:minmax(0,1fr) auto;margin-bottom:40px}
.shead > .klab,.shead > p:last-child{text-align:right}
.shead__col{display:grid;gap:24px;align-content:end;justify-items:start}
.shead__n{margin-bottom:20px}
.stage--shelf .stage__floor{height:clamp(280px,44vh,440px)}
.views{display:flex;gap:24px;font-size:var(--fs-ui)}
.views button[aria-current="true"]::after{transform:scaleX(1);background:var(--ink)}
.standing{--cuth:clamp(260px,38vh,400px);display:grid;place-items:end center;
  height:var(--cuth);min-height:0}
.standing img{height:var(--cuth);width:auto;max-width:100%;object-fit:contain}
/* The cup stands ON the floor — its base 64px off the section edge, deep in the
   lit band — while the type block stays up in the dark where --ink clears AA.
   Before this the cup floated 200px above the light and the 200px read as a
   gap, not as a room. */
.visit__grid{align-items:end;padding-bottom:64px}
@media (min-width:861px){ .visit__grid .c7-13{margin-bottom:120px} }
.panel--code{grid-template-columns:1fr}
.foot__cols{display:grid;grid-template-columns:repeat(3,1fr);gap:40px var(--col-gap)}
.rule{height:1px;background:var(--rule);border:0;margin:0}
.rule--series{background:var(--series);transform:scaleX(0);transform-origin:left center;
  transition:transform var(--dur-draw) var(--ease-out)}
.is-in .rule--series,.rule--series.is-in{transform:none}

/* nine series — type only, no hue at rest: exactly one may light, on hover */
.index{border-top:1px solid var(--rule)}
.idx{display:grid;grid-template-columns:48px minmax(0,1fr) auto;gap:24px;
  align-items:baseline;padding:24px 0;border-bottom:1px solid var(--rule);
  position:relative}
.idx__n{font-size:var(--fs-micro);letter-spacing:var(--tr-micro);color:var(--ink-dim);
  font-weight:500;transition:color var(--dur-micro) var(--ease-micro)}
.idx__name{font-family:var(--font-display);font-size:var(--fs-h3);
  line-height:var(--lh-h3);letter-spacing:var(--tr-h3)}
.idx__meta{font-size:var(--fs-ui);color:var(--ink-dim);white-space:nowrap}
.idx::after{content:"";position:absolute;left:0;right:0;bottom:-1px;height:1px;
  background:var(--series);transform:scaleX(0);transform-origin:left center;
  transition:transform var(--dur-draw) var(--ease-out)}
@media (hover:hover) and (pointer:fine){
  .idx:hover::after{transform:none}
  .idx:hover .idx__n{color:var(--series)}
}

/* A shelf of cut-outs standing on the lit floor. The label sits ABOVE the cup,
   on the dark ground: below the cup it would land in the 82–91% band of the
   gradient, where neither --ink nor --ink-stage clears 4.5:1 at 14px. */
.shelf{display:grid;grid-template-columns:repeat(4,1fr);gap:var(--col-gap);
  align-items:end;padding-bottom:64px}
.shelf__item{display:grid;align-content:end}
/* revealed by the container, not per item: on mobile the row is a horizontal
   scroller and items 3–4 would never intersect the viewport on their own */
.js .shelf__item{opacity:0;transform:translateY(64px) scale(.96)}
.js .shelf.is-in .shelf__item{opacity:1;transform:none;
  transition:transform var(--dur-stage) var(--ease-out),
             opacity var(--dur-stage) var(--ease-out);
  transition-delay:calc(var(--i,0) * var(--stagger-item))}
.shelf__name{display:block;font-size:var(--fs-ui);line-height:1.35;
  padding-bottom:12px;border-bottom:1px solid var(--rule)}
.shelf__row{display:flex;justify-content:space-between;gap:16px;
  padding:12px 0 24px;font-size:var(--fs-ui);color:var(--ink-dim)}
.shelf__row .num{color:var(--ink)}
.shelf__cut{--cuth:clamp(200px,28vh,300px);display:grid;place-items:end center;
  height:var(--cuth)}
.shelf__cut > .cut{min-height:0}
.shelf__cut img{height:var(--cuth);width:auto;max-width:100%;object-fit:contain}
.shelf__item .cut{transition:transform var(--dur-row) var(--ease-out)}
@media (hover:hover) and (pointer:fine){
  .shelf__item:hover .cut{transform:translateY(-10px)}
  .shelf__item:hover .cut__shadow{opacity:.8;transform:scaleX(1.12);filter:blur(18px)}
  .shelf__item:hover .cut__glow{opacity:.12}
}

/* LIMITED EDITION — the one full-bleed photo panel, 8/4 */
.panel{display:grid;grid-template-columns:8fr 4fr;gap:var(--col-gap);align-items:stretch}
.panel__ph{position:relative;overflow:hidden;aspect-ratio:16/10;background:var(--ground);
  margin-left:calc(-1 * var(--edge))}   /* the one full-bleed photo in the system */
/* the clip lives on the IMAGE, never on the observed box — a clip-path on the
   observed element zeroes its IntersectionObserver rect and it never reveals */
.js .panel__ph img{clip-path:inset(0 0 100% 0);transform:scale(1.08)}
.panel__ph img{width:100%;height:100%;object-fit:cover;
  transition:transform var(--dur-panel) var(--ease-out),
             clip-path var(--dur-panel) var(--ease-out)}
.js .panel__ph.is-in img{clip-path:inset(0 0 0 0);transform:none}
.panel__body{display:flex;flex-direction:column;justify-content:flex-end;gap:24px;
  padding-bottom:8px}
/* LIMITED EDITION carries its own heading inside the panel's right column: that
   column was 300px of empty above a bottom-aligned block, and a section heading
   stacked above the panel bought a second empty band. One object, not two. */
.panel--le .panel__body{justify-content:space-between;gap:64px}
/* align-self:start keeps the aspect-ratio deriving HEIGHT from the column width.
   Stretched, it derived WIDTH from the row height and overflowed its 8 columns. */
.panel--le .panel__ph{aspect-ratio:4/3;align-self:start}
.panel__head{display:grid;gap:24px;justify-items:start}
.panel__item{display:flex;flex-direction:column;gap:24px}
.panel__price{font-family:var(--font-display);font-size:var(--fs-h3);
  letter-spacing:var(--tr-h3)}

/* the 40-item grid — a declared data surface, radius 0, no shadow */
.tiles{display:grid;grid-template-columns:repeat(4,1fr);gap:var(--col-gap) var(--col-gap)}
.tile{display:block;padding:8px 8px 20px;background:transparent;
  transition:background-color var(--dur-micro) var(--ease-micro)}
.tile__ph{position:relative;display:block;aspect-ratio:1;overflow:hidden;background:var(--ground)}
.tile__ph img{width:100%;height:100%;object-fit:cover}
.tile__ph--cut{background:linear-gradient(180deg,
    #191714 0%,#191714 58%,#272421 68%,#3C3834 78%,#514C48 87%,#6D6862 94%,#89837C 100%)}
.tile__ph--cut img{object-fit:contain;padding:14% 18% 6%;
  transform:translateY(0)}
.tile__name{display:block;margin-top:16px;padding-bottom:10px;position:relative;
  font-size:var(--fs-ui);line-height:1.35}
.tile__name::after{content:"";position:absolute;left:0;right:0;bottom:0;height:1px;
  background:var(--series);transform:scaleX(0);transform-origin:left center;
  transition:transform var(--dur-draw) var(--ease-out)}
.tile__price{display:block;margin-top:10px;font-size:var(--fs-ui);color:var(--ink-dim)}
@media (hover:hover) and (pointer:fine){
  .tile:hover{background:var(--lift)}
  .tile:hover .tile__name::after{transform:none}
}

/* tables — 1px rules, no zebra, no radius */
.tbl{width:100%;border-collapse:collapse;font-size:var(--fs-ui)}
.tbl caption{display:table-caption;text-align:left;padding-bottom:16px}
.tbl th,.tbl td{text-align:left;padding:14px 16px;border-bottom:1px solid var(--rule);
  font-weight:400;vertical-align:top}
.tbl thead th{font-size:var(--fs-micro);letter-spacing:var(--tr-micro);
  text-transform:uppercase;color:var(--ink-dim);padding-block:10px}
html[data-lang="zh"] .tbl thead th{text-transform:none}
.tbl td:last-child,.tbl th:last-child{text-align:right}
.tbl tbody tr{position:relative}
.tbl .price{font-variant-numeric:tabular-nums;display:inline-block;
  transition:transform var(--dur-micro) var(--ease-micro)}
.tbl tbody tr td:first-child{position:relative}
.tbl tbody tr td:first-child::before{content:"";position:absolute;left:0;top:10px;bottom:10px;
  width:1px;background:var(--series);transform:scaleY(0);transform-origin:center;
  transition:transform var(--dur-micro) var(--ease-micro)}
@media (hover:hover) and (pointer:fine){
  .tbl--hover tbody tr:hover{background:var(--lift)}
  .tbl--hover tbody tr:hover .price{transform:translateX(-4px)}
  .tbl--hover tbody tr:hover td:first-child::before{transform:none}
}
.tbl--rows tbody tr{opacity:0;transition:opacity var(--dur-micro) var(--ease-micro)}
.tbl--rows.is-in tbody tr,.is-in .tbl--rows tbody tr{opacity:1}
.tbl--rows.is-in tbody tr,.is-in .tbl--rows tbody tr{transition-delay:calc(var(--i,0) * 24ms)}

/* the open / closed badge */
.badge{display:inline-flex;align-items:center;gap:10px;font-size:var(--fs-micro);
  font-weight:500;letter-spacing:var(--tr-micro);text-transform:uppercase}
html[data-lang="zh"] .badge{text-transform:none}
.badge i{width:7px;height:7px;border-radius:999px;background:var(--ink-dim)}
.badge.is-open i{background:var(--series)}

/* forms — bottom hairline only, no box, radius 0 */
.fields{display:grid;gap:32px}
.field{position:relative;display:block}
.field > span{display:block;font-size:var(--fs-micro);font-weight:500;
  letter-spacing:var(--tr-micro);text-transform:uppercase;color:var(--ink-dim);
  margin-bottom:10px}
html[data-lang="zh"] .field > span{text-transform:none}
.field input,.field textarea,.field select{width:100%;background:transparent;border:0;
  border-bottom:1px solid var(--rule);border-radius:0;color:var(--ink);
  font:400 var(--fs-body)/1.5 var(--font-body);padding:0 0 12px;min-height:44px}
.field textarea{min-height:96px;resize:vertical}
.field input:focus,.field textarea:focus,.field select:focus{outline:none}
.field::after{content:"";position:absolute;left:0;right:0;bottom:0;height:1px;
  background:var(--ink);transform:scaleX(0);transform-origin:var(--o,left) center;
  transition:transform var(--dur-draw) var(--ease-out);pointer-events:none}
.field:focus-within::after{transform:none}
.field input::placeholder,.field textarea::placeholder{color:var(--ink-dim)}
.form__foot{display:flex;align-items:center;gap:24px;flex-wrap:wrap;margin-top:40px}
.net-form.sent .fields,.net-form.sent .form__foot{opacity:.36;
  transition:opacity var(--dur-micro) var(--ease-micro)}
[data-form-ok]{margin-top:40px;border-top:1px solid var(--rule);padding-top:32px}
.net-form.sent [data-form-echo] tr{opacity:0}
.net-form.echo-in [data-form-echo] tr{opacity:1;
  transition:opacity var(--dur-micro) var(--ease-micro)}
.net-form.echo-in [data-form-echo] tr:nth-child(2){transition-delay:24ms}
.net-form.echo-in [data-form-echo] tr:nth-child(3){transition-delay:48ms}
.net-form.echo-in [data-form-echo] tr:nth-child(4){transition-delay:72ms}
.net-form.echo-in [data-form-echo] tr:nth-child(5){transition-delay:96ms}
.net-form.echo-in [data-form-echo] tr:nth-child(6){transition-delay:120ms}
.net-form.echo-in [data-form-echo] tr:nth-child(n+7){transition-delay:144ms}

/* map — drawn in 1px rules, no tiles, no external asset */
.map{width:100%;height:auto;display:block}
.map .st{stroke:var(--rule);stroke-width:1;fill:none}
.map .st--main{stroke:var(--ink-dim)}
.map .pin{fill:var(--series)}
.map text{fill:var(--ink-dim);font-family:var(--font-body);font-size:9px;
  letter-spacing:.18em;text-transform:uppercase}

/* ------------------------------------------------------------ the footer -- */
/* 96px tail: the shell's floating switcher needs ~76px clear bottom-left */
.foot{border-top:1px solid var(--rule);padding-block:var(--pad-section) 96px}
.foot__nav{display:grid;gap:12px}
.foot__nav a{font-size:var(--fs-ui);width:max-content}
.foot h2,.foot h3{font-size:var(--fs-micro);font-weight:500;letter-spacing:var(--tr-micro);
  text-transform:uppercase;color:var(--ink-dim);margin-bottom:20px}
html[data-lang="zh"] .foot h2,html[data-lang="zh"] .foot h3{text-transform:none}

/* ---------------------------------------------------------- the entrance -- */
/* every hidden state is scoped to html.js — no JS means the page reads plain */
.sp-w{display:inline-block}
.sp-c{display:inline-block;white-space:pre}
.js [data-split] .sp-c{opacity:0;transform:translateY(1.33em)}
.js [data-split].is-in .sp-c{opacity:1;transform:none;
  transition:transform var(--dur-glyph) var(--ease-out),
             opacity var(--dur-glyph) var(--ease-out);
  transition-delay:calc(var(--i) * var(--stagger-char))}
.js .h2[data-split] .sp-c,.js h2[data-split] .sp-c{--dur-glyph:var(--dur-h2glyph)}

.js [data-anim="lift"]{opacity:0;transform:translateY(26px)}
.js [data-anim="row"]{opacity:0;transform:translateY(20px)}
.js [data-anim="stage"]{opacity:0;transform:translateY(96px) scale(.9)}
.js [data-anim="item"]{opacity:0;transform:translateY(64px) scale(.96)}
.js [data-anim="fade"]{opacity:0}
.js [data-anim="lift"].is-in{opacity:1;transform:none;
  transition:transform var(--dur-lift) var(--ease-out),opacity var(--dur-lift) var(--ease-out);
  transition-delay:calc(var(--i,0) * var(--stagger-line))}
.js [data-anim="row"].is-in{opacity:1;transform:none;
  transition:transform var(--dur-row) var(--ease-out),opacity var(--dur-row) var(--ease-out);
  transition-delay:calc(var(--i,0) * var(--stagger-row))}
.js [data-anim="stage"].is-in{opacity:1;transform:none;
  transition:transform var(--dur-stage) var(--ease-out),opacity var(--dur-stage) var(--ease-out)}
.js [data-anim="item"].is-in{opacity:1;transform:none;
  transition:transform var(--dur-stage) var(--ease-out),opacity var(--dur-stage) var(--ease-out);
  transition-delay:calc(var(--i,0) * var(--stagger-item))}
.js [data-anim="fade"].is-in{opacity:1;
  transition:opacity var(--dur-lift) var(--ease-out)}
.is-in .cut__shadow,.cut__shadow.is-in{opacity:.62;transform:none}

/* preloader — first view per session only, appended by JS, never a no-JS gate */
.pl{position:fixed;inset:0;z-index:9500;background:var(--plate);color:var(--ink-stage);
  display:grid;grid-template-rows:1fr auto;place-items:center;
  padding:var(--inset);transform:translateY(0);
  transition:transform var(--dur-wipe) var(--ease-wipe)}
.pl.is-out{transform:translateY(-100%)}
.pl__mark{text-align:center}
.pl__mark b{display:block;font-family:var(--font-display);font-weight:400;
  font-size:clamp(40px,7vw,88px);line-height:1;letter-spacing:-.02em}
.pl__n{display:block;margin-top:24px;font-size:var(--fs-micro);font-weight:500;
  letter-spacing:var(--tr-micro);font-variant-numeric:tabular-nums}
.pl__cap{font-size:var(--fs-micro);font-weight:500;letter-spacing:var(--tr-micro);
  text-transform:uppercase;text-align:center;opacity:.62}

/* --------------------------------------------------------------- mobile  -- */
/* Its own design, not the desktop reflowed: the cup goes BEHIND the type and
   bleeds off the right edge so 78%+ emptiness survives at a quarter of the area. */
@media (max-width:860px){
  :root{--inset:16px;--col-gap:16px;--measure:40ch;
        --dur-glyph:340ms;--stagger-char:34ms;--dur-stage:780ms;--stagger-item:90ms}
  html[data-lang="zh"]{--stagger-char:68ms}
  .g12{grid-template-columns:repeat(4,1fr)}
  .c1-5,.c1-6,.c1-7,.c1-8,.c6-13,.c7-13,.c8-13,.c9-13,.c1-13{grid-column:1/-1}
  .nav{grid-template-columns:auto 1fr;align-items:center;gap:16px}
  .nav__set{display:none}
  .nav__mark{justify-self:start;text-align:left}
  .nav__mark b{font-size:20px}
  .nav__mark .klab{display:none}
  .nav__end{gap:16px;align-items:center}
  .nav__end .nav__mobile{display:inline-block;font-size:var(--fs-ui)}
  .nav__end .nav__order{display:none}
  .foot__cols{grid-template-columns:1fr 1fr;gap:32px 16px}
  .visit__grid{padding-bottom:120px;gap:48px}
  .standing{--cuth:clamp(200px,26vh,260px)}
  .stage--shelf .stage__floor{height:clamp(240px,34vh,320px)}
  .views{gap:20px}
  .lang button{font-size:var(--fs-micro);letter-spacing:.04em}
  /* the scroll cue moves ABOVE the pill so it never runs onto the cut-out
     bleeding in from the right; the cup is out of flow, so order only affects text */
  .hero{min-height:100svh;display:flex;flex-direction:column;align-items:stretch}
  .hero__type{padding-top:104px;position:relative;z-index:3;order:1}
  .hero__note{order:2} .hero__cue{order:3} .hero__cta{order:4}
  .hero__type h1{max-width:none}
  .hero__cup{left:auto;right:-12%;translate:0 0;bottom:13%;z-index:0;
    height:min(48svh,410px)}
  .hero .stage__floor{height:48%}
  .hero__note{position:relative;width:auto;max-width:34ch;margin-top:40px;
    bottom:auto;left:auto;padding-inline:var(--edge);z-index:3;color:var(--ink)}
  .hero__cta{position:relative;left:auto;bottom:auto;translate:none;display:block;
    margin-top:32px;margin-bottom:92px;padding-inline:var(--edge);z-index:3}
  .hero__cta .pill{display:flex;width:100%}
  .hero__cue{position:relative;right:auto;bottom:auto;margin-top:28px;
    padding-inline:var(--edge);z-index:3;color:var(--ink);max-width:52%}
  .shead{grid-template-columns:1fr;align-items:start;margin-bottom:40px}
  .shead > .klab,.shead > p:last-child{text-align:left}
  /* one shared floor level for all four cups: a 2x2 grid would stand row 1 on
     the dark top of the gradient and row 2 on the lit bottom, which kills the
     "standing under one light" read. A scroll container adds no animation. */
  .shelf{display:flex;grid-template-columns:none;gap:24px;overflow-x:auto;
    scroll-snap-type:x mandatory;scrollbar-width:none;padding-bottom:88px;
    margin-inline:calc(-1 * var(--inset));padding-inline:var(--inset)}
  .shelf::-webkit-scrollbar{display:none}
  .shelf__item{flex:0 0 62%;scroll-snap-align:start}
  .shelf__cut{--cuth:190px}
  .tiles{grid-template-columns:repeat(2,1fr)}
  .panel{grid-template-columns:1fr;gap:32px}
  .panel--le .panel__body{display:contents}
  .panel--le .panel__head{order:1}
  .panel--le .panel__ph{order:2}
  .panel--le .panel__item{order:3}
  .panel__ph{aspect-ratio:4/3}
  .idx{grid-template-columns:36px minmax(0,1fr);gap:16px;padding:20px 0}
  .idx__meta{grid-column:2;font-size:var(--fs-micro)}
  .foot{padding-bottom:104px}
  .tbl th,.tbl td{padding:12px 8px}
}
@media (min-width:861px){
  .last-block{padding-left:0}
}
@media (max-width:480px){
  .nav__mark b{font-size:18px}
}

/* ------------------------------------------------------------- reduced  -- */
@media (prefers-reduced-motion:reduce){
  *,*::before,*::after{transition:none!important;animation:none!important}
  .js [data-split] .sp-c,.js [data-anim],.js .shelf__item{opacity:1!important;transform:none!important}
  .stage__floor{transform:none!important}
  .cut__shadow{opacity:.62!important;transform:none!important}
  .panel__ph img{clip-path:none!important;transform:none!important}
  .tbl--rows tbody tr{opacity:1!important}
  .pl{display:none!important}
  .net-form.sent [data-form-echo] tr{opacity:1!important}
}
