/* Fig. 2 on the landing page, the model figure (landing-tsfm.js). The script draws an SVG of
   classes and moves it through attributes; this sheet paints every class with custom
   properties, so the theme toggle repaints it, and lays out the card, the stage and the three
   captions. The stage's size is fixed by CSS before the script runs (no layout shift): wide
   from 860px, then a fixed height, then portrait under 560px. Paper is the default theme. */
.tsfm { min-width: 0; margin: 0; }
.tsfm-card { padding: 1rem 1.15rem 0.95rem; }
.tsfm-head { display: flex; flex-wrap: wrap; align-items: center; gap: 0.5rem 0.6rem; padding-bottom: 0.75rem; border-bottom: 1px solid var(--rule); }
.tsfm-head .fig-number { font-size: var(--fs-label); font-weight: 600; }
.tsfm-head h3 { flex: 1 1 14rem; min-width: 0; margin: 0; font-size: var(--fs-body); font-weight: 500; line-height: var(--lh-ui); }
.tsfm-head .badge { padding: 0.15rem 0.4rem; background: transparent; }
.tsfm-head .badge::before { width: 5px; height: 5px; }
.tsfm-control {
  display: inline-flex; align-items: center; justify-content: center; gap: 0.35rem; min-width: 6.2rem; padding: 0.3rem 0.75rem;
  font: 500 var(--fs-label)/1.3 var(--sans); color: var(--ink); background: var(--surface); border: 1px solid var(--rule-strong); border-radius: 999px; cursor: pointer;
}
.tsfm-control[hidden] { display: none !important; }
.tsfm-control:hover { color: var(--brand); background: var(--brand-wash); border-color: var(--brand); }
.tsfm-control:focus-visible { outline: 2px solid var(--brand); outline-offset: 2px; }
.tsfm-icon { width: 13px; height: 13px; flex: none; fill: none; stroke: currentColor; stroke-width: 1.7; stroke-linecap: round; stroke-linejoin: round; }
.tsfm-icon .i-play { fill: currentColor; stroke: none; }
.tsfm-control:not([data-state="playing"]) .i-pause,
.tsfm-control:is([data-state="playing"], [data-state="done"]) .i-play,
.tsfm-control:not([data-state="done"]) .i-replay { display: none; }

