/* ============================================================
   CONCEPT C — "THE LAYER"
   layer.css — the dimension layer, the deeper affordance, the
   spine scroll-lock, and the concept badge.

   Design language is inherited wholesale from styles.css: no new
   colours, no new fonts. Every value below resolves to an existing
   token (--ink, --sky, --cream, --blue, --gold, --dark, --serif,
   --sans, --m, --safe-b) or to a rgba() of one of them.
   ============================================================ */

/* ============================================================
   SPINE SCROLL-LOCK
   The whole page is f(scrollY). While an overlay is open the spine
   must not scrub, and the exact scroll position must survive the
   round trip.

   NOTE: styles.css / dossier.js already reference a `.dossier-locked`
   class and set `body.style.top = -savedScroll`, but NO CSS rule for
   it was ever written — so on a statically-positioned body the `top`
   write is inert and the lock never actually locked. `.spine-locked`
   below is that missing rule. `position:fixed` + an explicit negative
   `top` is the iOS-Safari-safe technique: `overflow:hidden` on body is
   bypassed by Safari's rubber-band scrolling, `position:fixed` is not.
   JS still saves/restores scrollY explicitly (see layer.js) because
   fixing the body collapses scrollable height and zeroes scrollY.
   ============================================================ */
body.spine-locked{
  position:fixed;
  left:0; right:0; width:100%;
  /* `top` is written inline by JS as -savedScroll px */
}

/* ============================================================
   THE "DEEPER" AFFORDANCE — the cut-off look
   Not an arrow. A panel edge, clipped by the bottom of the
   viewport, showing the top ~56px of a page that is physically
   below this one. The clipping IS the signage: a sliced object
   reads as continuing out of frame. (Source/OpenNews: "if it needs
   a sign, it's bad design.")
   ============================================================ */
/* §R3 — a clean, fully-visible card (was a clipped "peek" that read as broken).
   Now an in-flow child of .act1-aside, stacked under the Amal card. */
.deeper{
  position:static; z-index:9;
  width:min(280px, 26vw);
  display:block; text-align:left;
  padding:13px 16px;
  border:1px solid rgba(153,217,223,.24);
  border-radius:14px;
  background:rgba(153,217,223,.05);
  font-family:var(--sans); color:var(--paper);
  cursor:pointer;
  opacity:0; pointer-events:none;
  transition:transform .22s cubic-bezier(.2,.7,.2,1), background .22s ease, border-color .22s ease;
}
.deeper:hover, .deeper:focus-visible{
  transform:translateY(-2px);
  background:rgba(153,217,223,.09);
  border-color:var(--blue);
  outline:none;
}
.deeper-label{
  display:block; font-size:11px; font-weight:700;
  letter-spacing:.14em; text-transform:uppercase;
  color:var(--gold); margin-bottom:7px;
}
.deeper-title{
  display:block; font-family:var(--display); font-weight:600;
  font-size:17px; line-height:1.25; color:#fff;
  white-space:nowrap; overflow:hidden; text-overflow:ellipsis;
}
/* the sliced third line — visible only as a few pixels of its
   ascenders, which is what sells "there is more below the fold" */
.deeper-more{
  display:block; margin-top:8px; font-size:13px;
  color:var(--sky-75); white-space:nowrap;
}
/* light acts (Act 2 sky, Act 4 cream) */
.scene-light .deeper, .scene-cream .deeper{
  background:rgba(243,242,179,.88);
  border-color:rgba(34,64,77,.20);
  color:var(--ink);
}
.scene-light .deeper:hover, .scene-cream .deeper:hover,
.scene-light .deeper:focus-visible, .scene-cream .deeper:focus-visible{
  background:rgba(243,242,179,.98);
  border-color:var(--inkdim);
}
.scene-light .deeper-label, .scene-cream .deeper-label{ color:var(--inkdim); }
.scene-light .deeper-title, .scene-cream .deeper-title{ color:var(--ink); }
.scene-light .deeper-more, .scene-cream .deeper-more{ color:var(--ink-70); }

