/* Story pieces shared by the case studies (docs/cs1-spec.md §4): knot, station, question station, pawn,
   question bubble, metric, exit mark, change diagrams, proposal tag, app screen. Needs tokens.css, shell.css.
   Outlines (Update 12 Nov 2026, Eden): every rounded outline is one SVG stroke drawn by js/outline.js, its centre on a
   device-pixel boundary, so it renders like the thread. Each piece sets its line in custom properties:
   --ol-w weight, --ol-line colour, --ol-fill inside, --ol-inset (the knot's ring inside its box), --ol-scale, --ol-t.
   The CSS two layers (outer colour, inner fill inset by the stroke) read the same properties and stay as the
   no-JS fallback; .has-outline (set by outline.js) switches them off. */

/* ---------- The outline layer (outline.js): under the content, never changes the element's box ---------- */
.has-outline > .ol {
  position: absolute;
  left: 0;
  top: 0;
  z-index: -1;
  display: block;
  width: 100%;
  height: 100%;
  overflow: visible;
  pointer-events: none;
  transform: scale(var(--ol-scale, 1));
  transition: transform var(--ol-t, 0s) ease;
}
.has-outline > .ol path {
  fill: var(--ol-fill);
  stroke: var(--ol-line);
  stroke-width: var(--ol-w);
  stroke-linejoin: miter; /* never the station icon's round joins: Chrome then rasters the path coarser */
  stroke-linecap: butt;
  vector-effect: non-scaling-stroke;
  transition: fill var(--ol-t, 0s) ease, stroke var(--ol-t, 0s) ease, stroke-width var(--ol-t, 0s) ease;
}

/* ---------- Knot (moved unchanged from home.css; cs1-spec §1, §4.3) · above the line; the thread module sets data-reached ---------- */
.knot {
  --ol-w: var(--stroke-exact);
  --ol-inset: 3px;
  --ol-line: var(--color-line-exact);
  --ol-fill: var(--color-bg-page);
  --ol-scale: 1;
  --ol-t: 0.4s;
  position: relative;
  isolation: isolate; /* the outline layer stays above the band's background */
  justify-self: center;
  width: 24px;
  height: 24px;
  border-radius: 50%; /* the ring's shape for outline.js (an 18 circle inside the 24 box) */
}
/* Ahead: an 18 dot with a 1.6 ring. Fallback without JS: two discs (a border would be rounded to whole pixels) */
.knot::before,
.knot::after {
  content: "";
  position: absolute;
  border-radius: 50%;
  transform: scale(var(--ol-scale));
}
.knot::before { inset: 3px; background: var(--ol-line); }          /* 18 */
.knot::after { inset: 4.6px; background: var(--ol-fill); }         /* 18 − 2 × 1.6 = 14.8 */
.knot.has-outline::before,
.knot.has-outline::after { content: none; }
/* Reached: case color, 20.7 (scale keeps the centre still) */
.knot[data-reached] {
  --ol-line: var(--case);
  --ol-fill: var(--case);
  --ol-scale: 1.15;
}
/* Home's knot transition (home-spec §9.3), both ways, 0.4s (--ol-t); home.css keeps its own copy (cs1-spec §12.2, Update 6 Nov 2026) */
.knot::before,
.knot::after { transition: background-color 0.4s ease, transform 0.4s ease; }

