/* inspiration-to-aisle.css -- the service map The Shortlist
   write-up draws in code, and the few things around it. One page loads this file,
   lab/inspiration-to-aisle.html, after style.css.

   WHY CODE AND NOT A PICTURE. A journey map and a service blueprint are
   mostly labels, and a label in a bitmap is a label the checks cannot read:
   resting.mjs cannot measure its contrast, typescale.mjs cannot see its
   size, and a screen reader gets alt text in place of a grid. So both are
   HTML: real headings, real cells, real text at the scale's sizes, on the
   palette's grounds, and every word of them is the page's own.

   ONE FIGURE, THE JOURNEY AND THE BLUEPRINT TOGETHER. A matrix: moments
   across, lanes down, a cell at each crossing. Six moments and seven
   lanes, read top to bottom from the shopper into the store: what they
   ask, what they still have, today's seam and the connected version, then
   the employee, what runs behind it and where it can fail, with two lane
   borders named, the line of visibility and the line of internal
   interaction. Until 2026-10-28 these were two figures with different
   moments in different sections, and a reader went back and forth. From 64rem
   the matrix is a grid with the lane names in a first column; under that it
   stacks moment by moment, each as a card with its lanes as rows, and the
   lane name is printed inside each cell (a real element, visually hidden
   where the first column carries it), so the stacked figure says the same
   words the wide one does.

   EVERY SIZE IS A STEP, every space a --space-*, every color a token. The
   figure's title is the serif at 400, as a figure's name is everywhere here
   (TYPOGRAPHY.md, "Tracked capitals never name a group"): 20px under 640,
   24 from it. Moment and lane names are the sans at 14, semibold, sentence
   case. A failure point takes the caution ink and a word, never the ink
   alone: "where it can fail" is a lane of its own.

   RATIOS, from COLOR.md section 2: charcoal on white 15.33 and on
   warm 14.02; muted-gray on white 6.47, on warm 5.91; accent-text on
   white 5.82, on warm 5.32; caution-text on white 6.45, on warm 5.90.
   The card is --figure-card since 2026-10-31, gray-light before, with
   the writing rail's card: warm on a white page, white on this page's
   tea chapter, where every ratio is the white one. Its edge is
   --rule-card, 1.48 on white. */

.ia-figure {
  --ia-pad-y: var(--space-lg);
  --ia-pad-x: var(--space-md);
  margin: var(--space-2xl) 0;
  overflow: clip;
  padding: var(--space-lg) var(--space-md);
  background: var(--figure-card);
  border: 1px solid var(--rule-card);
  border-radius: var(--radius-xl);
  box-shadow: var(--shadow-card);
}
@media (min-width: 640px) { .ia-figure { --ia-pad-y: var(--space-xl); --ia-pad-x: var(--space-xl); padding: var(--space-xl); } }
/* From 64rem the grid leaves the reading column for the page's container,
   as an article's rail does from 1024 (style.css, THE RAIL): six columns of
   words in the 832px column set each at about ten characters a line. The
   figure starts on the column's left edge, as every block does, and takes
   the full width, --col-full (style.css, the reading column). */
@media (min-width: 64rem) {
  .ia-figure {
    width: var(--col-full);
    max-width: none;
    --ia-pad-y: var(--space-2xl);
    --ia-pad-x: var(--space-3xl);
    padding: var(--space-2xl) var(--space-3xl);
  }
}

/* The caption is the service map's, as on the USDA case study
   (case-study/service-map.css, .svc-kicker and .svc-title), since
   2026-10-31: the kicker names the figure for what it is, a sentence in
   the serif says what it shows, and the standing line under them says it
   is illustrative. Until then the figcaption was itself the serif title,
   and the two maps opened differently. Each part restates its size and
   ink under two classes, because .case-section p outranks a bare class. */
.ia-figure > figcaption {
  margin: 0 0 var(--space-lg);
  max-width: var(--measure);
}
.ia-figure > figcaption .ia-kicker {
  margin: 0 0 var(--space-xs);
  font-size: var(--text-xs);
  font-weight: 600;
  line-height: var(--leading-ui);
  letter-spacing: var(--tracking-caps);
  text-transform: uppercase;
  color: var(--color-accent-text);
}
.ia-figure > figcaption .ia-title {
  margin: 0;
  font-family: var(--font-serif);
  font-weight: var(--weight-regular);
  font-size: var(--text-xl);
  line-height: var(--leading-tight);
  letter-spacing: var(--tracking-heading);
  color: var(--color-charcoal);
}
@media (min-width: 640px) {
  .ia-figure > figcaption .ia-title { font-size: var(--text-2xl); }
}
.ia-figure > figcaption .ia-standing {
  display: block;
  margin-top: var(--space-xs);
  font-family: var(--font-sans);
  font-size: var(--text-sm);
  line-height: var(--leading-ui);
  color: var(--color-muted-gray);
}

/* ---------- What the map shows ----------
   Since 2026-10-29 the map states its point, for a reader who will give
   it ten seconds: three claims, each a bold line, one sentence of
   evidence, and the moments that show it, in the moment discs the grid
   uses. For a day the claims opened the figure; since 2026-10-29 they
   close it, under the grid, so the moments they cite have been seen
   before they are named. The same component, in the same tokens, as
   .svc-short in case-study/case-study-base.css.

   No card of its own since 2026-10-29, the day it arrived: a white card
   inside the figure's card, over a row of white moment cards, read as one
   more box stacked on the map rather than as the map's own words. The
   claims are the figure's own foot. Since 2026-10-30 that foot is a band
   of tea-light running to the figure's edges, as .svc-short's is, and
   for the same reasons: the point is where a reader lands after the
   grid, and it reads as the map's conclusion rather than a card in it.
   Later the same day the band went charcoal, as .svc-short's did, in
   the same on-dark tokens. Stacked under 64rem; from
   64rem, three columns, the moment line on one baseline across them.
   The caption took the same three columns from 2026-10-29 until
   2026-10-30, when it went back to one stack at every width, as
   .svc-map's did and for the same reason. Each claim opens on its mark
   (map-rail.css, "The claims' marks"). For a few hours the claims stood in one column beside the
   caption instead, and read as a list squeezed into the corner of the
   figure. The label is .glance-kicker, the Kicker's treatment. Charcoal
   on warm is 14.02, muted-gray 5.91. */
.ia-short {
  margin: var(--space-xl) calc(-1 * var(--ia-pad-x)) calc(-1 * var(--ia-pad-y));
  padding: var(--space-lg) var(--ia-pad-x) var(--ia-pad-y);
  background: var(--color-charcoal);
}
/* Its size and ink said again under two classes, because .case-section p
   sets prose at --text-lg in charcoal and outranks the bare class (as
   .eng3-proof-client and .writing-meta in style.css do). */
