/* Deck layout. Loaded after theme.css, which keeps the BPMN, reveal, legend
   and tally machinery — this file only turns that machinery into slides.

   Everything that changes behaviour is scoped to [data-deck], set by js/deck.js
   once it runs. Without JS the page falls back to theme.css: every slide
   stacked, every stage visible, readable as a handout. */

:root {
  --bar-h: 2.6rem;
  --slide-pad: 1.15rem;

  /* Slide padding scales with the viewport rather than sitting at a fixed rem.
     At 1.9rem top it cost 30px of a 720px window — 4% of the screen — to hold
     a gap that reads the same at 16px there and at 24px on a 1080px one. */
  --slide-pad-top: clamp(0.9rem, 2.2svh, 1.9rem);
  --slide-pad-bot: clamp(0.7rem, 1.8svh, 1.55rem);

  /* Gutters. Generous enough that the deck reads as a composed page rather
     than a web page bleeding to the window edge. Costs the diagrams almost
     nothing, because they are constrained by height, not width. */
  --gutter: clamp(1.25rem, 4.4vw, 4.25rem);

  /* The masthead. Three bands, DERIVED from the type they hold, not guessed:
     a hand-picked rem value was right at 1440 (where the clamp keeps the font
     small) and 11px short on a wide window (where the font hits its cap),
     which collided the caption into the content below it. Change the type
     here and the band follows.

     The bands are FLOORS, not fixed heights. Reserving the worst case —
     two heading lines and three caption lines — charged every slide for the
     tallest one: five of seven headings are a single line, so they carried
     42px of dead space under the heading, and the title slides another 29px
     under the caption. The hole landed inside the heading/caption unit,
     which is precisely where a gap must not be. Each band now sizes to its
     own slide; see .caption-slot for how the stages stay stable. */
  --head-size: clamp(1.35rem, 2.4vw, 1.95rem);
  --head-lh: 1.18;
  --cap-size: clamp(1rem, 1.3vw, 1.14rem);
  --cap-lh: 1.42;

  /* Proximity. The heading and its caption are ONE unit: the gap inside the
     unit is small, the gap below it is large. The old bands made those two
     gaps roughly equal, so the caption read as floating between the heading
     and the content rather than belonging to the heading. */
  --cap-pad: 1.05rem;             /* heading -> caption, inside the unit */
  --cap-pad-title: 1.5rem;        /* the title slides set their heading in
                                     2.6rem against a 1.08 line, which leaves
                                     almost no slack under the text the way
                                     the 1.18 line on a slide heading does.
                                     A gap that reads as "related" has to
                                     scale with the type it separates. */
  --gap-masthead: 1.75rem;        /* caption -> content, between units */

  --band-meta: 1.5rem;
  --band-head: calc(var(--head-size) * var(--head-lh) + 0.65rem);
  --band-cap: calc(var(--cap-size) * var(--cap-lh));

  /* Measure. Presentation prose is read at distance and at a glance, so it
     wants a tighter line than a document would: ~60-65 characters, not 75+.
     Calibrated against this typeface, not assumed: Plus Jakarta's "0" is
     13.7px where its average character is 9.8px, so a ch is 1.4x an actual
     character. 44ch therefore lands at ~62 characters, where 52ch gave 72. */
  --measure-caption: 49ch;        /* ~68 characters */
  --measure-lead: 44ch;
  --measure-head: 32ch;
  --measure-body: 40ch;
}

/* ------------------------------------------------------------------ bar */

.deck-bar {
  position: sticky;
  top: 0;
  z-index: 40;
  height: var(--bar-h);
  display: flex;
  align-items: center;
  gap: 0.9rem;
  padding: 0 1rem;
  background: var(--color-primary);
  color: #fff;
}

.deck-bar .wrap {
  display: contents;              /* presenter.js appends its ? button here */
}

.deck-title {
  margin: 0;
  font-family: var(--font-heading);
  font-size: 0.78rem;
  font-weight: 700;
  letter-spacing: 0.01em;
  white-space: nowrap;
}

.deck-title .sample {
  margin-left: 0.5rem;
  padding: 0.1rem 0.4rem;
  border-radius: 999px;
  background: rgba(255, 255, 255, 0.18);
  font-size: 0.66rem;
  font-weight: 600;
  letter-spacing: 0.04em;
  text-transform: uppercase;
}

.deck-dots {
  display: flex;
  align-items: center;
  gap: 0.3rem;
  margin-left: auto;
}

.deck-dot {
  width: 0.62rem;
  height: 0.62rem;
  padding: 0;
  border: 1.5px solid rgba(255, 255, 255, 0.55);
  border-radius: 999px;
  background: transparent;
  cursor: pointer;
  transition: background 0.2s ease, border-color 0.2s ease, transform 0.2s ease;
}

.deck-dot.is-done {
  background: rgba(255, 255, 255, 0.5);
  border-color: rgba(255, 255, 255, 0.5);
}

.deck-dot.is-here {
  background: #fff;
  border-color: #fff;
  transform: scale(1.35);
}