/* ---------- Station (§4.1) · Next (default) → Active → Done, set by the page in data-state ---------- */
.station {
  --st: 56px;
  --st-r: var(--radius-tile);
  --st-line: var(--stroke-guide);
  --st-outer: var(--color-line-guide);
  --st-inner: var(--color-bg-page);
  --st-icon: var(--color-line-hand);
  --ol-w: var(--st-line);
  --ol-line: var(--st-outer);
  --ol-fill: var(--st-inner);
  --ol-t: 0.45s;
  position: relative;
  isolation: isolate;
  display: block;
  width: var(--st);
  height: var(--st);
  border-radius: var(--st-r);
  background: var(--st-outer);
}
.station::before {
  content: "";
  position: absolute;
  inset: var(--st-line);
  z-index: -1;
  border-radius: calc(var(--st-r) - var(--st-line));
  background: var(--st-inner);
}
.station.has-outline { background: none; }
.station.has-outline::before { content: none; }
.station--32 { --st: 32px; --st-r: var(--radius-m); }
.station--48 { --st: 48px; --st-r: var(--radius-l); }
.station[data-state="active"] {
  --st-line: var(--stroke-exact);
  --st-outer: var(--color-line-exact);
  --st-icon: var(--color-line-exact);
}
.station[data-state="done"],
.station--done {
  --st-line: var(--stroke-exact);
  --st-outer: var(--case);
  --st-inner: var(--case);
  --st-icon: var(--color-text-on-ink);
}
.station svg {
  display: block;
  width: 100%;
  height: 100%;
  fill: none;
  stroke: var(--st-icon);
  stroke-width: var(--stroke-exact);
  stroke-linecap: round;
  stroke-linejoin: round;
}
.station svg path { vector-effect: non-scaling-stroke; }
/* State changes (cs1-spec §12.2): fill, outline and icon stroke, 0.45s both ways (the pop is cs1.js) */
.station,
.station::before { transition: background-color 0.45s ease; }
.station svg { transition: stroke 0.45s ease; }

/* ---------- Question station (§4.2), State=Step · 40 × 40, white, 1.6 ink outline, the digit centred ---------- */
.qstation {
  --ol-w: var(--stroke-exact);
  --ol-line: var(--color-line-exact);
  --ol-fill: var(--color-bg-page);
  position: relative;
  isolation: isolate;
  display: grid;
  place-items: center;
  width: 40px;
  height: 40px;
  border-radius: var(--radius-m);
  background: var(--ol-line);
  color: var(--color-text-primary);
  font: 400 11px/1 "Martian Mono", ui-monospace, monospace;
  letter-spacing: 0;
}
.qstation::before {
  content: "";
  position: absolute;
  inset: var(--ol-w);
  z-index: -1;
  border-radius: calc(var(--radius-m) - var(--ol-w));
  background: var(--ol-fill);
}
.qstation.has-outline { background: var(--ol-fill); } /* a via with text: its own opaque fill (thread QA G4) */
.qstation.has-outline::before { content: none; }

/* ---------- Pawn (§4.4) · 24 × 30 ---------- */
.pawn {
  display: block;
  flex: none;
  width: 24px;
  height: 30px;
  overflow: visible;
}
.pawn * {
  stroke-width: var(--stroke-hand);
  stroke-linecap: round;
  vector-effect: non-scaling-stroke;
}
.pawn--asking * { fill: var(--color-bg-ink); stroke: var(--color-line-exact); }
.pawn--inside * { fill: var(--case); stroke: var(--case); }
.pawn--left * { fill: var(--color-bg-page); stroke: var(--color-line-guide); }

/* ---------- Question bubble (§4.5) · 1.6 ink outline, radius 22 22 22 4 ---------- */
.speaker {
  display: flex;
  align-items: flex-end;
  gap: 12px;
}
.bubble {
  --ol-w: var(--stroke-exact);
  --ol-line: var(--color-line-exact);
  --ol-fill: var(--color-bg-page);
  position: relative;
  isolation: isolate;
  width: 320px;
  max-width: 100%;
  margin: 0;
  padding: var(--in-m-y) var(--in-m-x);
  border-radius: var(--radius-bubble) var(--radius-bubble) var(--radius-bubble) var(--radius-tail);
  background: var(--color-line-exact);
  color: var(--color-text-primary);
}
.bubble.has-outline { background: none; }
.bubble.has-outline::before { content: none; }
.bubble::before {
  content: "";
  position: absolute;
  inset: var(--stroke-exact);
  z-index: -1;
  border-radius:
    calc(var(--radius-bubble) - var(--stroke-exact)) calc(var(--radius-bubble) - var(--stroke-exact))
    calc(var(--radius-bubble) - var(--stroke-exact)) calc(var(--radius-tail) - var(--stroke-exact));
  background: var(--color-bg-page);
}
.bubble--hug { width: auto; }

