/* The citizen-facing pages - landing, disclaimer, tour, intake, glass pipeline
   - on top of system.css. Page-specific leftovers, plus the one animated thing
   in this project.

   The reflow rules live in the design system and apply to every page. What is
   here is what only a citizen page has: the hero, the persona grid, the tour's
   step layout, the placeholder token, the before/after panels.

   THE HERO, IN ONE PARAGRAPH. Five stages are drawn once and stay drawn; a
   highlight ring and a sealed envelope walk along them on a 16 second loop,
   and the five captions in the document fade with the SAME keyframes at the
   same offsets, so the sentence a visitor reads always belongs to the stage
   that is lit. One keyframe set does all of it: the stagger is five negative
   `animation-delay` values, which is why the timing of the picture and the
   timing of the text cannot drift apart. Every animated property is `opacity`
   or `transform`. There is no JavaScript on this page and no request to
   anywhere.

   WHAT PART 18 CHANGED ABOUT THE HERO, AND WHAT IT DID NOT TOUCH. It is the
   flagship of the site and it looked like a diagram in a white box: same
   elevation as every card under it, 0.95rem stage names, a grey caption strip
   with a coloured edge. It is now a panel of its own - a tinted gradient
   surface, its own elevation, larger discs, heavier stage names, and a caption
   block that reads as a caption rather than as a note. NONE of the mechanics
   moved. The 16 second period, the five negative delays, the `hero-travel`
   geometry in 192 user-unit steps, the sibling-combinator pause control and
   the reduced-motion still frame are the part-17 versions character for
   character, because they were only just corrected and every one of them is
   pinned by a test that reads this file. */

/* ----------------------------------------------------------------- shared */

/* `.lead` MOVED TO system.css IN PART 21, found the same way the `.cta` move
   below was found: auditing every component on the two new grounds. `/metrics`
   and `/inbox` both open with `<p class="lead">` and neither of them loads this
   file, so on both of those pages the class resolved to nothing at all.

   IT DID NOT LOOK WRONG, AND THAT IS THE WHOLE REASON TO MOVE IT. Both of those
   paragraphs sit inside `.page-head`, and `.page-head > p` in the design system
   already sets the same size and the same ink - so those two pages rendered
   correctly by coincidence of WHERE the paragraph sits rather than because the
   class they ask for exists. Move that `<p>` out of the page head, or add a
   second lead further down either page, and the sentence silently becomes body
   text. `.cta` below was this same omission with a visible consequence, which
   is why it was found in part 17 by looking; this is the same omission with no
   visible consequence, which is why it took an audit. A component five
   templates ask for belongs in the one file every page loads.

   `.cta` MOVED TO system.css IN PART 17. It was defined here and used by
   `metrics.html`, which loads system.css and metrics.css and never loaded this
   file - so the metrics reload control asked for a class that did not exist on
   its page and rendered as a bare inline link with no background, no border
   and no padding. A control that does not look like one is most of the reason
   it read as dead. It is a design-system component and now lives there. */

/* ------------------------------------------------------------- the hero */

.hero {
  margin-top: var(--space-5);
}

/* THE ONE PIECE OF DISPLAY TYPE IN THE PROJECT. The landing headline is the
   page's voice; everywhere else the type ramp is a reading ramp. Fluid between
   2.125rem and 3.75rem, tracked in as it grows, and `text-wrap: balance` so a
   three-word last line never happens. Its `rem` term is what keeps a reader's
   own font size in the expression (1.4.4).

   SCOPED BY A CLASS, ON PURPOSE. `demo.css` is loaded by five pages and a rule
   on `.page-head > h1` would have given the tour, the intake form, the
   pipeline and the disclaimer page a 3.75rem headline too - four pages whose
   title is a label rather than a statement. `demo_base.html` exposes
   `page_head_class` and only `landing.html` fills it. */
