/* Builder P: act 4, the peak (the reversal that stops dead), drawn as the
   full payment journey on both sides in the glass-trail look. Everything is
   scoped to .st-peak. Colours come from the side tokens (var(--sc-*)), the
   glass recipe values are the contract's. Default rules describe the END
   state, so no-JS and reduced motion read the outcome. .st-live (added by
   story.js) switches on the scroll-driven states. */

/* ------------------------------------------------------------ type ---- */
/* Local fallbacks for the shared type classes (H: base.css). Same values as
   the contract, so they agree once base.css lands. */
.st-peak .display { margin: 0; font-family: var(--sc-font-display); font-optical-sizing: auto; text-wrap: balance; color: var(--sc-ink); }
.st-peak .display--head { font-size: var(--t-head); font-weight: 600; letter-spacing: -0.003em; line-height: 1.1; }
.st-peak .display--super { font-size: var(--t-super); font-weight: 600; letter-spacing: -0.015em; line-height: 1.05; font-variation-settings: "opsz" 32; }
.st-peak .caption { margin: 0; font-family: var(--sc-font-text); font-size: var(--t-caption); font-weight: 400; line-height: 1.4; color: var(--sc-ink-soft); text-wrap: pretty; }
.st-sr {
  position: absolute; width: 1px; height: 1px; margin: -1px; padding: 0;
  overflow: hidden; clip-path: inset(50%); white-space: nowrap; border: 0;
}
.st-col { position: relative; min-width: 0; }

/* ----------------------------------------------------------- timing ---- */
/* Ramps read the engine's --sc-p. The fallback of 1 is the end state, so a
   page without the engine still shows the outcome. --k-d is the depth drift
   of the planes: constant through the authored silence (p < 0.12). */
.st-peak {
  --k-d:      calc(clamp(0, (var(--sc-p, 1) - 0.12) / 0.84, 1) - 0.5);
  --k-seal:   clamp(0, (var(--sc-p, 1) - 0.655) / 0.05, 1);
  --k-stamp:  clamp(0, (var(--sc-p, 1) - 0.595) / 0.045, 1);
  --k-ledger: clamp(0, (var(--sc-p, 1) - 0.62) / 0.04, 1);
  --k-capl:   clamp(0, (var(--sc-p, 1) - 0.63) / 0.06, 1);
  --k-capr:   clamp(0, (var(--sc-p, 1) - 0.71) / 0.06, 1);
  --k-sub:    clamp(0, (var(--sc-p, 1) - 0.75) / 0.06, 1);
  --k-cta:    clamp(0, (var(--sc-p, 1) - 0.78) / 0.06, 1);
  --st-glass-bg: rgba(255, 255, 255, 0.06);
  --st-glass-hi: rgba(255, 255, 255, 0.35);
  --st-glass-lo: rgba(255, 255, 255, 0.06);
  --st-depth: 0 2px 4px rgba(0, 0, 0, 0.2), 0 12px 24px rgba(0, 0, 0, 0.3), 0 48px 96px rgba(0, 0, 0, 0.4);
}

/* ----------------------------------------------------------- layout ---- */
/* The markup is copy first (headline, caption, action), then the figure: the
   stacked order the mobile round asks for. The split (900 and up) lifts the
   figure above the copy with flex order, so the desktop composition is kept. */
.st-peak [data-sc-stage] > .split { height: 100%; }
.st-peak .side { min-width: 0; }
.st-peak .st-col--peak { display: flex; flex-direction: column; align-items: stretch; width: 100%; }
@media (min-width: 900px) {
  /* both drawings sit on the same line, so the two returns read as one mapping;
     the whole act is centred in the stage so the figure owns the screen */
  [data-sc-stage] > .split > .side.st-pside { justify-content: center; }
  .st-peak .st-fig { order: -2; }
  .st-peak .st-ledger { order: -1; }
  .st-peak .st-col--peak {
    /* the divider winds up to 2.5vw either way and the card side leans to 47%:
       keep at least 6vw of air on the inner edge after both */
    padding-right: 3.5vw;
  }
  .st-peak .side--vp .st-col--peak { padding-right: 0; padding-left: 3.5vw; }
  /* both columns are centred in the stage; the card column carries the
     height the VanPay text block has over its own (two super lines + the
     caption against two head lines + the ledger), so the two drawings sit
     on the same line */
  .st-peak .side--card .st-col--peak { padding-bottom: calc(2.1 * var(--t-super) + 10.4rem - 2.2 * var(--t-head) - 4.6rem); }
}

/* ------------------------------------------------------------ figure --- */
/* the peak owns the only super on the page: the figure takes the column
   (capped by the viewport height so the headline and caption still fit) */
.st-fig { position: relative; max-width: min(46vw, 56rem, 78vh); color: var(--sc-ink); container-type: inline-size; isolation: isolate; }
.st-peak.st-live .st-fig { transform-origin: 0 0; will-change: transform; }
.st-fig__svg { position: relative; z-index: 2; display: block; width: 100%; height: auto; overflow: visible; }