/* ---------- Metric (§4.6) · number + 12 + what it measures, baseline aligned ---------- */
.metric {
  display: flex;
  align-items: baseline;
  column-gap: 12px;
  row-gap: 4px;
  margin: 0;
}
.metric__value { flex: none; color: var(--color-text-primary); }
.metric__what { color: var(--color-text-secondary); }

/* ---------- Exit mark (§4.7) · 22 × 22 ---------- */
.exit-mark { display: block; flex: none; width: 22px; height: 22px; }
.exit-mark circle { fill: var(--color-bg-page); }
.exit-mark * {
  stroke: var(--color-line-exact);
  stroke-width: var(--stroke-guide);
  stroke-linecap: round;
  vector-effect: non-scaling-stroke;
}

/* ---------- Change diagrams (§4.8) · fixed size, hidden on mobile ---------- */
.diagram { display: block; flex: none; overflow: visible; fill: none; }
.diagram * { vector-effect: non-scaling-stroke; }
.diagram .d-hand { stroke: var(--color-line-hand); stroke-width: var(--stroke-hand); }
.diagram .d-guide { stroke: var(--color-line-guide); stroke-width: var(--stroke-guide); }
.diagram .d-exact { stroke: var(--color-line-exact); stroke-width: var(--stroke-exact); }
.diagram .d-exact-thin { stroke: var(--color-line-exact); stroke-width: var(--stroke-guide); }
.diagram .d-white { fill: var(--color-bg-page); }
.diagram .d-case { fill: var(--case); stroke: var(--case); stroke-width: var(--stroke-exact); }
.diagram .d-check { stroke: var(--color-text-on-ink); stroke-width: var(--stroke-exact); }
.diagram .d-round { stroke-linecap: round; stroke-linejoin: round; }
.diagram text {
  fill: var(--color-text-secondary);
  stroke: none;
  font-family: "Martian Mono", ui-monospace, monospace;
  font-size: 11px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}

/* ---------- Proposal tag (§4.9) · 1.2 ink outline, pill, hugs its text ---------- */
.proposal-tag {
  --ol-w: var(--stroke-guide);
  --ol-line: var(--color-line-exact);
  --ol-fill: var(--color-bg-page);
  position: relative;
  isolation: isolate;
  display: inline-flex;
  align-self: flex-start;
  margin: 0;
  padding: calc(4px + var(--stroke-guide)) calc(8px + var(--stroke-guide)); /* 4 / 8 inside the 1.2 line (Figma 86.4 × 28.4) */
  border-radius: var(--radius-pill);
  background: var(--color-line-exact);
  color: var(--color-text-primary);
}
.proposal-tag::before {
  content: "";
  position: absolute;
  inset: var(--stroke-guide);
  z-index: -1;
  border-radius: var(--radius-pill);
  background: var(--color-bg-page);
}
.proposal-tag.has-outline { background: none; }
.proposal-tag.has-outline::before { content: none; }

/* ---------- App screen (§4.10) ---------- */
.screen {
  display: flex;
  flex-direction: column;
  gap: var(--rh-tight);
  min-width: 0;
  margin: 0;
}
.screen__label {
  display: flex;
  justify-content: center;
  align-items: center;
  height: 28px;
  margin: 0;
  color: var(--color-text-secondary);
}
.screen__label--right { color: var(--color-text-primary); }
.screen__mark { position: relative; }
.screen__mark svg {
  position: absolute;
  left: 0;
  top: calc(100% + 4px);
  width: 100%;
  height: 6px;
  overflow: visible;
}
.screen__mark path,
.mark-underline path {
  fill: none;
  stroke: var(--color-line-exact);
  stroke-width: var(--stroke-exact);
  vector-effect: non-scaling-stroke;
  stroke-linecap: round;
}
.screen picture,
.screen img {
  display: block;
  width: 100%;
  height: auto;
}
.screen img { border-radius: 7.96% / 3.66%; }