.page-head-hero > h1 {
  font-size: var(--text-hero);
  letter-spacing: -0.03em;
  line-height: 1.04;
  max-width: 22ch;
  /* PART 23, AND THE HEADLINE IS WHY. "Statusfeststellungsverfahren" is
     twenty-seven characters and at 390 px it is wider than the column, so
     `overflow-wrap: break-word` on `body` did what it is there to do and split
     it mid-syllable with no hyphen - which reads as a rendering fault on the
     first line a visitor sees. The document declares its language, so the
     engine can break the compound where German breaks it and set the hyphen
     itself. Where an engine has no dictionary this changes nothing and the
     old behaviour is still the fallback. */
  hyphens: auto;
}

.hero-lead {
  font-size: var(--text-lg);
  line-height: 1.55;
  color: var(--ink-soft);
  max-width: 62ch;
}

.hero-actions {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-3);
  margin-bottom: var(--space-5);
  max-width: none;
}

.hero-actions .cta {
  margin: 0;
}

/* The panel. Its own surface, its own elevation and a hairline of brand along
   the top - the same accent the header and the closing band carry, so the
   three pieces of furniture on the page are visibly one family. */
.hero-figure {
  position: relative;
  margin: var(--space-6) 0 0;
  padding: var(--space-6) var(--space-5) var(--space-5);
  background-color: var(--surface);
  background-image: var(--grad-panel);
  border: 1px solid var(--line);
  border-radius: var(--radius-xl);
  box-shadow: var(--shadow-md);
  text-align: right;
}

.hero-figure::before {
  content: "";
  position: absolute;
  inset: 0 0 auto 0;
  height: 3px;
  border-radius: var(--radius-xl) var(--radius-xl) 0 0;
  background: var(--grad-rule);
}

.hero-svg {
  display: block;
  width: 100%;
  height: auto;
  max-width: 66rem;
  margin: 0 auto;
}

/* The drawing. `rem` font sizes inside an SVG viewBox resolve to user units,
   so the labels scale with the picture AND with the reader's root size. */
.hero-rail {
  fill: none;
  stroke: var(--line-strong);
  stroke-width: 2;
  stroke-linecap: round;
  stroke-dasharray: 2 10;
}

.hero-disc {
  fill: var(--surface);
  stroke: var(--line-strong);
  stroke-width: 2;
}

.hero-glyph {
  fill: none;
  stroke: var(--ink-soft);
  stroke-width: 2;
  stroke-linecap: round;
  stroke-linejoin: round;
}

.hero-name {
  fill: var(--ink);
  font-family: var(--font-sans);
  font-size: 1.05rem;
  font-weight: 650;
  letter-spacing: -0.01em;
  text-anchor: middle;
}

/* The ring that marks the stage the captions are talking about. */
.hero-ring {
  fill: none;
  stroke: var(--brand);
  stroke-width: 5;
  opacity: 0;
  animation: hero-beat 16s linear infinite;
}

/* THE DELAY RULE, WRITTEN DOWN BECAUSE IT READS BACKWARDS. Stage N lights
   during the Nth fifth of the loop. A negative delay ADVANCES the clock rather
   than postponing it, so the later a stage lights, the SMALLER its delay:
   stage N needs -(16 - (N-1) * 3.2)s. Getting this the intuitive way round
   walks the ring 1, 5, 4, 3, 2 while the envelope walks 1, 2, 3, 4, 5, which
   is what shipped in part 16 and what the browser pass caught. The same four
   values apply to `.hero-caption-N`, and the two lists have to agree. */
.hero-stage-2 .hero-ring {
  animation-delay: -12.8s;
}

.hero-stage-3 .hero-ring {
  animation-delay: -9.6s;
}

.hero-stage-4 .hero-ring {
  animation-delay: -6.4s;
}

.hero-stage-5 .hero-ring {
  animation-delay: -3.2s;
}

/* The case itself, travelling the rail. It gains its seal after stage 2, which
   is the one thing in the loop that is a statement rather than decoration. */
.hero-token {
  animation: hero-travel 16s linear infinite;
}