.deck-dot:focus-visible {
  outline: 2px solid var(--color-focus, #e6007e);
  outline-offset: 2px;
}

.deck-count {
  font-family: var(--font-mono);
  font-size: 0.7rem;
  opacity: 0.8;
  white-space: nowrap;
}

/* Which part of a multi-part slide you are on. Blank on single-part slides. */
.deck-step {
  font-family: var(--font-mono);
  font-size: 0.7rem;
  padding: 0.1rem 0.45rem;
  border-radius: 999px;
  background: rgba(255, 255, 255, 0.18);
  white-space: nowrap;
}

.deck-step:empty {
  display: none;
}

/* The presenter toggle sits in the bar, not in a page header. */
.deck-bar .presenter-toggle {
  margin-left: 0.35rem;
}

/* --------------------------------------------------------------- slides */

.deck-stage {
  display: block;
}

/* One slide is exactly one viewport — never taller, never shorter.

   This used to be min-height plus align-content:start. That pinned the
   masthead correctly, but everything below it then kept its natural size and
   the remainder was simply abandoned: 112px of a 720px window on the process
   slides, 118px on the page anatomy, while the diagrams inside them rendered
   their labels at 7px. A fixed height and a column give the content below the
   masthead a defined remainder to claim, and the fillers below claim it. */
[data-deck] .slide {
  height: calc(100svh - var(--bar-h));
  display: flex;
  flex-direction: column;
  padding: var(--slide-pad-top) var(--gutter) var(--slide-pad-bot);
  overflow: hidden;
}

[data-deck] .slide[hidden] {
  display: none;
}

/* Letterbox above the design size. A slide is one viewport tall, but the
   composition is drawn for a Teams share at roughly 1280x720 and its content
   has a fixed natural height — so on a 1250px-tall window every light slide
   was handing 500-600px of surplus to whatever absorbed it, as voids between
   blocks or as inflated cards. No amount of centring fixes that; the frame is
   simply bigger than the composition.

   40.5rem is the content height of a 1280x720 window: 720 less the bar and the
   two paddings. Cap the block there and centre it, and every window from 720
   upwards renders the identical slide — the one you rehearsed and the one the
   panel sees. The surplus becomes a margin around the slide instead of holes
   inside it. The diagrams stop growing past their 720 size, which is the trade:
   consistency over using every pixel of a display the panel does not have. */
[data-deck] .slide {
  justify-content: center;
}

[data-deck] .slide-in {
  max-height: 40.5rem;
}

.slide-in {
  width: 100%;
  max-width: 74rem;
  margin: 0 auto;
}

/* Scoped to [data-deck] deliberately. Unscoped, the handout inherited the
   column too, and .anatomy's `flex: 1 1 0` basis resolved to zero height in an
   auto-height container — which clipped the page anatomy out of the printable
   fallback entirely. The handout stays in normal flow. */
[data-deck] .slide-in {
  flex: 1 1 auto;
  min-height: 0;                  /* a flex child will not shrink past its
                                     content without this, which would restore
                                     the overflow the fixed height prevents */
  display: flex;
  flex-direction: column;
}

/* The masthead is the fixed part of the column: it keeps its own height and
   neither grows nor shrinks, so the heading baseline and the caption top stay
   identical on every slide regardless of what the content below is doing. */
[data-deck] .slide-kicker,
[data-deck] .slide h1,
[data-deck] .slide h2.slide-h,
[data-deck] .slide .title-h,
[data-deck] .caption-slot {
  flex: 0 0 auto;
}

/* Slides with no diagram or anatomy to claim the remainder — the two title
   slides and the outcome slide — used to leave it all at the bottom, 45% of
   the frame, which reads as unfinished rather than as restraint. Auto margins
   above the first content block and below the last centred the group in
   whatever was left instead.

   Centring solved the void at the foot by moving half of it upwards, into the
   gap between the caption and the content: 165px on the bookends and 174px on
   the outcome slide, on a 1080 window. That is five times the 32px the
   diagram slides use for the same joint, and it is the same unnatural hole
   the masthead bands used to make, one step lower down. A gap that size stops
   reading as "these are separate" and starts reading as "something is
   missing".

   So the gap is capped rather than free. The content follows the masthead at
   a distance that still separates it — roughly twice --gap-masthead, so the
   hierarchy inside the slide still runs smallest at the top — and the surplus
   collects once, at the foot of the frame, where a margin is conventional.
   One void at the bottom, not two either side of the content.

   Bounded in svh so it answers to the window rather than to the type: on a
   short Teams share there is little to give away and the cap barely binds; on
   a tall window it stops well short of the hole it replaced.

   Safe across reveals because the stage gating in theme.css is opacity-only —
   a `.from-3` block occupies its space from the first stage, so nothing
   reflows when it fades in. On slides that do have a filler, flex-grow takes
   the free space first and this resolves to its minimum. */
[data-deck] .slide:not(:has(.diagram, .anatomy)) .caption-slot + * {
  margin-top: clamp(2rem, 7svh, 4.5rem);
}

/* The surplus belongs at the foot. This was `auto`, which is what pulled the
   group back to the centre and reopened the gap above it. */
[data-deck] .slide:not(:has(.diagram, .anatomy)) .slide-in > *:last-child {
  margin-bottom: 0;
}

/* The bookend slides carry a three-part brief and the standing note, and the
   two are one composition, so the gap between them is capped and not free.
   Letting it take the surplus would split the leftover into two separate
   voids — 343px each on a 1250px window — which reads as two marooned
   islands. Same reasoning as the capped gap above, applied one joint lower:
   every gap on these slides is bounded, and the remainder lands at the foot. */
[data-deck] .slide.is-title .brief + .brief-note {
  margin-top: clamp(1rem, 3svh, 2.25rem);
}

/* The brief is three cards across, so these two need the full column rather
   than the 56rem a title slide normally takes. Specificity, not source order:
   .is-wide and .is-title score the same and .is-title is written later. */
[data-deck] .slide.is-title:has(.brief) .slide-in {
  max-width: 82rem;
}

.slide.is-wide .slide-in {
  max-width: 82rem;
}

.slide.is-narrow .slide-in {
  max-width: 52rem;
}

/* Slide heading block — a kicker and one line. The caption carries the rest. */
.slide-kicker {
  margin: 0;
  height: var(--band-meta);       /* reserved even when empty */
  display: flex;
  align-items: center;
  font-family: var(--font-mono);
  font-size: 0.68rem;
  font-weight: 500;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--color-muted-foreground);
}

.slide h1,
.slide h2.slide-h,
.slide .title-h {
  margin: 0;
  min-height: var(--band-head);   /* a floor of one line, not a fixed two.
                                     The heading never changes within a slide,
                                     so letting it size to its own text cannot
                                     reflow anything mid-reveal — and the top
                                     edge, which is the line the eye tracks,
                                     stays pinned by the fixed kicker above. */
  padding-top: 0.45rem;           /* top-aligned text would otherwise sit hard
                                     against the kicker above it */
  display: flex;
  align-items: flex-start;        /* the FIRST line always starts on one line,
                                     which is the one the eye tracks. This was
                                     flex-end — last lines on a shared baseline
                                     — and the band is reserved either way, so
                                     the caption below never moved. But it made
                                     the top of the headline jump 40px between
                                     a one-line slide and the two-line one, and
                                     that is the movement you see when you step
                                     through the deck. Bottom-aligning is right
                                     when most headings wrap; here only one
                                     does. */
  font-family: var(--font-heading);
  font-size: var(--head-size);
  line-height: var(--head-lh);
  letter-spacing: -0.015em;
  color: var(--color-card-foreground);
  max-width: var(--measure-head);
}

.slide .lead {
  margin: 0;
  font-size: clamp(0.98rem, 1.25vw, 1.15rem);
  color: var(--color-muted-foreground);
  max-width: var(--measure-lead);
}

/* ------------------------------------------------- captions and stages */

/* theme.css gates captions with an explicit per-stage list. Replace it with
   a rule that does not have to be extended every time a stage is added.

   Gated on visibility, not display: every caption keeps its box, so the slot
   below measures the tallest one and the off-stage captions hold that height
   open. Stepping through a slide therefore moves nothing, which is what the
   fixed band was for — but the height is now this slide's own worst case
   instead of the whole deck's, at whatever width the window happens to be. */
[data-deck] .slide .stage-caption {
  display: block;
  visibility: hidden;
}

[data-deck] .slide[data-stage="1"] .cap-1,
[data-deck] .slide[data-stage="2"] .cap-2,
[data-deck] .slide[data-stage="3"] .cap-3,
[data-deck] .slide[data-stage="4"] .cap-4,
[data-deck] .slide[data-stage="5"] .cap-5,
[data-deck] .slide[data-stage="all"] .cap-last {
  visibility: visible;
}

/* The slot holds the caption to the heading above it and opens the gap to the
   content below; the caption itself hugs its own text, so the blue rule is
   never taller than the words it belongs to. */
.caption-slot {
  min-height: var(--band-cap);
  margin: 0;
  padding-top: var(--cap-pad);
  padding-bottom: var(--gap-masthead);
  display: flex;
  align-items: flex-start;
}

/* Stacking the stages in one grid cell is what lets the slot self-size: the
   row resolves to the tallest caption on THIS slide. A slide whose captions
   all run short no longer reserves three lines because some other slide
   needs them. Scoped with :has() so the title slides — whose slot holds a
   subtitle and a byline in normal flow, not stages — keep the flex column. */
[data-deck] .caption-slot:has(.stage-caption) {
  display: grid;
  align-items: start;
}

