/* ============================================================
   SystemFlow — the rail, played as a film (/platform)
   Stage grammar: teal stage (--teal) = the system;
   ink console = the viewer's controls; white cards = external
   systems; cream cards = Pulse & Flow (ours). Yellow = the kit,
   the action, the live signal. Teal-mid = clinical state.
   Engine: /scripts/systemflow.js (deterministic timeline).
   ============================================================ */
.hnsf-scroll{overflow-x:auto;margin-top:38px}
/* Wide design canvas (1180×470 stage + 74px console) — fills the
   content column natively; below 980px the panel horizontal-scrolls.
   Type stays at instrument size; the width buys air, not magnification. */
.hnsf{position:relative;width:100%;max-width:1180px;min-width:980px;aspect-ratio:1180/590;margin:0 auto;background:var(--ink);border:1px solid rgb(var(--paper-rgb) / .22);border-radius:16px;overflow:hidden;font-family:var(--sans);user-select:none;-webkit-user-select:none}
.hnsf *{box-sizing:border-box}
.hnsf .stage{position:absolute;inset:46px 0 74px 0;background-color:var(--teal);background-image:radial-gradient(rgb(var(--paper-rgb) / .11) .9px,transparent 1.15px);background-size:26px 26px;background-position:13px 13px}
.hnsf svg.tr{position:absolute;inset:0;width:100%;height:100%}
.hnsf .srail{fill:none;stroke:var(--paper);stroke-width:1;stroke-linecap:round;stroke-dasharray:.1 5.2;stroke-opacity:.22;transition:stroke-opacity .4s var(--ease-move)}
.hnsf .srail.act{stroke-opacity:.65}.hnsf .srail.past{stroke-opacity:.33}
.hnsf .beam,.hnsf .btail{fill:none;stroke:var(--paper);stroke-linecap:round;stroke-opacity:0}
.hnsf .dcore,.hnsf .dhalo{fill:var(--paper);visibility:hidden}
.hnsf .pkg{visibility:hidden}
.hnsf .pkg .bx{fill:var(--yellow)}
.hnsf .pkg .sp{fill:var(--teal-mid)}
.hnsf .elab{position:absolute;font:600 8px/1 var(--sans);letter-spacing:.16em;text-transform:uppercase;color:rgb(var(--paper-rgb) / .9);opacity:.16;transition:opacity .4s var(--ease-move);z-index:3;white-space:nowrap}
.hnsf .elab.past{opacity:.45}.hnsf .elab.act{opacity:1}
/* Cards stay fully opaque (rails must never show through a dimmed card);
   past/future states are a stage-coloured veil over the content instead. */
.hnsf .scard{position:absolute;background:var(--white);border:1px solid rgb(var(--ink-rgb) / .14);border-radius:12px;padding:9px 11px;z-index:3;overflow:hidden}
.hnsf .scard::after{content:"";position:absolute;inset:0;background:var(--teal);opacity:.85;transition:opacity .4s var(--ease-move);pointer-events:none;z-index:4}
.hnsf .scard.past::after{opacity:.5}.hnsf .scard.act::after{opacity:0}
.hnsf .scard.hn{background:var(--cream);border-color:rgb(var(--ink-rgb) / .18)}
.hnsf .scard.hn .srow{border-top-color:rgb(var(--ink-rgb) / .1)}
.hnsf .scard.hn .shd{color:rgb(var(--ink-rgb) / .5)}
.hnsf .scard.hn .shd i{background:rgb(var(--ink-rgb) / .15)}
.hnsf .scard.hn.act .shd i{background:var(--ink);outline:2.5px solid rgb(var(--ink-rgb) / .15)}
.hnsf .scard.hn .schip{background:var(--paper)}
.hnsf .shd{display:flex;align-items:center;gap:6px;font:600 7.5px/1 var(--sans);letter-spacing:.12em;color:rgb(var(--ink-rgb) / .42);text-transform:uppercase;margin-bottom:6px}
.hnsf .shd i{width:4px;height:4px;border-radius:50%;background:var(--border);transition:background var(--t-base),outline var(--t-base);flex:0 0 4px}
.hnsf .scard.act .shd i{background:var(--yellow);outline:2.5px solid rgba(250,255,36,.35)}
.hnsf .srow{display:flex;align-items:center;justify-content:space-between;gap:8px;font:400 9.5px/1.3 var(--sans);color:var(--muted);padding:4px 0;border-top:1px solid rgb(var(--border-rgb) / .55);font-variant-numeric:tabular-nums}
.hnsf .srow b{font-weight:600;color:var(--ink)}
.hnsf .st{opacity:0;transform:translateY(2px);transition:opacity var(--t-base) var(--ease-move),transform var(--t-base) var(--ease-move)}
.hnsf .st.on{opacity:1;transform:none}
.hnsf .schip{font:500 8px/1 var(--sans);letter-spacing:.02em;padding:2.5px 7px;border-radius:99px;background:var(--cream);color:rgb(var(--ink-rgb) / .55);border:1px solid var(--border);white-space:nowrap}
.hnsf .schip.ok{color:var(--ink);background:transparent}
.hnsf .schip.ready{background:transparent;color:var(--teal-mid);border-color:rgb(var(--teal-mid-rgb) / .35)}
.hnsf .sfbtn{position:relative;display:inline-block;font:600 10px/1 var(--sans);letter-spacing:.01em;background:var(--yellow);color:var(--ink);border-radius:8px;padding:6px 11px;cursor:pointer;transition:transform .16s var(--ease-move)}
.hnsf .sfbtn.press{transform:scale(.93)}
.hnsf .sfbtn.invite::after{content:"";position:absolute;inset:-4px;border-radius:11px;border:1px solid rgb(var(--ink-rgb) / .35)}
/* The invite ring is set whenever the film is parked at either end — which under
   reduced-motion is true from the first frame, so it ran forever for exactly the
   people who asked for no motion. Animate it only when motion is welcome. */