.hero-token-body,
.hero-token-flap {
  fill: var(--surface);
  stroke: var(--brand-ink);
  stroke-width: 2;
  stroke-linejoin: round;
}

.hero-token-flap {
  fill: none;
}

.hero-token-seal {
  fill: none;
  stroke: var(--brand-ink);
  stroke-width: 2;
  opacity: 0;
  animation: hero-seal 16s linear infinite;
}

/* The padlock at stage 2, closing when the ring gets there: the delay rule
   above, for stage 2, so this value and `.hero-stage-2 .hero-ring` move
   together or the lock clicks shut in front of an empty stage. */
.hero-shackle {
  animation: hero-close 16s linear infinite;
  animation-delay: -12.8s;
}

.hero-gear {
  transform-box: fill-box;
  transform-origin: center;
  animation: hero-spin 16s linear infinite;
}

/* The captions: five paragraphs stacked in ONE grid cell, so the block is as
   tall as the tallest of them and nothing jumps when they swap. */
.hero-captions {
  display: grid;
  margin: var(--space-5) 0 0;
  padding: var(--space-4) var(--space-5);
  border: 1px solid var(--line);
  background: var(--surface);
  border-radius: var(--radius);
  box-shadow: var(--shadow-sm);
  text-align: left;
}

.hero-caption {
  grid-area: 1 / 1;
  margin: 0;
  color: var(--ink);
  font-size: var(--text-md);
  opacity: 0;
  animation: hero-beat 16s linear infinite;
}

/* The stage prefix as a chip rather than as bold text: it is a label on the
   sentence, and it is the one place a reader checks which stage they are
   looking at. */
.hero-caption-stage {
  display: inline-block;
  margin-right: var(--space-2);
  padding: 0.05em 0.6em;
  border: 1px solid var(--brand-ink);
  border-radius: var(--radius-pill);
  background: var(--tint-brand);
  color: var(--brand-ink-strong);
  font-size: var(--text-sm);
  font-weight: 700;
  white-space: nowrap;
}

/* The same four values as the rings above, for the same reason. */
.hero-caption-2 {
  animation-delay: -12.8s;
}

.hero-caption-3 {
  animation-delay: -9.6s;
}

.hero-caption-4 {
  animation-delay: -6.4s;
}

.hero-caption-5 {
  animation-delay: -3.2s;
}

/* One keyframe set, five delays. A stage is lit for a fifth of the loop with a
   short fade at each end. */
@keyframes hero-beat {
  0% {
    opacity: 0;
  }

  2% {
    opacity: 1;
  }

  18% {
    opacity: 1;
  }

  20% {
    opacity: 0;
  }

  100% {
    opacity: 0;
  }
}

@keyframes hero-travel {
  0% {
    opacity: 0;
    transform: translateX(0);
  }

  2% {
    opacity: 1;
    transform: translateX(0);
  }

  16% {
    opacity: 1;
    transform: translateX(0);
  }

  20% {
    transform: translateX(192px);
  }

  36% {
    transform: translateX(192px);
  }

  40% {
    transform: translateX(384px);
  }

  56% {
    transform: translateX(384px);
  }

  60% {
    transform: translateX(576px);
  }

  76% {
    transform: translateX(576px);
  }

  80% {
    opacity: 1;
    transform: translateX(768px);
  }

  94% {
    opacity: 1;
    transform: translateX(768px);
  }

  99% {
    opacity: 0;
    transform: translateX(768px);
  }

  100% {
    opacity: 0;
    transform: translateX(768px);
  }
}

/* The seal appears AT the sealing stage, not on the way to it. The envelope
   lands on stage 2 at 20 percent (`hero-travel`), so that is where this starts:
   arrival, then the padlock, then the seal. It rides the true clock with no
   delay, which is why the part-16 inversion never reached it. */
@keyframes hero-seal {
  0% {
    opacity: 0;
  }

  20% {
    opacity: 0;
  }

  26% {
    opacity: 1;
  }

  100% {
    opacity: 1;
  }
}