/* ---------- Compare · Before/After (Update 13 Nov 2026, Eden; Figma component 765:1968) ----------
   One template for every Before/After on CS1 and CS2. Large (≥ 601): screens 280 × 609, gap 32, label → screen 12,
   radius 22. Small (≤ 600): 145 × 315, gap 12, label → screen 8, radius 12. Narrower than that, the screens shrink to
   fit their column; the labels and the frame never scale. The frame is drawn by outline.js on top of the content:
   --color-line-guide, --stroke-exact 1.6, inside. The content (a photo, or CS2's drawn screen in .cmp__fit) scales as
   one picture to the screen's width. */
.cmp {
  --cmp-w: 280px;
  --cmp-gap: 32px;
  --cmp-label-gap: 12px;
  --cmp-r: var(--radius-screen);
  display: flex;
  align-items: flex-start;
  gap: var(--cmp-gap);
  margin: 0;
}
.cmp__col {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--cmp-label-gap);
  flex: none;
  width: min(var(--cmp-w), (100% - var(--cmp-gap)) / 2);
  min-width: 0;
  margin: 0;
}
/* Label: Site/Label 11, never scaled, centred over its own screen; both boxes 24 tall so the screens align */
.cmp__label {
  display: flex;
  flex-direction: column;
  align-items: center;
  height: 24px;
  margin: 0;
  color: var(--color-text-secondary);
  white-space: nowrap;
}
/* Update 14 Nov 2026 (Eden): BEFORE is text/secondary, AFTER is text/primary, as in Figma */
.cmp__label--after { color: var(--color-text-primary); }
.cmp__word { position: relative; display: block; }
/* AFTER: the hand mark, the word's width + 8, centred, directly under the text box (gap 0), 6 tall */
.cmp__label--after .cmp__word { padding-bottom: 6px; }
.cmp__word svg {
  position: absolute;
  left: -4px;
  bottom: 0;
  width: calc(100% + 8px);
  height: 6px;
  overflow: visible;
}
.cmp__screen {
  --ol-w: var(--stroke-exact);
  --ol-line: var(--color-line-guide);
  --ol-fill: none;
  position: relative;
  isolation: isolate;
  width: 100%;
  aspect-ratio: 280 / 609;
  overflow: hidden;
  border-radius: var(--cmp-r);
  background: var(--color-bg-page);
}
/* No-JS fallback frame; outline.js draws the frame as one SVG stroke aligned to device pixels, above the content */
.cmp__screen::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 2;
  border: var(--stroke-exact) solid var(--color-line-guide);
  border-radius: inherit;
  pointer-events: none;
}
.cmp__screen.has-outline::after { content: none; }
.cmp__screen.has-outline > .ol { z-index: 2; }
.cmp__screen picture,
.cmp__screen img {
  display: block;
  width: 100%;
  height: 100%;
}
/* CS2's drawn screen: laid out at 280 × 609 and scaled as one picture (--k = screen width / 280, set by cs2.js) */
.cmp__fit {
  position: absolute;
  left: 0;
  top: 0;
  width: 280px;
  height: 609px;
  transform: scale(var(--k, 1));
  transform-origin: 0 0;
}
.cmp__fit .has-outline > .ol path { vector-effect: none; } /* its lines scale with the picture */
@media (max-width: 600px) {
  .cmp {
    --cmp-w: 145px;
    --cmp-gap: 12px;
    --cmp-label-gap: 8px;
    --cmp-r: 12px;
  }
}

/* ---------- Thread drawAll (QA screenshots) and reduced motion: states at once, no transitions ---------- */
[data-thread-static] .knot::before,
[data-thread-static] .knot::after,
[data-thread-static] .station,
[data-thread-static] .station::before,
[data-thread-static] .station svg,
[data-thread-static] .has-outline > .ol,
[data-thread-static] .has-outline > .ol path { transition: none; }
@media (prefers-reduced-motion: reduce) {
  .knot::before,
  .knot::after,
  .station,
  .station::before,
  .station svg,
  .has-outline > .ol,
  .has-outline > .ol path { transition: none; }
}