[data-deck] .caption-slot:has(.stage-caption) > .stage-caption {
  grid-area: 1 / 1;
}

[data-deck] .slide .stage-caption {
  min-height: 0;
  margin: 0;
  font-size: var(--cap-size);
  line-height: var(--cap-lh);
  border-left-width: 5px;
  padding-left: 0.95rem;
  color: var(--color-card-foreground);
  max-width: var(--measure-caption);
}

/* A single-stage slide has nothing to reveal, so nothing should be dimmed. */
[data-deck] .slide[data-stages="1"] .tally {
  opacity: 1;
}

/* Stage counter, bottom-left, for the presenter's own orientation only. */
.stage-meter {
  position: fixed;
  left: 0.75rem;
  bottom: 0.6rem;
  z-index: 30;
  font-family: var(--font-mono);
  font-size: 0.68rem;
  color: var(--color-muted-foreground);
  opacity: 0.55;
  pointer-events: none;
}

/* ------------------------------------------------------------- diagrams */

/* A diagram claims the whole remainder of the slide — all of it, in both
   directions — and the SVG's own preserveAspectRatio lands it at the largest
   size that fits inside. There is no height budget to keep in step with the
   chrome above it any more, which is the point: the budget was a hand-picked
   constant measured against a 900px window, and on a 720px Teams share it left
   the diagram 46% of the screen and abandoned another 16% below it.

   The width was worse, and quieter. `justify-items: center` made the SVG a
   shrink-to-fit grid item, so its `width: 100%` never stretched and the
   `min-width: 46rem` floor in theme.css — which belongs to the no-JS scrolling
   handout — became its actual width. The diagram rendered at exactly 736px on
   a 1280px window and at exactly 736px on a 2560px one. Stretching it is the
   single largest legibility gain in the deck. */
[data-deck] .slide .diagram {
  flex: 1 1 0;
  min-height: 0;
  min-width: 0;
  width: 100%;
  margin: 0 0 0.7rem;
  padding: 0.5rem;
  display: block;
  overflow: visible;              /* crops replace scrolling in a deck */
}

[data-deck] .slide .bpmn {
  display: block;
  width: 100%;
  height: 100%;
  min-width: 0;                   /* the 46rem floor belongs to the handout */
  max-height: none;
}

[data-deck] .slide .legend {
  flex: 0 0 auto;
  margin-bottom: 0.25rem;
}

/* ------------------------------------------------------- slide 0 opener */

.opener-grid {
  display: grid;
  gap: 1.1rem;
}

@media (min-width: 60rem) {
  .opener-grid {
    grid-template-columns: 1.15fr 1fr;
    align-items: start;
  }
}

.fact-list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  gap: 0.55rem;
}

.fact-list li {
  display: grid;
  grid-template-columns: 8.5rem 1fr;
  gap: 0.75rem;
  align-items: baseline;
  padding-bottom: 0.55rem;
  border-bottom: 1px solid var(--color-border);
  font-size: 0.92rem;
}

.fact-list li:last-child {
  border-bottom: 0;
}

.fact-list .k {
  font-family: var(--font-mono);
  font-size: 0.7rem;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--color-muted-foreground);
}

.fact-list .v strong {
  color: var(--color-card-foreground);
}

/* ------------------------------------------------ slide 2 evidence list */

.evidence-grid {
  display: grid;
  gap: 0.75rem;
  margin: 0 0 1.1rem;
}

@media (min-width: 48rem) {
  .evidence-grid {
    grid-template-columns: repeat(3, 1fr);
  }
}

.ev {
  border: 1px solid var(--color-border);
  border-top: 4px solid var(--color-primary);
  border-radius: var(--radius);
  background: #fff;
  padding: 0.8rem 0.9rem;
}

.ev h3 {
  margin: 0 0 0.3rem;
  font-family: var(--font-heading);
  font-size: 0.95rem;
  color: var(--color-card-foreground);
}

.ev p {
  margin: 0;
  font-size: 0.85rem;
  color: var(--color-muted-foreground);
}

[data-deck] .slide .reframe {
  margin-bottom: 0.9rem;
  padding: 1.15rem 1.2rem;
}

[data-deck] .slide .reframe .big {
  font-size: clamp(1.05rem, 1.9vw, 1.45rem);
}

/* --------------------------------------------- slide 5 hierarchy labels */

.stair-key {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
  margin: 0 0 0.9rem;
}

.stair-key span {
  font-size: 0.78rem;
  color: var(--color-muted-foreground);
  border: 1px solid var(--color-border);
  border-radius: 999px;
  padding: 0.2rem 0.7rem;
  background: #fff;
}

/* The review cadence strip, revealed with the payoff. */
.cadence {
  display: grid;
  gap: 0.6rem;
  margin: 0 0 0.6rem;
}

@media (min-width: 48rem) {
  .cadence {
    grid-template-columns: repeat(3, 1fr);
  }
}

.cadence .c {
  border: 1px solid var(--color-border);
  border-left: 4px solid var(--color-primary);
  border-radius: var(--radius);
  background: #fff;
  padding: 0.6rem 0.8rem;
  font-size: 0.85rem;
}

.cadence .c strong {
  display: block;
  font-family: var(--font-heading);
  font-size: 0.9rem;
  color: var(--color-card-foreground);
}

.cadence .c span {
  color: var(--color-muted-foreground);
}

/* ------------------------------------------------- slide 8 page anatomy */

.anatomy {
  display: grid;
  align-items: start;
}

/* The two-up inside a layer: the artefact on the left, its notation on the
   right. This was on .anatomy itself until the slide grew a second and third
   artefact; .anatomy is now the container the three layers share. */
.anat-two {
  display: grid;
  gap: 1.1rem;
  align-items: start;
}

@media (min-width: 62rem) {
  .anat-two {
    grid-template-columns: 1.25fr 1fr;
  }
}

/* The rebuilt page template. Dummy labels, real structure. */
.tpl {
  border: 1px solid var(--color-border);
  border-radius: var(--radius);
  background: #fff;
  padding: 0.7rem;
  box-shadow: var(--elevation-1, 0 1px 3px rgba(0, 0, 0, 0.08));
}

.tpl-chrome {
  display: flex;
  align-items: center;
  gap: 0.35rem;
  padding-bottom: 0.5rem;
  border-bottom: 1px solid var(--color-border);
  margin-bottom: 0.6rem;
}