@keyframes hero-close {
  0% {
    transform: translateY(-0.22rem);
  }

  2% {
    transform: translateY(-0.22rem);
  }

  7% {
    transform: translateY(0);
  }

  100% {
    transform: translateY(0);
  }
}

@keyframes hero-spin {
  0% {
    transform: rotate(0deg);
  }

  100% {
    transform: rotate(360deg);
  }
}

/* The pause control (WCAG 2.2.2). The loop starts on its own, runs longer than
   five seconds and sits beside other content, so a reader must be able to stop
   it - and an operating-system preference is not a control on this page.

   THE CHECKBOX IS A DIRECT CHILD OF `.hero-figure`, WHICH IS THE WHOLE
   MECHANISM. `~` is the general SIBLING combinator: it reaches later siblings
   of the checkbox and nothing else. Part 16 nested the checkbox in a row
   `<div>` beside its label, which made it a COUSIN of `.hero-svg` and
   `.hero-captions` - every rule below matched nothing, the control was dead in
   every browser, and the test asserting that the stylesheet CONTAINED these
   rules stayed green throughout. The input and its label are laid out as one
   line rather than wrapped in a box, so nothing can come between the checkbox
   and the things it pauses again.

   PART 18 MADE IT LOOK LIKE A CONTROL AND CHANGED NO PART OF THE STRUCTURE.
   The figure is `text-align: right`, which puts the pair in the panel's top
   corner where a media control belongs, and the label carries the chip while a
   negative left margin pulls it back over the checkbox so the two read as one
   object. The checkbox stays a real checkbox, stays the FIRST child, stays
   before both of the things it pauses, and stays operable and labelled.

   It STOPS rather than freezing. `animation-play-state: paused` would hold
   whatever frame happened to be showing, which for four of the five captions
   is `opacity: 0` - a pause button that hides the text is not a pause button.
   So the paused state is the same still frame the reduced-motion answer
   produces: every stage lit, all five captions stacked and readable. */
.hero-pause {
  position: relative;
  z-index: 1;
  width: 1rem;
  height: 1rem;
  margin: 0;
  accent-color: var(--brand-ink);
  vertical-align: -0.16em;
}

/* Inline-block so its bottom margin counts towards the line box, which is what
   separates the control from the drawing without a wrapper. */
.hero-pause-label {
  display: inline-block;
  margin: 0 0 var(--space-4) calc(-1 * var(--space-5));
  padding: var(--space-1) var(--space-4) var(--space-1) var(--space-6);
  border: 1px solid var(--line-strong);
  border-radius: var(--radius-pill);
  background: var(--surface);
  color: var(--ink-soft);
  font-size: var(--text-sm);
  font-weight: 650;
  cursor: pointer;
  transition: border-color var(--tempo) var(--ease),
    background-color var(--tempo) var(--ease);
}

.hero-pause-label:hover {
  border-color: var(--brand-ink);
  background: var(--tint-brand);
}

/* The input keeps the design system's focus ring; the label repeats the state
   in the one place a reader is already looking. */
.hero-pause:focus-visible + .hero-pause-label {
  color: var(--brand-ink-strong);
  border-color: var(--brand-ink);
  text-decoration: underline;
}

.hero-pause:checked ~ .hero-svg .hero-ring,
.hero-pause:checked ~ .hero-svg .hero-token,
.hero-pause:checked ~ .hero-svg .hero-token-seal,
.hero-pause:checked ~ .hero-svg .hero-shackle,
.hero-pause:checked ~ .hero-svg .hero-gear,
.hero-pause:checked ~ .hero-captions .hero-caption {
  animation: none;
}

.hero-pause:checked ~ .hero-svg .hero-ring,
.hero-pause:checked ~ .hero-svg .hero-token-seal,
.hero-pause:checked ~ .hero-captions .hero-caption {
  opacity: 1;
}

.hero-pause:checked ~ .hero-captions {
  display: block;
}

.hero-pause:checked ~ .hero-captions .hero-caption {
  margin-bottom: var(--space-3);
}

