/* Mug Coffee & Roastery — chaptered editorial.
   Grounds step, they never cross-blend. No fixed nav bar; a folio in the margin.
   Type is self-hosted Newsreader + Manrope: no system-font dependency. */

:root{
  --burg:#90192D;
  --ink:#F4EBDD;
  --paper:#E7DCC9;
  --paper-ink:#241A15;
  --display:'Newsreader',Georgia,'Times New Roman',serif;
  --ui:'Manrope','Helvetica Neue',Arial,sans-serif;
  --gut:clamp(24px,5.4vw,140px);
  --maxw:1720px;
  --measure:56ch;
  --ease-out:cubic-bezier(.22,.61,.36,1);
}

*{margin:0;padding:0;box-sizing:border-box}
html{scroll-behavior:smooth;-webkit-text-size-adjust:100%}
body{
  background:var(--paper);color:var(--paper-ink);
  font:400 16px/1.7 var(--ui);
  letter-spacing:.002em;overflow-x:hidden;
}
img{max-width:100%;display:block}
/* <picture> must not become a layout box: the <img> keeps the positioning */
picture{display:contents}
h1,h2{font-family:var(--display);font-weight:400;letter-spacing:-.015em;line-height:1.06}
h1{font-size:clamp(44px,7.8vw,136px)}
h2{font-size:clamp(34px,4.9vw,84px)}
p{max-width:var(--measure)}

.skip{position:absolute;left:-9999px;top:0;z-index:99;background:var(--burg);color:#fff;
  padding:12px 18px;font:600 13px/1 var(--ui);letter-spacing:.06em}
.skip:focus{left:12px;top:12px}

a{color:inherit}
.link{color:inherit;text-decoration:none;border-bottom:1px solid currentColor;
  padding-bottom:1px;transition:opacity .2s}
.link:hover{opacity:.66}
.link--lg{border-bottom-width:2px;border-color:var(--burg)}
a:focus-visible,[tabindex]:focus-visible{outline:2px solid var(--burg);outline-offset:4px;
  border-radius:2px}

.eyebrow{font:700 12px/1 var(--ui);letter-spacing:.26em;text-transform:uppercase;opacity:.95}
.rule{width:64px;height:1px;background:currentColor;opacity:.55;margin:26px 0 22px}

/* ── folio: this grammar's nav ─────────────────────────────────────────── */
/* the rail reads as a printed margin folio: a hairline spine, a burgundy tick
   on the live chapter, and the chapter name set rather than abbreviated */
.folio{position:fixed;left:clamp(14px,2.2vw,46px);top:50%;transform:translateY(-50%);
  z-index:40;mix-blend-mode:difference}