.tpl-chrome i {
  width: 0.45rem;
  height: 0.45rem;
  border-radius: 999px;
  background: var(--nobel-200, #d6d8da);
}

.tpl-chrome b {
  margin-left: 0.4rem;
  font-family: var(--font-mono);
  font-size: 0.62rem;
  font-weight: 500;
  color: var(--color-muted-foreground);
}

.tpl-h {
  margin: 0 0 0.55rem;
  font-family: var(--font-heading);
  font-size: 0.98rem;
  color: var(--color-card-foreground);
}

/* Section headings inside the template. */
.tpl-sec {
  font-family: var(--font-heading);
  font-size: 0.74rem;
  font-weight: 700;
  color: var(--color-card-foreground);
  margin: 0 0 0.35rem;
  padding-bottom: 0.2rem;
  border-bottom: 1px solid var(--color-border);
}

/* Numbered pins, on the template and in the notes list. */
.pin {
  display: inline-grid;
  place-items: center;
  width: 1.1rem;
  height: 1.1rem;
  border-radius: 999px;
  background: var(--color-primary);
  color: #fff;
  font-family: var(--font-mono);
  font-size: 0.62rem;
  font-weight: 600;
  flex: none;
}

.anno-list {
  list-style: none;
  counter-reset: none;
  margin: 0;
  padding: 0;
  display: grid;
  gap: 0.5rem;
}

.anno-list li {
  display: grid;
  grid-template-columns: 1.1rem 1fr;
  gap: 0.6rem;
  align-items: start;
  border: 1px solid var(--color-border);
  border-radius: var(--radius);
  background: #fff;
  padding: 0.55rem 0.7rem;
  font-size: 0.82rem;
}

.anno-list strong {
  display: block;
  font-family: var(--font-heading);
  font-size: 0.86rem;
  color: var(--color-card-foreground);
}

.anno-list span {
  color: var(--color-muted-foreground);
}

.anno-list .pin {
  color: #fff;
}

/* Component states row, rebuilt properly. */
.states-row {
  display: grid;
  grid-template-columns: repeat(5, 1fr);
  gap: 0.45rem;
  margin: 0.15rem 0 0;
}

.st {
  text-align: center;
}

.st div {
  height: 1.9rem;
  display: grid;
  place-items: center;
  border: 1.5px solid var(--color-border);
  border-radius: 6px;
  background: #fff;
  font-size: 0.68rem;
  color: var(--color-card-foreground);
}

.st p {
  margin: 0.25rem 0 0;
  font-family: var(--font-mono);
  font-size: 0.58rem;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--color-muted-foreground);
}