@media (prefers-reduced-motion: no-preference){
.hnsf .sfbtn.invite::after{animation:hnsfring 2.6s var(--ease-move) infinite}
}
@keyframes hnsfring{0%{transform:scale(.97);opacity:.6}100%{transform:scale(1.13);opacity:0}}
.hnsf .sbar{height:2px;background:rgb(var(--ink-rgb) / .1);border-radius:1px;margin:6px 0 3px;overflow:hidden}
.hnsf .sbar i{display:block;height:100%;width:0;background:var(--teal-mid);border-radius:1px}
.hnsf .smono{font:400 8.5px/1.65 var(--mono);color:var(--muted);white-space:nowrap}
.hnsf .smono b{color:var(--ink);font-weight:600}
.hnsf .wpill{position:absolute;transform:translate(-50%,-50%);font:500 7.5px/1 var(--sans);letter-spacing:.02em;color:rgb(var(--paper-rgb) / .85);background:rgb(var(--ink-rgb) / .22);border:1px solid rgb(var(--paper-rgb) / .28);border-radius:99px;padding:3px 8px;white-space:nowrap;z-index:2;opacity:.14;transition:opacity .4s,color var(--t-base),border-color var(--t-base)}
.hnsf .wpill.past{opacity:.55}.hnsf .wpill.act{opacity:1}
.hnsf .wpill.hot{color:var(--paper);border-color:rgb(var(--paper-rgb) / .65)}
.hnsf .phone{border-radius:20px}
.hnsf .ssteps .srow:first-child{border-top:0}
.hnsf .ssteps .srow{justify-content:flex-start}
.hnsf .tick{width:11px;height:11px;border-radius:50%;border:1px solid rgb(var(--ink-rgb) / .18);display:inline-flex;align-items:center;justify-content:center;font-size:7px;color:transparent;flex:0 0 11px;transition:all var(--t-base) var(--ease-move);background:rgba(255,255,255,.5)}
.hnsf .st.on .tick{background:var(--teal-mid);border-color:var(--teal-mid);color:var(--paper)}
/* The narration bar — a taller teal strip across the TOP of the panel
   (same --teal as the stage, so it reads as one area that simply
   rises above the diagram); the line sits UP here, clear of the cards.
   Bar stays put; only the text fades per chapter. */