.tsfm-stage { position: relative; margin-top: 0.5rem; aspect-ratio: 5 / 2; }
@media (max-width: 859px) { .tsfm-stage { aspect-ratio: auto; height: clamp(340px, 62vw, 500px); } }
@media (max-width: 559px) { .tsfm-stage { height: auto; aspect-ratio: 5 / 6; } }
.tsfm-plot { position: absolute; inset: 0; display: block; width: 100%; height: 100%; overflow: hidden; }
.tsfm-fallback { position: absolute; inset: 0; display: grid; place-items: center; margin: 0; padding: 1rem; font-size: var(--fs-ui); text-align: center; color: var(--muted); }
.tsfm[data-tsfm-motion] .tsfm-fallback { display: none; }
.tsfm-plot .label { fill: var(--muted); font: 500 11.5px var(--sans); }
.tsfm-plot .s-a { stop-color: var(--glow-a); }
.tsfm-plot .s-b { stop-color: var(--glow-b); }
.tsfm-plot .s-c { stop-color: var(--glow-c); }
/* The library: small series in hairline cards, each on a deck of more, cut into pieces. */
.tsfm-plot .thumb-deck { fill: var(--surface); stroke: var(--rule); stroke-width: 1; }
.tsfm-plot .deck-1 { opacity: 0.8; }
.tsfm-plot .deck-2 { opacity: 0.5; }
.tsfm-plot .thumb-frame { fill: var(--surface); stroke: var(--rule); stroke-width: 1; }
.tsfm-plot .thumb-cut line { stroke: var(--rule-strong); stroke-width: 1; }
.tsfm-plot .thumb-line { fill: none; stroke: var(--ink-2); stroke-width: 1.25; stroke-linejoin: round; }
.tsfm-plot .flight { fill: none; stroke-width: 1.8; stroke-linecap: round; stroke-linejoin: round; vector-effect: non-scaling-stroke; }
.tsfm-plot .flight.tone-0 { stroke: var(--glow-a); }
.tsfm-plot .flight.tone-1 { stroke: var(--glow-b); }
.tsfm-plot .flight.tone-2 { stroke: var(--glow-c); }
/* The model: three rings in the brand gradient, a halo and six marks that light as it learns. */
.tsfm-plot .core-halo { fill: url(#tsfmHalo); }
.tsfm-plot .core-ring { fill: none; stroke: url(#tsfmCore); vector-effect: non-scaling-stroke; }
.tsfm-plot .ring-0 { stroke-width: 1.8; }
.tsfm-plot .ring-1 { stroke-width: 1.45; stroke-opacity: 0.85; }
.tsfm-plot .ring-2 { stroke-width: 1.2; stroke-opacity: 0.7; }
.tsfm-plot .core-dot.tone-0 { fill: var(--glow-a); }
.tsfm-plot .core-dot.tone-1 { fill: var(--glow-b); }
.tsfm-plot .core-dot.tone-2 { fill: var(--glow-c); }
.tsfm-plot .core-heart { fill: url(#tsfmCore); }
.tsfm-plot .core-ripple { fill: none; stroke: var(--glow-b); stroke-width: 1.2; vector-effect: non-scaling-stroke; }
/* The new series in ink, its parts, and what the model adds in the gradient. */
.tsfm-plot .part-wash { fill: var(--brand-wash); }
.tsfm-plot .part-cut line { stroke: var(--rule-strong); stroke-width: 1; stroke-dasharray: 2 4; }
.tsfm-plot .part-pill { fill: var(--rule); }
.tsfm-plot .part-pill-lit { fill: url(#tsfmSpan); }
.tsfm-plot .series { fill: none; stroke: var(--ink); stroke-width: 1.6; stroke-linejoin: round; }
.tsfm-plot .now { stroke: var(--muted); stroke-width: 1; stroke-dasharray: 3 4; }
.tsfm-plot .arc { fill: none; stroke: url(#tsfmSpan); stroke-width: 1.5; }
.tsfm-plot .arc-end { fill: var(--glow-a); stroke: var(--surface); stroke-width: 1.2; }
.tsfm-plot .glint-halo { fill: var(--glow-c); fill-opacity: 0.22; }
.tsfm-plot .glint-dot { fill: var(--glow-c); }
.tsfm-plot .band { fill: url(#tsfmSpan); }
.tsfm-plot .b95 { fill-opacity: 0.08; }
.tsfm-plot .b80 { fill-opacity: 0.12; }
.tsfm-plot .b50 { fill-opacity: 0.18; }
.tsfm-plot .median { fill: none; stroke: url(#tsfmSpan); stroke-width: 2.2; stroke-dasharray: 6 4; stroke-linecap: round; }
.tsfm-plot .fc-end { fill: var(--glow-c); stroke: var(--surface); stroke-width: 1.5; }

/* The three captions, real text under the stage. Without the script, and under reduced motion,
   they are a plain list; while it plays, the script fades each in on its step, marks the current
   one and fills its bar, all from the figure's one clock. */
.tsfm-steps { display: grid; grid-template-columns: 0.29fr 0.4fr 0.31fr; gap: 0.6rem 1.2rem; margin: 0.35rem 0 0; padding: 0.85rem 0 0; list-style: none; border-top: 1px solid var(--rule); }
.tsfm-steps li { position: relative; display: flex; align-items: flex-start; gap: 0.55rem; padding-bottom: 0.75rem; font-size: var(--fs-ui); line-height: var(--lh-ui); color: var(--ink); }
.tsfm-steps b { display: grid; flex: none; place-items: center; width: 22px; height: 22px; font: 600 var(--fs-label) var(--sans); color: var(--brand); background: var(--brand-wash); border: 1px solid var(--brand); border-radius: 6px; }
.tsfm-steps i { display: none; position: absolute; left: 0; right: 0; bottom: 0; height: 2px; border-radius: 2px; background: linear-gradient(90deg, var(--glow-a), var(--glow-b) 55%, var(--glow-c)); transform: scaleX(0); transform-origin: left center; }
.tsfm[data-tsfm-motion]:not([data-tsfm-state="still"]) .tsfm-steps li::before { content: ""; position: absolute; left: 0; right: 0; bottom: 0; height: 2px; border-radius: 2px; background: var(--rule-soft); }
.tsfm[data-tsfm-motion]:not([data-tsfm-state="still"]) .tsfm-steps i { display: block; }
.tsfm[data-tsfm-motion] .tsfm-steps li[data-state="on"] b { color: var(--brand-ink); background: var(--brand); }
.tsfm[data-tsfm-motion] .tsfm-steps li[data-state="done"] i { opacity: 0.4; }
.tsfm figcaption { max-width: var(--measure-caption); margin: 0.8rem 0 0; font-size: var(--fs-label); line-height: 1.5; color: var(--muted); }
.tsfm figcaption b { margin-right: 0.3rem; font-weight: 600; color: var(--ink); }
@media (max-width: 859px) { .tsfm-steps { grid-template-columns: repeat(3, minmax(0, 1fr)); } }
@media (max-width: 559px) {
  .tsfm-card { padding: 0.8rem 0.8rem 0.7rem; }
  .tsfm-head h3 { flex-basis: 100%; order: 1; font-size: var(--fs-ui); }
  .tsfm-steps { grid-template-columns: minmax(0, 1fr); gap: 0.55rem; }
  .tsfm-steps li { padding-bottom: 0.6rem; }
}
@media (forced-colors: active) {
  .tsfm-plot :is(.series, .median, .arc, .core-ring, .core-ripple, .flight, .thumb-line, .now) { stroke: CanvasText; }
  .tsfm-plot :is(.band, .core-halo, .glint-halo) { fill: none; }
  .tsfm-steps i { background: CanvasText; }
}