/* plane 1: the studio light (H's .studio::before, restated here as the local
   fallback), furthest back, drifts the most. A pre-rendered radial pool, no
   blur filter. */
.st-peak .st-fig::before {
  content: ""; position: absolute; z-index: -1; inset: -30% -8% -20% -8%;
  pointer-events: none;
  background: radial-gradient(60% 55% at 50% 48%, var(--studio-light, rgba(255, 255, 255, 0.07)), transparent 70%);
  translate: calc(var(--k-d) * -18px) calc(var(--k-d) * 34px);
}
.st-peak .side--vp .st-fig { --studio-light: color-mix(in oklab, var(--sc-accent) 30%, transparent); }
/* the VanPay studio light is dim until the seal lands, then the whole side
   lights up with it (opacity on a pre-rendered gradient, nothing re-blurs) */
.st-peak .side--vp .st-fig::before { inset: -45% -20% -30% -20%; opacity: calc(0.45 + 0.55 * var(--k-seal)); }
/* the studio floor: a thin horizon the reflections sit on */
.st-fig::after {
  content: ""; position: absolute; z-index: 1; left: 4%; right: 4%; top: 27.78%; height: 1px;
  background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.12) 30%, rgba(255, 255, 255, 0.12) 70%, transparent);
  pointer-events: none;
}
/* the floor reads as the top of the return box: low until the return starts */
.st-peak.st-live .st-fig::after { opacity: calc(0.25 + 0.75 * var(--st-flr, 1)); }
/* The route, the stations, the floor and the labels are one rigid structure
   (connectors meet station edges exactly, labels keep their gap), so only
   the light, the tags that land later and the foreground specular drift. */
.st-stamp, .st-seal { translate: 0 calc(var(--k-d) * -14px); }
.st-fore {
  position: absolute; z-index: 3; left: 10%; top: -4%; width: 34%; height: 22%;
  pointer-events: none;
  background: linear-gradient(115deg, transparent 30%, rgba(255, 255, 255, 0.05) 50%, transparent 70%);
  translate: calc(var(--k-d) * 36px) calc(var(--k-d) * -26px);
}