.ia-short .glance-kicker {
  margin: 0 0 var(--space-sm);
  font-size: var(--text-xs);
  line-height: var(--leading-ui);
  color: var(--color-accent-on-dark);
}
.ia-short-list { list-style: none; margin: 0; padding: 0; }
.ia-short-list > li { margin: 0; padding: var(--space-sm) 0; border-top: 1px solid var(--rule-on-dark); }
.ia-short-list > li:first-child { padding-top: 0; border-top: 0; }
.ia-short-list > li:last-child { padding-bottom: 0; }
.ia-figure .ia-short-claim {
  margin: 0 0 var(--space-2xs);
  font-size: var(--text-base);
  font-weight: var(--weight-semibold);
  line-height: var(--leading-tight);
  color: var(--ink-on-dark);
}
.ia-figure .ia-short-why {
  margin: 0;
  font-size: var(--text-sm);
  line-height: var(--leading-ui);
  color: var(--ink-on-dark);
}
.ia-figure .ia-short-at {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-2xs);
  margin: var(--space-xs) 0 0;
  font-size: var(--text-xs);
  font-weight: var(--weight-semibold);
  line-height: var(--leading-ui);
  color: var(--ink-on-dark-secondary);
}
@media (min-width: 64rem) {
  .ia-map > figcaption { margin-bottom: var(--space-xl); }
  .ia-short { margin-top: var(--space-2xl); padding-top: var(--space-xl); }
  .ia-short-list { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); }
  .ia-short-list > li,
  .ia-short-list > li:first-child,
  .ia-short-list > li:last-child { padding: 0 var(--space-lg); border-top: 0; border-left: 1px solid var(--rule-on-dark); }
  .ia-short-list > li:first-child { padding-left: 0; border-left: 0; }
  .ia-short-list > li:last-child { padding-right: 0; }
  /* The moment line sits on one baseline across the three columns. */
  .ia-short-list > li { display: flex; flex-direction: column; }
  .ia-figure .ia-short-at { margin-top: auto; padding-top: var(--space-sm); }
  .ia-figure .ia-short-claim { margin-bottom: var(--space-xs); font-size: var(--text-lg); }
}

/* ---------- The matrix ----------
   Stacked by default. Each moment is an <li> card on white with its name
   on top and its lanes under it, each lane a labelled row. */
.ia-matrix {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  gap: var(--space-md);
}
.ia-moment {
  background: var(--color-white);
  border: 1px solid var(--rule-card);
  border-radius: 12px;
  padding: var(--space-md);
}
.case-section .ia-moment-name,
.ia-moment-name {
  margin: 0 0 var(--space-sm);
  font-family: var(--font-sans);
  font-size: var(--text-base);
  font-weight: var(--weight-semibold);
  line-height: var(--leading-tight);
  color: var(--color-charcoal);
  /* The number in its own column and the name in the next, so a name that
     takes two lines wraps under its own first word, not under the disc. */
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  align-items: start;
  column-gap: var(--space-xs);
}
.ia-moment-name .ia-n,
.ia-short-at .ia-n {
  color: var(--color-accent-text);
  font-variant-numeric: tabular-nums;
}
.ia-lanes { margin: 0; }
.ia-lane {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: var(--space-2xs);
  padding: var(--space-xs) 0;
  border-top: 1px solid var(--rule-hairline);
}
.ia-lane:first-child { border-top: 0; padding-top: 0; }
/* The lane's name inside the cell, stacked; hidden from 64rem, where the
   first column names it once per row. */
.ia-lane dt {
  font-family: var(--font-sans);
  font-size: var(--text-xs);
  font-weight: var(--weight-semibold);
  line-height: var(--leading-ui);
  color: var(--color-muted-gray);
}
.ia-lane dd {
  margin: 0;
  font-family: var(--font-sans);
  font-size: var(--text-sm);
  line-height: var(--leading-ui);
  color: var(--color-charcoal);
}
.ia-lane dd p { margin: 0; font-size: inherit; line-height: inherit; color: inherit; }
.ia-lane dd p + p { margin-top: var(--space-2xs); }
/* A failure point: the caution ink, after the word that says what it is. */
.ia-lane--fail dd { color: var(--color-caution-text); }
/* A cell with nothing in it says so, quietly. */
.ia-lane dd.ia-none { color: var(--color-muted-gray); }

/* ---------- Wide: the grid ----------
   One row per lane, one column per moment, and a first column of lane
   names. The stacked cards become columns; each lane row runs across all
   of them with one rule under it, which is what makes the two named lines
   below possible. */
@media (min-width: 64rem) {
  /* The lane names' column, named once for the grid, the phase bands over
     it and the stepped grid the script composes ("Stepping through"). */
  .ia-map { --ia-names: 9rem; --ia-cell-pad: var(--space-sm); }
  .ia-matrix {
    gap: 0;
    grid-template-columns: var(--ia-names) repeat(var(--ia-moments), minmax(0, 1fr));
    column-gap: var(--space-md);
  }
  .ia-moment {
    display: contents;
    background: none;
    border: 0;
    padding: 0;
  }
  .case-section .ia-moment-name,
  .ia-moment-name {
    grid-row: 2;
    grid-column: calc(var(--ia-i) + 2);
    margin: 0;
    padding-bottom: var(--space-sm);
    border-bottom: 1px solid var(--rule-strong);
  }
  .ia-lanes { display: contents; }
  .ia-lane {
    display: contents;
  }
  /* The lane name, once, in the first column, from the first moment only;
     every other moment's copy is hidden but present. */
  .ia-lane dt {
    grid-row: calc(var(--ia-lane) + 2);
    grid-column: 1;
    padding: var(--ia-cell-pad) 0;
    border-bottom: 1px solid var(--rule-hairline);
    align-self: stretch;
    font-size: var(--text-sm);
    color: var(--color-charcoal);
  }
  .ia-moment:not(:first-child) .ia-lane dt {
    position: absolute;
    width: 1px; height: 1px;
    padding: 0; margin: -1px;
    overflow: hidden;
    clip: rect(0 0 0 0);
    white-space: nowrap;
    border: 0;
  }
  .ia-lane dd {
    grid-row: calc(var(--ia-lane) + 2);
    grid-column: calc(var(--ia-i) + 2);
    padding: var(--ia-cell-pad) 0;
    border-bottom: 1px solid var(--rule-hairline);
  }
  /* The two named lines of a blueprint: a stronger rule under the lane
     above each, and its name in the first column's cell above it. */
  .ia-lane--visible dt, .ia-lane--visible dd,
  .ia-lane--internal dt, .ia-lane--internal dd { border-bottom-color: var(--rule-strong); }
}
/* ---------- Read at a glance ----------
   The journey, made to be read in a few seconds.
   The same three moves, in tokens, as the service map in case-study/case-study-base.css, so the
   two read as one component:

   - The stage number sits in the station mark: the tea disc with the
     accent hairline, .fact-node's in style.css, sized to the line.
   - The payoff row is a row of tea-light tiles, its name in sage, so the
     eye lands on what changed before it reads anything else. Tea-light is
     the palette's word for "featured" (COLOR.md); charcoal on it is 12.90.
     The tile takes --rule-card, the edge every card on a ground takes,
     because tea on white is 1.19:1 and the sage hairline did not read
     (cards.mjs).
   - One phrase a cell is bold in the pain row and the payoff row, so the
     two rows read across as the story in a dozen words. Bold, never a
     second color: emphasis on this site is weight. */