/* Acts 1–4 keep bottom:0 — the affordance is genuinely clipped by the
   viewport edge, which is the whole metaphor. Verified clear of the
   copy in each: Act 1's stat-row and Act 3's/Act 4's footnotes are
   left-anchored and their ink stops well short of the right margin
   (their BOXES are full-width, but a box is not ink).

   Act 5 is the exception. Its footnote (.mult-fn) is centre-anchored
   and up to 1000px wide, so at 1280px it runs under the affordance's
   x-range — there is no width for the strip that clears it at every
   viewport. So Act 5's affordance lifts above the footnote/flywheel
   band and becomes a closed card. It loses the cut-off read; it keeps
   the collision-free layout, which matters more. */
#act5 .deeper{
  bottom:150px;
  border-radius:12px;
  border-bottom:1px solid rgba(255,255,255,.22);
  height:auto; padding-bottom:12px;
}
#act5 .deeper:hover, #act5 .deeper:focus-visible{ transform:translateY(-4px); }

/* ============================================================
   RAIL — "this chapter has a layer"
   A second chip, offset and clipped behind the number chip: the
   same cut-off grammar as the affordance, in the rail's own idiom.
   Purely an indicator. Clicking the rail still does exactly what it
   did before (jump to chapter) — no double-purpose control, nothing
   new to learn.
   ============================================================ */
.rail-item.has-layer .rail-num{ position:relative; z-index:1; }
.rail-item.has-layer::before{
  content:""; position:absolute;
  left:3px; top:3px; width:30px; height:30px; border-radius:50%;
  border:1px solid rgba(255,255,255,.20);
  z-index:0; pointer-events:none;
  transition:border-color .4s ease;
}
.rail.on-light .rail-item.has-layer::before{ border-color:rgba(34,64,77,.22); }
.rail-item.has-layer.active::before{ border-color:rgba(227,226,79,.55); }

/* ============================================================
   THE LAYER ITSELF
   Covers the viewport above the frozen field. The field is NOT torn
   down — it keeps rendering underneath at a dimmed fieldDim, which
   is what makes this read as a layer over the story rather than a
   new page.
   ============================================================ */