.st.is-hover div { border-color: var(--color-primary); background: #eef4fa; }
.st.is-sel div   { border-color: var(--color-primary); background: var(--color-primary); color: #fff; }
.st.is-err div   { border-color: var(--color-cost, #a8342a); background: #fbeceb; color: var(--color-cost-fg, #8a281f); }
.st.is-dis div   { border-style: dashed; color: var(--color-muted-foreground); background: var(--color-lane, #f4f5f6); }

/* ------------------------------------------- slide 7 governance pipeline */

.pipeline {
  display: grid;
  gap: 0.55rem;
  margin: 0 0 1rem;
}

@media (min-width: 52rem) {
  .pipeline {
    grid-template-columns: repeat(4, 1fr);
    align-items: stretch;
  }
}

.pipe {
  position: relative;
  border: 1px solid var(--color-border);
  border-radius: var(--radius);
  background: #fff;
  padding: 0.65rem 0.8rem;
}

.pipe b {
  display: block;
  font-family: var(--font-heading);
  font-size: 0.88rem;
  color: var(--color-card-foreground);
  margin-bottom: 0.15rem;
}

.pipe span {
  font-size: 0.78rem;
  color: var(--color-muted-foreground);
}

.pipe .step-n {
  position: absolute;
  top: -0.5rem;
  left: 0.7rem;
  font-family: var(--font-mono);
  font-size: 0.58rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  background: var(--color-primary);
  color: #fff;
  border-radius: 999px;
  padding: 0.08rem 0.45rem;
}

.pipe.is-last {
  border-color: var(--color-primary);
  background: #eef4fa;
}

/* ------------------------------------------------------- two-up options */

[data-deck] .slide .options {
  margin-bottom: 1rem;
}

[data-deck] .slide .tally {
  margin-bottom: 0;
}

/* ------------------------------------------------------------ integrity */

/* Small print that has to survive a compressed share without shouting. */
.provenance {
  margin: 0.7rem 0 0;
  font-size: 0.76rem;
  color: var(--color-muted-foreground);
  border-left: 3px solid var(--color-border);
  padding-left: 0.7rem;
  max-width: 62ch;
}

/* --------------------------------------------------------------- motion */

@media (prefers-reduced-motion: reduce) {
  .from-2, .from-3, .from-4, .from-5,
  .deck-dot {
    transition: none;
  }
}

/* ------------------------------------------------ no-JS handout fallback */

html:not([data-deck]) .deck-dots,
html:not([data-deck]) .deck-count,
html:not([data-deck]) .stage-meter {
  display: none;
}

html:not([data-deck]) .slide {
  padding: 2rem 1.4rem;
  border-bottom: 1px solid var(--color-border);
}

/* ------------------------------------ slide 5 · the hierarchy staircase */

.stair .lv rect {
  fill: #fff;
  stroke: var(--color-primary);
  stroke-width: 2;
}

.stair .lv .ado {
  font-family: var(--font-mono);
  font-size: 13px;
  font-weight: 500;
  letter-spacing: 0.1em;
  fill: var(--color-muted-foreground);
}

.stair .lv .art {
  font-family: var(--font-heading);
  font-size: 19px;
  font-weight: 700;
  fill: var(--color-card-foreground);
}

.stair .lv .eg {
  font-family: var(--font-body);
  font-size: 13.5px;
  fill: var(--color-muted-foreground);
}

.stair .link {
  fill: none;
  stroke: var(--color-primary);
  stroke-width: 2;
}

.stair .side {
  font-family: var(--font-heading);
  font-size: 17px;
  font-weight: 600;
  fill: var(--color-primary);
}

/* "Go to this beat" became a button when the overlay stopped navigating
   between pages, so it needs the anchor's appearance back. */
.pn-go[data-pn-go] {
  border: 0;
  background: none;
  padding: 0;
  color: var(--color-primary);
  text-decoration: underline;
  cursor: pointer;
  font-family: inherit;
}


/* ------------------------------- slide 8 · the page anatomy, zoomed out */

/* The whole page on one frame at reduced detail. Nothing is clipped: every
   section that carries a callout is visible at once, which is the point of
   an anatomy — the developer sees the shape before the specifics. */
.anatomy,
.anat-two {
  align-items: stretch;
}

[data-deck] .anatomy {
  flex: 1 1 0;
  min-height: 0;
}

/* The frame owns the height budget; the template inside is scaled to fit it
   by js/deck.js. transform-origin keeps it centred as it shrinks. */
/* Same story as the diagrams: a hand-picked height that had to be kept in
   step with the chrome above it. Under the deck it claims the remainder; in
   the handout it simply sizes to the artefact. */
.tpl-frame {
  display: flex;
  justify-content: center;
}

[data-deck] .tpl-frame {
  min-height: 0;
  overflow: hidden;
}

.tpl {
  width: 100%;
  flex: none;
  max-width: none;
  align-self: flex-start;
  transform-origin: top center;
  display: flex;
  flex-direction: column;
  gap: 0.26rem;
}

.tpl-row {
  display: flex;
  align-items: center;
  gap: 0.4rem;
}

.tpl-row .tpl-h,
.tpl-row .tpl-sec {
  margin: 0;
  flex: 1;
}

.tpl-row .pin {
  margin-left: auto;
}

/* CTA bar */
.tpl-cta {
  margin-top: 0.15rem;
  padding-top: 0.4rem;
  border-top: 1px solid var(--color-border);
  font-size: 0.6rem;
}

.tpl-cta .pin { margin-left: 0; }

/* Notes column sits alongside, not under. */
.anno-col {
  width: 100%;
  flex: none;
  max-width: none;
  align-self: flex-start;
  transform-origin: top center;
  display: flex;
  flex-direction: column;
}

/* The notes column gets the same budget as the template, so on a short window
   both shrink together rather than the notes pushing the slide off the fold. */
.notes-frame {
  align-items: flex-start;
}

/* ---------------------------------- slide 6 · framing the review cadence */

.cadence-lead {
  margin: 0 0 0.5rem;
  font-size: 0.88rem;
  color: var(--color-muted-foreground);
}

/* ------------------------------------------ slide 0 and 9 · title slides */

.slide.is-title .slide-in {
  max-width: 56rem;
}

/* Sized to sit on one line inside the shared heading band, so the title slide
   lands on the same baseline as every other slide rather than floating. */
.title-h {
  font-size: clamp(1.8rem, 3.3vw, 2.6rem) !important;
  line-height: 1.08 !important;
  max-width: 30ch !important;     /* wide enough to hold one line */
}

.slide.is-title .caption-slot {
  padding-top: var(--cap-pad-title);
}

.title-sub {
  margin: 0 0 0.3rem;
  font-family: var(--font-heading);
  font-size: clamp(1rem, 1.6vw, 1.25rem);
  color: var(--color-card-foreground);
}

.title-by {
  margin: 0;
  font-size: 0.95rem;
  color: var(--color-muted-foreground);
}

/* ------------------------------------ slide 8 · air before the outcomes */

[data-deck] .slide .pipeline {
  margin-top: 0.6rem;
  margin-bottom: 2.4rem;
}


/* The callout numbers have to survive the scale-down, so they are drawn larger
   inside the template than they are in the notes list. */
.tpl .pin {
  width: 1.45rem;
  height: 1.45rem;
  font-size: 0.85rem;
}

/* ============================================================ act gaps */

/* The talk is three acts — context, the decisions, the craft. Breaking the run
   of dots shows that shape instead of ten undifferentiated steps. */
.deck-act-gap {
  width: 0.75rem;
  height: 1px;
  background: rgba(255, 255, 255, 0.35);
}

/* Announced to screen readers only. */
.deck-announcer {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  overflow: hidden;
  clip: rect(0 0 0 0);
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

/* ==================================================== density: is-airy */

/* Slides carrying only two or three elements were leaving half the frame
   empty, which reads as unfinished rather than as restraint. These do not
   scale the whole slide — the heading stays put — they give the content
   itself a larger step on the type scale and more room to sit in. */

.slide.is-airy .fact-list li {
  grid-template-columns: 10rem 1fr;
  gap: 1.1rem;
  font-size: 1.12rem;
  padding-bottom: 1.15rem;
  margin-bottom: 0.4rem;
}

.slide.is-airy .fact-list .k {
  font-size: 0.78rem;
}

.slide.is-airy .ev {
  padding: 1.5rem 1.6rem;
}

.slide.is-airy .ev h3 {
  font-size: 1.28rem;
  margin-bottom: 0.55rem;
}

.slide.is-airy .ev p {
  font-size: 1.02rem;
  line-height: 1.5;
}

.slide.is-airy .evidence-grid {
  gap: 1.1rem;
  margin-bottom: 1.6rem;
}

.slide.is-airy .reframe {
  padding: 2rem 1.9rem;
}

.slide.is-airy .reframe .big {
  font-size: clamp(1.35rem, 2.5vw, 2rem);
}

.slide.is-airy .options {
  gap: 1.2rem;
}

.slide.is-airy .option {
  padding: 1.9rem 1.8rem;
}

.slide.is-airy .option h3 {
  font-size: 1.45rem;
  margin-bottom: 0.7rem;
}

.slide.is-airy .option p {
  font-size: 1.08rem;
  line-height: 1.55;
}

.slide.is-airy .pipe {
  padding: 1.1rem 1.2rem;
}

.slide.is-airy .pipe b {
  font-size: 1.06rem;
  margin-bottom: 0.3rem;
}

.slide.is-airy .pipe span {
  font-size: 0.92rem;
}

.slide.is-airy .tally .item {
  padding: 1.2rem 1.3rem;
}

.slide.is-airy .tally .figure {
  font-size: 1.4rem;
  margin-bottom: 0.35rem;
}

.slide.is-airy .tally p {
  font-size: 0.98rem;
  line-height: 1.45;
}

/* ================== slide 8 · two-column layout inside the anatomy */

/* Stacked, the artefact was tall enough that fitting it scaled the type down
   to about seven pixels — legible as shape, but on a compressed share that
   reads as a fault rather than a choice. Two columns roughly halve the height,
   so it renders at full size and still shows every section at once. */
.tpl-cols {
  display: grid;
  grid-template-columns: 1fr 1.05fr;
  gap: 0.9rem;
  align-items: start;
}

.tpl-col {
  display: flex;
  flex-direction: column;
  gap: 0.26rem;
  min-width: 0;
}

/* Padding and type alone did not close the gap — the blocks still sat in the
   top half. Give them the frame to fill, and let the cards stretch into it, so
   the composition is the full slide rather than a band across the top. */

.slide.is-airy .fact-list {
  min-height: calc(100svh - 21rem);
  align-content: space-evenly;
}

.slide.is-airy .evidence-grid {
  min-height: calc(100svh - 38rem);
  align-items: stretch;
}

.slide.is-airy .ev {
  display: flex;
  flex-direction: column;
  justify-content: center;
}

.slide.is-airy .options {
  min-height: calc(100svh - 24rem);
  align-items: stretch;
}

.slide.is-airy .option {
  display: flex;
  flex-direction: column;
  justify-content: center;
}

.slide.is-airy .pipeline {
  min-height: 8.5rem;
  align-items: stretch;
}

.slide.is-airy .pipe {
  display: flex;
  flex-direction: column;
  justify-content: center;
}

/* This used to be `min-height: calc(100svh - 36rem)`, hand-picked when the
   tally sat under a four-step pipeline and three captions. The pipeline came
   off the slide on 31 August and the constant did not follow: on a 1250px
   window it handed the four cards 602px to stretch into and they inflated
   into tall empty boxes. Bound the card instead of the frame — it grows with
   the window and stops, and whatever is left over is centred by the
   auto-margins like any other light slide. Do not put a viewport constant
   back here; it has to be re-tuned by hand every time the slide changes. */
.slide.is-airy .tally {
  align-items: stretch;
}

/* Top-anchored, not centred. The four bodies run one, two, two and three
   lines, so centring them in a shared min-height put each heading on a
   different line and the row read as ragged — the same fault as the page
   anatomy's centred layers, one slide along. Anchored to the top, the four
   headings sit on one line and the uneven bodies hang below them, which is
   where an uneven thing should go. */
.slide.is-airy .tally .item {
  display: flex;
  flex-direction: column;
  justify-content: flex-start;
  min-height: clamp(6.5rem, 21svh, 15rem);
}


/* On the bookends the second line is the promise and the third is the
   identity, not the other way round: the panel has had twenty minutes of
   interview and already knows the project name, so it sits under the line that
   says what the ten minutes will do. Sized and coloured to match. */
[data-deck] .slide.is-title:has(.brief) .title-sub {
  font-size: clamp(0.98rem, 1.35vw, 1.15rem);
  color: var(--color-card-foreground);
}

[data-deck] .slide.is-title:has(.brief) .title-by {
  font-size: 0.9rem;
  color: var(--color-muted-foreground);
}

/* ======================================== the brief · slides 1 and 7 */

/* The opening slide has three jobs: set expectations for what the panel is
   about to see, say why it is worth their ten minutes, and be the first piece
   of design work they see from me. It used to lead — at 2.6rem — with the
   project name, which is the one thing they already have from the interview,
   and it gave the loudest treatment on the slide to the confidentiality note,
   which is housekeeping. The order is now idea, identity, route map, the
   three acts, caveat — the agenda says what will be on screen, the cards say
   what the argument is, and they are deliberately weighted apart so the slide
   reads as one contents page rather than two.

   Slide 7 is the same component with the three answered, so the close mirrors
   the opening rather than restating it. Change one and change the other. */
.brief {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  gap: clamp(0.7rem, 1.3vw, 1.1rem);
}

@media (min-width: 52rem) {
  .brief {
    grid-template-columns: repeat(3, 1fr);
  }
}

/* Cards, because the deck already speaks in cards on the anatomy and outcome
   slides — the opening should look like it belongs to the same deck. The
   min-height takes a share of a tall window so the composition breathes
   instead of only the voids around it growing, and caps so it cannot turn
   into three empty boxes. */
.brief-item {
  display: flex;
  flex-direction: column;
  gap: 0.28rem;
  min-height: clamp(6rem, 15svh, 10.5rem);
  padding: clamp(0.85rem, 1.7svh, 1.45rem) clamp(1rem, 1.2vw, 1.35rem);
  border: 1px solid var(--color-border);
  border-radius: var(--radius);
  background: #fff;
  box-shadow: var(--elevation-1, 0 1px 3px rgba(0, 0, 0, 0.08));
}

/* The min-height above buys a share of a tall window so the composition
   breathes rather than the voids around it. The opening slide no longer has a
   window to share — the agenda took it — and at 162px the cards were holding
   32px of air each that pushed the standing note past the bottom of the frame.
   Where an agenda is present the cards size to their own content. Slide 7 has
   no agenda and still has the surplus, so it keeps the taller floor and the
   two slides still read as the same component. */
[data-deck] .slide:has(.agenda) .brief-item {
  min-height: clamp(5rem, 9svh, 8rem);
}

.brief-n {
  margin: 0;
  font-family: var(--font-mono);
  font-size: 0.72rem;
  font-weight: 500;
  letter-spacing: 0.1em;
  color: var(--color-primary);
}

.brief-h {
  margin: 0;
  font-family: var(--font-heading);
  font-size: clamp(1.05rem, 1.45vw, 1.3rem);
  font-weight: 700;
  letter-spacing: -0.01em;
  color: var(--color-card-foreground);
}

.brief-p {
  margin: 0.1rem 0 0;
  font-size: clamp(0.9rem, 1vw, 1rem);
  line-height: 1.42;
  color: var(--color-muted-foreground);
}

/* The agenda is a route map, not a second contents page. The three cards below
   carry the argument — problem, decision, handover — and this says what will
   actually be on screen and in what order, which is the thing a panel wants
   before they can settle. Different job, so it takes a deliberately quieter
   treatment: mono label, hairline rules, muted body, no card. If it competes
   with the cards for the eye it has failed, and the slide has two contents
   pages instead of one.

   No timings. A panel watching the clock is not watching the work, and a
   stated minute count is a promise the room can hold you to. */
.agenda {
  width: 100%;
  border-collapse: collapse;
  margin: 0 0 clamp(1.1rem, 2.6svh, 1.9rem);
  font-size: clamp(0.8rem, 0.92vw, 0.93rem);
  text-align: left;
}

/* The capped gap the light slides use for their content group is wrong here.
   It exists to hold a short block away from the masthead on a slide with
   surplus to spare; the agenda is orientation hanging off the byline above it
   on a slide that is now full.

   This margin is only half the gap — .caption-slot already carries
   --gap-masthead (1.75rem) as padding below the byline, and the two add up.
   At 3.2svh the total came to 66px against 17px below the table, so the
   agenda sat almost against the cards and a long way from the byline it
   belongs to. Nearly all of the separation the joint needs is already in
   --gap-masthead, so this adds a hair and the rest of the budget goes below
   the table instead: roughly 38 / 28 / 32 down the slide, which is even
   enough that no one gap reads as a mistake. */
[data-deck] .slide .caption-slot + .agenda {
  margin-top: clamp(0.2rem, 0.6svh, 0.5rem);
}

.agenda caption {
  caption-side: top;
  margin-bottom: 0.3rem;
  font-family: var(--font-mono);
  font-size: 0.68rem;
  font-weight: 500;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--color-muted-foreground);
  text-align: left;
}

.agenda tr {
  border-top: 1px solid var(--color-border);
}

.agenda tbody tr:last-child {
  border-bottom: 1px solid var(--color-border);
}

/* Five rows of padding is the single biggest lever on this slide's height —
   0.2rem either side of each row is 2rem of frame. Tuned against the tightest
   case rather than the roomiest: 2400x1200, where the card copy wraps longest. */
.agenda th,
.agenda td {
  padding: clamp(0.24rem, 0.45svh, 0.36rem) 0;
  vertical-align: baseline;
  line-height: 1.4;
}

/* The section name carries the row; the description is support. A ch measure
   rather than a percentage so the column tracks the words in it, not the
   window — at 82rem a percentage left the names on one line and a lake of
   white beside them. */
.agenda th {
  width: 1%;
  padding-right: clamp(1rem, 2.2vw, 2.25rem);
  white-space: nowrap;
  font-family: var(--font-heading);
  font-weight: 600;
  color: var(--color-card-foreground);
}

.agenda td {
  color: var(--color-muted-foreground);
}

/* Narrow windows cannot hold two columns and a nowrap name. Stack the pair
   and drop the rules to a single divider per row. */
@media (max-width: 52rem) {
  .agenda th {
    white-space: normal;
    padding-right: 0;
  }
}

/* The boundary is a caveat, not a headline. As a 2px cobalt box with semibold
   heading type it was the heaviest object on the opening slide — the first
   thing the eye landed on was the disclaimer. A hairline and quiet type says
   it just as clearly, and it is the first thing out of your mouth anyway. */
.brief-note {
  margin: 0;
  padding-top: clamp(0.7rem, 1.5svh, 1.1rem);
  border-top: 1px solid var(--color-border);
  font-size: 0.88rem;
  line-height: 1.45;
  color: var(--color-muted-foreground);
  max-width: 72ch;
}

.brief-note b {
  font-weight: 600;
  color: var(--color-primary);
}

/* ================================================ sub-step indicator */

/* Positioned into the masthead's meta band rather than flowed into it, so a
   slide with steps and a slide without occupy identical space. Top is the bar
   plus the slide's top padding; right is the gutter. */
.slide-steps {
  position: fixed;
  top: calc(var(--bar-h) + 1.9rem);
  right: var(--gutter);
  height: var(--band-meta);
  display: flex;
  align-items: center;
  gap: 0.32rem;
  z-index: 20;
  pointer-events: none;
}

.slide-steps[hidden] {
  display: none;
}

.slide-steps i {
  width: 1.35rem;
  height: 0.2rem;
  border-radius: 999px;
  background: var(--color-border);
  transition: background 0.25s ease;
}

.slide-steps i.is-done {
  background: var(--color-muted-foreground);
}

.slide-steps i.is-here {
  background: var(--color-primary);
}

@media (prefers-reduced-motion: reduce) {
  .slide-steps i {
    transition: none;
  }
}

/* ================================================== measure, applied */

.slide.is-airy .ev p,
.slide.is-airy .option p,
.slide.is-airy .pipe span,
.slide.is-airy .tally p {
  max-width: var(--measure-body);
}

.anno-list li {
  max-width: 46ch;
}

.provenance {
  max-width: var(--measure-caption);
}


/* ================================= slide 8 · the three-layer stack */

/* The slide moves between three artefacts: the handover map, the page anatomy
   with its notation, and the flows and new components behind it. They are
   superimposed in one grid cell rather than swapped with `display`, so the
   container is always as tall as the tallest layer and the masthead above it
   never moves. Same reason the stage gating in theme.css is opacity-only. */
.anat-layer {
  grid-area: 1 / 1;
  min-height: 0;
  display: flex;
  flex-direction: column;
  transition: opacity 0.35s ease;
}

[data-deck] .anat-layer > .anat-two,
[data-deck] .anat-layer > .hmap {
  flex: 1 1 0;
  min-height: 0;
}

/* The map is three short cards, not a full-height artefact, so it does not
   fill the shared cell. It used to be centred in what was left, which read as
   a composition on its own — but the three layers are seen in sequence, not
   side by side, and centring moved the top edge of the artefact 92px down
   between stage 1 and stage 2. Stepping through, that is a jump, and the
   whole point of the shared cell is that nothing jumps.

   Top-anchored, every layer starts its artefact on the same line and the
   surplus falls beneath it — the same rule the light slides follow. */
[data-deck] .anat-layer > .hmap {
  align-content: start;
}

/* from-N is "appears at N and stays". A layer needs a window instead, so it
   is written out rather than borrowed. */
.reveal[data-stage="2"] .lay-1,
.reveal[data-stage="3"] .lay-1,
.reveal[data-stage="4"] .lay-1,
.reveal[data-stage="5"] .lay-1,
.reveal[data-stage="1"] .lay-2,
.reveal[data-stage="4"] .lay-2,
.reveal[data-stage="5"] .lay-2,
.reveal[data-stage="1"] .lay-3,
.reveal[data-stage="2"] .lay-3,
.reveal[data-stage="3"] .lay-3 {
  opacity: 0;
  pointer-events: none;
}

/* Handout: no JS, so data-stage stays "all". Superimposed layers would be one
   illegible smear — they stack and the page scrolls, as it does everywhere
   else in the handout. */
.reveal[data-stage="all"] .anat-stack {
  display: block;
}

.reveal[data-stage="all"] .anat-layer + .anat-layer {
  margin-top: 1.6rem;
}


/* ------------------------------------------- layer 1 · the handover map */

/* Not a picture of the Figma canvas — a manifest. Each zone is labelled by
   the job it does, because the panel cares what a developer received, not
   how the file was arranged. That argument is slide 7's. */
.hmap {
  display: grid;
  gap: 1.1rem;
  align-items: stretch;
}

@media (min-width: 62rem) {
  .hmap {
    grid-template-columns: repeat(3, 1fr);
  }
}

.hz {
  display: flex;
  flex-direction: column;
  border: 1px solid var(--color-border);
  border-radius: var(--radius);
  background: #fff;
  padding: 0.9rem 1rem 1rem;
  box-shadow: var(--elevation-1, 0 1px 3px rgba(0, 0, 0, 0.08));
}

.hz-h {
  margin: 0;
  font-family: var(--font-heading);
  font-size: 1rem;
  font-weight: 700;
  color: var(--color-card-foreground);
}

.hz-j {
  margin: 0.1rem 0 0;
  font-family: var(--font-mono);
  font-size: 0.62rem;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--color-primary);
}

/* The sketch claims the free space, so the three zones stay the same height
   however long their notes run. */
.hz-art {
  flex: 1 1 auto;
  display: flex;
  align-items: center;
  padding: 1rem 0 0.9rem;
}

.hz-n {
  margin: 0;
  font-size: 0.78rem;
  line-height: 1.4;
  color: var(--color-muted-foreground);
}

.mini {
  width: 100%;
}

/* Deliberately unreadable. The zone is an inventory of what handover
   contained; the counts carry the volume and nothing invites reading. */
.mini-bar {
  flex: 1;
  height: 0.62rem;
  border-radius: 3px;
  background: var(--nobel-100, #ececec);
  border: 1px solid var(--nobel-200, #d6d8da);
}

.mini-bar.is-title { height: 0.95rem; }
.mini-bar.w-85 { max-width: 85%; }
.mini-bar.w-75 { max-width: 75%; }
.mini-bar.w-60 { max-width: 60%; }

.mini-page {
  display: grid;
  gap: 0.5rem;
}

.mini-row {
  display: flex;
  align-items: center;
  gap: 0.5rem;
}

.mini-pin {
  flex: none;
  display: grid;
  place-items: center;
  width: 1.05rem;
  height: 1.05rem;
  border-radius: 999px;
  background: var(--color-primary);
  color: #fff;
  font-family: var(--font-mono);
  font-size: 0.58rem;
  font-weight: 600;
}

.mini-flow {
  display: grid;
  gap: 0.45rem;
}

.mini-frow {
  display: flex;
  align-items: center;
  gap: 0.3rem;
}

.mini-frow .scr {
  flex: 1;
  height: 1.75rem;
  border-radius: 3px;
  background: var(--nobel-100, #ececec);
  border: 1px solid var(--nobel-200, #d6d8da);
}

.arw {
  flex: none;
  position: relative;
  width: 0.55rem;
  height: 1px;
  background: var(--color-border);
}

.arw::after {
  content: "";
  position: absolute;
  right: 0;
  top: -2px;
  border-left: 4px solid var(--color-border);
  border-top: 2.5px solid transparent;
  border-bottom: 2.5px solid transparent;
}

.mini-assets {
  display: grid;
  grid-template-columns: repeat(5, 1fr);
  gap: 0.35rem;
}

.mini-assets i {
  height: 1.3rem;
  border-radius: 3px;
  background: var(--nobel-100, #ececec);
  border: 1px solid var(--nobel-200, #d6d8da);
}

.mini-assets i.is-new,
.chipgrid i.is-new {
  background: #eef4fa;
  border-color: var(--color-primary);
}


/* -------------------------------- layer 2 · the anatomy, at low fidelity */

/* The section headings stay; the content goes. The panel needs to see that
   four alert states sit on one frame — it does not need to read four invented
   alert messages while you are talking over them. */
.sk-bar {
  display: block;
  height: 0.5rem;
  border-radius: 3px;
  background: var(--nobel-100, #ececec);
  border: 1px solid var(--nobel-200, #d6d8da);
}

.sk-crumb {
  width: 38%;
  height: 0.4rem;
  margin-bottom: 0.1rem;
}

.sk-steps {
  display: flex;
  gap: 0.9rem;
  padding: 0.3rem 0 0.5rem;
  border-bottom: 1px solid var(--color-border);
}

.sk-steps i {
  position: relative;
  width: 2.6rem;
  height: 0.4rem;
  margin-left: 0.65rem;
  border-radius: 3px;
  background: var(--nobel-100, #ececec);
  border: 1px solid var(--nobel-200, #d6d8da);
}

.sk-steps i::before {
  content: "";
  position: absolute;
  left: -0.65rem;
  top: 50%;
  transform: translateY(-50%);
  width: 0.42rem;
  height: 0.42rem;
  border-radius: 999px;
  border: 1.5px solid var(--color-border);
  background: #fff;
}

.sk-steps .is-done::before { background: var(--color-primary); border-color: var(--color-primary); }
.sk-steps .is-here::before { border-color: var(--color-primary); border-width: 2.5px; }

/* Each alert keeps its colour on the left edge only. That is enough to read
   "four states, all of them here" from a compressed share, without putting
   four sentences on screen for the panel to read instead of listening. */
.sk-alerts {
  display: grid;
  gap: 0.3rem;
  margin-bottom: 0.55rem;
}

.sk-al {
  display: block;
  height: 1.35rem;
  border: 1px solid;
  border-left-width: 4px;
  border-radius: 4px;
}

.sk-al.w-90 { width: 90%; }
.sk-al.w-80 { width: 80%; }
.sk-al.w-70 { width: 70%; }

.sk-al.is-err  { border-color: #e4b7b3; background: #fbeceb; border-left-color: var(--color-cost, #a8342a); }
.sk-al.is-warn { border-color: #e6cf9e; background: #fdf6e6; border-left-color: #b07d1a; }
.sk-al.is-ok   { border-color: #a9d3b6; background: #edf7f0; border-left-color: #2f7d4f; }
.sk-al.is-info { border-color: #a9c6dd; background: #eef4fa; border-left-color: #2a6496; }

.sk-fields {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 0.4rem 0.5rem;
  margin-bottom: 0.5rem;
}

.sk-fld i {
  display: block;
  width: 45%;
  height: 0.32rem;
  margin-bottom: 0.22rem;
  border-radius: 2px;
  background: var(--nobel-200, #d6d8da);
}

.sk-fld span {
  display: block;
  height: 1.15rem;
  border: 1px solid var(--color-border);
  border-radius: 4px;
  background: #fff;
}

.sk-fld.is-err span {
  border-color: var(--color-cost, #a8342a);
  box-shadow: 0 0 0 2px #fbeceb;
}

.sk-table {
  display: grid;
  gap: 0.22rem;
}

.sk-th {
  display: block;
  height: 0.85rem;
  border-radius: 3px;
  background: var(--color-lane, #f4f5f6);
  border: 1px solid var(--color-border);
}

.sk-tr {
  display: block;
  height: 0.8rem;
  border-bottom: 1px solid var(--color-border);
}

.sk-pager {
  display: flex;
  gap: 0.22rem;
  padding-top: 0.4rem;
}

.sk-pager span {
  width: 0.85rem;
  height: 0.85rem;
  border: 1px solid var(--color-border);
  border-radius: 3px;
  background: #fff;
}

.sk-pager span:first-child {
  background: var(--color-primary);
  border-color: var(--color-primary);
}

.sk-btn {
  width: 3.2rem;
  height: 1.1rem;
  border-radius: 999px;
  border: 1.5px solid var(--color-primary);
  background: #fff;
}

.sk-btn.is-p { background: var(--color-primary); }

.sk-btn.is-ghost {
  margin-right: auto;
  border-color: transparent;
  background: var(--nobel-100, #ececec);
}


/* ------------------ layer 3 · the flows, and the components that were new */

/* Layer 2 is the tallest, so it sets the height of the shared cell and these
   two panels do not fill it. They were centred in the surplus, which read as
   a composition on a still frame but put the top of the flows panel 100px
   below the top of the anatomy frame that precedes it — a visible drop on the
   step from stage 3 to stage 4, on a slide whose whole construction exists to
   stop things moving.

   Top-anchored, all three layers start on the same line. The frame still owns
   the height, so data-fit can shrink it on a short window. */
.sup-frame {
  align-items: flex-start;
}

.sup {
  width: 100%;
  flex: none;
  max-width: none;
  align-self: flex-start;
  transform-origin: top center;
  border: 1px solid var(--color-border);
  border-radius: var(--radius);
  background: #fff;
  padding: 0.85rem 0.9rem 0.9rem;
  box-shadow: var(--elevation-1, 0 1px 3px rgba(0, 0, 0, 0.08));
}

.sup-n {
  margin: 0.7rem 0 0;
  font-size: 0.76rem;
  line-height: 1.4;
  color: var(--color-muted-foreground);
}

.sup-h2 {
  margin-top: 1rem;
}

.flowstrip {
  display: grid;
  gap: 0.5rem;
  padding-top: 0.15rem;
}

.frow {
  display: flex;
  align-items: stretch;
  gap: 0.3rem;
}

.frow .arw {
  align-self: center;
}

/* A flow screen is a silhouette plus a state tag. The tag is the only part
   carrying information — it is what separates a flow from a row of
   screenshots, and it is the reason the strip earns its step. */
.fscr {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 0.22rem;
  border: 1px solid var(--color-border);
  border-radius: 4px;
  background: #fff;
  padding: 0.3rem 0.32rem 0.35rem;
}

.fs-hd {
  height: 0.42rem;
  border-radius: 2px;
  background: var(--nobel-200, #d6d8da);
}

.fs-b {
  height: 0.34rem;
  border-radius: 2px;
  background: var(--nobel-100, #ececec);
}

.fs-b.w-85 { width: 85%; }
.fs-b.w-75 { width: 75%; }
.fs-b.w-70 { width: 70%; }
.fs-b.w-60 { width: 60%; }

.fs-tag {
  align-self: flex-start;
  margin-top: 0.12rem;
  padding: 0.04rem 0.3rem;
  border-radius: 999px;
  border: 1px solid #a9c6dd;
  background: #eef4fa;
  font-family: var(--font-mono);
  font-size: 0.5rem;
  font-weight: 500;
  letter-spacing: 0.03em;
  color: var(--color-primary);
}

.fs-tag.is-err  { color: var(--color-cost-fg, #8a281f); background: #fbeceb; border-color: #e4b7b3; }
.fs-tag.is-warn { color: #7d5810; background: #fdf6e6; border-color: #e6cf9e; }
.fs-tag.is-ok   { color: #1f5a37; background: #edf7f0; border-color: #a9d3b6; }

.chipgrid {
  display: grid;
  grid-template-columns: repeat(7, 1fr);
  gap: 0.3rem;
  padding-top: 0.15rem;
}

.chipgrid i {
  height: 1.2rem;
  border-radius: 3px;
  background: var(--nobel-100, #ececec);
  border: 1px solid var(--nobel-200, #d6d8da);
}

.sup-legend {
  display: flex;
  align-items: center;
  gap: 0.4rem;
  margin: 0.5rem 0 0;
  font-size: 0.74rem;
  color: var(--color-muted-foreground);
}

/* The swatch has to match a chip exactly, or the legend is not a legend. */
.sup-legend i {
  flex: none;
  width: 1rem;
  height: 0.75rem;
  border-radius: 3px;
  border: 1px solid var(--color-primary);
  background: #eef4fa;
}