.ia-moment-name .ia-n,
.ia-short-at .ia-n {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 2em; height: 2em;
  border-radius: 50%;
  background: var(--color-tea-light);
  border: 1px solid var(--color-accent-ring);
  font-size: var(--text-xs);
  /* Centred on the name's first line, from that line's own box. */
  margin-top: calc((var(--text-base) * var(--leading-tight) - 2 * var(--text-xs)) / 2);
}
/* In the summary the disc sits in a centred row of its own. */
.ia-short-at .ia-n { margin-top: 0; background: var(--wash-on-dark); border-color: var(--color-accent-ring-on-dark); color: var(--color-accent-on-dark); }
.ia-line {
  display: block;
  margin-top: var(--space-2xs);
  font-size: var(--text-xs);
  font-weight: var(--weight-semibold);
  line-height: var(--leading-ui);
  color: var(--color-accent-text);
}
@media (min-width: 64rem) {
  .ia-line { margin-top: var(--space-xs); }
}

/* ---------- The hero ----------
   The question and the facts in the first column, the prototype in the
   second from 64rem. Under that the hero is one column, and the phone
   follows the facts. */
.ia-hero-grid { display: grid; grid-template-columns: minmax(0, 1fr); gap: var(--space-3xl); align-items: start; }
@media (min-width: 64rem) { .ia-hero-grid { grid-template-columns: minmax(0, 1.4fr) minmax(0, 1fr); } }
.ia-status {
  margin: var(--space-lg) 0 0;
  max-width: var(--measure);
  font-size: var(--text-sm);
  line-height: var(--leading-ui);
  color: var(--color-muted-gray);
}

/* ---------- The phone in the hero ----------
   The prototype itself, since 2026-10-29, where a capture of it stood and
   looked pressable without being so. It is lab/aisle.css's 24rem frame,
   centered in the column, under the one label that says it is the real
   thing, on the phone's width. Since 2026-10-30 no line says what to
   try; the app's own screens do.

   ONE HEIGHT FROM 64rem. Each screen is its own height, and the comparison
   is half again as tall as the first. Beside the facts, a phone that grew
   and shrank with every press would move the map up and down the page
   under the reader, so from 64rem the app holds the 42rem its frame was
   drawn at (never more than the viewport leaves under the header) and the
   screen scrolls inside it, under the app's bar, as a phone's does.
   lab/aisle.js starts each new screen at its top. Under 64rem the phone
   takes each screen's own height again, as on a phone itself: a box that
   scrolls inside a page that scrolls is a box a thumb gets caught in.

   The stage is the box that scrolls, so it would clip a control's focus
   ring at its edge; it gives the ring --space-2xs of room on every side
   and takes the same back from its margin, so nothing inside it moves. */
.ia-hero-app { min-width: 0; }
/* "Try it, it's live" (style.css) on the phone's column. */
.ia-hero-app p.try-live { max-width: 24rem; margin: 0 auto var(--space-md); }
@media (min-width: 64rem) {
  .ia-hero-app .ai-app {
    display: flex;
    flex-direction: column;
    height: min(42rem, calc(100svh - var(--nav-height) - 2 * var(--space-4xl)));
    min-height: 0;
  }
  .ia-hero-app .ai-bar { flex: none; }
  .ia-hero-app .ai-stage {
    flex: 1 1 auto;
    min-height: 0;
    overflow-y: auto;
    margin: calc(-1 * var(--space-2xs));
    padding: var(--space-2xs);
  }
}

/* ---------- The five decisions ----------
   In decisions.css since 2026-10-30, shared with the cockpit page: the
   decision on the left, a drawing of the guess on the right with the guess
   as its caption. */

/* ---------- The map's two views ----------
   With script (inspiration-to-aisle.js) the figure carries .is-connected
   or not, and shows one of its two middle lanes; the switch is two pressed
   buttons, the pressed one in the sage under white (5.82). Without script
   the switch stays hidden and both lanes show, which is the figure as
   it reads on paper. */
.ia-view {
  display: inline-flex;
  gap: var(--space-2xs);
  margin: 0 0 var(--space-lg);
  padding: var(--space-2xs);
  background: var(--color-white);
  border: 1px solid var(--rule-card);
  border-radius: var(--radius-pill);
}
.ia-view[hidden] { display: none; }
.ia-view-btn {
  padding: var(--space-xs) var(--space-md);
  background: transparent;
  border: 0;
  border-radius: var(--radius-pill);
  font: inherit;
  font-size: var(--text-sm);
  font-weight: var(--weight-semibold);
  line-height: var(--leading-ui);
  color: var(--color-charcoal);
  cursor: pointer;
  transition: background-color var(--motion-state) var(--ease), color var(--motion-state) var(--ease);
}
.ia-view-btn[aria-pressed="true"] { background: var(--color-accent-text); color: var(--color-white); }
.ia-view-btn:focus-visible { outline: 2px solid var(--color-focus-ring); outline-offset: 2px; }
.ia-map.is-today .ia-lane--connected,
.ia-map.is-connected .ia-lane--today { display: none; }
/* Today names its seam in the caution ink after the lane's word, as a
   failure point does; Connected is the page's charcoal. */
.ia-map .ia-lane--today dd { color: var(--color-caution-text); }

/* ---------- What the shopper still has ----------
   The thread: what the shopper built up, as small labels, gathering over
   the first three moments. Today the three are left at the door at moment
   four, so from there they are struck through on a dashed edge, in the
   muted ink, with the words saying so once; connected, they carry to the
   end. Wide, one sage line runs behind the labels from moment to moment,
   dashed where today drops them. */
.ia-lane--thread dd { display: flex; flex-wrap: wrap; gap: var(--space-2xs); align-items: center; align-content: flex-start; position: relative; }
.ia-carry {
  position: relative;
  z-index: 1;
  padding: 0 var(--space-xs);
  background: var(--color-white);
  border: 1px solid var(--color-accent-text);
  border-radius: var(--radius-pill);
  font-size: var(--text-xs);
  font-weight: var(--weight-semibold);
  line-height: var(--leading-ui);
  color: var(--color-accent-text);
}
.ia-lost-note {
  flex-basis: 100%;
  font-size: var(--text-xs);
  font-weight: var(--weight-semibold);
  line-height: var(--leading-ui);
  color: var(--color-caution-text);
}
.ia-map:not(.is-connected) .ia-moment[data-lost] .ia-carry {
  border-style: dashed;
  border-color: var(--color-rule);
  color: var(--color-muted-gray);
  text-decoration: line-through;
}
.ia-map.is-connected .ia-lost-note { display: none; }
@media (min-width: 64rem) {
  .ia-lane--thread dd::before {
    content: "";
    position: absolute;
    left: 0;
    right: calc(-1 * var(--space-md));
    top: calc(var(--ia-cell-pad) + 0.5lh);
    border-top: 2px solid var(--color-accent-text);
  }
  .ia-moment:last-child .ia-lane--thread dd::before { right: 0; }
  .ia-map:not(.is-connected) .ia-moment[data-lost] .ia-lane--thread dd::before { border-top-style: dashed; border-top-color: var(--color-rule); }
  .ia-matrix .ia-lane dd, .ia-matrix .ia-moment-name { padding-inline: var(--space-xs); }
}