.hnsf .subtbar{position:absolute;top:0;left:0;right:0;height:46px;display:flex;align-items:center;justify-content:center;padding:0 24px;background:var(--teal);z-index:2}
.hnsf .subt{text-align:center;font:italic 400 14px/1.35 var(--serif);color:rgb(var(--paper-rgb) / .95);letter-spacing:.01em;pointer-events:none;opacity:0;transition:opacity .45s var(--ease-move)}
.hnsf .subt.show{opacity:1}
.hnsf .sflegend{position:absolute;left:0;right:0;bottom:48px;height:26px;display:flex;gap:20px;align-items:center;padding:0 18px;border-top:1px solid rgb(var(--paper-rgb) / .12);font:500 8px/1 var(--sans);letter-spacing:.04em;color:rgb(var(--paper-rgb) / .6);z-index:5;background:var(--ink)}
.hnsf .sflegend .sli{display:inline-flex;align-items:center;gap:6px}
.hnsf .sflegend svg{display:block}
.hnsf .lgd-rail{stroke:var(--paper);stroke-opacity:.55}
.hnsf .lgd-box{fill:var(--yellow)}
.hnsf .lgd-tail{stroke:var(--paper);stroke-opacity:.3}
.hnsf .lgd-head{stroke:var(--paper);stroke-opacity:.95}
.hnsf .lgd-dot{fill:var(--paper)}
@media (prefers-reduced-motion: no-preference){
.hnsf .sflegend .lp{animation:hnsflp 1.6s ease-in-out infinite;transform-box:fill-box;transform-origin:center}
@keyframes hnsflp{0%,100%{transform:scale(.8);opacity:.8}50%{transform:scale(1.25);opacity:1}}
}
.hnsf .player{position:absolute;left:0;right:0;bottom:0;height:48px;border-top:1px solid rgb(var(--paper-rgb) / .08);display:flex;align-items:center;gap:14px;padding:0 18px;z-index:5;background:var(--ink)}
.hnsf .pp{width:26px;height:26px;border-radius:50%;border:1px solid rgb(var(--paper-rgb) / .3);background:rgb(var(--paper-rgb) / .06);display:flex;align-items:center;justify-content:center;cursor:pointer;flex:0 0 26px;transition:border-color .25s var(--ease-move)}
.hnsf .pp:hover{border-color:rgb(var(--paper-rgb) / .65)}
.hnsf .pp svg path,.hnsf .pp svg rect{fill:rgb(var(--paper-rgb) / .8);transition:fill var(--t-quick)}
.hnsf .pp:hover svg path,.hnsf .pp:hover svg rect{fill:var(--paper)}
.hnsf .pp svg{display:block}
.hnsf .rl{position:relative;flex:1;height:48px;cursor:pointer}
.hnsf .track{position:absolute;left:0;right:0;top:31px;height:1.5px;background:rgb(var(--paper-rgb) / .18);border-radius:1px}
.hnsf .fillb{position:absolute;left:0;top:31px;height:1.5px;background:rgb(var(--paper-rgb) / .8);border-radius:1px;width:0}
.hnsf .phd{position:absolute;top:31.75px;width:6px;height:6px;border-radius:50%;background:var(--paper);transform:translate(-50%,-50%);transition:transform .18s var(--ease-move)}
.hnsf .rl:hover .phd{transform:translate(-50%,-50%) scale(1.35)}
.hnsf .ck{position:absolute;top:28px;width:1px;height:7px;background:rgb(var(--paper-rgb) / .25)}
.hnsf .cl{position:absolute;top:10px;margin-left:4px;font:500 7.5px/1 var(--sans);letter-spacing:.04em;color:rgb(var(--paper-rgb) / .55);white-space:nowrap;transition:color .25s;cursor:pointer}
.hnsf .cl.now{color:var(--paper)}
.hnsf .tg{display:flex;align-items:center;gap:7px;cursor:pointer;flex:0 0 auto}
.hnsf .tg span{font:500 8.5px/1 var(--sans);letter-spacing:.05em;color:rgb(var(--paper-rgb) / .55);transition:color .25s}
.hnsf .tg.on span{color:var(--paper)}
.hnsf .sw{position:relative;width:24px;height:13px;border-radius:99px;background:rgb(var(--paper-rgb) / .18);transition:background .25s var(--ease-move);flex:0 0 24px}
.hnsf .sw i{position:absolute;top:2px;left:2px;width:9px;height:9px;border-radius:50%;background:var(--paper);transition:left .25s var(--ease-move)}
.hnsf .tg.on .sw{background:rgb(var(--paper-rgb) / .85)}
.hnsf .tg.on .sw i{left:13px;background:var(--ink)}

/* Scrubbing must not also pan the horizontal scroller underneath it. */
.hnsf .rl{touch-action:none}

/* ── Mobile: one vertical rail ──────────────────────────────────────────────────
   The desktop canvas is 1180x470 with min-width:980px — 2.5x a phone, which left
   Pulse (the hub) entirely off-screen and the narration 87% clipped. Below 700px it
   is replaced by this: the actors as stations on a single vertical rail, driven by
   the same clock and the same data. */