/* gradient stops (SVG stop-color cannot read var() inline, so classes) */
.st-stop-coin-hi  { stop-color: color-mix(in oklab, var(--sc-accent) 45%, #fff); }
.st-stop-coin-mid { stop-color: var(--sc-accent); }
.st-stop-coin-lo  { stop-color: var(--vp-blue-lo); }
.st-stop-matte-hi  { stop-color: #D5D6DA; }
.st-stop-matte-mid { stop-color: #86868B; }
.st-stop-matte-lo  { stop-color: #3A3A3F; }
.st-stop-rim-a { stop-color: #fff; stop-opacity: 0.65; }
.st-stop-rim-b { stop-color: #fff; stop-opacity: 0.04; }
.st-stop-rim-c { stop-color: #fff; stop-opacity: 0.4; }
.st-stop-glass-a { stop-color: #fff; stop-opacity: 0.14; }
.st-stop-glass-b { stop-color: #fff; stop-opacity: 0.04; }
.st-stop-path-a { stop-color: var(--sc-ink-soft); }
.st-stop-path-b { stop-color: var(--sc-accent); }
.st-stop-path-matte-a { stop-color: #4A4A4F; }
.st-stop-path-matte-b { stop-color: #C9CACF; }
.st-stop-smear-a { stop-color: #8E9096; stop-opacity: 0; }
.st-stop-smear-b { stop-color: #8E9096; stop-opacity: 0.55; }
.st-stop-comet-a { stop-color: var(--sc-accent); stop-opacity: 0; }
.st-stop-comet-b { stop-color: color-mix(in oklab, var(--sc-accent) 40%, #fff); stop-opacity: 0.95; }
.st-stop-sweep-a { stop-color: #fff; stop-opacity: 0; }
.st-stop-sweep-b { stop-color: #fff; stop-opacity: 0.55; }

/* glass objects: fill from the glass gradient, a 1px gradient rim, a blurred
   specular top-left, one drop shadow per plane. No outlines. */
.st-disc, .st-tile { fill: url(#st-g-glass); stroke: none; }
.st-disc--faint { fill: rgba(255, 255, 255, 0.03); }
.st-tile--dark { fill: #141416; }
.st-tile--matte { fill: url(#st-g-matte); }
.st-disc--matte { fill: url(#st-g-matte); }
.st-rim { fill: none; stroke: url(#st-g-rim); stroke-width: 1; vector-effect: non-scaling-stroke; }
.st-rim--matte { stroke: url(#st-g-rim-matte); }
.st-spec { fill: #fff; opacity: 0.6; }
.st-spec--matte { opacity: 0.25; }
.st-avatar { fill: rgba(255, 255, 255, 0.82); }
.st-fig--card .st-avatar { fill: #141416; }
.st-mark { fill: var(--sc-accent); }
.st-mark--soft { opacity: 0.45; }
.st-slot { fill: rgba(255, 255, 255, 0.12); }
.st-slot--led { fill: #B0B3BA; }
.st-slot--ink { fill: rgba(0, 0, 0, 0.35); }
.st-ring { fill: none; stroke: url(#st-g-rim); stroke-width: 1.5; vector-effect: non-scaling-stroke; }
.st-ring--inner { stroke: var(--sc-accent); stroke-width: 0.8; opacity: 0.7; }
.st-split { fill: color-mix(in oklab, var(--sc-accent) 45%, #fff); }
.st-split--halo { fill: var(--sc-accent); opacity: 0.6; }
.st-fee__slot { fill: rgba(0, 0, 0, 0.4); }
.st-reflect { opacity: 0.35; filter: blur(1.2px); }

/* ------------------------------------------------- station reactions --- */
/* Each station answers the payment. Values come from story.js as section
   variables; every fallback is the END state (no-JS, reduced motion). The
   past reacts in greys (a dull click, no glow), the future with the accent. */
.st-stn { transform-box: fill-box; transform-origin: center; }
.st-stn--lc    { transform: scale(calc(1 + var(--st-lpc, 0) * 0.04)); }
.st-stn--merch { transform: scale(calc(1 + var(--st-lpm, 0) * 0.04)); }
.st-stn--rc    { transform: scale(calc(1 + var(--st-rpc, 0) * 0.04)); }
.st-stn--vp    { transform: scale(calc(1 + var(--st-rv, 0) * 0.04)); }
.st-stn--ex    { transform: scale(calc(1 + var(--st-rx, 0) * 0.04)); }
.st-stn--split { transform: scale(calc(1 + var(--st-rsp, 0) * 0.5)); }
/* card processor: the payment waits in the well, the switch lights dull grey,
   the hold ring ticks round once */
.st-well { fill: rgba(0, 0, 0, 0.45); }
.st-hold__tick { stroke: #A4A6AC; stroke-width: 1.6; stroke-linecap: round; opacity: 0.75; }
.st-peak.st-live .st-hold__tick { opacity: 0.16; }
.st-peak.st-live .st-hold__tick.is-on { opacity: 0.75; }
.st-switch { fill: rgba(255, 255, 255, 0.1); }
.st-switch--lit { fill: #C9CACF; opacity: var(--st-lsw, 1); }
/* merchant account: the drawer opens a few units when the payment drops in */
.st-drawer__gap { fill: rgba(0, 0, 0, 0.55); }
.st-drawer__face { fill: #9A9BA1; }
.st-drawer { transform: translateY(calc(var(--st-ldr, 1) * 4px)); }
.st-smear { fill: url(#st-g-smear); opacity: var(--st-lsm, 0); }
/* VanPay: the rim flares and the mark brightens as the payment passes */
.st-flare-rim { fill: none; stroke: color-mix(in oklab, var(--sc-accent) 55%, #fff); stroke-width: 1.5; vector-effect: non-scaling-stroke; opacity: var(--st-rv, 0); }
.st-mark-lit { fill: color-mix(in oklab, var(--sc-accent) 30%, #fff); opacity: calc(var(--st-rv, 0) * 0.85); }
/* exchange: the ring lights and a light sweep crosses it during the flip */
.st-ring-lit { fill: none; stroke: color-mix(in oklab, var(--sc-accent) 55%, #fff); stroke-width: 1.5; vector-effect: non-scaling-stroke; opacity: var(--st-rx, 0); }
.st-sweep { fill: url(#st-g-sweep); opacity: var(--st-rx, 0); }
/* fee tile: lights when the slice lands, and stays lit */
.st-flare-rim--fee { opacity: var(--st-rfee, 1); }
.st-fee .st-fee__slot { fill: color-mix(in oklab, var(--sc-accent) calc(var(--st-rfee, 1) * 60%), rgba(0, 0, 0, 0.4)); }
/* the light trail right behind the coin */
.st-comet { fill: url(#st-g-comet); opacity: var(--st-rcm, 0); }

/* wallet device: the screen lights exactly once, after the stamp */
.st-wallet-glyph__screen { fill: #0A0D14; }
.st-wallet-glyph__screen-lit { fill: color-mix(in oklab, var(--sc-accent) 32%, #0A0D14); opacity: 1; transition: opacity 220ms var(--ease-fade); }
.st-wallet-glyph__check {
  fill: none; stroke: #fff; stroke-width: 2.4; stroke-linecap: round; stroke-linejoin: round;
  stroke-dasharray: 1 2; stroke-dashoffset: calc(1 - var(--st-rck, 1));
  opacity: 1; transition: opacity 220ms var(--ease-fade) 80ms;
}
/* the coin docks: the screen glows and the check draws, dim (received, not
   yet final); after the stamp (data-st-r="held") both light fully */
.st-peak.st-live:not([data-st-r="held"]) .st-wallet-glyph__screen-lit { opacity: calc(var(--st-rw, 0) * 0.65); transition: none; }
.st-peak.st-live:not([data-st-r="held"]) .st-wallet-glyph__check { opacity: 0.45; transition: none; }

/* the payment: a coin on both sides; on VanPay it arrives as a glass note
   and leaves the exchange as the coin */
.st-coin { fill: url(#st-g-coin); stroke: none; }
.st-coin--matte { fill: url(#st-g-matte); }
.st-tok__note { fill: url(#st-g-glass); }
.st-tok__fiat, .st-tok__coin { transform-box: fill-box; transform-origin: center; }
/* end state: the coin has become "received" in the wallet device */
.st-tok--vp { opacity: 0; }
.st-peak.st-live:not([data-st-r="held"]) .st-tok--vp { opacity: var(--st-rtok, 1); }
.st-peak.st-live:not([data-st-slice]) .st-tok--slice { opacity: 0; }

/* ---------------------------------------------------- the light paths -- */
.st-rail { fill: none; stroke: rgba(255, 255, 255, 0.12); stroke-width: 1; vector-effect: non-scaling-stroke; }
.st-trail {
  fill: none; stroke: url(#st-g-path); stroke-width: 1.5; stroke-linecap: round; stroke-linejoin: round;
  stroke-dasharray: 1 2; stroke-dashoffset: calc(1 - var(--st-tr, 1));
}
.st-trail--matte { stroke-dashoffset: calc(1 - var(--st-tl, 1)); }
.st-trail--matte { stroke: url(#st-g-path-matte); }
.st-trail--glow { stroke-width: 4; opacity: 0.35; }
.st-trail--fee { stroke: var(--sc-accent); stroke-width: 1; stroke-dashoffset: calc(1 - var(--st-s, 1)); }
.st-trail--fee.st-trail--glow { stroke-width: 3; }
.st-track { fill: none; stroke: none; }

/* ------------------------------------------------ the return (signature) */
.st-ret { fill: none; stroke-linecap: round; stroke-linejoin: round; stroke-dasharray: 1 2; }
.st-ret--card { stroke: url(#st-g-ret-matte); stroke-width: 1.5; stroke-dashoffset: calc(1 - var(--st-l, 1)); }
.st-ret--vp   { stroke: url(#st-g-ret); stroke-width: 1.5; stroke-dashoffset: calc(1 - var(--st-r, 0.4)); }
.st-ret--glow { stroke-width: 4; opacity: 0.35; }
.st-ret--vp.st-ret--glow { stroke-width: 5; opacity: 0.45; }
/* the tip: a bright point of light with its halo (the jitter rides this) */
.st-tip__dot { fill: #fff; }
.st-tip__halo { fill: var(--sc-accent); opacity: 0.8; }
.st-tip--card .st-tip__halo { fill: #C9CACF; opacity: 0.5; }
.st-peak.st-live:not([data-st-draw]) .st-tip { opacity: 0; }

/* the glass gate: a frosted pill with a beam; it flares once when the light
   arrives and stops (one keyframe run on the attribute, transform + opacity). */
.st-peak.st-live .st-gate { opacity: var(--st-gt, 1); }
.st-gate__glass { fill: rgba(255, 255, 255, 0.1); }
.st-gate__beam { stroke: #fff; stroke-width: 1.5; stroke-linecap: round; opacity: 0.9; }
.st-gate__flare { fill: var(--sc-accent); opacity: 0; transform-box: fill-box; transform-origin: center; }
.st-gate__burst { fill: color-mix(in oklab, var(--sc-accent) 70%, #fff); opacity: 0; transform-box: fill-box; transform-origin: center; }
.st-peak[data-st-gate] .st-gate__flare { animation: st-gate-flare 700ms var(--ease-fade) 1 both; }
.st-peak[data-st-gate] .st-gate__burst { animation: st-gate-burst 900ms var(--ease-fade) 1 both; }
@keyframes st-gate-flare {
  0%   { opacity: 0.95; transform: scale(0.6, 0.8); }
  35%  { opacity: 0.8;  transform: scale(1.5, 1.2); }
  100% { opacity: 0;    transform: scale(2.1, 1.4); }
}
@keyframes st-gate-burst {
  0%   { opacity: 0.85; transform: scale(0.3); }
  30%  { opacity: 0.6;  transform: scale(1.4); }
  100% { opacity: 0;    transform: scale(2.4); }
}
/* the whole studio flashes once when the return hits the gate: a pre-rendered
   radial light, opacity only (no blur animates) */
.st-flash {
  position: absolute; z-index: 1; inset: -25% -10%; pointer-events: none; opacity: 0;
  background: radial-gradient(45% 40% at 62% 70%, color-mix(in oklab, var(--sc-accent) 55%, transparent), transparent 70%);
}
.st-peak[data-st-gate] .st-flash { animation: st-flash 1100ms var(--ease-fade) 1 both; }
@keyframes st-flash {
  0%   { opacity: 0.95; }
  100% { opacity: 0; }
}

/* labels: 14px caps, centred on their column. Every label keeps the same
   6px gap to its station at every size: row 1 sits above the station tops
   (y 44 of 360: 12.22%), row 2 under the station bottoms (y 100: 27.78%),
   the fee under its tile (y 132: 36.67%). */
.st-peak { --st-tag-gap: 0.375rem; }
.st-fig__tag {
  position: absolute; z-index: 4; bottom: calc(87.78% + var(--st-tag-gap)); white-space: nowrap;
  font: 500 0.875rem/1.2 var(--sc-font-text); letter-spacing: 0.08em; text-transform: uppercase;
  color: var(--sc-ink-soft);
  transform: translateX(-50%);
}
@media (max-width: 1024px) {
  /* the drawing is narrower than the labels in one line: two-word labels
     wrap and the labels take two rows on the same grid. Row 1 (columns 1, 3,
     5) stays above, anchored to the station tops so a two-line label grows
     upward; row 2 (the card processor, VanPay) sits the same gap under the
     station bottoms. The fee keeps its place under its own tile. */
  .st-fig__tag { max-width: 5.5em; white-space: normal; text-align: center; line-height: 1.15; }
  .st-fig__tag--proc, .st-fig__tag--vp { top: calc(27.78% + var(--st-tag-gap)); bottom: auto; }
  .st-fig__tag--fee { max-width: none; white-space: nowrap; }
}
/* the five columns: x 56 / 186 / 316 / 446 / 576 of 640 */
.st-fig__tag--a   { left: 8.75%; }
.st-fig__tag--vp  { left: 29.0625%; }
.st-fig__tag--mid { left: 49.375%; }
.st-fig__tag--end { left: 90%; }
/* the fee, under its tile on column 4 */
.st-fig__tag--fee { left: 69.6875%; top: calc(36.67% + var(--st-tag-gap)); bottom: auto; color: #7FA6FF; } /* 4.3:1 as --sc-accent over the ambient light; lifted */

/* the chargeback: a flat grey glass tag that lands (scale 1.1 to 1, opacity) */
.st-stamp {
  position: absolute; z-index: 5; left: 42%; top: 72.2%;
  padding: 0.55em 1em 0.5em;
  border-radius: 999px;
  background: rgba(255, 255, 255, 0.1);
  box-shadow: inset 0 1px 0 var(--st-glass-hi), inset 0 -1px 0 var(--st-glass-lo), var(--st-depth);
  color: var(--sc-ink);
  font: 600 clamp(1rem, 0.6rem + 1.2vw, 1.75rem)/1 var(--sc-font-text);
  letter-spacing: 0.08em; text-transform: uppercase; white-space: nowrap;
  opacity: var(--k-stamp);
  transform: translate(-50%, -50%) scale(calc(1 + (1 - var(--k-stamp)) * 0.1));
}
.st-ledger {
  margin: clamp(1rem, 1.8vw, 1.5rem) 0 0;
  opacity: var(--k-ledger);
  transform: translate3d(0, calc((1 - var(--k-ledger)) * 0.5rem), 0);
}
.st-ledger b { color: var(--sc-ink); font-weight: 600; text-decoration: line-through; text-decoration-thickness: 1px; }

/* the seal: a frosted glass disc on the path the reversal never reached.
   The one backdrop-filter in this act. */
.st-seal {
  position: absolute; z-index: 5; left: 36%; top: 72.2%;
  width: 30%; aspect-ratio: 1;
  display: grid; place-items: center;
  border-radius: 50%;
  color: var(--sc-ink);
  background: var(--st-glass-bg);
  -webkit-backdrop-filter: blur(18px) saturate(160%);
  backdrop-filter: blur(18px) saturate(160%);
  box-shadow: inset 0 1px 0 var(--st-glass-hi), inset 0 -1px 0 var(--st-glass-lo), 0 30px 60px rgba(0, 0, 0, 0.45);
  opacity: var(--k-seal);
  transform: translate(-50%, -50%) scale(calc(1 + (1 - var(--k-seal)) * 0.35));
}
.st-seal::before {
  content: ""; position: absolute; inset: 0; border-radius: inherit; padding: 1px;
  background: linear-gradient(135deg, rgba(255, 255, 255, 0.65), rgba(255, 255, 255, 0.04) 50%, rgba(255, 255, 255, 0.4));
  -webkit-mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
  mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
  -webkit-mask-composite: xor;
  mask-composite: exclude;
  pointer-events: none;
}
.st-seal__text {
  position: relative; text-align: center;
  font: 600 0.875rem/1.25 var(--sc-font-text);
  letter-spacing: 0.08em; text-transform: uppercase;
}
.st-seal__text > span { display: block; white-space: nowrap; }

/* captions: the card side states it, the VanPay side lands it */
.st-cap { margin: clamp(1.25rem, 2.4vw, 2rem) 0 0; }
.st-cap--card {
  max-width: 14ch;
  opacity: var(--k-capl);
  transform: translate3d(0, calc((1 - var(--k-capl)) * 12px), 0) scale(calc(0.96 + var(--k-capl) * 0.04));
  transform-origin: left top;
}
.st-peak .st-cap--vp {
  /* the real super: the peak owns the only --t-super on the page */
  font-size: var(--t-super);
  max-width: min(820px, 7.6em); /* always "No" / "chargebacks.": the poster line */
  opacity: var(--k-capr);
  transform: translate3d(0, calc((1 - var(--k-capr)) * 12px), 0) scale(calc(0.96 + var(--k-capr) * 0.04));
  transform-origin: left top;
}
.st-cap-sub {
  margin: 1.5rem 0 0; max-width: 40rem;
  opacity: var(--k-sub);
  transform: translate3d(0, calc((1 - var(--k-sub)) * 8px), 0);
}
/* the one action of the act: lands after the caption (p 0.78) with the
   caption's own motion. While the act is live and the cue has not come it
   is hidden outright, so it is never focusable at opacity 0; story.js sets
   data-st-cta at the cue. Reduced motion and no-JS show the end state. */
.st-cta-row {
  margin: 1.5rem 0 0;
  opacity: var(--k-cta);
  transform: translate3d(0, calc((1 - var(--k-cta)) * 12px), 0);
}
.st-cta { min-height: 3rem; padding-inline: 1.5rem; }
.st-live:not([data-st-cta]) .st-cta-row { visibility: hidden; }
.st-peak .st-cta-row:focus-within { opacity: 1; transform: none; visibility: visible; }

/* --------------------------------------------------------- stacked ---- */
/* Below 900 the act stacks: past copy, past object, future copy + action,
   future object, each on its side's ground (base.css paints the ground, the
   14px caps label and the era). The rhythm variables carry the contract's
   24 / 64 at tablet height and shrink with the viewport height so the pinned
   stage still fits a phone with the browser chrome open. The figures shrink
   with the height too (never hidden): --st-fig is the drawing's width. */
@media (max-width: 899.98px) {
  .st-peak {
    --st-pad: 1rem;             /* side band -> first block, last block -> side end */
    --st-gap-sub: 1.5rem;       /* head -> sub (24) */
    --st-gap-cta: 1rem;         /* sub -> action */
    --st-gap-obj: 2rem;         /* copy -> object (64 at tablet height, see below) */
    --st-fig: clamp(13rem, (100vh - 36rem) * 0.889, 18rem);
    --st-fig-card: var(--st-fig);
    --st-fig-crop: 0px;         /* air cropped below the drawing on short phones */
  }
  .st-peak .side { align-items: stretch; }
  .st-peak .side.st-pside[data-label] { padding-top: calc(var(--band) + var(--st-pad)); padding-bottom: var(--st-pad); }
  .st-peak .display { text-wrap: pretty; }
  /* type floors: the super (the loudest line on the page) never under 48,
     the head never under 32; the tokens already floor there, restated so a
     narrower token can never pull them down */
  .st-peak .display--head { font-size: max(2rem, var(--t-head)); }
  .st-peak .display--super, .st-peak .st-cap--vp { font-size: max(3rem, var(--t-super)); max-width: none; }
  .st-cap { margin-top: 0; }
  .st-cap--card { max-width: none; }
  .st-ledger { margin: var(--st-gap-sub) 0 0; }
  .st-cap-sub { margin-top: var(--st-gap-sub); max-width: none; line-height: 1.35; }
  .st-cta-row { margin-top: var(--st-gap-cta); }
  .st-fig { width: 100%; max-width: var(--st-fig); margin-inline: auto; margin-top: var(--st-gap-obj); margin-bottom: calc(-1 * var(--st-fig-crop)); }
  .st-fig--card { max-width: var(--st-fig-card); margin-top: calc(var(--st-gap-obj) + 0.75rem); }
  /* labels in two rows so they never collide on a narrow drawing: the
     customer, the exchange and the far station sit above their stations
     (anchored to the station tops, so two-line labels grow upward), VanPay
     and the card processor sit below theirs, the fee under its tile */
  /* the customer label centres on its disc (it may lean into the gutter) and
     the far label leans the other way, so the exchange label has air */
  .st-fig__tag { letter-spacing: 0.06em; }
  .st-fig__tag--end { left: auto; right: -0.75rem; transform: none; text-align: right; }
  /* the card side has no label above its middle column, so its far label needs
     no lean: it ends on the drawing's edge, sized to its longest word */
  .st-fig--card .st-fig__tag--end { right: 0; max-width: none; width: min-content; }
  /* the card processor label is alone in row 2, so it takes one line and
     keeps clear of the CHARGEBACK pill on the return below it */
  .st-fig--card .st-fig__tag--proc { max-width: none; white-space: nowrap; }
  /* the seal is a frosted pill on the stacked drawing (a disc wide enough for
     its 14px text would cover the whole return) */
  .st-seal {
    left: 40%; width: max-content; aspect-ratio: auto; border-radius: 999px;
    padding: 0.55em 1em 0.5em; font-size: 0.875rem;
  }
  .st-seal__text { font-size: 1em; white-space: nowrap; }
  .st-seal__text > span { display: inline; }
  .st-stamp { font-size: 0.875rem; }
  .st-stamp, .st-seal { translate: 0 calc(var(--k-d) * -6px); }
}
/* tablet portrait: room for the full rhythm and a larger drawing */
@media (max-width: 899.98px) and (min-width: 600px) and (min-height: 960px) {
  .st-peak { --st-gap-obj: 4rem; --st-pad: 1.5rem; --st-fig: clamp(13rem, (100vh - 40rem) * 0.889, 22rem); }
}
/* short portrait phones (640 to 700 high, e.g. 360x640 or a 390 phone with
   the browser chrome open): the whole act still fits the pinned stage.
   Tighter rhythm, the past drawing at 10rem, the future drawing at 12rem,
   the 15% of air below each drawing cropped, labels at 12px (the agreed
   floor), the seal pill at 12px. The type floors stay (48 / 32 / 14). */
@media (max-width: 899.98px) and (max-height: 700px) and (min-height: 500.01px) {
  .st-peak {
    --st-pad: 0.25rem; --st-gap-sub: 0.375rem; --st-gap-cta: 0.5rem; --st-gap-obj: 1.375rem;
    --st-fig: 12rem; --st-fig-card: 10rem; --st-fig-crop: 0.95rem;
  }
  .st-peak .display--super, .st-peak .st-cap--vp { line-height: 1; }
  .st-cap-sub { line-height: 1.3; }
  .st-fig__tag { font-size: 0.75rem; letter-spacing: 0.02em; }
  .st-seal { left: 46%; font-size: 0.75rem; letter-spacing: 0.05em; }
  .st-stamp { font-size: 0.75rem; }
  /* the pill holds still a few px under the line (no upward drift into the label) */
  .st-stamp { translate: 0 3px; }
  /* the card drawing's far label wraps to two lines and grows upward, so it
     needs the room that the tight rhythm takes away above the drawing */
  .st-fig--card { margin-top: calc(var(--st-gap-obj) + 1.25rem); }
}
/* landscape phones: the coordinator unpins the act (data-short), so it flows
   as a stacked act with base.css's section rhythm; the drawings stay under
   40vh and the act shows its end state (nothing to scrub in a flowing act) */
@media (max-height: 500px) {
  .st-peak { --st-gap-obj: 2.5rem; --st-fig: min(22rem, 71vh); --st-fig-card: var(--st-fig); --st-fig-crop: 0px; }
  html[data-short] .st-peak { --k-d: 0; --k-seal: 1; --k-stamp: 1; --k-ledger: 1; --k-capl: 1; --k-capr: 1; --k-sub: 1; --k-cta: 1; }
  html[data-short] .st-peak .st-trail, html[data-short] .st-peak .st-ret--card { stroke-dashoffset: 0; }
  html[data-short] .st-peak .st-ret--vp { stroke-dashoffset: calc(1 - var(--st-clamp, 0.4)); }
  html[data-short] .st-peak .st-tip { opacity: 1 !important; }
  html[data-short] .st-peak .st-tok--vp { opacity: 0 !important; }
  html[data-short] .st-peak .st-tok--slice { opacity: 1 !important; }
  html[data-short] .st-peak .st-wallet-glyph__screen-lit, html[data-short] .st-peak .st-wallet-glyph__check { opacity: 1 !important; transition: none; }
  html[data-short] .st-peak .st-cta-row { visibility: visible; }
}

/* ------------------------------------------ desktop: vertical routes --- */
/* story.js sets data-st-lay="v" from 900 wide (not on short screens) and
   draws both routes top to bottom on one shared row grid (viewBox 150 x 384:
   rows y 36 / 140 / 244 / 348 = 9.375% / 36.458% / 63.542% / 90.625%, the
   split and the fee on y 296 = 77.083%, the gate and the seal on y 192 = 50%,
   the CHARGEBACK pill on row 3). Card: labels | return lane (x 26 = 17.333%) | axis (x 106).
   VanPay: axis (x 44) | fee + return lane (x 124 = 82.667%) | labels.
   The drawing comes first, the copy under it; both drawings hang from the
   same top so the rows line up across the divider. --st-fh is the drawing's
   height: what the stage leaves after the VanPay copy (two super lines, the
   qualifier, the action). */
.st-peak[data-st-lay="v"] {
  --st-fh: clamp(15rem, 100vh - 2 * clamp(4.5rem, 10vh, 7rem) - 2.1 * var(--t-super) - 9.75rem, 26rem);
  --st-lab: 11rem;     /* the card side's label column, left of its drawing */
  --st-lane: 82.667%;  /* lane to the far edge of the box, both sides */
}
.st-peak[data-st-lay="v"] [data-sc-stage] > .split > .side.st-pside { justify-content: flex-start; }
.st-peak[data-st-lay="v"] .side--card .st-col--peak { padding-bottom: 0; }
.st-peak[data-st-lay="v"] .st-fig {
  width: calc(var(--st-fh) * 150 / 384); max-width: none; align-self: flex-start;
}
.st-peak[data-st-lay="v"] .st-fig--card { margin-left: var(--st-lab); }
.st-peak[data-st-lay="v"] .st-fig::after,
.st-peak[data-st-lay="v"] .st-reflect { display: none; }
.st-peak[data-st-lay="v"] .st-fig--card::before { inset: -12% -90% -12% -110%; }
.st-peak[data-st-lay="v"] .side--vp .st-fig::before { inset: -18% -150% -18% -60%; }
.st-peak[data-st-lay="v"] .st-flash { inset: -10% -60%; background: radial-gradient(30% 35% at 60% 50%, color-mix(in oklab, var(--sc-accent) 55%, transparent), transparent 70%); }
.st-peak[data-st-lay="v"] .st-fore { left: -20%; top: 2%; width: 90%; height: 16%; }
/* labels: one column beyond the lane, centred on their rows */
.st-peak[data-st-lay="v"] .st-fig__tag {
  top: 9.375%; bottom: auto; max-width: none; width: auto;
  white-space: nowrap; line-height: 1.2; letter-spacing: 0.08em;
  transform: translateY(-50%);
}
.st-peak[data-st-lay="v"] .st-fig--vp .st-fig__tag { left: calc(var(--st-lane) + 1rem); right: auto; text-align: left; }
.st-peak[data-st-lay="v"] .st-fig--card .st-fig__tag { left: auto; right: calc(var(--st-lane) + 1rem); text-align: right; }
.st-peak[data-st-lay="v"] .st-fig__tag--vp,
.st-peak[data-st-lay="v"] .st-fig__tag--proc { top: 36.458%; }
.st-peak[data-st-lay="v"] .st-fig--vp .st-fig__tag--mid { top: 63.542%; }
.st-peak[data-st-lay="v"] .st-fig__tag--fee { top: 77.083%; }
.st-peak[data-st-lay="v"] .st-fig__tag--end { top: 90.625%; }
/* the CHARGEBACK pill hangs on the card lane on row 3 (free on the card
   side: mid-way between the processor and merchant account labels); it
   reaches outward, never over the main axis */
.st-peak[data-st-lay="v"] .st-stamp {
  left: auto; right: calc(var(--st-lane) - 0.75rem); top: 63.542%;
  font-size: clamp(1rem, 0.5rem + 0.9vw, 1.375rem);
  transform-origin: right center;
  transform: translate(0, -50%) scale(calc(1 + (1 - var(--k-stamp)) * 0.1));
}
/* the seal: a frosted pill beside the gate (the gate's bar ends at 102.667%) */
.st-peak[data-st-lay="v"] .st-seal {
  left: calc(102.667% + 0.5rem); top: 50%;
  width: max-content; aspect-ratio: auto; border-radius: 999px;
  padding: 0.6em 1.1em 0.55em;
  transform-origin: left center;
  transform: translate(0, -50%) scale(calc(1 + (1 - var(--k-seal)) * 0.35));
}
.st-peak[data-st-lay="v"] .st-seal__text { white-space: nowrap; }
.st-peak[data-st-lay="v"] .st-seal__text > span { display: inline; }
.st-peak[data-st-lay="v"] .st-cap { margin-top: clamp(1.5rem, 2.4vw, 2rem); }
/* "chargebacks." (5.8em) always fits its column on narrow desktops (1024) */
.st-peak[data-st-lay="v"] .st-cap--vp { font-size: min(var(--t-super), 6.9vw); }
.st-peak[data-st-lay="v"] .st-ledger { margin-top: clamp(1.25rem, 2vw, 1.75rem); }

/* --------------------------------------------------- reduced motion ---- */
@media (prefers-reduced-motion: reduce) {
  .st-peak { --k-d: 0; --k-seal: 1; --k-stamp: 1; --k-ledger: 1; --k-capl: 1; --k-capr: 1; --k-sub: 1; --k-cta: 1; }
  .st-trail { stroke-dashoffset: 0; }
  .st-ret--card { stroke-dashoffset: 0; }
  .st-ret--vp { stroke-dashoffset: calc(1 - var(--st-clamp, 0.4)); }
  .st-peak .st-tip { opacity: 1 !important; }
  .st-peak .st-tok--vp { opacity: 0 !important; }
  .st-peak .st-tok--slice { opacity: 1 !important; }
  .st-peak .st-wallet-glyph__screen-lit, .st-peak .st-wallet-glyph__check { opacity: 1 !important; transition: none; }
  .st-peak[data-st-gate] .st-gate__flare, .st-peak[data-st-gate] .st-gate__burst, .st-peak[data-st-gate] .st-flash { animation: none; }
}