/* ---------- Following one moment down ----------
   A moment's name is a button (the script makes it one). Under 64rem,
   pressed, its card takes tea-light, so a reader follows one moment
   without losing the rest; from 64rem the same press opens the moment
   instead ("Stepping through", below). Every ink here clears its floor
   on tea-light: charcoal 13.1, caution-text 5.43, accent-text 4.90. */
.ia-moment-pick {
  padding: 0;
  background: none;
  border: 0;
  font: inherit;
  color: inherit;
  text-align: left;
  cursor: pointer;
  /* The script moves the disc and the name into this button, so the
     name's two columns are drawn here: a name that wraps hangs under its
     own first word, not under the disc. */
  display: grid;
  grid-template-columns: subgrid;
  grid-column: 1 / -1;
  align-items: start;
}
.ia-moment-pick:focus-visible { outline: 2px solid var(--color-focus-ring); outline-offset: 2px; }
@media (hover: hover) and (pointer: fine) {
  .ia-moment-pick:hover { text-decoration: underline; text-underline-offset: 3px; }
}
.ia-moment.is-followed { background: var(--color-tea-light); }

/* ---------- Wide: the moments as one rail ----------
   A column is about ten characters wide, so beside its disc a name like
   "With a person" took two lines. From 64rem the disc sits over the name
   instead, and one sage line joins the discs across the head of the grid,
   the trip read left to right before a lane is. The name gets the
   column's whole width and stays on one line. */
@media (min-width: 64rem) {
  .case-section .ia-moment-name,
  .ia-moment-name { position: relative; grid-template-columns: minmax(0, 1fr); }
  .ia-moment-pick { grid-template-columns: minmax(0, 1fr); row-gap: var(--space-xs); }
  .ia-moment-name .ia-n { position: relative; z-index: 1; margin-top: 0; }
  .ia-moment-name::before {
    content: "";
    position: absolute;
    left: var(--space-xs);
    right: calc(-1 * var(--space-md));
    top: var(--text-xs);
    border-top: 2px solid var(--color-accent-text);
  }
  .ia-moment:last-child .ia-moment-name::before { display: none; }
}

/* ---------- Where the trip happens ----------
   Two bands over the moments, the way a journey map names its phases:
   the first three at home on the phone, the last three in the store. The
   bands sit on the matrix's own columns, so each one ends where its
   moments do. Wide only; stacked, each card already says where it is. */
.ia-phases { display: none; }
@media (min-width: 64rem) {
  .ia-phases {
    display: grid;
    grid-template-columns: var(--ia-names) repeat(var(--ia-moments), minmax(0, 1fr));
    column-gap: var(--space-md);
    margin: 0 0 var(--space-sm);
  }
  .ia-phase {
    grid-column: calc(var(--ia-from) + 1) / calc(var(--ia-to) + 1);
    padding: var(--space-2xs) var(--space-sm);
    border-radius: var(--radius-pill);
    background: var(--color-tea-light);
    font-size: var(--text-xs);
    font-weight: var(--weight-semibold);
    line-height: var(--leading-ui);
    color: var(--color-charcoal);
  }
  .ia-phase + .ia-phase { background: var(--color-muted-light); }
}

/* ---------- How sure they feel ----------
   The lane a journey map draws as a curve. Each moment carries its two
   readings, --ia-t for today and --ia-c connected, from 2 (sure) down to
   -2 (lost), and says them in words under the plot, so the curve is never
   the only place they live. Wide, one SVG in the first moment's cell
   spans all six columns, inset by half a gap each side so its points fall
   on the column centres, and each cell sets its own dots at the same
   heights. The switch brings one line forward and greys the other. */
.ia-lane--feel dd { display: grid; gap: var(--space-2xs); }
.ia-curve, .ia-dot { display: none; }
.ia-feel { display: block; }
.ia-feel--today { color: var(--color-caution-text); }
.ia-feel-k { font-weight: var(--weight-semibold); }
.ia-map.is-today .ia-feel--connected,
.ia-map.is-connected .ia-feel--today,
.ia-map.is-today .ia-feel-k,
.ia-map.is-connected .ia-feel-k { display: none; }
@media (min-width: 64rem) {
  .ia-lane--feel dd {
    --ia-plot: 4rem;
    position: relative;
    align-content: start;
    padding-top: calc(var(--ia-plot) + 2 * var(--ia-cell-pad));
  }
  .ia-curve {
    display: block;
    position: absolute;
    z-index: 1;
    top: var(--ia-cell-pad);
    left: calc(var(--space-md) / -2);
    width: calc(var(--ia-moments) * (100% + var(--space-md)));
    max-width: none;
    height: var(--ia-plot);
    overflow: visible;
  }
  .ia-curve polyline {
    fill: none;
    stroke-width: 2;
    stroke-linejoin: round;
    vector-effect: non-scaling-stroke;
    transition: stroke var(--motion-state) var(--ease);
  }
  .ia-curve-connected { stroke: var(--color-accent-text); }
  .ia-curve-today { stroke: var(--color-caution-text); stroke-dasharray: 6 4; }
  .ia-map.is-today .ia-curve-connected,
  .ia-map.is-connected .ia-curve-today { stroke: var(--color-rule); }
  .ia-dot {
    display: block;
    position: absolute;
    z-index: 2;
    left: 50%;
    width: var(--space-sm);
    height: var(--space-sm);
    border-radius: 50%;
    border: 2px solid var(--color-white);
    translate: -50% -50%;
  }
  .ia-dot--connected { top: calc(var(--ia-cell-pad) + (2 - var(--ia-c)) / 4 * var(--ia-plot)); background: var(--color-accent-text); }
  .ia-dot--today { top: calc(var(--ia-cell-pad) + (2 - var(--ia-t)) / 4 * var(--ia-plot)); background: var(--color-caution-text); }
  .ia-map.is-today .ia-dot--connected,
  .ia-map.is-connected .ia-dot--today { background: var(--color-rule); z-index: 1; }
}

/* ---------- A mark for each lane ----------
   A line icon before each lane's name, drawn as a mask so it takes the
   name's own ink: a question, a pulse, a bag, an eye on the two visible
   lanes, a person, the layers behind, a warning. It sits centred on the
   name's first line, from that line's box. */