.layer{ position:fixed; inset:0; z-index:80; display:none; }
.layer.show{ display:block; }
.layer-scrim{
  position:absolute; inset:0;
  /* §4.6 — the field DIMS + DESATURATES behind a layer, it never blurs (the
     blur "hole" was the F1 complaint). Deeper dim + a saturate() knock-down
     replace the old backdrop blur. */
  background:rgba(12,22,27,.66);
  backdrop-filter:saturate(.35);
  animation:fade .35s ease;
}
.layer-sheet{
  position:absolute; left:50%; bottom:0; transform:translateX(-50%);
  width:min(860px, 94vw); max-height:94vh; overflow-y:auto;
  -webkit-overflow-scrolling:touch;             /* iOS momentum inside the layer */
  overscroll-behavior:contain;                  /* don't chain to the (locked) spine */
  background:var(--cream); color:var(--ink);
  border-radius:20px 20px 0 0;
  padding:clamp(28px,4vw,52px);
  box-shadow:0 -20px 60px rgba(12,22,27,.4);
  animation:slideUp .5s cubic-bezier(.2,.7,.2,1);
}
.layer-close{
  position:sticky; top:0; float:right; margin:-8px -8px 0 0;
  width:38px; height:38px; border-radius:50%;
  border:1px solid rgba(34,64,77,.2); background:rgba(255,255,255,.7);
  color:var(--ink); font-size:20px; line-height:1; cursor:pointer;
  z-index:2;
}
.layer-close:hover{ background:var(--ink); color:#fff; }

.layer-eyebrow{
  font-size:12.5px; font-weight:700; letter-spacing:.14em; text-transform:uppercase;
  color:var(--inkdim); line-height:1.7; margin-bottom:18px;
}
.layer-title{
  font-family:var(--display); font-weight:600; letter-spacing:-.012em;
  font-size:clamp(28px,3.2vw,44px); line-height:1.12; max-width:22ch;
}
.layer-stat{
  display:flex; align-items:baseline; gap:18px;
  margin:34px 0 8px; padding-top:26px;
  border-top:1px solid rgba(34,64,77,.12);
}
.layer-stat-figure{
  font-family:var(--display); font-weight:600;
  font-size:clamp(48px,6vw,86px); line-height:.9; letter-spacing:-.03em;
  color:var(--ink); flex:none;
}
.layer-stat-label{
  font-family:var(--display); font-size:clamp(16px,1.5vw,21px);
  line-height:1.3; max-width:26ch; color:var(--ink);
}
.layer-body{
  font-family:var(--display); font-size:clamp(16px,1.5vw,18px);
  line-height:1.62; color:var(--ink); max-width:62ch; margin-top:26px;
}
.layer-body p{ margin-bottom:14px; }
.layer-breakdown{ margin:26px 0 0; display:flex; flex-direction:column; gap:10px; max-width:62ch; }
.layer-breakdown li{ display:flex; align-items:baseline; gap:14px; font-size:15px; }
.layer-breakdown .lb-name{ font-family:var(--display); font-size:17px; flex:none; width:16ch; }
.layer-breakdown .lb-bar{ flex:1; height:6px; border-radius:3px; background:rgba(34,64,77,.09); overflow:hidden; }
.layer-breakdown .lb-fill{ display:block; height:100%; border-radius:3px; background:var(--blue); }
.layer-breakdown .lb-val{ font-family:var(--display); font-weight:600; flex:none; width:4ch; text-align:right; }

/* the sibling hop: spine → person, opened from inside a layer.
   Replaces the layer (history.replaceState) — it never stacks. */
.layer-person{
  margin-top:30px; padding-top:22px;
  border-top:1px solid rgba(34,64,77,.12);
}
.layer-person-btn{
  font-family:var(--sans); font-size:13px; font-weight:700;
  color:var(--ink); background:transparent;
  border:1px solid rgba(34,64,77,.28); border-radius:999px;
  padding:9px 16px; cursor:pointer;
  transition:background .22s ease, color .22s ease, border-color .22s ease;
}
.layer-person-btn:hover{ background:var(--ink); color:var(--cream); border-color:var(--ink); }

.layer-foot{
  margin-top:26px; padding-top:18px;
  border-top:1px solid rgba(34,64,77,.12);
  font-size:13px; line-height:1.5; color:rgba(34,64,77,.7);
}
/* .layer-placeholder is gone with its markup — five italic "Placeholder:
   … pending the respondent-level dataset" lines, one per layer sheet. The
   caveat is true and now lives in a source comment in index.html, which is
   who it was written for. */

/* the copy store in index.html is never rendered in place */
.layer-store{ display:none; }

/* ============================================================
   CONCEPT BADGE
   ============================================================ */
/* Top-right: the bottom-right corner belongs to the "deeper" affordance,
   and bottom-left is the footnote slot (§G5). Top-right is the only
   corner with nothing in it — .scene-logos is a space-between flex with
   a single child, so it sits left. */
.concept-badge{
  position:fixed; right:14px; top:12px; z-index:10000;
  font-family:var(--sans); font-size:10px; font-weight:700;
  letter-spacing:.1em; text-transform:uppercase;
  color:rgba(227,226,79,.82);
  background:rgba(34,64,77,.72);
  border:1px solid rgba(227,226,79,.4);
  border-radius:999px; padding:4px 11px;
  pointer-events:none; user-select:none;}

/* ============================================================
   STATIC / FALLBACK (reduced-motion or < 1280px)
   A reader who never opens a layer must get exactly today's
   experience — and in static mode the layer mechanic is off
   entirely (there is no spine to freeze). The affordances are
   hidden rather than left inert.
   ============================================================ */
body.static .deeper{ display:none; }
body.static .rail-item.has-layer::before{ display:none; }

@media (prefers-reduced-motion: reduce){
  .deeper{ transition:none; }
  .layer-scrim, .layer-sheet{ animation:none; }
}

/* ============================================================
   CONCEPT C — THE FIELD IS THE NAVIGATION
   styles.css sets .field{pointer-events:none} because the canvas was
   pure decoration under the copy. It is now the primary control: every
   one of the 2,480 dots opens. Overridden here rather than there so
   styles.css stays as main wrote it — layer.css loads second, same
   specificity, later wins.

   The stage above it keeps pointer-events:none (styles.css:92), so the
   copy layer does not eat clicks meant for the field. Actual copy
   blocks (.mask elements) are already excluded from the dot layout, so
   there is never a dot underneath a paragraph to be stolen anyway.
   ============================================================ */
.field{ pointer-events:auto; }

/* ============================================================
   CONCEPT C — THE FILTER PILL  (?only=)
   Only chrome the filter adds, and only while a filter is on. It must
   be readable BEFORE a click: the refusal state should never be the
   first time a reader discovers the field was narrowed.
   ============================================================ */
.filter-pill{
  position:fixed; left:14px; top:12px; z-index:10000;
  display:flex; align-items:center; gap:9px;
  font-family:var(--sans); font-size:10px; font-weight:700;
  letter-spacing:.09em; text-transform:uppercase;
  color:rgba(243,242,179,.9);
  background:rgba(34,64,77,.72);
  border:1px solid rgba(243,242,179,.28);
  border-radius:999px; padding:4px 11px;
  pointer-events:none; user-select:none;}
.filter-pill[hidden]{ display:none; }
.filter-pill .fp-n{ color:var(--gold); }
/* below K the pill says the field is closed before you touch it */
.filter-pill.fp-closed{ border-color:rgba(227,226,79,.55); }
.filter-pill.fp-closed .fp-n::after{ content:" · closed"; color:rgba(243,242,179,.62); }
/* §P3.3 — active filter terms as removable chips (reflow with Flip on dismiss). */
.fp-terms{ display:flex; align-items:center; flex-wrap:wrap; gap:6px; }
.fp-term{ display:inline-flex; align-items:center; gap:5px; pointer-events:auto;
  background:rgba(243,242,179,.12); border:1px solid rgba(243,242,179,.30);
  border-radius:999px; padding:2px 3px 2px 9px; white-space:nowrap; }
.fp-term-label{ color:rgba(243,242,179,.92); }
.fp-x{ pointer-events:auto; cursor:pointer; width:16px; height:16px; display:inline-flex;
  align-items:center; justify-content:center; border:none; border-radius:50%;
  background:rgba(243,242,179,.14); color:rgba(243,242,179,.9); font-size:13px; line-height:1;
  transition:background .16s,color .16s; }
.fp-x:hover{ background:var(--gold); color:var(--ink); }

/* ============================================================
   CONCEPT C — THE PERSON SHEET: "A LIFE IN FIVE MOVES"
   Lives inside .dossier-panel (cream, styles.css:225), so it inherits
   the panel's ground, width and close button. Everything below is the
   sheet's own structure.

   No new colours. Ink is "yes", ink at low alpha is "everyone else",
   gold is you — the same three-way reading the field has taught for
   five acts, just on cream instead of navy.
   ============================================================ */

/* ---- the provenance stamp ----
   Fixed furniture: EVERY sheet has one, first in the reading order,
   and it is in the screenshot however the panel is cropped. The
   hatching is a repeating-linear-gradient of --ink, not an icon and
   not a coloured "warning" box — it reads as a printed overprint on a
   document, which is exactly what it is. Its CONTENT varies; its slot
   never does. That is what keeps it a designed element rather than a
   banner bolted to the top. */
.person-stamp{
  margin:-6px 0 22px; padding:9px 14px;
  font-family:var(--sans); font-size:10px; font-weight:700;
  letter-spacing:.12em; text-transform:uppercase; line-height:1.5;
  border-radius:3px;
}
.person-stamp--modelled{
  color:rgba(34,64,77,.72);
  border:1px solid rgba(34,64,77,.22);
  background:
    repeating-linear-gradient(-45deg,
      rgba(34,64,77,.055) 0 5px, rgba(34,64,77,0) 5px 11px);
}
.person-stamp--verbatim{
  color:var(--inkdim);
  border:1px solid rgba(227,226,79,.75);
  background:
    repeating-linear-gradient(-45deg,
      rgba(227,226,79,.20) 0 5px, rgba(227,226,79,.05) 5px 11px);
}
.person-stamp--refuse{
  color:rgba(34,64,77,.75);
  border:1px solid rgba(34,64,77,.3);
  background:rgba(34,64,77,.06);
}

/* ---- head ---- */
.person-head{ margin-bottom:6px; }
.person-ref{
  font-family:var(--display); font-weight:600;
  font-size:clamp(28px,3vw,40px); line-height:1.08; color:var(--ink);
}
.person-meta{
  margin-top:7px; font-family:var(--sans); font-size:12.5px;
  color:var(--ink-55); letter-spacing:.02em;
}
.person-meta .meta-sep{ opacity:.5; }
/* An invented field says so where it is, not in a footnote nobody
   reaches. Dotted underline = "this value is modelled". */
.person-meta .invented{
  border-bottom:1px dotted rgba(34,64,77,.45);
  cursor:help;
}
.person-lede{
  margin:18px 0 30px; font-family:var(--display);
  font-size:16px; line-height:1.6; color:var(--ink-70);
  max-width:56ch;
}

/* ---- the five moves ----
   The gold thread down the gutter IS the trajectory: one node per
   dimension, filled where the dimension landed for this person,
   hollow where it did not. You can read a life off the gutter alone
   in about a second, then go and read why. */
.moves{ list-style:none; margin:0; padding:0; }
.move{
  position:relative; padding:0 0 34px 34px;
}
/* the thread */
.move::before{
  content:""; position:absolute; left:6px; top:6px; bottom:0;
  width:1px; background:rgba(34,64,77,.18);
}
.move:last-child::before{ display:none; }
.move-node{
  position:absolute; left:0; top:1px;
  width:13px; height:13px; border-radius:50%;
  border:1.5px solid var(--ink); background:var(--cream);
  box-sizing:border-box;
}
/* CONCEPT C — the node is THREE states, not two.
   Four of these five dimensions are ordinal in the spine, not binary:
   founder > employed > NEET; mentors > engaged > gone; 6+ > 3–6 > 0–3
   months. A yes/no gutter flattens exactly the distinction that makes
   the normal case legible — 2,144 of 2,480 are not founders, and
   "employed, not a founder" is a real answer, not a miss. So: solid
   gold = the full state, gold ring on cream = the middle state,
   hollow ink = none. Amal reads 2·2·1·2·2 and her thread visibly dips
   at Work. It should. */
.move[data-level="1"] .move-node{
  background:var(--cream);
  box-shadow:inset 0 0 0 2.5px var(--gold);
  border-color:rgba(34,64,77,.55);
}
.move[data-level="2"] .move-node{ background:var(--gold); border-color:var(--ink); }

/* Per-move provenance. Amal only — every other sheet is modelled end
   to end and says so once, at the top. */
.move-src{
  font-family:var(--sans); font-size:9.5px; font-weight:700;
  letter-spacing:.13em; text-transform:uppercase;
  margin:6px 0 0; display:inline-block;
}
/* solid gold rule = sourced; the hatch below = modelled. The two tags
   must be told apart at a glance, from across a meeting room, without
   reading either. */
.move-src--said{
  color:rgba(34,64,77,.62);
  padding:2px 7px 2px 8px; border-left:2px solid var(--gold);
}
.move-src--model{
  color:rgba(34,64,77,.42);
  padding:2px 7px; border-radius:2px;
  background-image:repeating-linear-gradient(
    -45deg, rgba(34,64,77,.07) 0 3px, transparent 3px 6px);
  box-shadow:inset 0 0 0 1px rgba(34,64,77,.16);
}

.move-head{ display:flex; align-items:baseline; gap:10px; }
.move-num{
  font-family:var(--sans); font-size:10px; font-weight:700;
  letter-spacing:.16em; color:rgba(34,64,77,.4);
}
.move-name{
  font-family:var(--sans); font-size:11px; font-weight:700;
  letter-spacing:.16em; text-transform:uppercase; color:var(--ink);
}
.move-claim{
  margin-top:8px; font-family:var(--display);
  font-size:clamp(17px,1.7vw,21px); line-height:1.4; color:var(--ink);
  max-width:44ch;
}
.move-scale{
  margin-top:9px; font-family:var(--sans); font-size:11.5px;
  color:var(--ink-55); line-height:1.5;
}

/* ---- ROUND 21 (client item 3) — the moves still ahead of the reader ----
   Open Amal in chapter 2 and moves 3–5 are not gone, they are WAITING. The
   client's call was greyed, not hidden: he wants the reader to see that there
   is more life here and that reading on is what opens it.

   So a locked move keeps the thread, the node and its number + name, and
   loses its claim, its panels and its scale line. It reads as a row that has
   not happened yet rather than as a row that failed to load — which is why
   the node goes hollow and dashed (a state this list already speaks: hollow
   ink = none) instead of simply fading the whole row out.

   Everything here stays above the ink-55 floor the rest of the sheet uses;
   "greyed" must not mean "under the contrast minimum". */
.move.is-locked .move-node{
  background:transparent;
  border-style:dashed;
  border-color:rgba(34,64,77,.38);
  box-shadow:none;
}
.move.is-locked .move-num,
.move.is-locked .move-name{ color:rgba(34,64,77,.42); }
.move-locked{
  margin-top:8px; font-family:var(--sans); font-size:12px;
  color:var(--ink-55); line-height:1.5; font-style:italic;
}
/* the one line that explains the mechanic, under the lede */
.person-gate{
  margin:10px 0 0; font-family:var(--sans); font-size:12.5px;
  line-height:1.55; color:var(--ink-55);
  padding-left:11px; border-left:2px solid var(--gold);
}

/* ---- the miniature fields ----
   The same formation the reader has already scrolled through, at 1:10,
   with their dot in gold. Nothing here is a new visual idea; that is
   the point. */
.move-panels{ margin-top:14px; }
.panel{ position:relative; }
.panel-field{ display:block; width:100%; }
/* skills: five strips, one per capability — NOT the Act 2 bar
   geometry, which partitions people by proportion and says nothing
   about any individual's skills (see formations.js F.BARS). */
.move-panels[data-kind="skill"]{
  display:grid; grid-template-columns:auto 1fr auto;
  gap:2px 12px; align-items:center;
  border-top:1px solid rgba(34,64,77,.1);
  border-bottom:1px solid rgba(34,64,77,.1);
  padding:8px 0;
}
.move-panels[data-kind="skill"] .panel{ display:contents; }
.panel-label{
  font-family:var(--sans); font-size:11px; color:var(--ink-70);
  white-space:nowrap; text-align:right;
}
.panel-tick{
  font-family:var(--sans); font-size:9.5px; font-weight:700;
  letter-spacing:.1em; text-transform:uppercase;
  color:rgba(34,64,77,.3);
}
.panel:has(.panel-tick) .panel-tick{ }
.move-panels[data-kind="skill"] .panel .panel-tick{ color:rgba(34,64,77,.32); }

/* ---- the words ----
   Rendered ONLY when the row says this person wrote something. There
   is no empty slot on the other 1,736 sheets, so there is nothing for
   a reader to notice as missing. That is the whole disappointment
   argument, expressed as markup. */
.words{
  margin-top:14px; padding-top:26px;
  border-top:1px solid rgba(34,64,77,.14);
}
.words-head{
  font-family:var(--sans); font-size:11px; font-weight:700;
  letter-spacing:.16em; text-transform:uppercase; color:var(--ink);
  margin-bottom:18px;
}
.words .portrait{ margin-bottom:18px; }

/* The .words-gap block — a dashed, hatched panel reading "This respondent
   left a written answer. We have not put it in their mouth." — is gone
   along with its markup. It was drawn to match the modelled stamp, which
   is precisely the family it should never have joined: it dressed a
   missing quote up as a designed hole and put it where the reader looks
   for a person. The slot renders placeholder prose now (words.js). */

/* ---- provenance footer ---- */
.person-prov{
  margin-top:26px; padding-top:16px;
  border-top:1px solid rgba(34,64,77,.12);
  font-family:var(--sans); font-size:11.5px; line-height:1.6;
  color:var(--ink-55); max-width:66ch;
}

/* ============================================================
   CONCEPT C — THE REFUSAL
   A designed state, not a dead click. Reached identically by clicking
   a dot and by a cold ?person= deep link.
   ============================================================ */
.person--refused .refuse-title{ margin-bottom:16px; }
.refuse-lead{
  font-family:var(--display); font-size:clamp(17px,1.7vw,21px);
  line-height:1.45; color:var(--ink); max-width:46ch;
}
.refuse-body{
  margin-top:14px; font-family:var(--sans); font-size:13.5px;
  line-height:1.65; color:var(--ink-70); max-width:60ch;
}
.refuse-note{ color:var(--ink-55); font-style:italic; }
.refuse-btn{
  margin-top:24px; cursor:pointer;
  font-family:var(--sans); font-size:12px; font-weight:700;
  color:var(--cream); background:var(--ink);
  border:1px solid var(--ink); border-radius:999px;
  padding:9px 18px;
}
.refuse-btn:hover{ background:var(--ink); }

/* ============================================================
   THE STORY CARD — THE PASSPORT (round 15).

   Approved design: mockups-card-redesign.html, Direction A with the
   third card's layout (A3). Reading order is fixed and the same in
   every chapter:

     identity strip (name · flag · program chip)
     → chapter kicker
     → at most ONE big element
     → the chapter's own lines
     → their verbatim quote (aqua rule, italic, cite)
     → the honesty footline

   Ground is the passport gradient on .dossier-panel (styles.css :root),
   so ink text clears its contrast floor against a real surface, never
   over moving dots. Accent is Enterprise Aqua — the yellow rule that
   used to sit under the name is gone: yellow is the FIELD's one accent
   and it was competing with the dots behind the panel.
   ============================================================ */
.story{ padding-top:2px; }

/* ---- the identity strip: who this is, before anything else ---- */
.story-id{
  display:flex; align-items:center; gap:12px;
  padding:2px 0 14px; margin-bottom:18px;
  border-bottom:1px solid rgba(34,64,77,.14);
}
.story-flag{
  width:26px; height:18px; border-radius:3px; flex:0 0 auto; object-fit:cover;
  box-shadow:0 0 0 1px rgba(34,64,77,.18);
}
.story-who{ min-width:0; }
.story-name{
  display:block; font-family:var(--display); font-weight:700;
  font-size:clamp(19px,2vw,22px); line-height:1.1; letter-spacing:-.01em;
  color:var(--ink);
}
.story-who span{
  display:block; margin-top:2px;
  font-family:var(--sans); font-size:12.5px; color:var(--ink-70);
}
.story-prog{
  margin-left:auto; flex:0 0 auto; max-width:132px; text-align:center;
  font-family:var(--display); font-size:10px; font-weight:700;
  letter-spacing:.06em; text-transform:uppercase; line-height:1.35;
  color:var(--inkdim); border:1px solid rgba(40,95,116,.35);
  border-radius:999px; padding:5px 11px;
}

/* ---- ROUND 15.1: the story card no longer draws a chapter kicker, a big
   element or the 0-10 dot row — its body is three plain sentences (.story-line
   below). These rules are kept because AMAL's dossier shares this stylesheet
   and .story-prog is hers; the rest stand ready if a big element ever comes
   back. Nothing in js/story.js emits them. ---- */
.story-chap{
  font-family:var(--display); font-size:11px; font-weight:700;
  letter-spacing:.2em; text-transform:uppercase; color:var(--accent);
  margin-bottom:14px;
}
/* ONE big element per card, max. Belief gets the 0–10 number; work gets
   the short status statement; skills / return / multiplier get neither. */
.story-big{
  font-family:var(--display); font-weight:800;
  font-size:clamp(46px,5vw,60px); line-height:.95; letter-spacing:-.02em;
  color:var(--ink);
}
.story-big small{ font-size:.4em; font-weight:700; color:var(--ink-70); letter-spacing:0; }
.story-big--text{ font-size:clamp(26px,2.8vw,32px); line-height:1.15; }
.story-biglabel{
  margin-top:7px; font-family:var(--sans); font-size:13px; color:var(--ink-70);
}
.story-dots10{ display:flex; gap:5px; margin:15px 0 2px; }
.story-dots10 i{ width:9px; height:9px; border-radius:50%; background:var(--inkdim); opacity:.92; }
.story-dots10 i.off{ background:none; box-shadow:inset 0 0 0 1.4px rgba(40,95,116,.4); opacity:.8; }

/* ROUND 15.1 — the three intro lines ARE the body now, so they carry a
   touch more size and air than they did as a footnote under a big number:
   three sentences a reader can take in at a glance, then the quote. */
.story-line{
  margin-top:13px; font-family:var(--sans);
  font-size:clamp(14.5px,1.45vw,16px); line-height:1.55; color:var(--ink);
}
.story-line:first-child{ margin-top:0; }
.story-line b{ font-weight:700; }
.story-body + .story-quote{ margin-top:20px; }

/* ---- their words. Styled apart from everything the card says in its own
   voice: aqua rule, tinted well, italic, and the REPORT's attribution line —
   never the invented name in the strip above. ---- */
.story-quote{
  margin:0; padding:15px 17px 13px; border-left:3px solid var(--accent);
  background:rgba(0,192,202,.07); border-radius:0 8px 8px 0;
}
.story-quote-text{
  margin:0; font-family:var(--sans); font-style:italic; font-weight:400;
  font-size:clamp(14px,1.45vw,16px); line-height:1.6; color:var(--ink);
  /* no clamp — a clipped verbatim quote is worse than a tall card, and the
     panel scrolls (a clamp cut the closing line of the Yemen quote). */
}
.story-quote-attr{
  display:block; margin-top:10px;
  font-family:var(--display); font-style:normal; font-weight:700;
  font-size:10.5px; letter-spacing:.08em; text-transform:uppercase; color:var(--inkdim);
}
body.phone .story-quote-text{ font-size:14.5px; }

.story-disclose{
  margin-top:20px; padding-top:14px;
  border-top:1px solid rgba(34,64,77,.14);
  font-family:var(--sans); font-size:11px; line-height:1.5;
  color:rgba(34,64,77,.62); max-width:52ch;
}
/* ROUND 17C — "what the gold meant on the page you came from". Same size class
   as the honesty footline it sits with, and it takes the rule so the two read
   as one closing block rather than two separate rules stacked. */
.story-gold + .story-disclose{ margin-top:8px; padding-top:0; border-top:none; }

/* ---- the LONG variant: Amal's testimonial. Same aqua rail and tinted well,
   but thirteen paragraphs of italic is unreadable, so the text keeps the
   dossier's upright setting inside the passport's frame. ---- */
.story-quote--long{ padding:20px 22px 16px; }
.story-quote--long .dossier-quote p:last-child{ margin-bottom:0; }
.story-quote--long .dossier-quote{ font-size:clamp(15px,1.4vw,17px); }