.hnsfm{display:none}
@media(max-width:700px){
  .js .hnsf-scroll{display:none}
  .hnsfm{display:block;margin-top:30px;color:var(--paper);background:var(--ink);border-radius:18px;padding:20px 18px 14px}

  .hnsfm-top{display:flex;align-items:baseline;justify-content:space-between;gap:12px}
  .hnsfm-chap{font-family:var(--mono);font-size:11px;letter-spacing:.16em;text-transform:uppercase;color:var(--yellow)}
  .hnsfm-step{font-family:var(--mono);font-size:11px;color:var(--slate)}
  .hnsfm-prog{height:2px;margin-top:10px;background:rgb(var(--paper-rgb) / .14);border-radius:1px;overflow:hidden}
  .hnsfm-prog i{display:block;height:100%;width:0;background:var(--yellow)}

  /* the narrative line — full width and actually readable, unlike the clipped subtitle */
  .hnsfm-sub{margin:16px 0 0;min-height:3.4em;font-family:var(--serif);font-weight:300;font-size:17px;line-height:1.42;color:var(--paper);opacity:0;transition:opacity var(--t-slow) var(--ease)}
  .hnsfm-sub.show{opacity:1}

  .hnsfm-stack{position:relative;margin-top:18px;padding-left:26px}
  .hnsfm-rail{position:absolute;left:5px;top:14px;bottom:14px;width:1px;background:rgb(var(--paper-rgb) / .18)}
  /* the parcel travelling between two stations */
  /* Colour grammar follows the desktop legend exactly: the physical parcel (kit /
     sample) is yellow like .lgd-box; data and signal are paper like .beam/.dcore. */
  .hnsfm-move{display:flex;align-items:center;gap:9px;margin:12px 0 0;min-height:20px;opacity:0;transition:opacity .25s var(--ease)}
  .hnsfm-move.show{opacity:1}
  .hnsfm-mk{font-family:var(--mono);font-size:9px;letter-spacing:.1em;text-transform:uppercase;color:var(--ink);background:var(--paper);border-radius:100px;padding:3px 8px;flex:0 0 auto}
  .hnsfm-mk.parcel{background:var(--yellow)}
  .hnsfm-mr{font-family:var(--mono);font-size:10px;letter-spacing:.03em;color:var(--slate);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
  /* the dot itself carries no text, so it can pass a station without covering it */
  .hnsfm-beam{position:absolute;left:1px;top:0;z-index:2;width:9px;height:9px;margin-top:-4.5px;
    border-radius:50%;background:var(--paper);opacity:0;transform:translateY(0);
    box-shadow:0 0 0 4px rgb(var(--paper-rgb) / .16);transition:opacity var(--t-quick) linear}
  .hnsfm-beam.parcel{background:var(--yellow);box-shadow:0 0 0 4px rgba(250,255,36,.18)}

  .hnsfm-node{position:relative;padding:11px 0;display:flex;align-items:baseline;gap:10px;
    border-top:1px solid rgb(var(--paper-rgb) / .1);opacity:.4;transition:opacity .35s var(--ease)}
  .hnsfm-node:first-of-type{border-top:0}
  .hnsfm-node.act{opacity:1}
  .hnsfm-node.past{opacity:.62}
  .hnsfm-pip{position:absolute;left:-24px;top:50%;width:9px;height:9px;margin-top:-4.5px;border-radius:50%;
    background:var(--ink);border:1px solid rgb(var(--paper-rgb) / .35);transition:background var(--t-base),border-color var(--t-base)}
  .hnsfm-node.act .hnsfm-pip{background:var(--yellow);border-color:var(--yellow)}
  .hnsfm-node.past .hnsfm-pip{background:rgb(var(--paper-rgb) / .5);border-color:transparent}
  .hnsfm-n{font-size:14.5px;font-weight:500;color:var(--paper);flex:0 0 auto}
  /* Desktop marks Pulse and Flow as ours with cream cards. Cream is indistinguishable
     from paper on an ink ground, and yellow already means "the kit / the live signal",
     so ours is marked with a raised surface instead of a colour — no third meaning. */
  .hnsfm-node.ours .hnsfm-n{background:rgb(var(--paper-rgb) / .1);border-radius:7px;padding:3px 9px;margin-left:-9px}
  .hnsfm-v{flex:1 1 auto;text-align:right;font-family:var(--mono);font-size:10px;letter-spacing:.04em;color:var(--slate);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
  .hnsfm-node.act .hnsfm-v{color:var(--paper)}

  .hnsfm-player{display:flex;align-items:center;gap:14px;margin-top:16px;padding-top:12px;border-top:1px solid rgb(var(--paper-rgb) / .1)}
  /* 44px hit area — the desktop control is 26px, below the touch minimum */
  .hnsfm-pp{flex:0 0 auto;width:44px;height:44px;border-radius:50%;border:1px solid rgb(var(--paper-rgb) / .3);
    background:rgb(var(--paper-rgb) / .06);color:var(--paper);display:flex;align-items:center;justify-content:center;cursor:pointer;-webkit-tap-highlight-color:transparent}
  .hnsfm-pp svg{width:20px;height:20px}
  .hnsfm-pp path{fill:var(--paper)}
  .hnsfm-pp:focus-visible{outline:2px solid var(--yellow);outline-offset:2px}
  /* generous vertical padding so the 2px track has a 44px grab area */
  .hnsfm-rl{flex:1 1 auto;padding:21px 0;cursor:pointer;touch-action:none}
  .hnsfm-track{height:2px;background:rgb(var(--paper-rgb) / .16);border-radius:1px;overflow:hidden}
  .hnsfm-track i{display:block;height:100%;width:0;background:var(--paper)}
}