.hero-pause:checked ~ .hero-captions .hero-caption:last-child {
  margin-bottom: 0;
}

/* Somebody who asked for less motion gets the same still frame without having
   to ask again. Answered HERE rather than left to the design system's blanket
   rule, because that rule freezes an animation at its last keyframe - which
   for these captions is `opacity: 0`. */
@media (prefers-reduced-motion: reduce) {
  .hero-ring,
  .hero-token,
  .hero-token-seal,
  .hero-shackle,
  .hero-gear,
  .hero-caption {
    animation: none;
  }

  .hero-ring,
  .hero-token-seal,
  .hero-caption {
    opacity: 1;
  }

  .hero-captions {
    display: block;
  }

  .hero-caption {
    margin-bottom: var(--space-3);
  }

  .hero-caption:last-child {
    margin-bottom: 0;
  }

  /* The control stays on the page rather than being hidden with the motion.
     It is the same still frame either way, so unchecking it here changes
     nothing - but a control that vanishes when a preference is set reads as a
     control this page took away, and it is also the only thing on the page
     that explains what the still frame IS. */
  .hero-pause,
  .hero-pause-label {
    display: inline-block;
  }
}

/* ---------------------------------------------------------- the tour page */

.tour-toc {
  margin-bottom: var(--space-5);
}

/* The step marker: a numbered chip in front of the heading. The number is
   decorative repetition - the heading text says which step it is, and the
   steps are an ordered list of sections in source order. */
.step-mark {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 2.4rem;
  height: 2.4rem;
  margin-right: var(--space-3);
  border: 0;
  border-radius: var(--radius-pill);
  background: var(--grad-cta);
  color: var(--cta-ink);
  font-size: var(--text-md);
  font-weight: 700;
  box-shadow: var(--shadow-sm);
}

/* A tour step already carries a numbered chip in front of its heading, so it
   does not ALSO take the design system's accent tick and heading rule. Two
   markers on one heading is one too many - and in the two-column layout above
   64rem the rule would underline the left column rather than the section, so
   it would be drawing the wrong thing as well as a second one. */
.step > h2 {
  border-bottom: 0;
  padding-bottom: 0;
}

.step > h2::before {
  content: none;
}

/* The list of what to look at inside a step. */
.watch-for {
  list-style: none;
  margin: 0 0 var(--space-4);
  padding: 0;
}

.watch-for > li {
  margin-bottom: var(--space-3);
  padding: var(--space-1) 0 var(--space-1) var(--space-4);
  border-left: 3px solid var(--brand);
}

/* ------------------------------------------------------------ intake page */

.tabs {
  margin: var(--space-4) 0;
}

.tab-current {
  border-color: var(--brand-ink);
  background: var(--tint-brand);
  color: var(--brand-ink-strong);
}

.persona-list {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: var(--space-4);
  list-style: none;
  margin: 0 0 var(--space-4);
  padding: 0;
}

/* A PERSONA IS A CARD, AND THE FOUR OF THEM ARE ONE ROW. They hold text of
   wildly different lengths - one is three sentences, one is twelve - so the
   heading is pinned to the top and the body is allowed to be as long as it is,
   with every card ending on the same line. */
.persona {
  display: flex;
  flex-direction: column;
  margin: 0;
  max-width: none;
  padding: var(--space-5);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: var(--surface);
  box-shadow: var(--shadow-sm);
  font-size: var(--text-sm);
  transition: border-color var(--tempo) var(--ease),
    box-shadow var(--tempo) var(--ease), transform var(--tempo) var(--ease);
}

.persona:hover {
  border-color: var(--brand);
  box-shadow: var(--shadow-md);
  transform: translateY(-2px);
}

.persona:focus-within {
  border-color: var(--brand);
  box-shadow: var(--shadow-md);
}

.persona h3 {
  margin-top: 0;
  font-size: var(--text-md);
}

.persona h3 a {
  text-decoration: none;
}

.persona h3 a:hover {
  text-decoration: underline;
}

.persona > *:last-child {
  margin-bottom: 0;
}