.folio::before{content:"";position:absolute;left:3px;top:-10px;bottom:-10px;width:1px;
  background:#fff;opacity:.16}
.folio ol{list-style:none;display:flex;flex-direction:column;gap:clamp(15px,1.7vh,22px)}
.folio a{position:relative;display:flex;align-items:center;gap:13px;text-decoration:none;
  color:#fff;font:600 10.5px/1 var(--ui);letter-spacing:.22em;text-transform:uppercase;
  opacity:.34;padding-left:16px;transition:opacity .3s}
.folio a::before{content:"";position:absolute;left:0;top:50%;width:7px;height:1px;
  background:#fff;transform:translateY(-50%) scaleX(0);transform-origin:0 50%;
  transition:transform .35s var(--ease-out)}
.folio a.is-here::before,.folio a:hover::before{transform:translateY(-50%) scaleX(1)}
.folio i{font-style:normal;font-size:10.5px;font-variant-numeric:tabular-nums}
.folio span{max-width:0;overflow:hidden;white-space:nowrap;opacity:0;
  transition:max-width .4s var(--ease-out),opacity .3s}
.folio a:hover span,.folio a.is-here span{max-width:170px;opacity:1}
.folio a.is-here{opacity:1;font-size:12.5px;letter-spacing:.2em}
.folio a.is-here i{font-size:12.5px}

/* ── acts ──────────────────────────────────────────────────────────────── */
.act{position:relative;isolation:isolate;min-height:calc(var(--span,1) * 100vh)}
.wrap{position:relative;z-index:3;padding:0 var(--gut);margin:0 auto;max-width:var(--maxw);width:100%}
.wrap--split{display:grid;grid-template-columns:minmax(0,.86fr) minmax(0,1.14fr);
  gap:clamp(28px,5vw,90px);align-items:center}
.act--place .wrap--split{grid-template-columns:minmax(0,.72fr) minmax(0,1.28fr);
  gap:clamp(26px,3.4vw,62px)}

/* entrance: cheap, compositor-only, front-loaded so it is legible early */
[data-in]{opacity:0;transform:translateY(14px);
  transition:opacity .62s var(--ease-out),transform .62s var(--ease-out)}
[data-in].is-in{opacity:1;transform:none}
[data-in-d="1"]{transition-delay:.07s}[data-in-d="2"]{transition-delay:.13s}
[data-in-d="3"]{transition-delay:.19s}[data-in-d="4"]{transition-delay:.25s}
.pair-side[data-in]{transition-delay:.30s}
[data-in-d="5"]{transition-delay:.31s}

.plate{position:absolute;inset:0;z-index:0;overflow:hidden}
.plate img{width:100%;height:100%;object-fit:cover}
.tint{position:absolute;inset:0;mix-blend-mode:color;z-index:1}

/* ── 01 title page ─────────────────────────────────────────────────────── */
/* the title block spans the measure instead of shrink-wrapping and floating:
   `margin:0 auto` on a column flex item collapsed it to content width, which is
   what left a small composition adrift in the middle of a wide screen */
.act--title{display:flex;flex-direction:column;justify-content:center;
  background:var(--paper);padding:14vh 0 12vh;overflow:hidden}
.act--title .wrap{width:100%;max-width:var(--maxw)}
.act--title .eyebrow{color:var(--burg);margin-bottom:30px}
.act--title h1{margin-bottom:38px;max-width:14ch}
.lede{font-size:clamp(16px,1.18vw,22px);line-height:1.7;max-width:44ch;opacity:.82}

/* ONE brand gesture: the real traced Mug star, enormous and almost subliminal,
   holding the open right field. Geometry comes from assets/brand/star.js — the
   same path as the mark and the Act 3 exit, so it can never drift from them. */
.titlemark{position:absolute;right:-19vw;top:46%;width:104vh;height:104vh;
  transform:translateY(-50%);z-index:0;pointer-events:none;overflow:visible}
.titlemark svg{width:100%;height:100%;overflow:visible}
/* a pressed impression in the paper: a barely-there tint, a hairline edge and
   a single light catch below it. No new geometry — the traced Mug star only. */
.titlemark .star-p{fill:rgba(102,44,58,.030);stroke:rgba(102,44,58,.085);
  stroke-width:.0055;vector-effect:non-scaling-stroke;
  filter:drop-shadow(0 1.5px 0 rgba(255,252,246,.55))}
.title-meta{display:flex;flex-wrap:wrap;gap:18px;align-items:center;margin-top:clamp(44px,6vh,72px);
  font:600 12px/1 var(--ui);letter-spacing:.17em;text-transform:uppercase;opacity:.72;
  max-width:none}
.cue{position:absolute;left:var(--gut);bottom:34px;z-index:3;
  font:600 10px/1 var(--ui);letter-spacing:.28em;text-transform:uppercase;opacity:.45}

/* ── 02 the place ──────────────────────────────────────────────────────── */
/* The sandstone plate is a GROUND, not a photograph of a wall. Graded well
   down in contrast and saturation so the type sits on it instead of fighting
   it, with a vertical scrim keeping the reading column clean. */
.act--place{background:#DCD2BF;padding:0}
.plate--sand img{filter:contrast(.52) saturate(.62) brightness(1.09) blur(.6px);
  transform:scale(1.04)}
.tint--sand{background:#DDD3C1;opacity:.66}
.act--place::before{content:"";position:absolute;inset:0;z-index:2;pointer-events:none;
  background:linear-gradient(96deg,rgba(226,217,199,.92) 0%,rgba(226,217,199,.62) 38%,
    rgba(226,217,199,.20) 66%,rgba(226,217,199,.42) 100%)}
.act--place .col-text{color:#241A15}
.act--place p{opacity:.86;font-size:clamp(15.5px,1.06vw,19px)}
.col-media{position:relative;min-height:auto}
.fig{position:relative;will-change:transform}
/* diffuse and offset, so the frames sit in the light rather than on the wall */
.fig img{box-shadow:0 42px 78px -28px rgba(62,44,24,.42),0 6px 16px -8px rgba(62,44,24,.16)}
/* the split is held inside one viewport-height band so neither figure can be
   clipped by the fold at any scroll position: the storefront is shown whole */
.act--place .wrap--split{min-height:100vh;align-content:center;
  padding-top:8vh;padding-bottom:6vh}
/* The interior is the dominant frame — it is also the only real photograph we
   hold at 1920px. The storefront is deliberately secondary, overlapping its
   lower left so the two read as one layered spread rather than two cards. */
.col-media{display:grid;grid-template-columns:repeat(12,1fr);align-items:start}
.fig--b{grid-column:1/13;grid-row:1;width:100%;margin:0}
.fig--a{grid-column:1/5;grid-row:1;align-self:end;width:100%;margin:0 0 -20% -6%;
  z-index:2;transform-origin:0 100%}
.fig--a img{box-shadow:0 30px 58px -22px rgba(62,44,24,.48)}
/* the dominant frame's caption sits right, clear of the overlapping inset */
.fig--b figcaption{text-align:right}
.fig figcaption{font:600 10.5px/1.5 var(--ui);letter-spacing:.16em;text-transform:uppercase;
  opacity:.6;margin-top:12px}
/* authored silence, trimmed: enough to be a held breath, not a dead field */
.silence{height:22vh;display:flex;align-items:center;padding:0 var(--gut);position:relative;z-index:3}
.silence p{font-family:var(--display);font-size:clamp(22px,2.4vw,32px);opacity:.66;max-width:30ch}

/* ── 03 the pinned product stage: ONE CONTINUOUS WORLD ─────────────────── */
.act--stage{background:#241A15;height:calc(var(--span) * 100vh)}
.pin{position:sticky;top:0;height:100vh;overflow:hidden;isolation:isolate;
  --cupH:66vh;   /* 64-68vh */
  --cupX:65.5vw; /* optical centre, 64-67vw */
  --cupBase:76vh;/* seated on the counter */
}
.world{position:absolute;inset:0;z-index:0}
.wcol{position:absolute;inset:0;background:#241A15}
/* one room. 118% tall and nudged up so the counter lands under the cup's baseline */
.wplate{position:absolute;left:0;top:-2%;width:100%;height:118%;object-fit:cover;
  object-position:50% 50%;opacity:1}
.wtint{position:absolute;inset:0;mix-blend-mode:color;background:#241A15;opacity:.86}
/* counter lip: the same plate drawn again IN FRONT of the vessel, clipped to
   the counter surface. Desktop keeps its accepted mask entrance and never
   paints this. Declared inside the portrait query so the file is only fetched
   where it is used — and it is the same file the plate already loaded. */
.wlip,.wliptint{display:none}
.wgrade{position:absolute;inset:0;mix-blend-mode:multiply;opacity:.35}
.wlight{position:absolute;left:0;top:0;width:150%;height:150%;pointer-events:none;
  background:radial-gradient(closest-side,rgba(255,242,220,.30),rgba(255,242,220,.10) 46%,transparent 72%);
  will-change:transform}
.wvig{position:absolute;inset:0;pointer-events:none;background:
  radial-gradient(120% 88% at 62% 44%,transparent 42%,rgba(0,0,0,.30));}

.depth{position:absolute;inset:0;z-index:1;pointer-events:none}


/* ── one continuous room: the geometry persists, only the atmosphere changes ── */
/* large cropped out-of-focus foreground shapes */
.fg{position:absolute;border-radius:50%;pointer-events:none;filter:blur(26px);
  will-change:transform,opacity}
.fg--l{left:-18vw;bottom:-18vh;width:50vw;height:44vh;
  background:radial-gradient(closest-side,rgba(0,0,0,.58),transparent 78%);opacity:.9}
.fg--r{right:-22vw;top:-16vh;width:42vw;height:46vh;
  background:radial-gradient(closest-side,rgba(0,0,0,.46),transparent 76%);opacity:.75}
/* restrained edge geometry: a soft architectural upright, never a prop */
.edge{position:absolute;pointer-events:none;will-change:transform,opacity}
.edge--l{left:-2vw;top:-6vh;width:13vw;height:118vh;filter:blur(9px);
  background:linear-gradient(90deg,rgba(0,0,0,.42),rgba(0,0,0,.16) 62%,transparent)}

/* ── two shadow layers, graded per environment ─────────────────────────── */
.sh{position:absolute;border-radius:50%;pointer-events:none;
  transform:translate(-50%,-50%);will-change:opacity,background,width}
.sh--contact{left:var(--cupX);top:var(--cupBase)}
.sh--cast{left:var(--cupX);top:var(--cupBase)}

/* ── editorial paper plane ─────────────────────────────────────────────────
   The anchor holds the position; .plane holds paper AND copy and takes the
   single travelling transform, so padding is structural and can never erode.
   Height is content-driven: the copy states stack in one grid cell, so the
   box is always as tall as its tallest state and nothing can fall out.      */
.planeanchor{position:absolute;z-index:2;left:4vw;top:50%;
  width:33vw;max-width:470px;transform:translateY(-50%);pointer-events:none}
/* min-height gives the sheet enough body to relate to the counter line rather
   than hovering; the copy centres inside it and the padding still bounds it */
.plane{position:relative;padding:clamp(48px,3.4vw,60px);min-height:38vh;
  display:flex;flex-direction:column;justify-content:center;will-change:transform}
.paper{position:absolute;inset:0;z-index:0;border-radius:5px;
  background:
    repeating-linear-gradient(96deg,rgba(0,0,0,.014) 0 2px,transparent 2px 5px),
    radial-gradient(120% 90% at 22% 12%,rgba(255,255,255,.55),transparent 62%),
    linear-gradient(168deg,#F5EDE0,#EADFCD);
  box-shadow:0 22px 60px rgba(24,14,6,.20),0 1px 0 rgba(255,255,255,.5) inset;
  /* opaque throughout: it arrives by being uncovered, never by fading. */
  clip-path:inset(0 100% 0 0);will-change:clip-path}


.cupwrap{position:absolute;inset:0;z-index:3;pointer-events:none}
/* base and liquid share ONE box, so they are registered by construction */
.cup{position:absolute;left:var(--cupX);top:calc(var(--cupBase) - var(--cupH));
  height:var(--cupH);aspect-ratio:1139/1511;transform:translateX(-50%);
  will-change:transform,opacity}
.cst{position:absolute;inset:0;width:100%;height:100%;object-fit:fill;opacity:0;
  will-change:opacity}
.cst.is-on{opacity:1}

/* the three states share one grid cell: the box sizes to the tallest of them,
   so every state sits inside the same padding and nothing reflows on change */
.say{position:relative;z-index:1;display:grid}
.said{grid-area:1/1;opacity:0;visibility:hidden;will-change:opacity}
.said.is-on{visibility:visible}
.said>*{max-width:100%}
/* Act 3's headings are sized to the PANEL, not the viewport. They must not
   inherit the enlarged global h2 scale: the panel is a fixed 470px box, and at
   84px every product name wrapped to two lines. */
.said h2{font-size:clamp(30px,2.75vw,54px);min-height:1.18em;margin-top:18px;
  text-wrap:balance}
.said .note{font-size:16px;line-height:1.7;max-width:32ch;opacity:.9}
.said[data-s="0"],.said[data-s="0"] .eyebrow{color:#F4EBDD}
.said[data-s="0"] .note{color:rgba(244,235,221,.88)}
.said[data-s="1"],.said[data-s="1"] .eyebrow,
.said[data-s="2"],.said[data-s="2"] .eyebrow{color:#2A1C12}
.said[data-s="1"] .note,.said[data-s="2"] .note{color:rgba(42,28,18,.86)}

.star{position:absolute;inset:0;width:100%;height:100%;z-index:6;pointer-events:none;
  overflow:visible}
.star-g{transform:translate(50%,50%) scale(0);transform-origin:0 0;will-change:transform}
.star-p{fill:var(--burg)}

/* ── 04 roasting ───────────────────────────────────────────────────────── */
/* the three bands are spread across the act's full height by the layout, not
   by magic offsets, so it reads at any viewport instead of leaving a long
   empty bean field under a single block of type */
.act--roast{background:#12100E;color:var(--ink);padding:11vh 0 9vh;
  display:flex;flex-direction:column;justify-content:space-between}
.act--roast .wrap{width:100%}
.band-label{font:700 clamp(11px,.86vw,14px)/1 var(--ui);letter-spacing:.24em;
  text-transform:uppercase;color:#D8B98C;opacity:.9;margin-bottom:30px}
.plate--beans img{transform:scale(1.045);will-change:transform}
.act--roast .scrim{position:absolute;inset:0;z-index:1;background:
  linear-gradient(92deg,rgba(10,9,7,.93) 0%,rgba(10,9,7,.80) 42%,rgba(10,9,7,.34) 74%,
  rgba(10,9,7,.50) 100%)}
.act--roast .eyebrow{color:#D8B98C}
.act--roast h2{margin-top:22px}
.act--roast p{opacity:.88;font-size:clamp(16px,1.16vw,21px)}
/* the four stages are a real beat, not a caption strip: a numbered rank with
   display numerals, so the middle of the act carries weight of its own */
.stages{list-style:none;display:grid;grid-template-columns:repeat(4,minmax(0,1fr));
  gap:clamp(20px,2.6vw,48px);margin:0;max-width:1180px}
.stages li{display:flex;flex-direction:column;gap:clamp(12px,1.4vh,20px);
  padding-top:clamp(16px,1.8vh,24px);border-top:1px solid rgba(216,185,140,.34);
  font:600 clamp(13px,1.02vw,18px)/1.25 var(--ui);letter-spacing:.13em;
  text-transform:uppercase;opacity:.92}
.stages i{font-style:normal;font-family:var(--display);font-weight:400;
  font-size:clamp(30px,3.1vw,54px);line-height:1;letter-spacing:-.02em;
  color:#D8B98C;opacity:.92;margin:0;text-transform:none}
.counts{display:flex;flex-wrap:wrap;gap:clamp(30px,5vw,70px);margin:0}
.counts dt{font:400 clamp(46px,5.4vw,96px)/1 var(--display);letter-spacing:-.025em}
.counts dd{font:600 clamp(10.5px,.78vw,13px)/1.5 var(--ui);letter-spacing:.2em;
  text-transform:uppercase;opacity:.72;margin-top:14px}

/* ── 05 pairing ────────────────────────────────────────────────────────────
   Rebuilt around real photography. The dominant frame is a crop of Mug's own
   pairing still (hands, a real laminated roll, a branded cup, daylight) — so
   the contact shadow, the grounding and the light are photographic rather than
   simulated. Sources are 512px, so both frames are capped and never enlarged
   past ~1.1x; that ceiling is what sets the composition's scale. */
.act--pair{background:#EFE6D6;color:#241A15;padding:0;
  display:flex;align-items:center;overflow:hidden}
.act--pair::before{content:"";position:absolute;inset:0;z-index:0;pointer-events:none;
  background:radial-gradient(78% 62% at 68% 44%,rgba(255,243,222,.85),transparent 70%),
             linear-gradient(180deg,#F2EADB,#E8DDC8)}
.act--pair .eyebrow{color:var(--burg)}
.act--pair p{opacity:.86;font-size:clamp(15.5px,1.06vw,19px)}
/* Both photographs are present at once and together hold the right field: the
   pairing still is dominant, the bakery case steps down and back from it. Both
   are 512px sources, so both are capped — the composition is built from
   overlap and spacing rather than from scale neither source can support. */
.pair{display:grid;align-items:center;
  grid-template-columns:minmax(0,.78fr) minmax(0,1.22fr);
  column-gap:clamp(28px,3.2vw,58px);row-gap:0;min-height:82vh}
.pair-text{grid-column:1;grid-row:1;position:relative;z-index:4;
  padding-right:clamp(0px,2vw,40px)}
.pair-hero{grid-column:2;grid-row:1;justify-self:start;align-self:center;
  position:relative;z-index:2;width:min(40vw,520px)}
.pair-hero{box-shadow:0 44px 84px -30px rgba(58,38,18,.46),0 4px 12px -4px rgba(58,38,18,.18)}
.pair-hero img{width:100%;border-radius:2px}
/* the secondary frame sits down-right of the hero, overlapping it, and reaches
   into the outer margin so the right field is composed rather than empty */
.pair-side{grid-column:2;grid-row:1;justify-self:end;align-self:end;position:relative;
  z-index:3;width:min(24vw,330px);margin:0 0 -3.5vh 0;
  transform:translate(26%,0)}
.pair-side img{width:100%;border-radius:2px}
.pair-side picture{display:contents}
.pair-side figcaption{font:600 10.5px/1.5 var(--ui);letter-spacing:.16em;
  text-transform:uppercase;opacity:.62;margin-top:13px;max-width:22ch}
/* The reveal is applied to the IMG, never to the figure.
   A clip-path on the figure itself clipped it to zero rendered area, and Chrome's
   IntersectionObserver then never reported it intersecting — so the class that
   would have removed the clip was never added. The element hid itself with the
   one property that stopped anything from un-hiding it. Both figures are now
   driven by Act 5's scroll progress instead, which also makes them reverse. */
.pair-hero picture,.pair-hero img{display:block}
.pair-hero img{clip-path:inset(0 0 100% 0)}
.pair-side{opacity:0;transform:translate(26%,0) translateY(var(--e5,14px))}

/* ── 06 colophon ───────────────────────────────────────────────────────────
   A dark burgundy field: the page arrives somewhere instead of dissolving into
   the same cream it opened on. Authentic Mug geometry only — the traced star,
   at mast scale. No repeat of the Act 3 transition. */
.act--colophon{background:#5E1020;color:#F6EEE2;display:flex;align-items:center;
  padding:11vh 0;position:relative;overflow:hidden}
.act--colophon::before{content:"";position:absolute;inset:0;z-index:0;pointer-events:none;
  background:radial-gradient(76% 70% at 22% 34%,rgba(160,32,56,.55),transparent 68%),
             linear-gradient(160deg,#6B1224,#3F0A16)}
.act--colophon .wrap{width:100%;position:relative;z-index:2;min-height:74vh;
  display:grid;align-content:space-between;gap:clamp(40px,6vh,84px)}
.act--colophon .eyebrow{color:#E9A9B6;margin-bottom:26px}
.close-line{font-family:var(--display);font-size:clamp(34px,5.4vw,96px);line-height:1.05;
  max-width:none;letter-spacing:-.02em}

/* ordering is a ranked editorial list: numbered entries on fine rules, with a
   directional arrow that extends on hover. Not a button island. */
.act--colophon .wrap{grid-template-columns:minmax(0,1fr) auto;
  grid-template-areas:"head mark" "orders mark" "foot foot"}
.close-head{grid-area:head}
.orders{grid-area:orders;list-style:none;margin:0;max-width:760px}
.orders li{border-top:1px solid rgba(246,238,226,.26)}
.orders li:last-child{border-bottom:1px solid rgba(246,238,226,.26)}
.orders a{display:grid;grid-template-columns:auto 1fr auto auto;align-items:baseline;
  gap:clamp(16px,2vw,34px);text-decoration:none;color:#F6EEE2;
  padding:clamp(20px,2.4vh,30px) 4px;transition:color .3s}
.orders i{font-style:normal;font:600 clamp(10.5px,.78vw,12px)/1 var(--ui);
  letter-spacing:.2em;opacity:.5;font-variant-numeric:tabular-nums}
.o-k{font-family:var(--display);font-size:clamp(24px,2.5vw,42px);line-height:1.1;
  letter-spacing:-.014em}
.o-s{font:600 clamp(10.5px,.78vw,12.5px)/1 var(--ui);letter-spacing:.18em;
  text-transform:uppercase;opacity:.6;white-space:nowrap}
.o-a{width:clamp(28px,2.4vw,38px);height:8px;align-self:center;opacity:.55;
  transition:transform .35s var(--ease-out),opacity .3s}
.orders a:hover .o-a,.orders a:focus-visible .o-a{transform:translateX(8px);opacity:1}
.orders a:hover .o-s{opacity:.9}
.orders a:focus-visible{outline:2px solid #F6EEE2;outline-offset:3px;border-radius:2px}
/* the second entry is quieter than the first, so the ranking is visible */
.orders li:last-child .o-k{font-size:clamp(20px,1.9vw,32px);opacity:.86}

.closemark{grid-area:mark;align-self:center;justify-self:end;
  width:clamp(120px,13vw,210px);opacity:.2;pointer-events:none}
.closemark svg{width:100%;height:auto;overflow:visible}
.closemark path{fill:#F6EEE2}

.close-foot{grid-area:foot;display:flex;flex-wrap:wrap;align-items:flex-end;
  justify-content:space-between;gap:clamp(28px,4vw,64px)}
.branches{list-style:none;display:flex;flex-wrap:wrap;gap:clamp(24px,3.2vw,58px);margin:0}
.branches li{display:flex;flex-direction:column;gap:6px}
.branches b{font:600 clamp(12px,.95vw,15px)/1 var(--ui);letter-spacing:.13em;
  text-transform:uppercase}
.branches span{font-size:clamp(13px,.9vw,15px);opacity:.66}
.mast{display:flex;align-items:center;gap:11px;margin:0;
  font:600 clamp(10.5px,.78vw,12px)/1 var(--ui);letter-spacing:.19em;text-transform:uppercase;
  opacity:.72;max-width:none;flex-wrap:wrap}
.mast .mark{width:15px;height:15px;display:block}
.mast .mark svg{width:100%;height:100%;overflow:visible}
.act--colophon .mast .star-p{fill:#F6EEE2}
.act--colophon .link{border-bottom-color:rgba(246,238,226,.55)}

/* ── tablet ────────────────────────────────────────────────────────────── */
@media (max-width:1024px){
  .wrap--split{grid-template-columns:1fr;gap:44px}
  /* must out-specify the desktop Act 2 column rule, or the heading is squeezed
     into a narrow column at phone width */
  .act--place .wrap--split{grid-template-columns:1fr;gap:40px}
  .col-media{min-height:auto}
  .fig--a{width:74%}.fig--b{width:88%;margin-top:-6%}
}
/* landscape tablet keeps the side-by-side stage, on a narrower plane so the
   travelling paper can never reach the vessel */
@media (max-width:1024px) and (orientation:landscape){
  .pin{--cupH:58vh;--cupX:66vw;--cupBase:74vh}
  .planeanchor{left:4vw;width:34vw;max-width:400px}
  .plane{padding:clamp(40px,4vw,52px);min-height:36vh}
}
/* portrait tablet uses the stacked composition, like a phone: the vessel is
   centred and the paper sits beneath it, never beside it */
@media (max-width:1024px) and (orientation:portrait){
  .pair{grid-template-columns:1fr;row-gap:36px;min-height:auto}
  .pair-text{grid-column:1;grid-row:1}
  .pair-hero{grid-column:1;grid-row:2;justify-self:start;width:min(86vw,560px)}
  .pair-side{grid-column:1;grid-row:3;justify-self:end;width:min(34vw,250px);
    margin:-16% 0 0 0;transform:translateY(var(--e5,14px))}
  .pin{--cupH:46vh;--cupX:50vw;--cupBase:55.2vh}
  /* grounded crop: the counter edge sits at exactly 54% of the plate height,
     which is --cupBase, so the vessel meets the surface at every phone width */
  .wplate{height:100%;top:0}
  .wlip{display:block;position:absolute;left:0;top:0;width:100%;height:100%;
    object-fit:cover;object-position:50% 50%;z-index:4;pointer-events:none;
    clip-path:inset(var(--cupBase) 0 0 0)}   /* tracks the vessel baseline */
  /* The room's own tint must stay INSIDE .world and below the vessel, or its
     colour blend lands on the cup and drains the burgundy out of the star.
     The counter lip therefore gets its own grade layer, clipped to exactly the
     lip region so it can never touch the vessel or the editorial plane. */
  .wliptint{display:block;position:absolute;inset:0;z-index:5;pointer-events:none;
    mix-blend-mode:color;clip-path:inset(var(--cupBase) 0 0 0)}
  /* the editorial plane stands ON the counter, so it must clear the lip */
  .planeanchor{z-index:6}
  .planeanchor{left:5vw;right:7vw;width:auto;max-width:none;
    top:auto;bottom:5vh;transform:none}
  .plane{padding:clamp(32px,5vw,48px);min-height:0}
  .said[data-s="0"],.said[data-s="0"] .eyebrow{color:#2A1C12}
  .said[data-s="0"] .note{color:rgba(42,28,18,.86)}
  .said .note{max-width:none}
}
/* ── phone ─────────────────────────────────────────────────────────────── */
@media (max-width:720px){
  /* on a phone the folio is a position marker, not a menu: only the live
     chapter shows, so it cannot crowd the reading column */
  .folio{left:7px}
  .folio span{display:none}
  .folio a{opacity:0;transition:opacity .3s}
  .folio a.is-here{opacity:.85}
  .pin{--cupH:45vh;--cupX:50vw;--cupBase:54vh}
  .planeanchor{left:5vw;right:7vw;width:auto;max-width:none;
    top:auto;bottom:4.5vh;transform:none}
  .plane{padding:32px;min-height:0}
  .said[data-s="0"],.said[data-s="0"] .eyebrow{color:#2A1C12}
  .said[data-s="0"] .note{color:rgba(42,28,18,.86)}
  .said .note{max-width:none;font-size:15px}
  .said h2{font-size:clamp(27px,7.2vw,36px);min-height:1.2em}
  .said .rule{margin:20px 0 18px}
  .silence{height:24vh}
  /* the meta line wraps on a phone; the separator before the wrap would be
     left dangling at the end of its line, so the last one is dropped and the
     CTA simply starts the new line */
  .title-meta{gap:9px 14px;font-size:10.5px}
  .title-meta .sep--last{display:none}
  .stages{grid-template-columns:repeat(2,minmax(0,1fr));gap:20px 18px}
  .act--roast{padding:8vh 0}
  .act--pair{padding:9vh 0}
  .pair{grid-template-columns:1fr;row-gap:34px;min-height:auto}
  .pair-text{grid-column:1;grid-row:1}
  .pair-hero{grid-column:1;grid-row:2;justify-self:stretch;width:100%}
  .pair-side{grid-column:1;grid-row:3;justify-self:start;width:56%;
    margin:-14% 0 0 0;transform:translateX(6%) translateY(var(--e5,14px))}
  .act--colophon .wrap{grid-template-columns:1fr;
    grid-template-areas:"head" "orders" "mark" "foot"}
  .orders a{grid-template-columns:auto 1fr auto;row-gap:6px}
  .o-s{grid-column:2/4;white-space:normal}
  .closemark{justify-self:start;width:132px;opacity:.24}
  .close-foot{flex-direction:column;align-items:flex-start;gap:30px}
  /* the mark is a wide-screen gesture; at phone size it reads as a blob, so it
     is held far back and much smaller rather than shown at any cost */
  .titlemark{right:-46vw;top:34%;width:58vh;height:58vh}
  .titlemark .star-p{opacity:.032}
  /* stacked, not overlapped: at this width an inset collided with the bar and
     put the two captions on top of each other */
  .col-media{grid-template-columns:1fr;row-gap:26px}
  .fig--b{grid-column:1;grid-row:1;width:100%}
  .fig--a{grid-column:1;grid-row:2;width:66%;margin:0;align-self:start;
    justify-self:end;transform:none}
  .fig--b figcaption{text-align:left}
}

/* small phones: the plane keeps a real margin without starving the measure */
@media (max-width:380px){
  .plane{padding:24px}
  .said .note{font-size:14.5px}
}

/* ── reduced motion: nothing is skipped, only the movement stops ───────── */
@media (prefers-reduced-motion:reduce){
  html{scroll-behavior:auto}
  [data-in]{opacity:1;transform:none;transition:none}
  .reveal img{clip-path:none;transform:none;transition:none}
  .ing img{transform:translate(-50%,-50%) rotate(var(--r,0deg))}
  .fig{transform:none!important}
  .plate--beans img{transform:scale(1.02)!important}
  .star-g{transition:none}
  .panel{transition:none}
}

/* the chapter ticks are interface, not story: only the live chapter shows in
   Act 3, and it shows as a number alone so no label sits on the cinematic frame */
.act--stage ~ * .folio i,.folio i{opacity:.55}
body.in-stage .folio a:not(.is-here){opacity:0;pointer-events:none}
body.in-stage .folio a.is-here span{max-width:0;opacity:0}

/* reading columns clear the folio's expanded label at desktop widths */
@media (min-width:1025px){
  .wrap{padding-left:max(var(--gut),220px)}
  .silence{padding-left:max(var(--gut),220px)}
  .cue{left:max(var(--gut),220px)}
  /* Act 3's plane clears the rail too — there the folio shows a number only */
  .planeanchor{left:7vw}
}
