/* ==========================================================
   STORY PAGE — a layout kind of the generator (ORDER W7 §8.25);
   for now the page is its hero alone (§8.29 (c), §8.30 (a), §8.31 (a))
   Loaded only by story pages, after site.css. The motion here is
   the named "story page" exception in apps/public-web/DESIGN-RULES.md:
   a reveal may run to 600 ms and the entrance to 1.2 s; controls keep
   150/200/250. One curve. Only opacity, transform, colour and shadow
   animate — except a stage opening, which is grid-template-rows by
   the order's own rule, so the page never jumps. The stage line draws
   itself by stroke-dashoffset.
   ========================================================== */
/* The same file as the site's face (already preloaded), with `optional`: if it
   is not ready for the first paint, this page keeps the system face for the
   visit instead of swapping and moving every line (§8.25 Four (e): CLS 0.00).
   Measured before this: the swap alone was a shift of 0.011 at 1440. */
@font-face{font-family:'InterVar Story';src:url('/assets/inter.woff2') format('woff2');font-weight:100 900;font-style:normal;font-display:optional}
:root{--font:"InterVar Story",Inter,-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,sans-serif}
:root{--story-ease:cubic-bezier(0.2,0,0,1);--story-motion:1;--story-field:#17130F;--story-cream:#FCFAF6;--story-cream-2:rgba(252,250,246,.78)}
@media (prefers-reduced-motion:reduce){:root{--story-motion:0}}

/* The action is the only tomato on the screen (§8.25 Three): on a story page
   the navigation's "Get in touch" wears the quiet button, not the primary. */
.nav .btn-primary{background:var(--surface);color:var(--ink);border-color:var(--line-strong);box-shadow:none}

.sr-only{position:absolute!important;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}

/* ---------- the hero: the skyline, the veil, the words ---------- */
/* The veil is measured, not chosen: over the photograph's brightest pixel
   (255,255,252) a 70 % veil of the field colour leaves the cream at 6.6 : 1
   and the 78 % cream (eyebrow, units, the Chinese name) at 4.78 : 1. */
.story-top{position:relative;isolation:isolate;min-height:100vh;min-height:100svh;display:flex;align-items:flex-end;padding:calc(var(--nav-h) + 28px) 0 clamp(56px,10vh,104px);color:var(--story-cream);overflow:hidden;
  background:var(--story-field) url("data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wAARCAAVACADASIAAhEBAxEB/8QAGQAAAgMBAAAAAAAAAAAAAAAAAAMCBAUG/8QAJxAAAgIBAwIFBQAAAAAAAAAAAQIDEQAEBRITIRQxQVFhIiNxsfD/xAAYAQACAwAAAAAAAAAAAAAAAAABAgADBf/EABoRAAIDAQEAAAAAAAAAAAAAAAABAhJBURH/2gAMAwEAAhEDEQA/ANqIxCbo39yrrHp0nLBWVipogHyOc427Isvio5DbijS3x/qx2lZjG3hiJEkjIZ2bjRJ8zf6xrJ6JVrDeMfsMTJAGBusSdy6UaK0QJ419Lcu9dsp7hu7ppw0Y4NZBPHsR6VeFSI4+lJdv0rqgaM0oqlNX+ffGLpdOpIVHUH0EhGGGZ95dLSTwadDfSJPy5s4l4tPwJEJHxzOGGG8uitn/2Q==") center/cover no-repeat}
.story-bg{position:absolute;inset:0;z-index:-1;clip-path:inset(0)}
.story-bg::after{content:"";position:absolute;inset:0;background:var(--story-veil)}
:root{--story-veil:rgba(23,19,15,.70)}
/* A fixed layer clipped to the hero — never background-attachment. */
.story-bg-fix{position:fixed;inset:0;pointer-events:none}
.story-bg-fix img{width:100%;height:100%;object-fit:cover;display:block;transform-origin:50% 40%}
/* The hero's own measure: the gutters, and on the right room for the stage line (never under the words). */
.story-top-in{width:100%;max-width:none;position:relative;padding:0 calc(max(var(--gut),56px) + 24px) 0 var(--gut)}
.story-main{max-width:100%}
.story-eyebrow{color:var(--story-cream-2);margin:0 0 14px}
/* One line at every width (§8.31 (a)): "Melbourne in My Eyes" measures 11.2 em
   in the heading face (American Typewriter, and Cutive tuned to it), so the
   size is the room between the gutters divided by 11.4, at most 88 px. The
   journey measures it on every width it is shown at. */
.story-title{font-size:min(88px,calc((100vw - var(--gut) - max(var(--gut),56px) - 24px) / 11.4));line-height:1.04;white-space:nowrap;margin:0;color:var(--story-cream)}
.story-title-en{display:block}
.story-title .sw{display:inline-block}
.story-title-zh{display:block;width:fit-content;font-family:var(--font);font-size:clamp(17px,1.9vw,27px);font-weight:540;letter-spacing:.1em;line-height:1.3;margin-top:.45em;color:var(--story-cream-2)}
.story-sub{font-size:clamp(21px,2.4vw,34px);line-height:1.2;margin:clamp(14px,2vh,22px) 0 0;color:var(--story-cream)}

.story-count{margin:clamp(26px,4vh,40px) 0 0}
.story-count-label{font-size:13px;font-weight:620;letter-spacing:.16em;text-transform:uppercase;color:var(--story-cream-2);margin:0 0 12px}
.story-cells{display:inline-flex;gap:clamp(8px,1.4vw,16px)}
.story-cell{display:flex;flex-direction:column;align-items:center;min-width:clamp(60px,6.4vw,96px);padding:12px 6px 10px;border-radius:16px;background:rgba(252,250,246,.08);border:1px solid rgba(252,250,246,.16)}
.story-num{font-size:clamp(32px,3.8vw,56px);font-weight:600;line-height:1;letter-spacing:-.03em;font-variant-numeric:tabular-nums;width:2ch;text-align:center;color:var(--story-cream)}
.story-num[data-u="d"]{width:3ch}
.story-unit{margin-top:8px;font-size:12px;font-weight:560;letter-spacing:.12em;text-transform:uppercase;color:var(--story-cream-2)}
.story-count-words{margin:14px 0 0;font-size:15px;color:var(--story-cream-2)}
/* A clock more than five minutes out: the words only, never a wrong number. Space kept, so nothing moves. */
.story-skewed .story-cells,.story-skewed .story-count-label{visibility:hidden}
.story-act{margin-top:clamp(24px,3.6vh,36px)}
.story-action{font-size:16px;padding:15px 28px}

/* ---------- the stage line, on the right ---------- */
.story-rail{position:absolute;top:20%;bottom:20%;right:max(14px,calc(var(--gut) - 28px));width:44px;z-index:2}
.story-rail-line{position:absolute;left:21px;top:0;width:2px;height:100%;overflow:visible;pointer-events:none}
.story-rail-line line{stroke:rgba(255,75,68,.5);stroke-width:2;stroke-dasharray:1 1;stroke-dashoffset:0}
/* The glow is its own blurred copy of the line, on its own layer — never a filter over the photograph. */
.story-rail-glow{left:18px;width:8px;filter:blur(4px)}
.story-rail-glow line{stroke:rgba(255,75,68,.4);stroke-width:2}
.story-rail ol{list-style:none;margin:0;padding:0;height:100%;display:flex;flex-direction:column;justify-content:space-between}
.story-stop{position:relative;height:0}
.story-dot{all:unset;box-sizing:border-box;position:absolute;left:0;top:-22px;width:44px;height:44px;display:grid;place-items:center;cursor:pointer;border-radius:50%}
.story-dot:focus-visible{outline:2px solid var(--story-cream);outline-offset:2px}
.story-dot-mark{width:10px;height:10px;border-radius:50%;background:var(--story-cream);box-shadow:0 0 8px 2px rgba(255,75,68,.6);transition:transform 200ms var(--story-ease)}
.story-stop.is-current .story-dot-mark{width:14px;height:14px;background:#FF4B44;box-shadow:0 0 0 4px rgba(255,75,68,.22),0 0 14px 4px rgba(255,75,68,.65)}
.story-dot:hover .story-dot-mark,.story-dot:focus-visible .story-dot-mark{transform:scale(1.6)}
.story-dot-name{position:absolute;right:46px;top:50%;white-space:nowrap;font-size:13.5px;font-weight:620;letter-spacing:.01em;padding:6px 12px;border-radius:100px;
  color:var(--story-cream);background:rgba(23,19,15,.78);border:1px solid rgba(252,250,246,.16);-webkit-backdrop-filter:blur(10px);backdrop-filter:blur(10px);
  opacity:0;transform:translate(10px,-50%);transition:opacity 200ms var(--story-ease),transform 200ms var(--story-ease);pointer-events:none}
.story-dot-dates{font-weight:500;color:var(--story-cream-2)}
.story-dot:hover .story-dot-name,.story-dot:focus-visible .story-dot-name{opacity:1;transform:translate(0,-50%)}

/* ---------- the stage cards, on the site's one popover ---------- */
.stagepop h3{margin:2px 0 4px}
.stage-card .eyebrow{margin-bottom:8px}
.stage-card-dates{margin:0;font-weight:600;color:var(--ink)}
.stage-card-brief{margin:12px 0 0;color:var(--ink-2)}
.stage-card ul{margin:12px 0 0;padding:0 0 0 18px}
.stage-card li{margin:5px 0}
.stage-card h4{font-size:13px;font-weight:660;letter-spacing:.14em;text-transform:uppercase;color:var(--ink-2);margin:22px 0 0}
.stage-card h4 + p{margin:8px 0 0}
.stage-card-media{list-style:none;padding:0!important;display:flex;flex-wrap:wrap;gap:8px}
.stage-card-media li{margin:0;padding:6px 12px;border-radius:100px;border:1px solid var(--line-strong);font-size:14px}
.stage-card-fee{margin:18px 0 0;padding:12px 16px;border-radius:var(--r);background:var(--bg-2);border:1px solid var(--line);font-weight:560}
.stage-card-terms{margin:12px 0 0;color:var(--ink-2)}
.stage-card-venue p{margin:4px 0 0}
.story-venue-name{font-weight:620;color:var(--ink)}
html.js .stage-card:not(.is-shown){display:none}
/* Without script the cards are on the page, after it, as plain text. */
html:not(.js) .stagepop{position:static;transform:none;opacity:1;pointer-events:auto;width:auto;max-width:760px;max-height:none;margin:40px auto;box-shadow:none}
html:not(.js) .stagepop .pop-close{display:none}
html:not(.js) .stage-card + .stage-card{margin-top:32px}

/* ---------- Sign up to keep updated (only while the quick join is on) ---------- */
.story-join{position:absolute;top:calc(var(--nav-h) + 20px);right:calc(var(--gut) + 48px);width:320px;padding:20px;border-radius:20px;z-index:3;
  background:rgba(23,19,15,.66);border:1px solid rgba(252,250,246,.16);-webkit-backdrop-filter:blur(18px) saturate(140%);backdrop-filter:blur(18px) saturate(140%);color:var(--story-cream)}
.story-join-h{font-size:20px;line-height:1.2;margin:0 0 12px;color:var(--story-cream)}
.story-join-form{display:flex;flex-direction:column;gap:10px}
.story-join-trap{position:absolute;left:-9999px;width:1px;height:1px;overflow:hidden}
.story-join-field{display:flex;flex-direction:column;gap:4px;font-size:13px;font-weight:600;color:var(--story-cream-2)}
.story-join-field input{font:inherit;font-size:15px;font-weight:450;color:var(--story-cream);background:rgba(252,250,246,.08);border:1px solid rgba(252,250,246,.3);border-radius:10px;padding:9px 11px}
.story-join-field input:focus-visible{outline:2px solid var(--story-cream);outline-offset:1px}
.story-join-field input[aria-invalid="true"]{border-color:#FF9691}
.story-join-tick{display:flex;gap:9px;align-items:flex-start;font-size:13.5px;line-height:1.4;color:var(--story-cream)}
.story-join-tick input{margin-top:2px;accent-color:#FF4B44}
.story-join-msg{margin:0;font-size:13px;color:var(--story-cream)}
.story-join-msg:empty{display:none}
.story-join-msg.is-bad{color:#FF9691}
.story-join-btn{align-self:flex-start;color:var(--story-cream);border-color:rgba(252,250,246,.4);background:rgba(252,250,246,.06)}
.story-join-notice{margin:2px 0 0;font-size:11.5px;line-height:1.45;color:var(--story-cream-2)}
.story-join-notice a,.story-join-done{color:var(--story-cream)}
.story-join-done{margin:0;font-size:15px;line-height:1.5}

/* With the panel on, the words keep to the left of it, and the title fits that room, still one line. */
@media (min-width:701px){
  .story-top--join .story-top-in{padding-right:calc(var(--gut) + 400px)}
  .story-top--join .story-title{font-size:min(88px,calc((100vw - 2 * var(--gut) - 400px) / 11.4))}
}

/* ---------- the sponsor slot (empty for now; rendered only with entries) ---------- */
.story-sponsors{position:absolute;right:calc(var(--gut) + 48px);bottom:24px}
.story-sponsors ul{list-style:none;margin:0;padding:0;display:flex;gap:18px;align-items:center}
.story-sponsors img{height:28px;width:auto;display:block}

/* ---------- the phone: the line at the right edge, its names always shown ---------- */
@media (max-width:700px){
  .story-top{min-height:max(100svh,920px);align-items:flex-start;padding:calc(var(--nav-h) + 14px) 0 36px}
  .story-top-in{padding:0 var(--gut)}
  .story-title{font-size:calc((100vw - 2 * var(--gut)) / 11.4)}
  .story-eyebrow{font-size:10.5px;letter-spacing:.14em;margin-bottom:10px;max-width:calc(100% - 92px)}
  .story-main > :not(.story-title):not(.story-eyebrow){max-width:calc(100% - 92px)}
  .story-sub{font-size:21px}
  .story-cells{display:flex;gap:6px;width:100%}
  .story-cell{min-width:0;flex:1 1 0;padding:10px 2px 8px;border-radius:12px}
  .story-num{font-size:24px}
  .story-num[data-u="d"]{width:2.6ch}
  .story-unit{font-size:9.5px;letter-spacing:.06em}
  .story-count-words{font-size:13.5px}
  .story-action{font-size:15px;padding:13px 20px}
  .story-rail{right:8px}
  .story-dot-name{opacity:1;transform:translate(0,-50%);font-size:12px;padding:5px 10px;right:40px;pointer-events:none}
  .story-dot-dates{display:none}
  .story-join{position:relative;top:auto;right:auto;width:auto;margin:28px var(--gut) 0;max-width:calc(100% - 92px - var(--gut))}
  .story-top{flex-wrap:wrap}
  .story-sponsors{position:static;margin:24px var(--gut) 0}
}

/* ---------- the entrance: once per visit, 1.2 s in all ---------- */
@keyframes story-settle{from{transform:scale(1.04)}to{transform:none}}
/* From a quarter, not from nothing: the words are on the page at first paint,
   so the largest paint is not held back by the entrance (§8.25 Four (e)). */
@keyframes story-rise{from{opacity:.25;transform:translateY(12px)}to{opacity:1;transform:none}}
@keyframes story-fade{from{opacity:0}to{opacity:1}}
/* The countdown's words are the phone's largest paint: from a quarter too, never from nothing. */
@keyframes story-fade-q{from{opacity:.25}to{opacity:1}}
@keyframes story-draw{from{stroke-dashoffset:1}to{stroke-dashoffset:0}}
@keyframes story-light{from{opacity:0;transform:scale(.4)}to{opacity:1;transform:none}}
/* The current stage's dot pulses once, as it lights — never in a loop. */
@keyframes story-pulse{0%{opacity:0;transform:scale(.4)}55%{opacity:1;transform:scale(1.5)}100%{opacity:1;transform:none}}
html.story-enter .story-bg-fix img{animation:story-settle 1200ms var(--story-ease) both}
html.story-enter .story-eyebrow{animation:story-rise 500ms var(--story-ease) 100ms both}
html.story-enter .story-title .sw{animation:story-rise 600ms var(--story-ease) both;animation-delay:calc(150ms + var(--i) * 40ms)}
html.story-enter .story-title-zh,html.story-enter .story-sub{animation:story-rise 600ms var(--story-ease) 400ms both}
html.story-enter .story-count{animation:story-fade-q 300ms var(--story-ease) 400ms both}
html.story-enter .story-act{animation:story-rise 500ms var(--story-ease) 650ms both}
html.story-enter .story-rail-line line{animation:story-draw 600ms var(--story-ease) 250ms both}
/* backwards, not both: once lit, the dot is the dot again, so hover and focus can grow it. */
html.story-enter .story-dot-mark{animation:story-light 200ms var(--story-ease) backwards}
html.story-enter .story-stop:nth-child(1) .story-dot-mark{animation-delay:700ms}
html.story-enter .story-stop:nth-child(2) .story-dot-mark{animation-delay:850ms}
html.story-enter .story-stop:nth-child(3) .story-dot-mark{animation-delay:1000ms}
html.story-enter .story-stop.is-current .story-dot-mark{animation-name:story-pulse}
html.story-enter .story-join{animation:story-fade 400ms var(--story-ease) 600ms both}

/* ---------- the countdown's seconds cross-fade, two names so no reflow is needed ---------- */
@keyframes story-tick-a{from{opacity:.35}to{opacity:1}}
@keyframes story-tick-b{from{opacity:.35}to{opacity:1}}
.story-num[data-f="a"]{animation:story-tick-a 200ms var(--story-ease)}
.story-num[data-f="b"]{animation:story-tick-b 200ms var(--story-ease)}

/* Without motion the page stands still and whole. The countdown still ticks. */
@media (prefers-reduced-motion:reduce){
  html.story-enter .story-bg-fix img,html.story-enter .story-eyebrow,html.story-enter .story-title .sw,html.story-enter .story-title-zh,html.story-enter .story-sub,
  html.story-enter .story-count,html.story-enter .story-act,html.story-enter .story-rail-line line,html.story-enter .story-dot-mark,html.story-enter .story-stop.is-current .story-dot-mark,html.story-enter .story-join{animation:none}
  .story-num[data-f]{animation:none}
  .story-dot-mark,.story-dot-name{transition:none}
}