.ia-lane dt { position: relative; padding-left: 1.75em; }
.ia-lane dt::before {
  content: "";
  position: absolute;
  left: 0;
  top: calc(var(--ia-dt-pad, 0px) + 0.5lh);
  width: 1.25em;
  height: 1.25em;
  translate: 0 -50%;
  background: currentColor;
  -webkit-mask: var(--ia-icon) center / contain no-repeat;
  mask: var(--ia-icon) center / contain no-repeat;
}
@media (min-width: 64rem) { .ia-lane dt { --ia-dt-pad: var(--ia-cell-pad); } }
.ia-lane--asks { --ia-icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='1.8' stroke-linejoin='round'%3E%3Cpath d='M4 5h16v11h-9l-4 4v-4H4z'/%3E%3C/svg%3E"); }
.ia-lane--feel { --ia-icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='1.8' stroke-linecap='round'%3E%3Cpath d='M2 14c3 0 4-7 7-7s4 11 7 11 3-6 6-6'/%3E%3C/svg%3E"); }
.ia-lane--thread { --ia-icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='1.8' stroke-linejoin='round'%3E%3Cpath d='M5 8h14l-1 13H6z'/%3E%3Cpath d='M9 8V6a3 3 0 0 1 6 0v2'/%3E%3C/svg%3E"); }
.ia-lane--visible { --ia-icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='1.8'%3E%3Cpath d='M2 12s4-6.5 10-6.5S22 12 22 12s-4 6.5-10 6.5S2 12 2 12z'/%3E%3Ccircle cx='12' cy='12' r='3'/%3E%3C/svg%3E"); }
.ia-lane--internal { --ia-icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='1.8' stroke-linecap='round'%3E%3Ccircle cx='12' cy='8' r='3.5'/%3E%3Cpath d='M5 20c0-4 3-6.5 7-6.5s7 2.5 7 6.5'/%3E%3C/svg%3E"); }
.ia-lane--behind { --ia-icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='1.8' stroke-linejoin='round'%3E%3Cpath d='M3 8l9-4.5L21 8l-9 4.5z'/%3E%3Cpath d='M3 12.5l9 4.5 9-4.5'/%3E%3Cpath d='M3 17l9 4.5 9-4.5'/%3E%3C/svg%3E"); }
.ia-lane--fail { --ia-icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='1.8' stroke-linejoin='round' stroke-linecap='round'%3E%3Cpath d='M12 3.5l9.5 16.5h-19z'/%3E%3Cpath d='M12 10v4.5'/%3E%3Cpath d='M12 17.5v.01'/%3E%3C/svg%3E"); }

/* ---------- The storyboard ----------
   One small scene over each moment, as a journey map's storyboard row:
   the shopper photographing a friend's lamp, comparing at home, saving
   two, walking in, standing in the aisle, at the counter. Drawn in the
   Lucy Learns style with one shopper and one employee throughout, in one
   ChatGPT chat so the six are in one hand, cut to 720x480, and alt="",
   because the moment's name under each says what it shows.

   From the store door the two trips part, so 04 to 06 have a drawing for
   each view, and the switch shows one in the cell both share. Connected's
   shopper follows her phone and shows the employee her two; Today's puts
   it away at the door, stands between two lamps unsure which were hers,
   and describes the lamp with her hands. Each Today drawing is its
   Connected one a few seconds apart, drawn against it in the same chat, so
   a press changes what she does and nothing else. Without script the
   switch is hidden and Today's shows, as the thread lane does, because the
   page starts there. */
.ia-map:not(.is-connected) .ia-scene--connected,
.ia-map.is-connected .ia-scene--today { display: none; }
.ia-scene {
  display: block;
  width: 100%;
  max-width: 15rem;
  height: auto;
  aspect-ratio: 3 / 2;
  object-fit: cover;
  margin: 0 0 var(--space-sm);
  border-radius: 12px;
}
@media (min-width: 64rem) {
  .ia-scene {
    grid-row: 1;
    grid-column: calc(var(--ia-i) + 2);
    max-width: none;
    margin: 0 0 var(--space-sm);
    border: 1px solid var(--rule-card);
  }
}

/* ---------- Stepping through, one moment at a time ----------
   Since 2026-11-01, from 64rem. Six moments across leave each about ten
   characters a line: a map to scan, not to read. "Step through the trip"
   (inspiration-to-aisle.js) opens one moment at a time. Its column takes
   --ia-open shares of the width to every other column's one, on the
   tea-light ground, and the other five fold to strips. A strip keeps what
   carries the trip across: its drawing, cut to a tall slice; its disc and
   its name, in the muted ink; the two confidence dots, which the curve
   still runs through; and the thread line, solid or dashed. Its words
   fold away and its row lines stay, so each lane still reads from its
   name in the first column across to the open moment.

   The open moment reads a size up: its name at --text-xl, the shopper's
   question in the serif at --text-2xl, every lane at --text-base. Its
   drawing keeps its 3:2, so the storyboard row is two thirds of the width
   the open column will have, --ia-stage-h, which the script sets.

   THE WHOLE MAP FITS THE WINDOW. Since 2026-11-02, so a laptop steps
   01 to 06 without scrolling. While stepping the lane names get
   --ia-names-open, wide enough that each takes one line, the rows close
   to --space-xs, their words to --leading-tight and the confidence plot
   to 3rem; the script then gives
   the storyboard what the window has left over the lanes and the bar,
   never more than the 3:2 height and never less than 8rem, and scrolls
   the map up under the nav when it does not already sit there. A drawing
   held under its 3:2 height is narrowed to keep its shape, at the left of
   its column, rather than cropped. Every
   ink in the open column clears its floor on tea-light: charcoal 13.1,
   caution-text 5.43, accent-text 4.90, muted-gray 5.44. The ground takes
   --rule-card for its edge, as every card on a ground does, because tea
   on white is 1.19:1 (cards.mjs).

   NOTHING MOVES BUT THE COLUMNS. Since the same day, a press changes
   no height anywhere. The script wraps each cell's words in .ia-cell
   while stepping, and every cell, open or folded, is laid out at the
   width the open column will have, --ia-open-w, in the open column's
   type; a folded cell is only hidden. So every lane is as tall as its
   tallest moment in every step, and the grid, the bar under it and the
   page under that hold still from 01 to 06. Today and Connected share one
   row while stepping, the inactive one hidden rather than removed, so the
   switch moves nothing either. A name is held to two lines of a strip's
   size, which is taller than the open name's one, so the names row holds
   too.

   And nothing rewraps. A cell never changes width, so the opening
   column's words are not reflowed through ten widths on the way; they
   wait, and arrive when the column has settled (--motion-move into the
   glide, over --motion-state), and the closing column's words go at once.
   The columns glide on --motion-enter, the open column widening as the
   last one folds, and the tea ground slides with them from the column it
   was on to the next (the script, from the columns' own widths).

   A bar steps it, stuck to the foot of the window while the map is on
   screen: back, where the reader is, Next, and a close. It holds one
   width: the count, the longest name and "See it all" are all laid out in
   it at once, and only the current ones show. It is the dark band's
   charcoal with the warm ink; the count is accent-on-dark, and Next is
   charcoal on accent-on-dark, 7.47 either way round. */
@media (min-width: 64rem) {
  .ia-map {
    --ia-open: 5.5;
    --ia-folded-opacity: 0.6;
    --ia-names-open: 12rem;
  }
  /* Tighter rows while stepping, so the whole map fits a laptop's window. */
  .ia-map.is-stepping { --ia-cell-pad: var(--space-xs); }
  .ia-map.is-stepping .ia-lane--feel dd { --ia-plot: 3rem; }
  .ia-map.is-stepping .ia-lane dt { white-space: nowrap; }
  .ia-map.can-step .ia-matrix,
  .ia-map.can-step .ia-phases {
    grid-template-columns: var(--ia-cols);
    transition: grid-template-columns var(--motion-enter) var(--ease-enter);
  }
  /* Leaving goes straight back to the whole map: a glide there would
     rewrap every cell of it on the way. */
  .ia-map.is-leaving .ia-matrix,
  .ia-map.is-leaving .ia-phases { transition: none; }

  /* The view switch and the way in, on one line. */
  .ia-toolbar {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--space-md);
    margin: 0 0 var(--space-lg);
  }
  .ia-toolbar .ia-view { margin: 0; }

  /* The open column's ground, placed by the script (--ia-spot-x and
     --ia-spot-w) so it can slide between columns rather than jump. Under
     every cell: the grid isolates, and the ground sits at -1 in it. */
  .ia-map.can-step .ia-matrix { position: relative; isolation: isolate; }
  .ia-map.can-step .ia-matrix::before {
    content: "";
    position: absolute;
    z-index: -1;
    top: calc(-1 * var(--space-sm));
    bottom: calc(-1 * var(--space-sm));
    left: calc(var(--ia-spot-x, 0px) - var(--space-sm));
    width: calc(var(--ia-spot-w, 0px) + 2 * var(--space-sm));
    background: var(--color-tea-light);
    border: 1px solid var(--rule-card);
    border-radius: var(--radius-xl);
    opacity: 0;
    transition: opacity var(--motion-state) var(--ease);
    pointer-events: none;
  }
  .ia-map.is-stepping .ia-matrix::before { opacity: 1; }

  /* The storyboard, as a strip of slices around one drawing. */
  .ia-map.is-stepping .ia-matrix { grid-template-rows: var(--ia-stage-h); }
  .ia-map.is-stepping .ia-scene {
    height: 100%;
    aspect-ratio: auto;
    align-self: stretch;
    transition: opacity var(--motion-state) var(--ease);
  }
  .ia-map.is-stepping .ia-moment:not(.is-open) .ia-scene {
    opacity: var(--ia-folded-opacity);
    cursor: pointer;
  }
  .ia-map.is-stepping .ia-moment.is-open .ia-scene {
    width: min(100%, calc(var(--ia-stage-h) * 3 / 2));
    box-shadow: var(--shadow-card-raised);
  }

  /* The names: two lines of a strip's size, whichever is open. */
  .ia-map.is-stepping .ia-moment-label {
    display: -webkit-box;
    -webkit-box-orient: vertical;
    -webkit-line-clamp: 2;
    overflow: hidden;
    height: calc(2 * var(--text-sm) * var(--leading-tight));
    font-size: var(--text-sm);
  }
  .ia-map.is-stepping .ia-moment:not(.is-open) .ia-moment-name { color: var(--color-muted-gray); }
  .ia-map.is-stepping .ia-moment.is-open .ia-moment-label {
    display: block;
    white-space: nowrap;
    font-size: var(--text-xl);
    animation: ia-arrive var(--motion-state) var(--ease) var(--motion-move) backwards;
  }
  .ia-map.is-stepping .ia-n { transition: background-color var(--motion-state) var(--ease), color var(--motion-state) var(--ease); }
  .ia-map.is-stepping .ia-moment.is-open .ia-n {
    background: var(--color-accent-text);
    border-color: var(--color-accent-text);
    color: var(--color-white);
  }

  /* The cells: every one at the open width in the open type, and only
     the open one shown. A folded cell is hidden rather than made clear,
     so the checks and a screen reader leave it too. */
  .ia-map.is-stepping .ia-cell {
    flex: none;
    width: calc(var(--ia-open-w) - 2 * var(--space-xs));
    font-size: var(--text-base);
    line-height: var(--leading-tight);
  }
  .ia-map.is-stepping .ia-lane--asks .ia-cell {
    font-family: var(--font-serif);
    font-weight: var(--weight-regular);
    font-size: var(--text-2xl);
    line-height: var(--leading-heading);
  }
  .ia-map.is-stepping .ia-lane--thread .ia-cell {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-2xs);
    align-items: center;
    align-content: flex-start;
  }
  .ia-map.is-stepping .ia-moment:not(.is-open) .ia-cell { visibility: hidden; }
  .ia-map.is-stepping .ia-moment.is-open .ia-cell {
    animation: ia-arrive var(--motion-state) var(--ease) var(--motion-move) backwards;
  }
  .ia-map.is-stepping .ia-moment.is-open .ia-dot { width: var(--space-md); height: var(--space-md); }

  /* Today and Connected in one row while stepping, the other one hidden,
     so the switch changes no height. The note under the thread the same. */
  .ia-map.is-stepping.is-today .ia-lane--connected,
  .ia-map.is-stepping.is-connected .ia-lane--today { display: contents; }
  .ia-map.is-stepping .ia-lane--connected :is(dt, dd) { grid-row: calc(var(--ia-lane) + 1); }
  .ia-map.is-stepping.is-today .ia-lane--connected :is(dt, dd),
  .ia-map.is-stepping.is-connected .ia-lane--today :is(dt, dd) { visibility: hidden; }
  .ia-map.is-stepping.is-connected .ia-lost-note { display: block; visibility: hidden; }

  /* The bar. */
  .ia-stepper {
    position: sticky;
    bottom: var(--space-lg);
    z-index: 3;
    align-items: center;
    gap: var(--space-xs);
    width: fit-content;
    margin: var(--space-lg) auto 0;
    padding: var(--space-2xs);
    background: var(--color-charcoal);
    border-radius: var(--radius-pill);
    box-shadow: var(--shadow-card-raised);
  }
  .ia-step-btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: var(--space-xs);
    height: var(--space-3xl);
    min-width: var(--space-3xl);
    padding: 0;
    background: var(--wash-on-dark);
    border: 0;
    border-radius: var(--radius-pill);
    font: inherit;
    font-size: var(--text-sm);
    font-weight: var(--weight-semibold);
    line-height: var(--leading-ui);
    color: var(--color-warm);
    cursor: pointer;
    transition: background-color var(--motion-state) var(--ease), color var(--motion-state) var(--ease);
  }
  .ia-step-btn svg { width: 1.125em; height: 1.125em; flex: none; }
  .ia-step-btn:focus-visible { outline: 2px solid var(--color-focus-ring); outline-offset: 2px; }
  /* At the first moment there is nothing behind; the button keeps its
     place, so the count does not move under the reader. */
  .ia-step-btn[aria-disabled="true"] { visibility: hidden; }
  .ia-step-next {
    padding: 0 var(--space-md) 0 var(--space-lg);
    background: var(--color-accent-on-dark);
    color: var(--color-charcoal);
  }
  .case-section .ia-step-count {
    display: flex;
    align-items: baseline;
    gap: var(--space-xs);
    margin: 0 var(--space-xs);
    font-size: var(--text-sm);
    line-height: var(--leading-ui);
    font-variant-numeric: tabular-nums;
    color: var(--color-warm);
  }
  .ia-step-of { color: var(--color-accent-on-dark); }
  .ia-step-name { font-weight: var(--weight-semibold); }
  /* What the bar can say, laid out in one cell so the widest decides the
     width; only what is current is shown. */
  .ia-step-name, .ia-step-next-label { display: inline-grid; }
  .ia-step-name > *, .ia-step-next-label > * { grid-area: 1 / 1; }
  .ia-step-name > [aria-hidden="true"],
  .ia-step-next-label > [aria-hidden="true"] { visibility: hidden; }
}
/* The way in, and the bar, are for the wide grid only. */
.ia-step-start, .ia-stepper { display: none; }
@media (min-width: 64rem) {
  .ia-step-start {
    display: inline-flex;
    align-items: center;
    gap: var(--space-xs);
    padding: var(--space-xs) var(--space-md);
    background: var(--color-white);
    border: 1px solid var(--rule-card);
    border-radius: var(--radius-pill);
    font: inherit;
    font-size: var(--text-sm);
    font-weight: var(--weight-semibold);
    line-height: var(--leading-ui);
    color: var(--color-charcoal);
    cursor: pointer;
    transition: background-color var(--motion-state) var(--ease);
  }
  .ia-step-start svg { width: 1.125em; height: 1.125em; flex: none; }
  .ia-step-start:focus-visible { outline: 2px solid var(--color-focus-ring); outline-offset: 2px; }
  .ia-map.is-stepping .ia-step-start { visibility: hidden; }
  .ia-map.is-stepping .ia-stepper { display: flex; }
}
@media (min-width: 64rem) and (hover: hover) and (pointer: fine) {
  .ia-step-start:hover { background: var(--color-tea-light); }
  .ia-step-btn:hover { background: var(--color-accent-ring-on-dark); }
  .ia-step-btn.ia-step-next:hover { background: var(--color-warm); }
  .ia-map.is-stepping .ia-moment:not(.is-open) .ia-scene:hover { opacity: 1; }
}
@keyframes ia-arrive { from { opacity: 0; } }

/* ---------- Narrow: the moments side by side ----------
   Since 2026-10-29, under 64rem the six moments sit in a row the reader
   swipes along, as the trip runs, rather than in a column more than six
   screens tall, where the friend's lamp was out of sight by the counter
   and no lane could be read across the trip. The same layout, in the same
   tokens, as .svc-stages in case-study/case-study-base.css ("Narrow").

   - The row reaches the figure's edges, and each moment is the figure's
     width less --space-3xl (never more than 20rem), so the next moment
     shows at the right and says there is more without a word. Each swipe
     stops on one moment.
   - The drawing sits beside the name, not over it, so a moment is about a
     screen tall, and the disc stands over the name.
   - The lanes line up across the moments: each moment is a subgrid of the
     row, so "Where it can fail" sits at one height in all six, and a
     swipe made while reading a lane lands on the same lane. The switch
     hides one lane in every moment at once, so the rows stay matched. A
     browser without subgrid gets the same cards, unaligned.
   - map-rail.js puts the moment discs over the row as buttons, the
     current one filled (map-rail.css). Without the script the row still
     swipes.
   From 64rem none of this applies, and the grid above is unchanged. */
@media (max-width: 63.98rem) {
  .ia-figure .ia-matrix {
    grid-auto-flow: column;
    grid-auto-columns: min(calc(100% - var(--space-3xl)), 20rem);
    gap: 0 var(--space-sm);
    margin-inline: calc(-1 * var(--space-md));
    padding: 0 var(--space-md);
    scroll-padding-inline: var(--space-md);
    overflow-x: auto;
    overscroll-behavior-x: contain;
    scroll-snap-type: x mandatory;
    scrollbar-width: none;
  }
  .ia-figure .ia-matrix::-webkit-scrollbar { display: none; }
  .ia-figure .ia-matrix:focus-visible { outline: 2px solid var(--color-focus-ring); outline-offset: 2px; }
  .ia-moment {
    display: grid;
    grid-template-columns: 6rem minmax(0, 1fr);
    column-gap: var(--space-sm);
    scroll-snap-align: start;
    scroll-snap-stop: always;
  }
  .ia-scene { grid-column: 1; grid-row: 1; margin: 0 0 var(--space-sm); }
  .ia-figure .ia-moment-name {
    grid-column: 2;
    grid-row: 1;
    align-self: center;
    grid-template-columns: minmax(0, 1fr);
    row-gap: var(--space-2xs);
  }
  .ia-moment-pick { row-gap: var(--space-2xs); }
  .ia-moment-name .ia-n { margin-top: 0; justify-self: start; }
  .ia-lanes, .ia-lane { grid-column: 1 / -1; }
  @supports (grid-template-rows: subgrid) {
    /* Nine rows a moment: the drawing and name, and the eight lanes, one
       of which the switch hides in all six. */
    .ia-figure .ia-matrix { grid-template-rows: repeat(9, auto); }
    .ia-moment { grid-row: span 9; grid-template-rows: subgrid; }
    .ia-lanes { display: contents; }
    .ia-lane { grid-template-rows: auto 1fr; align-content: start; }
  }
}
@media (min-width: 640px) and (max-width: 63.98rem) {
  .ia-figure .ia-matrix {
    margin-inline: calc(-1 * var(--space-xl));
    padding: 0 var(--space-xl);
    scroll-padding-inline: var(--space-xl);
  }
}

/* The hero's four facts, under the dek: two to a row in the hero's text
   column, where the strip's four columns would be too narrow to read. The
   button row comes next, a component's step below, more than the --space-xl
   between the facts' own rows so it does not read as a fifth. */
.ia-facts { margin: var(--space-2xl) 0; }
@media (min-width: 1024px) { .ia-facts { grid-template-columns: repeat(2, 1fr); } }
.ia-facts dd a {
  color: var(--color-accent-text);
  font-weight: var(--weight-semibold);
  text-decoration: underline;
  text-underline-offset: 0.2em;
}
.ia-facts dd a:focus-visible { color: var(--color-charcoal); }
@media (hover: hover) and (pointer: fine) {
  .ia-facts dd a:hover { color: var(--color-charcoal); }
}

/* Accessibility, under the five decisions: one paragraph, its lead in
   the semibold. */
.ia-access { margin-top: var(--space-3xl); }

/* THE TRAIL, in the closing chapter on charcoal: the three stretches of the
   career the work drew on, each a picture over its years, a title that links
   to the page telling it, its one sentence, and where the link goes. Until
   2026-10-30 they were a bold-led list with nothing to press, on the one
   chapter where a prose link cannot go (accent-text on charcoal fails
   resting.mjs), so the trail sets its own inks: the warm for the title, the
   secondary for the sentence, and sage on dark for the years and the go line,
   7.47:1. It leaves the measure for the frame's full width, --col-full,
   from the column's left edge like the figures above it (Adam, 2026-10-30:
   "make this section full width"), three across from 720 as .build-eras
   does.

   The title's link covers the card with a pseudo-element, so the whole step
   is one target and a screen reader hears one link with the title's name;
   the go line repeats it for the eye and is hidden from the tree. Hover
   lifts the picture inside its frame by --motion-lift and underlines the
   title; no ink changes, so states.mjs has no new color to measure. The
   frame is a ring, not a border, on all four sides (curves.mjs). */
.aisle-trail {
  list-style: none;
  margin: var(--space-2xl) 0 var(--space-3xl);
  padding: 0;
  display: grid;
  gap: var(--space-2xl);
  width: var(--col-full);
  max-width: none;
}
@media (min-width: 720px) {
  .aisle-trail { grid-template-columns: repeat(3, minmax(0, 1fr)); gap: var(--space-xl); }
}
.aisle-trail-step { position: relative; display: grid; gap: var(--space-xs); align-content: start; }
.aisle-trail-art {
  aspect-ratio: 16 / 9;
  margin-bottom: var(--space-xs);
  border-radius: var(--radius-xl);
  overflow: hidden;
  box-shadow: 0 0 0 1px var(--rule-on-dark-strong);
}
.aisle-trail-art img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
  transition: transform var(--motion-move) var(--ease);
}
/* 16:9 because the SAP picture is, and its headline is part of it: a
   narrower frame cut that headline mid-word. The studio picture is wider,
   and anchors right so its logo stays whole; the Agent Review drawing is
   16:9 already. */
.aisle-trail-art--right img { object-position: right center; }
.build-chapter.ground-charcoal .aisle-trail-when {
  margin: 0;
  font-family: var(--font-sans);
  font-size: var(--text-xs);
  font-weight: var(--weight-semibold);
  letter-spacing: var(--tracking-caps);
  text-transform: uppercase;
  color: var(--color-accent-on-dark);
}
.build-chapter.ground-charcoal .aisle-trail-title {
  margin: 0;
  font-family: var(--font-sans);
  font-size: var(--text-lg);
  font-weight: var(--weight-semibold);
  line-height: var(--leading-tight);
  letter-spacing: var(--tracking-normal);
  color: var(--ink-on-dark);
}
.aisle-trail-title a {
  color: inherit;
  text-decoration: none;
  text-underline-offset: 0.2em;
}
.aisle-trail-title a::after { content: ""; position: absolute; inset: 0; border-radius: var(--radius-xl); }
.aisle-trail-title a:focus-visible { outline: none; text-decoration: underline; }
.aisle-trail-title a:focus-visible::after { outline: 2px solid var(--color-focus-ring); outline-offset: var(--space-xs); }
.build-chapter.ground-charcoal .aisle-trail-text {
  margin: 0;
  font-size: var(--text-base);
  line-height: var(--leading-body);
  color: var(--ink-on-dark-secondary);
}
.build-chapter.ground-charcoal .aisle-trail-go {
  margin: var(--space-2xs) 0 0;
  font-family: var(--font-sans);
  font-size: var(--text-sm);
  font-weight: var(--weight-semibold);
  color: var(--color-accent-on-dark);
}
.aisle-trail-go span { display: inline-block; transition: transform var(--motion-move) var(--ease); }
@media (hover: hover) and (pointer: fine) {
  .aisle-trail-step:hover .aisle-trail-art img { transform: scale(var(--motion-lift)); }
  .aisle-trail-step:hover .aisle-trail-title a { text-decoration: underline; }
  .aisle-trail-step:hover .aisle-trail-go span { transform: translateX(var(--space-2xs)); }
}
@media (prefers-reduced-motion: reduce) {
  .aisle-trail-art img, .aisle-trail-go span { transition: none; }
}

/* THE TEST PLAN, since 2026-10-30 (#evaluation). One column of eight
   paragraphs read as a list of things to do; it is a plan with a shape,
   so the shape is drawn. On the left, what is being bet and the one guess
   everything rests on; on the right, who it is tried with, as hairline rows
   like the decisions ledger above; across both, the three ways it can end.
   From 64rem the block takes --col-full from the column's left edge and
   each side keeps the measure; under that it stacks in reading order.

   The riskiest guess sits on a tea-light plate, the pull-out's ground
   (.eng3-pull, style.css): it restates the question the whole plan exists
   to answer. Tea-light, not caution: nothing here is refused. Its edge is
   --rule-card, and the plate is rounded on all four sides with no stripe.
   The three endings are the trail's titles (sans 18, semibold) under a
   line mark in sage on a tea-light disc, the homepage group heads' mark, so the eye finds the verdict before the condition. */
.ia-test {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: var(--space-2xl);
  align-items: start;
}
.ia-test-bet { font-size: var(--text-lg); max-width: var(--measure); }
.case-section .ia-test-bet p { margin-bottom: var(--space-lg); }
.case-section .ia-test-bet p.ia-test-risk {
  margin: 0;
  padding: var(--space-lg) var(--space-xl);
  background: var(--color-tea-light);
  border: 1px solid var(--rule-card);
  border-radius: var(--radius-xl);
}
.ia-test-who { margin: 0; max-width: var(--measure); }
.ia-test-who > div {
  padding: var(--space-lg) 0;
  border-top: 1px solid var(--rule-hairline);
}
.ia-test-who > div:first-child { padding-top: 0; border-top: 0; }
.ia-test-who > div:last-child { padding-bottom: 0; }
.ia-test-who dt {
  margin: 0 0 var(--space-2xs);
  font-family: var(--font-sans);
  font-size: var(--text-lg);
  font-weight: var(--weight-semibold);
  line-height: var(--leading-tight);
  color: var(--color-charcoal);
}
.ia-test-who dd {
  margin: 0;
  font-size: var(--text-lg);
  line-height: var(--leading-reading);
  color: var(--color-charcoal);
}

.ia-test-ends {
  list-style: none;
  margin: var(--space-3xl) 0 0;
  padding: var(--space-2xl) 0 0;
  border-top: 1px solid var(--rule-hairline);
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: var(--space-xl);
}
.ia-test-ends > li { margin: 0; padding: 0; max-width: var(--measure); }
.ia-test-ends > li::before { content: none; }
.ia-test-mark {
  display: block;
  box-sizing: border-box;
  width: var(--space-3xl);
  height: var(--space-3xl);
  margin-bottom: var(--space-md);
  padding: var(--space-xs);
  background: var(--color-tea-light);
  border-radius: var(--radius-pill);
  fill: none;
  stroke: var(--color-accent-text);
  stroke-width: 2;
  stroke-linecap: round;
  stroke-linejoin: round;
}
.case-section .ia-test-ends h3 {
  margin: 0 0 var(--space-2xs);
  font-family: var(--font-sans);
  font-size: var(--text-lg);
  font-weight: var(--weight-semibold);
  line-height: var(--leading-tight);
  letter-spacing: var(--tracking-normal);
  color: var(--color-charcoal);
}
.case-section .ia-test-ends p {
  margin-bottom: var(--space-xs);
  font-size: var(--text-base);
  line-height: var(--leading-body);
}
/* Each end is a line saying whether it takes all of its list or any one,
   then the list, so the list closes the column with no margin of its own. */
.ia-test-ends .build-list { margin-bottom: 0; }
@media (min-width: 40rem) {
  .ia-test-ends { grid-template-columns: repeat(3, minmax(0, 1fr)); gap: var(--space-2xl); }
}
@media (min-width: 64rem) {
  .ia-test, .ia-test-ends { width: var(--col-full); max-width: none; }
  .ia-test-who { max-width: none; }
  .ia-test { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--space-4xl); }
  .ia-test-ends { gap: var(--space-3xl); }
}