/* The chosen persona is named "gewaehlt" in a tag inside its own heading; the
   brand edge repeats that and carries nothing on its own. */
.persona-current {
  border-color: var(--brand-ink);
  background-color: var(--tint-brand-soft);
  box-shadow: var(--shadow-md);
}

.hints dt {
  margin-top: var(--space-2);
}

/* ---------------------------------------------------------- pipeline page */

/* One of the seven stages. The rule above the heading is what makes the page
   read as a sequence rather than as a wall. */
.stage > h2 {
  padding-top: var(--space-1);
  margin-bottom: var(--space-5);
}

/* A placeholder token is monospaced and boxed so it reads as a MACHINE token
   rather than as text somebody wrote. `mark` keeps its own semantics; the
   border is what survives a monochrome display, and the colour is what makes
   the seal POP on the machine ground - `--code-seal` is the page's own ink
   everywhere else, so a placeholder that ever renders on a light page looks
   exactly as it always has. */
.placeholder {
  border: 1px solid var(--line-strong);
  border-radius: var(--radius-sm);
  background: var(--surface-sunken);
  color: var(--code-seal);
  padding: 0 var(--space-1);
  font-family: var(--font-mono);
  font-size: 0.9em;
  word-break: break-all;
}

/* THE WORKING COPY IS CODE AND IS PAINTED AS CODE (part 23).

   Three classes, written by `api/demo.py::segments` around runs it identified
   server-side - no script, no highlighting library, no second parse of the
   page after it loaded. They appear on the STRUCTURED dumps only, which is the
   `antragsteller.name = [[PII|NAME|...]]` block: a key, the separator, and
   what the machine actually holds. The free-text parts beside them are a
   person's own words with the identity values sealed out, so they get the seal
   and nothing else, and the Anhoerung letter further down the page is a
   document and gets neither.

   Each token resolves to the page's own ink on the citizen and caseworker
   grounds. This is a machine-ground treatment, held in tokens rather than in a
   selector that names a ground, so it follows the design system's one rule. */
.tok-key {
  color: var(--code-key);
}

.tok-punct {
  color: var(--code-punct);
}

.tok-value {
  color: var(--code-value);
}

.side-by-side {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: var(--space-4);
  margin-bottom: var(--space-4);
}

.side-by-side h4 {
  margin-top: 0;
  margin-bottom: var(--space-2);
}

/* --------------------------------------- the simulated letter (part 19) */

/* THE ANHOERUNG, AS THE DOCUMENT IT IS. The flowchart this part implements drew
   a popup; this is a letter instead, and it has to LOOK like one or the
   distinction is only in the source. A sheet with generous margins, the body
   face rather than the monospaced one (`pre` is for machine text - a working
   copy, a message body - and this is a letter a person would have read), and a
   left rule that marks it as an enclosure rather than as page prose.

   Every colour is a token, so the sheet follows whichever ground it lands on:
   the citizen canvas on `/demo/gegenpartei`, the deep blue-slate of the machine
   phase on `/demo/case/{id}/pipeline`. Nothing here declares a colour of its
   own, which is what keeps the contrast floors computed from `system.css` true
   of it (tests/test_review_accessibility.py).

   `pre-line` rather than `<br>`: the letter arrives as paragraphs from
   `engine/demo/gegenpartei.py` and two of them carry their own line breaks (the
   reference block, the sign-off). Whitespace is the only thing that has to
   survive, and a template that injected markup into text a visitor's own
   company name is interpolated into would be the wrong place to start. */
.letter {
  margin: 0 0 var(--space-5);
  padding: var(--space-6) var(--space-6) var(--space-5);
  border: 1px solid var(--line);
  border-left: 4px solid var(--line-strong);
  border-radius: var(--radius);
  background: var(--surface-alt);
  box-shadow: var(--shadow-sm);
}

.letter > p {
  margin: 0 0 var(--space-4);
  white-space: pre-line;
}

.letter > p:first-child {
  font-weight: 650;
  margin-bottom: var(--space-1);
}

/* The subject line sits directly under the sender and belongs with it. */
.letter > p:nth-child(2) {
  font-weight: 600;
}

.letter > p:last-child {
  margin-bottom: 0;
}

@media (max-width: 40rem) {
  .letter {
    padding: var(--space-4);
  }
}

/* The hand-off between two phases. Deliberately the loudest thing on its
   page: a visitor who loses the thread here loses the tour. */
.handover {
  margin: var(--space-5) 0;
  padding: var(--space-5);
  border: 1px solid var(--brand-ink);
  border-left: 5px solid var(--brand-ink);
  border-radius: var(--radius);
  background: var(--tint-brand);
  box-shadow: var(--shadow-sm);
  font-size: var(--text-md);
  font-weight: 600;
}

/* The queue row a visitor was handed to. Display only: the marker is the words
   "Ihr Vorgang" in the row itself, and this only repeats them. */
tbody .tour-row > th,
tbody .tour-row > td {
  background: var(--tint-ok);
  border-bottom-color: var(--ok);
}

/* ------------------------------------------------ the desktop breakpoints */

@media (min-width: 48rem) {
  .persona-list {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }

  .side-by-side {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
}

@media (min-width: 64rem) {
  /* Four personas across, which is exactly how many there are: the picker
     becomes one row a visitor reads without scrolling. */
  .persona-list {
    grid-template-columns: repeat(4, minmax(0, 1fr));
  }

  /* A tour step becomes two columns: the heading and its number stay with the
     reader on the left, the prose runs on the right. */
  .step {
    display: grid;
    grid-template-columns: minmax(0, 18rem) minmax(0, 1fr);
    gap: var(--space-7);
    align-items: start;
  }

  .step > h2 {
    position: sticky;
    top: 7rem;
    margin: 0;
  }

  .hero {
    display: grid;
    grid-template-columns: minmax(0, 1fr);
    gap: var(--space-4);
  }

  .hero-figure {
    padding: var(--space-7) var(--space-7) var(--space-6);
  }
}

/* ------------------------------------------------------------- the reflow */

/* THE STAGE NAMES COME OUT OF THE DRAWING ON A PHONE, AND THAT IS THE FIX
   RATHER THAN THE DAMAGE.

   The picture is one `viewBox` of 960 by 160 user units, and its geometry is
   load-bearing: `hero-travel` walks the envelope in steps of 192 user units,
   which is a fifth of that width, and a test reads those five numbers out of
   this file. So the drawing cannot be re-laid-out for a narrow screen without
   rebuilding the mechanics part 17 had just finished correcting.

   What that costs on a 390 px phone is the labels. The SVG renders about 350
   px wide, so a 1.05rem label inside the viewBox comes out at roughly 6 CSS
   px - text that is present, is counted by every checker as present, and can
   be read by nobody. Illegible text is worse than no text: it is noise that
   claims to be information.

   Below 48rem the names are therefore hidden and the label band is cropped off
   the bottom with a negative margin (52 of 160 user units, which is 5.4 % of
   the picture's width, which is what a percentage margin resolves against).
   The drawing becomes what it can be at that size - a rail of five stages with
   one of them ringed - and the stage's NAME is read where it is legible: the
   caption directly beneath, whose chip carries "1. Eingang" and whose sentence
   is the one belonging to the lit stage. Nothing is lost from the document,
   from the accessible name or from the translation table; the `<title>` and
   `<desc>` that name the picture for assistive technology are untouched. */
@media (max-width: 48rem) {
  .hero-name {
    display: none;
  }

  .hero-svg {
    margin-bottom: -5.4%;
  }
}

@media (max-width: 40rem) {
  .hero-actions {
    display: block;
  }

  .hero-figure {
    padding: var(--space-5) var(--space-3) var(--space-4);
  }

  .hero-captions {
    padding: var(--space-3) var(--space-4);
  }

  .hero-caption {
    font-size: var(--text-base);
  }

  .step-mark {
    margin-right: var(--space-2);
  }
}
