/* dispatch-cockpit.css -- the cockpit prototype's own components, and nothing
 * else. Loaded by one page, prototype/dispatch-cockpit.html, after style.css.
 *
 * WHY ITS OWN FILE. The same reason design-psychology.css gives: reach, not
 * taxonomy. Nothing on any other page is a recommendation panel, a factor
 * list or a sortable fleet data table, and style.css is loaded by twenty
 * pages that would download all of this and render none of it.
 *
 * WHAT IT INHERITS. The page is a style.css page, so the hero, the prose
 * column, the chapter grounds, the footer blocks, the global focus ring on
 * links and buttons, and the reduced-motion blanket all come from there.
 * This file adds the cockpit and extends the focus ring to the controls
 * style.css does not cover: inputs, textareas and disclosure summaries.
 *
 * NO UPPERCASE, ANYWHERE. The site's kickers are tracked capitals; this
 * page's labels are lowercase sentence fragments at the same size and
 * weight, and the hero reuses .case-kicker, which is one of the two site
 * labels that is not uppercased. The glance block and the design
 * psychology note are not used here for that reason.
 *
 * NO MEANING IN COLOR ALONE. Every state a row or a card can be in is also a
 * word: "recommended", "assigned", "over hours", "helps", "hurts". The grounds
 * and glyphs are a second channel, never the only one.
 *
 * TWO STATUS COLORS, BOTH TOKENS. Until 2026-09-11 this file said "no new
 * color" and made the hours rule the darkest thing on the screen because the
 * palette had nothing warm that cleared a floor on a light ground. COLOR.md
 * section 2 now has a Status family, entered with measured rows for exactly
 * this page: --color-caution-text (6.45 on white, 5.09 on muted-light, and
 * 5.90 under warm) and --color-caution-light (charcoal on it 12.44). Sage is
 * still "fine": the recommendation, a factor that helps, the status line's
 * icon. Caution is "not fine": a close call the system will not pick, a
 * factor that hurts, a driver the rule removes. Every ratio below is from
 * COLOR.md section 2, on the ground it sits on:
 *
 *   charcoal      on white 15.33, warm 14.02, tea-light 12.90, muted-light 12.10
 *   muted-gray    on white  6.47, warm  5.91, tea-light  5.44, muted-light  5.11
 *   accent-text   on white  5.82, warm  5.32, tea-light  4.90, muted-light  4.60
 *   warm          on accent-text 5.32 (the primary button), on accent-hover 6.90
 *   accent-deep   as a ring or border: white 4.51, warm 4.12, tea-light 3.80
 *   muted-gray    as a border on white 6.47
 *   caution-text  on white 6.45, warm 5.90, tea-light 5.43, caution-light 5.23
 *   charcoal      on caution-light 12.44 (the close-call status line, the rule)
 *   charcoal      on caution-light 12.44
 *   on charcoal, the table head only: warm 14.02, ink-on-dark-secondary 8.49,
 *                 ink-on-dark-muted 5.26, accent-on-dark 7.47
 *
 * EVERY SIZE IS A STEP, every space a --space-*, every duration a --motion-*.
 * Two classes deep where the rule has to beat .case-section p, which is
 * class-and-element and would otherwise size the cockpit's paragraphs at
 * --text-lg on reading leading. style.css says this in its own margins; this
 * is the same lesson, applied.
 *
 * HIERARCHY FROM GROUNDS, NOT FROM NEW COLOR. Until #67 every zone was the
 * same white card on the same warm ground with the same 1px rule, so nothing
 * said which of them was the answer. Now the recommendation sits on
 * tea-light -- COLOR.md's own feature ground, "hero card, pull-outs" -- with
 * the load above it and the fleet below it still white on warm: context,
 * answer, reference, told apart by ground alone. The status line moved to
 * muted-light for the same reason, so it stops being the color of the zone
 * it sits under. The two rules above still hold: every ground is also a
 * word, and no token was added.
 *
 * ICONS, NOT GLYPHS. The polish pass took them further: one per situation on the tabs,
 * one per fact on the load, a leading icon on each card heading, an info
 * mark on the status line and a pointer on the rail's Try, and the
 * recommended and assigned chips filled -- sage under warm at 5.32, charcoal
 * under warm at 14.02 -- with a check in each. The one color the palette has
 * that is not sage or charcoal, --color-caution, is about 2.4:1 on white,
 * under even the 3:1 an icon or a border answers to, which is why COLOR.md
 * keeps it on charcoal and why there is no terracotta here; status color on
 * these white cards would need a token entered in COLOR.md section 2 with a
 * measured row. Direction and state were text glyphs -- a triangle, a
 * tick, a dash -- in muted-gray at the smallest size, which made the most
 * useful signal on the card the quietest thing on it. They are inline SVG
 * now, in the idiom the site header already uses, with the word still beside
 * every one. Helps is sage; hurts is the caution ink; neutral is muted-gray.
 * Icons are on the controls and the states -- the tabs, the directions, the
 * chips, the rule, the status line -- and not on labels or headings, where
 * a pass on 2026-09-10 put them and they read as clutter.
 *
 * THE RAIL. A column beside the cockpit that says, for the situation on
 * screen, what the point is, three things to look at, and one thing to try.
 * Numbered badges on the cockpit match the numbers in the rail, and change
 * with the situation. It is a rail and not a run of popovers because a
 * reader skimming a portfolio will not click Next seven times, a sequence
 * loses the thread the moment one is missed, and popovers are script-applied
 * state for states.mjs to measure; a column is prose. It is also the page's
 * own argument applied to itself: evidence beside the answer.
 */

/* ---------- The hero's disclosure ----------
   The one thing the credibility of the page depends on, so it is a box, not
   a sentence in the dek. On the warm hero, with the fill sage as its edge:
   accent-deep is 4.12:1 on warm, over the 3:1 a boundary answers to. Full
   border and the site's card radius, because curves.mjs is right. */
.ck-disclosure {
  max-width: var(--measure);
  margin: calc(-1 * var(--space-md)) 0 0;
  padding: var(--space-lg) var(--space-xl);
  border: 1px solid var(--color-accent-deep);
  border-radius: var(--radius-xl);
  background: var(--color-white);
}
.ck-disclosure p {
  margin: 0;
  font-family: var(--font-sans);
  font-size: var(--text-base);
  line-height: var(--leading-body);
  color: var(--color-charcoal);
}
.ck-disclosure p + p { margin-top: var(--space-xs); }
.ck-disclosure strong { font-weight: var(--weight-semibold); }

/* ---------- The four decisions, each beside its evidence ----------
   Until #78 this was a numbered list of four paragraphs, each ending with a
   line naming where on the screen to go and look. That asked a reader to hold
   a position in their head and scroll three sections up to check it, which is
   the same thing the cockpit itself refuses to ask of a dispatcher: the page
   was arguing for evidence beside the answer while keeping its own evidence a
   screen away. Each decision now carries a capture of the thing it decided.

   Two columns from 64rem: the argument on the left at a readable measure, the
   picture on the right. The numbered disc stays where it was, in the margin of
   the copy column, because the number orders the arguments and not the
   pictures. */
.ck-decisions {
  list-style: none;
  /* the paragraph that introduces the list ends flush against it otherwise;
     space above the first item matches the gap between the items */
  margin: var(--space-3xl) 0 0;
  padding: 0;
  counter-reset: decision;
  display: grid;
  gap: var(--space-block);
  /* The disc, and the one number this block authors. It is the case
     studies' step marker -- w-10 h-10 on a bg-accent circle with the
     numeral reversed out, in sap-product-maturity, dispatch-complexity and
     innovators-studio -- which is 40px, and 40px is --space-3xl but it is
     not a space: it sizes a mark. Named once here so the disc, the indent
     the prose hangs on and the title's minimum height cannot drift apart. */
  --ck-num: 40px;
}
.ckw-decision {
  counter-increment: decision;
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: var(--space-2xl);
  align-items: start;
}
/* THE ARGUMENT AT ITS MEASURE, THE EVIDENCE AT ITS OWN SIZE. This was halves,
   on the argument that a capture should not be enlarged and half the
   container was near the size the card captures were drawn at. Half was
   near, and near in the wrong direction: the card is 622 and half of the
   container is 584, so the two card captures were the only pictures on the
   site rendered UNDER their own scale, and every one of the four that span
   the row was rendered over it -- the rule card worst, at 651 drawn and 1216
   shown, which is an enlargement of 1.87 and is what makes that frame shout
   over the paragraph it is evidence for.

   So the column is set from the copy instead, and the pictures are capped
   individually below. 28rem is the measure at the lead's size once the disc
   and its gap come out of it, which leaves 720 for the evidence at the full
   container: enough for a card capture at 1:1, with the slack falling to the
   right of it the way the copy's slack already falls to the right of the
   text. Nothing here is sized to a fraction of the container any more.

   72rem and not the 64rem the halves used, because a fixed copy column
   changes what the breakpoint has to buy. At 64rem the evidence column came
   out 470 and a 622px card capture was shrunk into it by a quarter -- the
   two columns arriving before there was room for them. Below 72rem the item
   runs in one column and the card sits at 1:1 with ground beside it, which
   is the better of the two arrangements at that width. */
@media (min-width: 72rem) {
  .ckw-decision { grid-template-columns: minmax(0, 28rem) minmax(0, 1fr); gap: var(--space-4xl); }
  .ckw-decision .ckw-shot { margin-left: 0; }
}
.ckw-decision-copy {
  position: relative;
  /* the disc plus the case studies' own gap-3 between it and the title */
  padding-left: calc(var(--ck-num) + var(--space-sm));
}
/* Reversed out rather than set in sage: accent-deep is the FILL step of the
   sage and white on it is 4.51:1, where the same sage as small TEXT on a
   light ground is not (color.css says so at the token). A numeral inside the
   disc is also unambiguously a marker and not the start of the sentence
   beside it, which is what the hanging serif figure kept looking like. */
.ckw-decision-copy::before {
  content: counter(decision, decimal-leading-zero);
  position: absolute;
  left: 0;
  top: 0;
  display: grid;
  place-items: center;
  width: var(--ck-num);
  height: var(--ck-num);
  border-radius: 50%;
  background: var(--color-accent-deep);
  color: var(--color-white);
  font-family: var(--font-sans);
  font-size: var(--text-base);
  font-weight: var(--weight-semibold);
}
.ck .ckw-decision h3,
.ckw-decision h3 {
  /* The disc is taller than this title's line, so the title takes the
     disc's height and centres in it -- the case studies' items-center,
     reached without a wrapper. Top-aligning instead would drop the disc
     halfway into the paragraph below. */
  min-height: var(--ck-num);
  display: flex;
  align-items: center;
  margin: 0 0 var(--space-xs);
  font-family: var(--font-sans);
  font-size: var(--text-xl);
  font-weight: var(--weight-semibold);
  line-height: var(--leading-tight);
  letter-spacing: var(--tracking-heading);
  color: var(--color-charcoal);
}
.case-section .ckw-decision .ckw-lead {
  margin: 0;
  max-width: var(--measure);
  font-size: var(--text-lg);
  line-height: var(--leading-reading);
  color: var(--color-charcoal);
}

/* A capture, framed the way style.css frames a wide product screenshot, so a
   picture of an interface reads the same here as on the three build
   write-ups. The captures carry their own ground out to the edge, so the
   ring inside --shadow-media is what tells a reader where the screen stops;
   a border of its own beside that ring drew a 2px line. */
.ckw-shot { margin: 0; min-width: 0; }
.ckw-shot img {
  display: block;
  width: 100%;
  height: auto;
  border-radius: 12px;
  box-shadow: var(--shadow-media);
}
/* NOTHING IS PRINTED ABOVE THE SIZE IT WAS DRAWN, and the size a capture was
   drawn at is half its file, because these are taken at two device pixels to
   one. The ceiling is per capture and not per column: a column can only say
   how much room there is, and four of these had been taking all of it, which
   is how a 651px card came to be printed at 1216 next to a 1288px table
   printed at the same 1216 -- two pictures at wildly different scales,
   presented as though they were at one. Upscaling a screenshot softens every
   edge the interface drew crisply, and it makes the frame argue louder than
   the paragraph it is evidence for.

   A floor still beats this ceiling at narrow widths, on purpose: min-width
   wins over max-width in CSS, so .ckw-scroll below keeps its horizontal
   scroll rather than shrinking a table into illegibility. */
.ckw-shot img,
.ckw-frames img { max-width: var(--shot-w, 100%); }
/* The recommendation card and the record card, which are the same card
   captured twice and so the same width. */
.ckw-shot--card { --shot-w: 622px; }
.ckw-frame--rule { --shot-w: 651px; }
.ckw-frame--stale { --shot-w: 888px; }
/* A whole screen, which is drawn at about 1048 and shown at very nearly
   that. The cap is a round 64rem rather than the file's own width so that a
   recapture at a slightly different viewport does not silently change the
   width of the page. */
.ckw-decision--screen .ckw-shot { --shot-w: 64rem; }
.case-section .ckw-shot figcaption,
.case-section .ckw-frame-cap {
  margin: var(--space-sm) 0 0;
  max-width: var(--measure);
  font-family: var(--font-sans);
  font-size: var(--text-xs);
  line-height: var(--leading-ui);
  color: var(--color-muted-gray);
}
/* The label that has to survive the picture being screenshotted, quoted or
   pulled into a feed: the outcome history is invented, and a figure that
   travels without the sentence around it has to say so itself. */
.ckw-cap-label { font-weight: var(--weight-semibold); color: var(--color-caution-text); }

/* A SCREEN DOES NOT FIT BESIDE A PARAGRAPH, SO IT DOES NOT SIT BESIDE ONE.
   Three of the seven captures are the fleet data table or the width of the
   panel, and the table is 60rem of interface before it starts to scroll
   because its argument is that seven trucks and five factors stay in reach
   at once. In a 720px column that renders near 0.6, which puts its type at
   10px: the page would be claiming the table is legible while showing that
   it is not.

   Those two decisions run in ONE column instead -- the argument at its
   measure, the picture under it. The old arrangement kept the item in two
   columns and let only the figure span, which left the copy in a 28rem
   column with an empty 720px beside it and then a slab underneath. The void
   was the awkward part, not the picture.

   The three captures are taken at a 1080 viewport rather than 1320 (see
   cockpit-shots.mjs), so a whole screen is about 1048 drawn and sits inside
   the 64rem cap below at nearly 1:1, rather than being a 1288px file printed
   as wide as the page can print it. */
.ckw-decision--screen { gap: var(--space-2xl); }
/* THE PICTURE LINES UP WITH THE PARAGRAPH, NOT WITH THE NUMBER. Wherever an
   item runs in one column -- the two screen decisions at every width, and
   all five between 64 and 72rem -- the figure takes the same indent the copy
   takes, so the disc is the only thing left hanging in the margin and the
   block has one left edge instead of two. Beside the copy it needs none: it
   starts its own column there. Not below 64rem, where .ckw-scroll bleeds the
   picture out through the gutter to the viewport and an indent would be
   taking back the width that bleed exists to give. */
@media (min-width: 64rem) {
  .ckw-shot { margin-left: calc(var(--ck-num) + var(--space-sm)); }
}
@media (min-width: 72rem) {
  .ckw-decision--screen { grid-template-columns: minmax(0, 1fr); }
  .ckw-decision--screen .ckw-shot { margin-left: calc(var(--ck-num) + var(--space-sm)); }
}
.ckw-frames {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: var(--space-xl);
}
.ckw-frames > li { min-width: 0; }
.ckw-frames img {
  display: block;
  width: 100%;
  height: auto;
  border-radius: 12px;
  box-shadow: var(--shadow-media);
}
/* "First" and "Then" in the sage, so the two frames read as a sequence
   without a drawn arrow between them. The same shape .build-flow-cap uses on
   the Lucy Learns flow, for the same job. */
.case-section .ckw-frame-cap span {
  margin-right: var(--space-2xs);
  font-weight: var(--weight-semibold);
  color: var(--color-accent-text);
}

.ck-label {
  font-family: var(--font-sans);
  font-size: var(--text-xs);
  font-weight: var(--weight-semibold);
  letter-spacing: var(--tracking-normal);
  color: var(--color-accent-text);
}

/* ---------- The hero: the argument beside the interface ----------
   The page used to open with a kicker, a title and a 90-word dek, and the
   first thing a reader saw of the product was a device frame a screen and a
   half down. A hiring reader gets three questions answered in the first
   screen instead: what the problem is, what was designed, and how much of it
   is real. The picture answers the middle one, and it is a capture of the
   close call rather than a drawing, because a drawing of an interface is a
   claim about an interface.

   One column until 64rem, which is where the copy column would otherwise
   drop under the measure and the capture would be too small to read. */
.ckw-hero { padding-bottom: var(--space-block); }
/* minmax(0, 1fr) and not the implicit auto, in one column as well as two:
   the capture below sits in a box that scrolls, and a grid track sized to its
   content would grow to the capture's floor and carry the whole page sideways.
   .ck-stage says the same thing about the fleet data table. */
.ckw-hero-grid { display: grid; grid-template-columns: minmax(0, 1fr); gap: var(--space-3xl); align-items: start; }
/* Not 1:1. The capture is a 1736px screenshot of an interface whose whole
   point is five factors a reader can actually read, and an even split at 1440
   rendered it into 584px, which is about 9px of option-card body text. 1.18
   moves 48px across: the capture takes 632 and the copy 536.

   What that costs the copy is less than it looks. The measure is not the
   binding constraint on either side of this ratio -- 52ch at the dek's size
   is 826px, so the column was already the narrower of the two at 1:1 and
   still is. The trade is line length against legibility, and 536px of lede
   is a comfortable line where 584px of screenshot is not a readable table. */
@media (min-width: 64rem) {
  .ckw-hero-grid {
    grid-template-columns: minmax(0, 1fr) minmax(0, 1.18fr);
    gap: var(--space-4xl);
  }
}
/* --type-title is sized for a title that spans the page; this one shares the
   row with a picture, which is exactly what --type-title-inset exists for --
   type.css authors it for the homepage hero beside the portrait.

   FROM 768 UP, though, and not below, which is where .hero-title on the
   homepage has always put it and where this rule did not. The inset ramp's
   window opens at 48rem because that is where the title stops spanning the
   container, and under that it does nothing but hold its own 36px floor.
   That was invisible while every other h1 sat at 34 on a phone: this one
   was two pixels larger and nobody could see the seam. With the phone floor
   at 40 it is the one title on the site that got smaller than its
   neighbours, which is the same bug the whole time, finally visible. Below
   768 it takes --type-title from style.css, like every other h1. */
.ckw-hero-title { margin-bottom: var(--space-lg); }
@media (min-width: 768px) {
  .ckw-hero-title { font-size: var(--type-title-inset); }
}
.case-hero .ckw-hero-dek {
  max-width: var(--measure);
  margin: 0;
  font-family: var(--font-sans);
  font-size: var(--type-lede);
  line-height: var(--leading-body);
  color: var(--color-charcoal);
}
/* The copy column now ends on the actions, so the bottom margin that used to
   hold the disclosure off comes back to nothing. */
.ckw-hero-act {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-lg) var(--space-xl);
  margin: var(--space-2xl) 0 0;
}
.ckw-hero-link {
  font-family: var(--font-sans);
  font-size: var(--text-base);
  font-weight: var(--weight-semibold);
  color: var(--color-accent-text);
}
.ckw-hero-link:hover { color: var(--color-accent-hover); }
.ckw-hero-figure { margin: 0; min-width: 0; }
.ckw-hero-figure img {
  display: block;
  width: 100%;
  height: auto;
  border-radius: 12px;
  box-shadow: var(--shadow-media);
}
.case-hero .ckw-hero-figure figcaption {
  margin: var(--space-sm) 0 0;
  max-width: var(--measure);
  font-family: var(--font-sans);
  font-size: var(--text-xs);
  line-height: var(--leading-ui);
  color: var(--color-muted-gray);
}
.case-hero .ckw-hero-figure figcaption strong {
  font-weight: var(--weight-semibold);
  color: var(--color-charcoal);
}
/* ---------- The project, in six facts ----------
   Until 2026-09-19 this was a two-paragraph disclosure in a box, and it
   arrived before a reader had any reason to care what was being disclosed:
   the page led with its limits. The same facts are still here and still in
   the open -- self-directed, synthetic, not tested, not a model, informed by
   real dispatch work and not a copy of it -- but as the answers to the six
   questions a hiring reader asks of any case study, in the case studies'
   own metadata treatment (.build-facts in style.css). Six cells in three
   columns rather than four, so the two rows are even; the one sentence
   under them is the part of the disclosure that is a caveat and not a fact.
   Below 64rem the grid is style.css's own two, then one. */
.ckw-facts {
  margin: var(--space-4xl) 0 0;
  max-width: none;
}
@media (min-width: 1024px) {
  .ckw-facts { grid-template-columns: repeat(3, 1fr); }
}
.case-hero .ckw-facts dd { max-width: var(--measure); }
.case-hero .ckw-facts-note {
  margin: var(--space-xl) 0 0;
  /* The measure, not none. Under a three-column grid the one sentence used
     to run the grid's full width, 163 characters at 14px on a laptop against
     the 70 SPACING.md sets; the cells above it are each capped, and a
     caveat is prose, not a rule across the page. */
  max-width: var(--measure);
  font-family: var(--font-sans);
  font-size: var(--text-sm);
  line-height: var(--leading-body);
  color: var(--color-muted-gray);
}

/* ---------- What to try, and what this is ----------
   Two dash lists over the prototype, in the write-ups' .build-list, side by
   side from 48rem. The first is orientation and the second is the colophon:
   that the thing under them was designed and built by the same hands, in
   plain HTML, CSS and JavaScript, on invented data. The cockpit's own
   checklist under each tab is the detailed version of the first list and
   ticks itself off; this one names the four scenarios' worth of things to
   do in three lines and gets out of the way. */
.ckw-try-grid {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: var(--space-xl) var(--space-3xl);
  margin: var(--space-xl) 0 0;
}
@media (min-width: 48rem) {
  .ckw-try-grid { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); }
}
.ckw-try-grid .ck-label { display: block; margin: 0 0 var(--space-xs); }
.case-section .ckw-try-grid .build-list { margin: 0; }
.case-section .ckw-try-grid .build-list li { font-size: var(--text-sm); line-height: var(--leading-body); }
.ckw-try-grid .build-list a { color: var(--color-accent-text); font-weight: var(--weight-semibold); }
.ckw-try-grid .build-list a:hover { color: var(--color-accent-hover); }

/* ---------- The close ----------
   The page's last paragraph, in the serif at the key-ideas size the writing
   recap uses, and without the recap's box because it stands on the tea
   ground already. The sage rule over it is the mark the case studies set
   above a body heading, doing the same job for a paragraph that has none. */
.ckw-close { margin: var(--space-3xl) 0 0; }
.ckw-close::before {
  content: "";
  display: block;
  width: 4rem;
  height: 4px;
  margin-bottom: var(--space-lg);
  background: var(--color-accent-deep);
}
.case-section .ckw-close p {
  text-wrap: pretty;
  margin: 0;
  max-width: var(--measure);
  font-family: var(--font-serif);
  font-size: var(--text-xl);
  line-height: var(--leading-tight);
  letter-spacing: var(--tracking-heading);
  color: var(--color-charcoal);
}

/* ---------- A capture that will not shrink past reading ----------
   Below 64rem, where the decisions stop being two columns, the column is
   narrower than the interface in these captures,
   and `width: 100%` on a 1288px screenshot in a 342px column is a picture of
   a data table nobody can read: the page would be showing that the fleet
   stays in reach while making it unreadable to show it. So the capture keeps
   a floor and the box under it scrolls, which is what .ck-table-wrap does
   with the live table at the same widths and what .build-flow-row does with
   the Lucy Learns phones.

   ONLY THE TABLE. This floor used to apply to every capture on the page at a
   second, lower value -- 38rem -- and a card does not earn it. A card is one
   surface with one column of text on it, and shrinking it to a phone's width
   costs nothing but size; a data table shrunk to the same width loses the
   thing it is evidence for, which is that seven trucks and five factors are
   in reach at once. What the lower floor actually produced was five captures
   pinned at 608px in a 500px column, each scrolling sideways to show a
   picture the column could have held whole. The sideways scroll is now the
   three screen captures' alone, where it is the argument, and a card capture
   takes the column it is in.

   The floor that is left is not a number chosen here: the fleet capture is
   the data table plus its ground, and the table authors its own minimum at
   60rem, so 62rem is that minimum and the two insets around it. The box
   bleeds through the gutter to the viewport so a phone gets the width back,
   and the caption stays outside it: a caption that scrolled away from its
   picture would be the one piece of this that has to stay put. */
.ckw-scroll { display: block; }
@media (max-width: 63.99rem) {
  .ckw-decision--screen .ckw-scroll {
    margin-inline: calc(var(--gutter) * -1);
    padding-inline: var(--gutter);
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
    scrollbar-width: thin;
  }
  .ckw-decision--screen .ckw-scroll img { min-width: 62rem; }
}

/* THE WAY BACK TO FULL SIZE. A card capture that takes the column is printed
   under the size it was drawn -- the stale note is 888px of interface and
   renders about 500 in a phone column, a little over half -- so the page owes
   the reader a way to see it whole. That way is the file itself: these are
   taken at two device pixels to one, so the file is twice the size the page
   prints, and a browser's own image viewer pinches, pans and zooms it better
   than anything built here -- with no script and no state for states.mjs to
   reach.

   The link rides at the end of the caption rather than on the picture. On the
   picture it would have no name to read, and it would wrap a focus ring
   around a 12px curve that curves.mjs is right to ask questions about. It is
   gone above 64rem, where every card capture in the decisions is already at
   its drawn size and the file is not a larger picture but the same one.
   Accent-text is the inline link ink this page already uses, in
   .ckw-try-grid, and accent-hover is what .ckw-hero-link does with it.

   THE HERO CAPTURE IS THE EXCEPTION, and its link never hides. That picture
   never reaches its drawn size anywhere on this page: one column below 64rem,
   and above it the two-column ratio hands the figure 1.18fr of the container,
   which is 537px at 1100 and about 632 at 1440 against 868 drawn. The ratio
   is a deliberate trade of copy width against legibility -- the comment on
   .ckw-hero-grid argues it out -- and a way back to the whole picture is the
   other half of that trade rather than a concession at narrow widths. */
.ckw-full {
  white-space: nowrap;
  font-weight: var(--weight-semibold);
  color: var(--color-accent-text);
}
.ckw-full:hover { color: var(--color-accent-hover); }
@media (min-width: 64rem) {
  .ckw-decision .ckw-full { display: none; }
}

/* ---------- The one drawing, and the one that closes ----------
   Everything else on this page is a capture. These two are the room the
   interface is used in and the thesis it is built on, neither of which the
   interface can show. Sixteen by nine at container width, in the style the
   writing features are cut to and through the same script. */
.ckw-scene { margin: var(--space-2xl) 0 0; }
.ckw-scene img {
  display: block;
  width: 100%;
  height: auto;
  border-radius: 12px;
}
.case-section .ckw-scene figcaption,
.case-footer .ckw-scene figcaption {
  margin: var(--space-sm) 0 0;
  max-width: var(--measure);
  font-family: var(--font-sans);
  font-size: var(--text-xs);
  line-height: var(--leading-ui);
  color: var(--color-muted-gray);
}
.ckw-scene--close { margin: 0 0 var(--space-3xl); }

/* ---------- The design question ----------
   One sentence, on the feature ground, because it is the thing the four
   decisions are all answers to and it was previously the fourth sentence of
   the third paragraph. */
.case-section .ckw-question {
  max-width: var(--measure);
  margin: var(--space-2xl) 0 0;
  padding: var(--space-lg) var(--space-xl);
  border-left: 2px solid var(--color-accent-deep);
  background: var(--color-white);
  font-family: var(--font-sans);
  font-size: var(--text-lg);
  line-height: var(--leading-body);
  color: var(--color-charcoal);
}
.ckw-question-label {
  display: block;
  font-size: var(--text-xs);
  font-weight: var(--weight-semibold);
  color: var(--color-accent-text);
}

/* ---------- The deeper argument, folded ----------
   What a reader is OWED stays in the open: what the factor comparison is not,
   that the outcome history is invented, that Assign here stages a choice Undo
   reverses. What is folded is the reasoning behind a decision already stated
   in full. The summary says which of the two it is rather than "read more",
   so a reader can tell from the label that nothing load-bearing is hidden. */
.ckw-more {
  margin: var(--space-md) 0 var(--space-xl);
  max-width: var(--measure);
  border-top: 1px solid var(--rule-hairline);
}
.ckw-more summary {
  display: flex;
  align-items: center;
  gap: var(--space-xs);
  padding: var(--space-sm) 0 0;
  font-family: var(--font-sans);
  font-size: var(--text-sm);
  font-weight: var(--weight-semibold);
  line-height: var(--leading-ui);
  color: var(--color-accent-text);
  cursor: pointer;
  list-style: none;
}
.ckw-more summary::-webkit-details-marker { display: none; }
.ckw-more summary::marker { content: ''; }
.ckw-more summary:hover { color: var(--color-accent-hover); }
/* The chevron is drawn rather than fetched, because it is the only mark in
   this block and an inline SVG per summary would be six copies of it in the
   markup. It turns on open, which is the one thing the state has to say that
   the word above it does not. */
.ckw-more summary::after {
  content: '';
  width: 0.5em;
  height: 0.5em;
  border-right: 2px solid currentColor;
  border-bottom: 2px solid currentColor;
  transform: translateY(-0.15em) rotate(45deg);
  transition: transform var(--motion-state) var(--ease);
}
.ckw-more[open] summary::after { transform: translateY(0.1em) rotate(-135deg); }
.ckw-more-body { padding-top: var(--space-xs); }
.case-section .ckw-more-body p {
  margin: var(--space-sm) 0 0;
  max-width: var(--measure);
  font-size: var(--text-base);
  line-height: var(--leading-body);
  color: var(--color-charcoal);
}

/* ---------- The study, as a shape ----------
   Two conditions and what is between them. The second side takes the feature
   ground and the sage edge, because it is the one with the recommendation on
   it and the comparison is otherwise two identical cards. */
.ckw-compare {
  display: grid;
  gap: var(--space-md);
  margin: var(--space-2xl) 0 var(--space-lg);
  align-items: stretch;
}
@media (min-width: 48rem) {
  .ckw-compare { grid-template-columns: minmax(0, 1fr) auto minmax(0, 1fr); gap: var(--space-xl); }
}
.ckw-compare-side {
  padding: var(--space-lg) var(--space-xl);
  border: 1px solid var(--color-tag-border);
  border-radius: var(--radius-xl);
  background: var(--color-white);
}
.ckw-compare-side--b { border-color: var(--color-accent-deep); }
.case-section .ckw-compare-side p {
  margin: var(--space-xs) 0 0;
  font-size: var(--text-base);
  line-height: var(--leading-body);
  color: var(--color-charcoal);
}
.case-section .ckw-compare-h {
  margin: 0;
  font-family: var(--font-sans);
  font-size: var(--text-lg);
  font-weight: var(--weight-semibold);
  line-height: var(--leading-tight);
  color: var(--color-charcoal);
}
.case-section .ckw-compare-vs {
  margin: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  font-family: var(--font-sans);
  font-size: var(--text-sm);
  line-height: var(--leading-ui);
  color: var(--color-muted-gray);
  text-align: center;
}
.case-section .ckw-compare-note {
  margin: 0;
  /* On the note itself, at its own 16px. The wrapper it sits in is capped
     at 18px, which SPACING.md warns about: a cap resolved at the wrong size
     is the wrong cap, and this one came out at 77 characters. */
  max-width: var(--measure);
  font-size: var(--text-base);
  line-height: var(--leading-body);
  color: var(--color-charcoal);
}

/* ---------- Three questions, and what each would change ----------
   A card each, rather than three bullets, so the section reads as a plan and
   not as a list of things that might go wrong. */
.ckw-questions {
  list-style: none;
  margin: var(--space-2xl) 0 0;
  padding: 0;
  display: grid;
  gap: var(--space-xl);
}
@media (min-width: 60rem) {
  .ckw-questions { grid-template-columns: repeat(3, minmax(0, 1fr)); }
}
.ckw-questions > li {
  padding: var(--space-lg) var(--space-xl);
  border: 1px solid var(--color-tag-border);
  border-radius: var(--radius-xl);
  background: var(--color-white);
}
.case-section .ckw-questions h3 {
  margin: 0 0 var(--space-xs);
  font-family: var(--font-sans);
  font-size: var(--text-base);
  font-weight: var(--weight-semibold);
  line-height: var(--leading-tight);
  letter-spacing: var(--tracking-normal);
  color: var(--color-charcoal);
}
.case-section .ckw-questions p {
  margin: 0;
  font-size: var(--text-base);
  line-height: var(--leading-body);
  color: var(--color-charcoal);
}

/* ---------- The assumption most likely to be wrong ----------
   On the caution ground, which COLOR.md's Status family entered for this page
   and which charcoal reads 12.44:1 on. It is the one thing in the section
   that is not a plan: it is a prediction that the plan will find the card
   structured wrongly.

   The caution ground is 1.04:1 against ground-tea, which is a tint and not
   an edge: the card reads as a smudge on the section rather than as a card
   beside the three above it. Nothing measured it before, because both
   resting.mjs and states.mjs read ink and not the boundary between two
   grounds. The edge is the caution ink at the 1px the question cards use, so
   the two weights match and only the color differs; the ink is 5.43:1 on tea
   and 5.23:1 on the fill, both well past the 3:1 a boundary owes. */
.ckw-callout {
  display: flex;
  align-items: center;
  gap: var(--space-2xl);
  margin: var(--space-2xl) 0 var(--space-2xl);
  padding: var(--space-lg) var(--space-xl);
  border: 1px solid var(--color-caution-text);
  border-radius: var(--radius-xl);
  background: var(--color-caution-light);
}
/* The mark: a drawing of the assumption, in the hand the case studies'
   impact bands took in #208 -- the clipboard with its five lines, and the
   tag it has no row for, standing clear of it. A PNG whose only ink is the
   line, filed at 320x180 for a 160px slot; the height follows the file's
   16:9, so the width is the one number here. The line is painted in the
   caution ink, because this mark sits on the caution ground and not on the
   deep accent band the impact marks' white line was drawn for: 5.23:1 on
   the fill, past the 3:1 a non-text mark owes. `flex: none` so the measure
   is what gives. It used to be a hairline SVG in a 100-unit box that drew
   itself, stroke by stroke, as the callout entered the viewport; the draw
   rules, the keyframes, the reduced-motion override and the script that
   set .is-inview went with it, because a picture has no path to draw. */
.ckw-callout-mark {
  flex: none;
  width: 160px;
  height: auto;
  display: block;
}
.ckw-callout-body { min-width: 0; }
@media (max-width: 640px) {
  .ckw-callout {
    flex-direction: column;
    align-items: flex-start;
    gap: var(--space-lg);
  }
}
/* Three classes, because `.case-section .ckw-callout p` is two classes and an
   element and therefore outranked the two-class selector this used to be. It
   won everything: the heading rendered at 16px charcoal on leading-body with
   no margin under it, so the label sat welded to its paragraph while the
   three cards above kept their 8px. What is written here now is what the
   page actually shows -- the question cards' h3 treatment exactly, which is
   the spacing the card was asked to match. */
.case-section .ckw-callout .ckw-callout-h {
  margin: 0 0 var(--space-xs);
  font-family: var(--font-sans);
  font-size: var(--text-base);
  font-weight: var(--weight-semibold);
  line-height: var(--leading-tight);
  letter-spacing: var(--tracking-normal);
  color: var(--color-charcoal);
}
.case-section .ckw-callout p {
  margin: 0;
  max-width: var(--measure);
  font-size: var(--text-base);
  line-height: var(--leading-body);
  color: var(--color-charcoal);
}

/* ---------- The hero, into the cockpit ----------
   120px of nothing sat between the disclosure card and "The cockpit" at
   1440, and 96 at 390: the hero's own bottom padding plus the chapter's
   top. On a build write-up that gap is a section change and earns its
   keep, because the chapter under the hero is a different ground. Here it
   is not -- the hero is warm and this chapter is ground-warm -- so the two
   paddings stack across a boundary nobody can see, and the page opens with
   a hole. The chapter keeps a break; it just stops paying for one twice.
   Scoped to this page, because the other three build write-ups do change
   ground there and their spacing is right. */
#the-cockpit { padding-top: var(--space-2xl); }

/* ---------- The cockpit frame ----------
   The prototype is framed rather than set loose on the ground, for the
   reason style.css gives for .build-phone and .build-laptop: a page that
   frames its captures in a bezel and shows the live thing as a bare column
   is showing two ideas of what a screen is. So this is the same object --
   one --bezel of --device-chrome, --shadow-device under it, and the inner
   radius DERIVED from the outer rather than authored a second time.

   Two values are authored, both by precedent. --shell-radius is the laptop
   lid's 14 and not the phone's 26, because 26 on a box this wide reads as a
   lozenge, which is the argument style.css already makes at .build-laptop.
   ON THE CONTENT'S WIDTH, NOT THE MONITOR'S. Until 2026-09-11 the screen was
   1920 and the frame left the container to hold it, on the argument that a
   dispatch cockpit is a monitor-width interface and the 1280px container
   puts the fleet data table and the recommendation into a column. That was
   true, and it cost more than it bought. It made the demo the one element on
   the page that started on its own line: the hero's assumption card, the five
   slides above and every heading down the page range to the container's left
   edge, and the frame ranged to the viewport's middle, 100px outboard of all
   of them at 1440. A page whose subject is an interface that fits cannot
   itself look unaligned.

   So the frame is the container's content box: --container-max less its two
   gutters, capped by the viewport less the same, centred. Centring and
   ranging are the same thing at this width -- a box the width of the content
   column, centred in the viewport, has its left edge exactly where .container
   puts the text -- which is why there is no margin-inline-start here.

   What it costs is real and is the reason the 1920 existed: the cockpit's
   two-column stage at 1216 is narrower than at 1920, so the fleet data table
   reaches its own min-width sooner and scrolls inside its wrap on viewports
   where it used to sit whole. The wrap is built for that and says so; the
   whole-table view now wants a wider monitor than it did. */
.ck-frame {
  --shell-radius: 14px;
  width: min(100% - var(--gutter) * 2, calc(var(--container-max) - var(--gutter) * 2));
  margin: var(--space-3xl) auto 0;
  padding: var(--bezel);
  border-radius: var(--shell-radius);
  background: var(--device-chrome);
  box-shadow: var(--shadow-device);
}

/* The screen. It keeps the section's warm ground, so the cockpit is lit the
   way it was designed and nothing inside it changes contrast by being
   framed; what the bezel adds is an edge, not a new surface to measure. */
.ck {
  border-radius: calc(var(--shell-radius) - var(--bezel));
  background: var(--color-warm);
  padding: var(--space-xl);
}
@media (min-width: 48rem) {
  .ck { padding: var(--space-3xl); }
}

/* ---------- The cockpit on its own: ?embed, and nothing else ------------
   The homepage's prototype card opens this page inside the tablet that
   app-device.js stands over the page, and a tablet with a site nav in it is
   a tablet showing a website. So the flag in the head of the page hands the
   document data-embed and these rules take everything off it but the
   cockpit: the skip link, the nav, the hero, the slideshow, the three
   chapters of write-up and the footer. What is left is the one thing the
   card promised.

   THE FRAME COMES OFF WITH THEM, and that is the point of the block rather
   than an afterthought in it. .ck-frame is the site's device chrome -- a
   bezel of --device-chrome with --shadow-device under it -- and inside the
   tablet it would be a bezel inside a bezel, the same doubling the prototype
   card's own note talks itself out of. The tablet is the frame here; the
   cockpit is the screen.

   Nothing is deleted from the DOM and no rule here is reachable without the
   flag, so the four browser checks measure this page exactly as they did:
   they load it at its own address, where data-embed is not set. */
html[data-embed],
html[data-embed] body { background: var(--color-warm); }
/* THE NAV IS 80px TALL AND IS NOT HERE, so the one number that describes it
   is zero. Three things read it and all three were wrong by 80px with the
   nav hidden: the tab strip is sticky at top: var(--nav-height), and sticky
   pushes an element DOWN when its natural position is above that offset, so
   the strip landed 12px over the first line of the scenario's sentence;
   style.css scroll-padding-top parks every anchor 80px low; and the
   scroll-margin under #ck-panel adds the same 80 to every control it keeps
   out from under the strip. One declaration, because one fact changed. */
html[data-embed] { --nav-height: 0px; }
html[data-embed] .skip-link,
html[data-embed] .site-nav,
html[data-embed] .case-footer,
html[data-embed] main > :not(#try-it),
html[data-embed] #try-it > .container { display: none; }
html[data-embed] #try-it { padding: 0; }
html[data-embed] .ck-frame {
  width: 100%;
  margin: 0;
  padding: 0;
  border-radius: 0;
  background: none;
  box-shadow: none;
}
html[data-embed] .ck { border-radius: 0; }
/* ====================== THE PAGE RANGES LEFT ==============================
   .case-narrow is 56rem with margin: 0 auto, so on every other page of the
   site a heading and its paragraph sit in the middle of the 1280 container
   with the ground either side of them. That is right for an essay, where the
   column IS the page. It is wrong here, because this page's subject is three
   pieces of interface -- the hero's assumption card, the four slides and the
   cockpit itself -- and all three range to the container's left edge. A
   centred 56rem column started 192px inboard of them at 1440, so the reader
   got a left edge for the pictures and a different one for the words about
   them.

   Ranging rather than widening: the measure is untouched. .writing-measure
   and --measure still hold a line to about 70 characters, and 56rem still
   caps what sits inside .case-narrow. The only thing that changes is which
   end of the container the leftover ground is on.

   Scoped to this page by a class on <body> rather than edited in style.css,
   because .case-narrow is the shared helper twenty-odd other pages lay their
   text out with and none of them has this problem.

   The child combinator is load-bearing. Three blocks on this page carried
   .container and .case-narrow on the SAME div, where margin-inline: 0 ranges
   the CONTAINER left and drops the page's own 1280 centring with it -- the
   heading landed on the viewport's gutter, 80px outboard of everything it was
   supposed to line up with. Those three are now a .case-narrow inside a
   .container, like every other block here, and this rule only reaches a
   .case-narrow that has a .container above it. */
.ckw-page .container .case-narrow { margin-inline: 0; }

/* ============================ THE SLIDESHOW ==============================
   Four screens in a row, one ranged to the page's left edge, the next cut by
   the right edge of the track. The cut is the only thing on the page that
   says there are more, and it has to be a real one: a fade or a gradient over
   the next slide would say "there is more" about an image whose contrast this
   site measures, and it would say it to nobody who cannot see it. So the
   neighbours are at full strength and simply run off the sides, and the dots
   under the track say the same fact in a form a screen reader can read.

   RANGED, NOT CENTRED. Until 2026-09-11 the slide sat in the middle of the
   viewport, and the paragraph over it and the assumption card over that did
   not: they range to the container's left edge, so the tablet started 68px
   to the right of the sentence introducing it. --slide-x is that edge -- the
   .container's own arithmetic, half of what is left over past --container-max
   plus the gutter -- and the first slide starts there. The cost is the cue on
   the left: under about 1344px the gutter is narrower than the gap between
   slides, so the previous screen does not show at all. That cue was never
   the important one -- the reader has already seen that screen -- and the
   arrow under the track says it anyway.

   The mechanism is the browser's. overflow-x plus scroll-snap is the whole
   slideshow; cockpit-slides.js adds arrows, dots and a spoken position on top
   of a thing that already worked without it. -------------------------------- */
.ck-show {
  /* The width of one slide, and the source of every other number here. The
     capture is 680 of screen and 680 plus two bezels was the widest worth
     showing -- past its own size it is an upscale. 660 is under that on
     purpose, and it is a tenth over the 600 it was until 2026-09-17: at 616
     outer the tablet read as a card, and the head and caption were carrying
     more of the explaining than the screen they were about. At 676 the
     capture is still a downscale, which is sharp, and the 20px short of the
     cap goes to the next screen at the right, which is the one cue saying
     there are more. 84vw is what leaves a neighbour showing on anything too
     narrow for the cap. */
  --slide-w: min(calc(660px + var(--bezel) * 2), 84vw);
  --slide-gap: var(--space-xl);
  /* Where the slide starts: the left edge of a .container, which is the edge
     the assumption card in the header ranges to. 100% is the viewport here,
     because .ck-show is full-bleed. */
  --slide-x: max(var(--gutter), calc((100% - var(--container-max)) / 2 + var(--gutter)));
  margin-top: var(--space-2xl);
}
/* On a phone the ground has to come out of the slide rather than out of the
   gap: 88vw with a 32px gap put the next slide's left edge a pixel past the
   viewport, which is a slideshow that looks like a single picture. 80 and a
   narrower gap leave about 24px of the next screen showing, which is the
   whole cue. */
@media (max-width: 47.99rem) {
  .ck-show { --slide-w: 80vw; --slide-gap: var(--space-md); }
}
.ck-slides {
  list-style: none;
  margin: 0;
  display: flex;
  gap: var(--slide-gap);
  overflow-x: auto;
  scroll-snap-type: x mandatory;
  /* A flick that runs out of slides should stop at the end of the slideshow
     rather than carry the page sideways behind it. */
  overscroll-behavior-inline: contain;
  /* The start padding is what puts the first slide on the container's edge,
     and the end padding is what lets the last one get there too: without it
     the scroller runs out of room with the fourth screen still short of the
     line the other three snapped to. scroll-padding matches the start so a
     snap lands in the same place a press does. */
  padding-inline: var(--slide-x) max(0px, calc(100% - var(--slide-x) - var(--slide-w)));
  scroll-padding-inline-start: var(--slide-x);
  /* Room for the focus ring and the shadow under each screen; without it both
     are clipped by the scroll box. */
  padding-block: var(--space-2xs) var(--space-sm);
  scrollbar-width: none;
}
.ck-slides::-webkit-scrollbar { display: none; }
/* The list is focusable, because a region that scrolls has to be reachable
   without a pointer. The ring goes round the whole track rather than the
   active slide: the track is what the key is scrolling. */
.ck-slides:focus-visible {
  outline: 2px solid var(--color-accent-deep);
  outline-offset: 2px;
  border-radius: 4px;
}
.ck-slide {
  flex: 0 0 auto;
  width: var(--slide-w);
  min-width: 0;
  scroll-snap-align: start;
}
/* A neighbour is something to pull in. The script marks every slide before
   the one on show is-prev and every one after it is-next, the cut neighbour
   takes the pointer, and a click on it scrolls it into place -- the same
   move as the arrow under the track, from the thing the eye is already on.

   IT USED TO GROW AN ARROW UNDER THE POINTER AND NO LONGER DOES. A round
   badge faded in over the tablet on hover, saying what the cursor had
   already said. On a page whose argument is that an interface can be calm,
   a control that appears when the pointer crosses a photograph is one more
   thing moving, and it moved over the very captures this section is asking
   the reader to look at. The cursor is the affordance now; the arrows under
   the track are the visible ones, and they never move. */
.ck-slide.is-prev,
.ck-slide.is-next { cursor: pointer; }

/* The situation, over the screen. A number, the situation's own name in the
   sage, then what this particular screen is -- the same three-part line the
   tabs and the blurb make under the cockpit, folded into one row.

   Two classes deep, for the reason .build-diagram .build-switch-head is:
   .case-section p is class-and-element, so a single class on a <p> loses to
   it and this line would come back at reading size and reading leading. */
.ck-show .ck-slide-head {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  align-items: center;
  column-gap: var(--space-xs);
  row-gap: var(--space-2xs);
  margin: 0 0 var(--space-md);
  font-family: var(--font-sans);
  line-height: var(--leading-ui);
}
.ck-slide-n {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 1.5rem;
  height: 1.5rem;
  border-radius: var(--radius-pill);
  background: var(--color-accent-text);
  font-size: var(--text-2xs);
  font-weight: var(--weight-semibold);
  color: var(--color-warm);
  font-variant-numeric: tabular-nums;
}
.ck-slide-sit {
  font-size: var(--text-xs);
  font-weight: var(--weight-semibold);
  letter-spacing: var(--tracking-normal);
  color: var(--color-accent-text);
}
/* What is happening on the screen, in a plain sentence, under the number and
   the situation and across both columns. --text-lg, because at half the
   width the picture no longer explains itself and this line is doing the
   work the picture used to. */
.ck-slide-title {
  grid-column: 1 / -1;
  font-size: var(--text-lg);
  font-weight: var(--weight-semibold);
  color: var(--color-charcoal);
}

/* The screen, in the tablet. The same object as .ck-frame under it and the
   homepage card's thumb: one --bezel of --device-chrome, --shadow-device,
   and the inner radius DERIVED from the outer so the two corners are
   concentric. --shell-radius is --radius-xl, the card's, because this is
   the card's tablet -- nearly square, no foot -- and not the laptop the
   1920px frame below takes its 14 from. Under 48rem the shell holds the
   phone capture and takes the phone's 30, which is .build-phone's.

   The ratio is declared on the image rather than inherited from the file,
   because <picture> swaps 4:3 for a portrait one at 48rem and a box that
   resizes after the image decodes is a layout shift. The capture carries
   its own warm ground to the edge; the bezel is what says where the screen
   stops, which is why there is no border here any more. */
.ck-slide-fig { margin: 0; }
.ck-slide-screen {
  --shell-radius: var(--radius-xl);
  padding: var(--bezel);
  border-radius: var(--shell-radius);
  background: var(--device-chrome);
  box-shadow: var(--shadow-device);
}
.ck-slide-screen img {
  display: block;
  width: 100%;
  height: auto;
  aspect-ratio: 4 / 3;
  border-radius: calc(var(--shell-radius) - var(--bezel));
  background: var(--color-warm);
}
@media (max-width: 47.99rem) {
  .ck-slide-screen { --shell-radius: 30px; }
  .ck-slide-screen img { aspect-ratio: 780 / 1640; }
}
/* --text-sm and charcoal rather than the --text-xs muted grey every other
   caption on this page takes: those captions annotate a picture that is
   already legible, and this one is half the explanation. */
.case-section .ck-slide-fig figcaption {
  margin: var(--space-md) 0 0;
  /* The measure, or the slide, whichever is narrower. --measure resolves to
     about 620 and the slide is 616, so without the min() the caption would
     be the one thing on the slide wider than the tablet it describes. */
  max-width: min(var(--measure), 100%);
  font-family: var(--font-sans);
  font-size: var(--text-sm);
  line-height: var(--leading-body);
  color: var(--color-charcoal);
}

/* ---------- The controls under the track ----------
   Ranged to the same edge as the slide, --slide-x, so the arrows sit under
   the screen they move rather than under the middle of a full-bleed track.
   They were centred while the slide was; a centred control under a ranged
   slide would be the one thing on the section on a different line. */
.ck-show-bar {
  display: flex;
  align-items: center;
  gap: var(--space-md);
  margin-top: var(--space-lg);
  padding-inline-start: var(--slide-x);
}
.ck-show-group {
  display: flex;
  align-items: center;
  gap: var(--space-sm);
}
.ck-show-nav {
  appearance: none;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  /* 44, which is the pointer target every other round control on this site
     takes, and well over the 24 the success criterion asks for. */
  width: 2.75rem;
  height: 2.75rem;
  padding: 0;
  border: 1px solid var(--color-rule);
  border-radius: var(--radius-pill);
  background: var(--color-white);
  color: var(--color-charcoal);
  cursor: pointer;
  transition: background-color var(--motion-state) var(--ease),
              border-color var(--motion-state) var(--ease);
}
.ck-show-nav .ck-icon { width: 1.25rem; height: 1.25rem; vertical-align: 0; }
.ck-show-nav:not([aria-disabled="true"]):hover { background: var(--wash-on-light-hover); }
/* At either end the button stays in the tab order and stays pressable; it
   just has nowhere to go, and says so. Not [disabled]: disabling the element
   the reader is standing on drops their focus to the top of the document. */
.ck-show-nav[aria-disabled="true"] {
  border-color: var(--color-tag-border);
  color: var(--color-muted-gray);
  background: none;
  cursor: default;
}
.ck-show-dots {
  display: flex;
  align-items: center;
  /* 2px, tighter than --space-2xs: the dots are one control, not five. */
  gap: 2px;
}
.ck-show-dot {
  appearance: none;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  /* The mark is 8px; the button around it is 24, which is the target size
     rather than the drawing. */
  width: 1.5rem;
  height: 1.5rem;
  padding: 0;
  border: 0;
  background: none;
  cursor: pointer;
}
.ck-show-dot-mark {
  width: 0.5rem;
  height: 0.5rem;
  border-radius: var(--radius-pill);
  background: var(--color-tag-border);
  transition: background-color var(--motion-state) var(--ease),
              width var(--motion-move) var(--ease);
}
.ck-show-dot:hover .ck-show-dot-mark { background: var(--color-muted-gray); }
/* The one at the middle of the track is a bar rather than a dot, so which
   screen you are on survives being seen out of the corner of an eye. */
.ck-show-dot[aria-current="true"] .ck-show-dot-mark {
  width: 1.25rem;
  background: var(--color-accent-text);
}
.ck-show .ck-show-count {
  margin: 0;
  font-family: var(--font-sans);
  font-size: var(--text-xs);
  line-height: var(--leading-ui);
  color: var(--color-muted-gray);
  font-variant-numeric: tabular-nums;
}

/* ---------- The stage: the situation over the cockpit ----------
   One column, always. Until 2026-09-11 this was a two-column grid: a 19rem
   rail on the left carrying the situation, three numbered callouts and a
   nudge, with a matching badge hung on each element the callouts named, and
   the cockpit in the track beside it. Two things were wrong with that and
   only one of them was the clutter. The other was arithmetic: the frame runs
   to 1920 BECAUSE a dispatch cockpit is a monitor-width interface, and then
   spent a fifth of it on an aside, which put the fleet data table back into a
   scrolling wrapper on the one screen wide enough to hold it whole.

   The four screens above this section do the explaining now, from outside the
   interface, where nothing has to be drawn on top of it. What is left here is
   the sentence saying what the situation is and the one thing to try, over
   the screen rather than beside it, which is the arrangement a slide uses. */
.ck-stage {
  display: grid;
  /* minmax(0, 1fr) and not the implicit auto: the fleet's data table has a
     min-width of its own, and an auto column would grow to it and carry the
     whole cockpit past the frame. The wrap scrolls; the column does not. */
  grid-template-columns: minmax(0, 1fr);
  gap: var(--space-xl);
  margin-top: var(--space-xl);
}
/* The situation's two lines keep the prose measure even though the screen
   under them does not. A sentence set to 1840px is not a sentence anyone
   reads; it is the reason .writing-measure exists on the page around it. */
.ck-situation {
  display: grid;
  gap: var(--space-sm);
  justify-items: start;
  max-width: var(--measure);
}
.ck .ck-rail-h {
  margin: 0 0 var(--space-xs);
  font-family: var(--font-sans);
  font-size: var(--text-xs);
  font-weight: var(--weight-semibold);
  line-height: var(--leading-ui);
  letter-spacing: var(--tracking-normal);
  color: var(--color-accent-text);
}
/* ---------- What to try, and whether you have ----------
   The nudge was one unchanging sentence of instruction. It is now the
   situation's two or three steps, each ticking itself off as the reader does
   it, which matters here for a reason particular to a demonstration: a
   visitor is not a dispatcher and cannot tell when they have seen the thing
   they were sent to see. The tick is what says "that was it".

   DONE IS A SHAPE, A HIDDEN WORD AND A COUNT BEFORE IT IS A COLOUR. A filled
   check against a hollow ring, ". Done." / ". Not done yet." inside the
   step, and "2 of 3 done" in the head. states.mjs forces .is-done onto every
   step, so the rule underneath it changes nothing that carries text -- the
   mark's colour and nothing else. */
.ck .ck-try {
  margin: 0;
  padding: var(--space-sm) var(--space-md);
  border-radius: var(--radius-xl);
  background: var(--color-tea-light);
  color: var(--color-charcoal);
}
.ck .ck-try:empty { display: none; }
.ck .ck-try-h {
  display: flex;
  align-items: center;
  gap: var(--space-2xs);
  margin: 0;
  font-size: var(--text-xs);
  line-height: var(--leading-ui);
  color: var(--color-accent-text);
}
.ck .ck-try-h .ck-icon { flex-shrink: 0; color: var(--color-accent-text); }
.ck .ck-try-count {
  margin-left: auto;
  font-weight: var(--weight-semibold);
  color: var(--color-muted-gray);
  font-variant-numeric: tabular-nums;
}
.ck .ck-try-list {
  list-style: none;
  margin: var(--space-xs) 0 0;
  padding: 0;
  display: grid;
  gap: var(--space-2xs);
}
.ck .ck-try-step {
  display: flex;
  align-items: flex-start;
  gap: var(--space-xs);
  max-width: var(--measure);
  font-size: var(--text-sm);
  line-height: var(--leading-ui);
  color: var(--color-charcoal);
}
/* The mark. 16px of it either way, so a step does not shift when it lands.
   The ring is charcoal at 12.90 on tea-light and the check accent-deep at
   3.80: both are marks rather than text, and both clear the 3:1 floor. */
.ck .ck-try-mark {
  flex: 0 0 auto;
  width: 1rem;
  height: 1rem;
  margin-top: 0.15em;
  color: var(--color-accent-deep);
}
.ck .ck-try-mark-open {
  box-sizing: border-box;
  border: 2px solid var(--color-charcoal);
  border-radius: var(--radius-pill);
}
.ck .ck-try-end {
  margin: var(--space-xs) 0 0;
  font-size: var(--text-xs);
  line-height: var(--leading-ui);
  color: var(--color-muted-gray);
}

/* ---------- Now, on the load ----------
   The clock the derived "at pickup" column is figured from, stated where the
   load is rather than in a footnote: a derived figure whose inputs are
   hidden is a figure nobody can argue with, which is the failure this whole
   prototype is about. */
.ck .ck-load-now {
  display: flex;
  align-items: flex-start;
  gap: var(--space-2xs);
  margin: var(--space-md) 0 0;
  padding-top: var(--space-sm);
  border-top: 1px solid var(--rule-hairline);
  font-size: var(--text-sm);
  line-height: var(--leading-ui);
  color: var(--color-charcoal);
}
.ck .ck-load-now .ck-icon { flex-shrink: 0; color: var(--color-muted-gray); }

/* ---------- The window reading ----------
   Three states, each a word first. Clear takes no ground at all -- most
   trucks make most windows, and a badge on the ordinary case is a badge on
   nothing. Tight and misses take the caution ground, because both are a
   reading the dispatcher may want to act on; neither blocks, which is what
   keeps them different from the rule. */
.ck .ck-window {
  display: flex;
  align-items: flex-start;
  gap: var(--space-2xs);
  margin: var(--space-xs) 0 0;
  font-size: var(--text-sm);
  line-height: var(--leading-ui);
  color: var(--color-charcoal);
}
.ck .ck-window .ck-icon { flex-shrink: 0; color: var(--color-muted-gray); }
.ck .ck-window[data-window="tight"],
.ck .ck-window[data-window="misses"] {
  align-items: center;
  margin-top: var(--space-sm);
  padding: var(--space-2xs) var(--space-sm);
  border-radius: var(--radius-pill);
  background: var(--color-caution-light);
}
.ck .ck-window[data-window="tight"] .ck-icon,
.ck .ck-window[data-window="misses"] .ck-icon { color: var(--color-caution-text); }

/* Inline icons: the header's idiom, sized to the text they sit in. */
.ck-icon {
  width: 1em;
  height: 1em;
  vertical-align: -0.125em;
  flex-shrink: 0;
}
/* AN ICON AT THE HEAD OF A LINE IS AS TALL AS THE LINE. Every row that puts
   a glyph before running text is a flex box aligned to the top, so the glyph
   stays on the first line when the text wraps; and each used to nudge its
   1em glyph down by a hand-picked margin, 0.15em here and 0.25em there,
   which is close and never right -- at 14px on --leading-ui the clock sat
   1.4px above the words it opens. The box is the line's own height instead,
   and the viewBox centres itself in it (preserveAspectRatio's default), so
   the glyph is centred on the first line by construction, in whichever
   leading the row sets, and there is no margin to keep in step. The rows
   that centre a single line (.ck-try-h, the tight and missed windows) get
   the same box and the same answer. */
.ck .ck-load-now .ck-icon,
.ck .ck-window .ck-icon,
.ck .ck-status .ck-icon,
.ck .ck-fresh .ck-icon,
.ck .ck-try-h .ck-icon,
.ck .ck-sort-icon { height: 1lh; }

/* .ck-show-live is a <p>, so it needs the class twice over for the same
   reason the slide's head does. */
.ck-show .ck-show-live,
.ck-visually-hidden {
  position: absolute;
  width: 1px; height: 1px;
  padding: 0; margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}

/* The four situations, as tabs. A selected tab is heavier and carries a
   charcoal rule under it; the ring on focus is the site's. */
/* The four situations, as a segmented control. They are the demo's primary
   control and were its lightest element. Selected is charcoal with warm
   text, 14.02:1; the site's actions are sage, so navigating and acting are
   two colors. The hover wash is the one .ck-btn-quiet already uses, and it
   is scoped to the tabs that are not selected: the selected one is charcoal
   under warm text, and a wash forced onto it composites to 1.12:1, which
   states.mjs is right to refuse even though the cascade never shows it. */
.ck .ck-tabs-label {
  margin: 0 0 var(--space-xs);
  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);
}
/* Sticky, because the cockpit is 1521px tall on a desktop and 3220px on a
   phone: scroll to the fleet and the only way back to another situation was
   to scroll all the way up. It parks under the site header, carries the
   screen's own ground so cards do not show through, and sits above them.
   The label above it is allowed to scroll away -- four named situations say
   what they are once you have read it once. */
.ck-tabs {
  position: sticky;
  top: var(--nav-height);
  z-index: 2;
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2xs);
  padding-block: var(--space-sm);
  margin-block: calc(-1 * var(--space-sm));
  background: var(--color-warm);
}
/* Below the width where the row fits, the four pills scroll sideways in one
   row rather than wrapping. Two by two was 101px of sticky bar on a phone,
   which is too much of a 844px viewport to spend on a switcher; one row is
   62px. The fourth pill is deliberately cut off at the right edge, which is
   what tells you the strip scrolls. Snap so a flick lands on a whole pill.
   The negative margin lets the strip bleed to the screen's edge while its
   padding keeps the first pill on the content line. */
@media (max-width: 63.98rem) {
  .ck-tabs {
    flex-wrap: nowrap;
    overflow-x: auto;
    scroll-snap-type: x proximity;
    scrollbar-width: none;
    margin-inline: calc(-1 * var(--space-md));
    padding-inline: var(--space-md);
    scroll-padding-inline: var(--space-md);
  }
  .ck-tabs::-webkit-scrollbar { display: none; }
  .ck .ck-tab { flex: 0 0 auto; scroll-snap-align: start; }
}

/* WHAT THE STICKY STRIP COSTS EVERY CONTROL UNDER IT.

   Two things sit over this page while the cockpit is being read: the site nav,
   fixed at 0 and 80px tall, and the strip above, stuck to the bottom of it and
   62px tall -- a height the block above fixes deliberately, one row at every
   width. So the top 142px of the viewport belongs to furniture.

   style.css sets `scroll-padding-top: var(--nav-height)` on `html`, which
   clears the nav and knows nothing about the strip. Anything the browser
   scrolls to a top edge therefore lands at y=80, 62px inside something opaque.
   Shift-Tab upward through the data table did exactly that: T-142's row button
   took focus at y=89 and could not be seen at all, which is 2.4.11 Focus Not
   Obscured, and not a thing any check in scripts/ can measure -- they read
   colour, and this is geometry.

   scroll-margin rather than a bigger scroll-padding on `html`: the fault is
   these controls passing under this strip, and the page's own anchors
   (#the-cockpit, #the-decisions) have no such problem and should keep landing
   where they always have.

   #ck-panel and not .ck, because the strip cannot obscure itself. A tab is
   sticky at the very offset this margin is made of, so handing it one asks
   the browser to scroll 154px to reveal something already in plain sight --
   which is the bug this changeset removes, reintroduced one element along. */
#ck-panel :is(a, button, input, textarea, select, summary, [tabindex]) {
  scroll-margin-top: calc(var(--nav-height) + 3.875rem + var(--space-sm));
}

.ck .ck-tab {
  appearance: none;
  display: inline-flex;
  align-items: center;
  gap: var(--space-2xs);
  background: none;
  border: 1px solid transparent;
  border-radius: var(--radius-pill);
  padding: var(--space-xs) var(--space-md);
  font-family: var(--font-sans);
  font-size: var(--text-sm);
  font-weight: var(--weight-medium);
  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);
}
.ck .ck-tab:not([aria-selected="true"]):hover { background: var(--wash-on-light-hover); }
.ck .ck-tab[aria-selected="true"] {
  font-weight: var(--weight-semibold);
  background: var(--color-charcoal);
  border-color: var(--color-charcoal);
  color: var(--color-warm);
}
.ck .ck-blurb {
  margin: 0;
  font-size: var(--text-base);
  line-height: var(--leading-body);
  color: var(--color-charcoal);
}

/* The panel under the tabs: load, recommendation, status, the optional
   question, then the whole fleet. One column, always; the pair inside the
   recommendation is the only thing that goes side by side. */
.ck-panel {
  display: grid;
  /* The same lesson as .ck-stage, one level down: without an explicit
     column the implicit auto track grows to the fleet table's natural
     width, 1184px, and every card in the panel stretches with it. On the
     page the stage's minmax(0, 1fr) track happened to hold it; in the
     capture, where the stage is a block, nothing did, and the thumbnail
     came back cropped flush on its right. */
  grid-template-columns: minmax(0, 1fr);
  gap: var(--space-xl);
  min-width: 0;
}

/* A white card is the cockpit's surface on the section's warm ground. */
.ck-card,
.ck-load,
.ck-why,
.ck-table-wrap {
  background: var(--color-white);
  border: 1px solid var(--color-rule);
  border-radius: var(--radius-xl);
}

/* ---------- The load ---------- */
.ck-load { padding: var(--space-lg) var(--space-xl); }
.ck .ck-load-id {
  margin: 0 0 var(--space-sm);
  font-size: var(--text-lg);
  font-weight: var(--weight-semibold);
  line-height: var(--leading-tight);
  color: var(--color-charcoal);
}
.ck .ck-load-id .ck-label { margin-right: var(--space-2xs); }
.ck-sep { color: var(--color-muted-gray); }
.ck-load-facts {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: var(--space-sm) var(--space-xl);
  margin: 0;
}
.ck-load-facts dt {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2xs);
  font-size: var(--text-xs);
  font-weight: var(--weight-semibold);
  line-height: var(--leading-ui);
  color: var(--color-muted-gray);
}
.ck-load-facts dd {
  margin: 0;
  font-size: var(--text-sm);
  line-height: var(--leading-ui);
  color: var(--color-charcoal);
}
@media (min-width: 800px) {
  .ck-load-facts { grid-template-columns: repeat(4, minmax(0, 1fr)); }
}

/* ---------- The hard rule ----------
   A rule is a rule: the one caution-colored card on the page, with a 2px
   edge in the caution ink, above the recommendation rather than inside it,
   because it is not a low score and must not read as one. Charcoal on
   caution-light is 12.44; the ink as a border on white is 6.45. */
.ck-rule {
  /* Hugs what it holds, like .ck-fresh and .ck-status: the text inside is
     held to the measure, and a box that ran the panel's width past it was
     two-thirds empty caution ground on a monitor. */
  width: fit-content;
  max-width: 100%;
  padding: var(--space-lg) var(--space-xl);
  border: 2px solid var(--color-caution-text);
  border-radius: var(--radius-xl);
  background: var(--color-caution-light);
}
.ck .ck-rule-glyph { color: var(--color-caution-text); }
.ck .ck-rule-head {
  margin: 0 0 var(--space-2xs);
  font-size: var(--text-lg);
  font-weight: var(--weight-semibold);
  line-height: var(--leading-tight);
  color: var(--color-charcoal);
}
.ck-rule-glyph { display: inline-block; width: 1.25em; height: 1.25em; vertical-align: -0.25em; margin-right: var(--space-2xs); }
.ck .ck-rule-text {
  margin: 0;
  max-width: var(--measure);
  font-size: var(--text-base);
  line-height: var(--leading-body);
  color: var(--color-charcoal);
}

/* ---------- The recommendation ----------
   The answer zone: tea-light, the feature ground, with the white cards on
   it. Its inks are warm's -- charcoal 12.90, muted-gray 5.44, accent-text
   4.90 -- so nothing inside changes color to sit here. A kicker names what
   the zone is before the headline says what it says. */
.ck-reco { display: grid; gap: var(--space-lg); }
.ck-lead {
  padding: var(--space-xl);
  border-radius: var(--radius-xl);
  background: var(--color-tea-light);
}
/* A CLOSE CALL IS NOT A CAUTION, AND USED TO BE PAINTED LIKE ONE.
   --color-caution-light was carrying two unrelated meanings on this screen:
   the hard rule and the blocked row, where it says "you cannot do this", and
   the close-call zone and its status line, where it says "the system looked
   and the two are level". The second is not a warning at all -- it is the
   system being honest about its own resolution, which this page argues is a
   good outcome -- and painting it in the refusal colour taught the reader
   that pink meant nothing in particular.

   The close call takes --color-muted-light, the alternate ground, so it reads
   as a different KIND of answer rather than as a problem. Caution is now spent
   on exactly one thing: a rule refusing a truck. Every ink inside clears on
   muted-light -- charcoal 12.10, muted-gray 5.11, accent-text 4.60 -- and the
   kicker goes charcoal, because sage there would read as a recommendation and
   caution would put the warning back. */
.ck-lead[data-tone="close"] { background: var(--color-muted-light); }
/* Two classes deep, and for the reason this file's header gives: .ck-label is
   one class (0-1-0) and .case-section p is class-and-element (0-1-1), so a
   label on a <p> loses both its size and its colour. Every other .ck-label on
   the page sits on a <span>, where nothing competes, which is why this was
   the only one rendering at 18px charcoal instead of 12px sage -- close
   enough to the 24px headline under it to read as a second title, which is
   the stacking this kicker was introduced to remove. */
.ck .ck-lead-kicker {
  margin: 0 0 var(--space-2xs);
  font-size: var(--text-xs);
  line-height: var(--leading-ui);
  color: var(--color-accent-text);
}
.ck-lead[data-tone="close"] .ck-lead-kicker { color: var(--color-charcoal); }
/* The dek under this is capped to the measure and this was not, so the close
   call's 78-character headline set itself on one 1072px line at 1440 -- the
   one sentence on the screen nobody could read without moving their head. */
.ck .ck-reco-h {
  margin: 0;
  max-width: var(--measure);
  font-family: var(--font-sans);
  font-size: var(--text-2xl);
  font-weight: var(--weight-semibold);
  line-height: var(--leading-tight);
  letter-spacing: var(--tracking-normal);
  color: var(--color-charcoal);
}
.ck .ck-reco-dek {
  margin: var(--space-xs) 0 0;
  max-width: var(--measure);
  font-size: var(--text-base);
  line-height: var(--leading-body);
  color: var(--color-charcoal);
}
.ck-pair {
  display: grid;
  gap: var(--space-lg);
  margin-top: var(--space-lg);
}
@media (min-width: 800px) {
  .ck-pair { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
.ck-pair > div { min-width: 0; }

.ck-card { padding: var(--space-lg) var(--space-xl); }
.ck-card + .ck-confidence,
.ck-pair + .ck-confidence,
.ck-confidence + .ck-also { margin-top: var(--space-lg); }
.ck .ck-card-head {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2xs);
  margin: 0 0 var(--space-xs);
  font-size: var(--text-xs);
  font-weight: var(--weight-semibold);
  line-height: var(--leading-ui);
  color: var(--color-accent-text);
}
.ck .ck-card-truck {
  margin: 0;
  font-size: var(--text-lg);
  font-weight: var(--weight-semibold);
  line-height: var(--leading-tight);
  color: var(--color-charcoal);
}
.ck .ck-card-driver {
  display: block;
  font-size: var(--text-sm);
  font-weight: var(--weight-regular);
  line-height: var(--leading-ui);
  color: var(--color-muted-gray);
}
.ck .ck-card-note {
  margin: var(--space-sm) 0 0;
  font-size: var(--text-base);
  line-height: var(--leading-body);
  color: var(--color-charcoal);
}
.ck .ck-card-act { margin: var(--space-lg) 0 0; }

/* The factors: name, value, direction, one row each, with the direction as
   a glyph and a word. The value is tabular so the column reads. */
.ck-factors {
  list-style: none;
  margin: var(--space-md) 0 0;
  padding: 0;
  border-top: 1px solid var(--rule-hairline);
}
.ck-factor {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto auto;
  gap: var(--space-md);
  align-items: baseline;
  padding: var(--space-xs) 0;
  border-bottom: 1px solid var(--rule-hairline);
}
.ck .ck-factor-name {
  font-size: var(--text-sm);
  line-height: var(--leading-ui);
  color: var(--color-charcoal);
}
/* THE VALUE IS THE THING BEING CHECKED, AND IT USED TO BE LABEL-SIZED.
   38 mi, 8.4 h, dry van, 11 of 12, 12 mi are the five readings a dispatcher
   came to this card for, and at --text-sm they sat at the same size as the
   words naming them, the word judging them and the footnote underneath. A
   census of the screen found 143 of its 156 text elements at 12 or 14px and
   exactly one above 18, which is a card with no scan layer at all: nothing
   is bigger than anything else, so the eye reads the whole panel as texture.

   --text-lg gives the row three rungs -- 14 for the name, 18 for the value,
   12 for helps or meets -- so the five figures carry the card and the words
   around them explain it. It is a step the scale already has; nothing new is
   invented, and the baseline alignment on .ck-factor is what keeps the taller
   value sitting on the same line as its name. */
.ck .ck-factor-value {
  font-size: var(--text-lg);
  font-weight: var(--weight-semibold);
  line-height: var(--leading-ui);
  font-variant-numeric: tabular-nums;
  color: var(--color-charcoal);
  text-align: right;
}
/* HELPS, HURTS, MEETS, NEUTRAL -- THE VERDICT, WHICH WAS THE SMALLEST TYPE
   ON THE CARD. A census of the cockpit found 148 of its 163 visible text
   nodes at 12 or 14px, and the word saying which way a factor CUT was in the
   12px tier, level with the footnote under the list and a step below the
   name of the thing being judged. A dispatcher scanning five rows for
   trouble is scanning for exactly one of these words.

   14px, which is the name's size, so a row reads name / value / verdict at
   14 / 18 / 14 rather than 14 / 18 / 12. And "hurts" takes a chip: the one
   verdict worth interrupting for gets a ground of its own, caution-light,
   carrying caution ink at 5.23. The other three stay flat, because a chip on
   all four is a chip on none. */
.ck .ck-factor-dir {
  display: inline-flex;
  align-items: center;
  justify-content: flex-end;
  gap: var(--space-2xs);
  min-width: 4.5rem;
  font-size: var(--text-sm);
  font-weight: var(--weight-semibold);
  line-height: var(--leading-ui);
  color: var(--color-muted-gray);
  text-align: right;
}
.ck .ck-factor-dir[data-dir="helps"],
.ck .ck-factor-dir[data-dir="meets"] { color: var(--color-accent-text); }
.ck .ck-factor-dir[data-dir="hurts"] {
  color: var(--color-caution-text);
  padding: 0 var(--space-xs);
  border-radius: var(--radius-pill);
  background: var(--color-caution-light);
}
/* ---------- When the figure was last true ----------
   A second line under the factor's name, at the footnote size, saying where
   the figure came from and how long ago: GPS for the miles, the ELD for the
   hours, the span for the record. Muted while it is fresh. Stale takes the
   caution ink and the clock glyph, and stays a line under a name rather
   than a chip on the value: the value is still the value, and what has
   changed is how far it can be trusted. Caution-text on white is 6.45, on
   muted-light 5.09; the name cell is 1fr and the age wraps inside it. */
.ck .ck-factor-age {
  display: block;
  margin-top: var(--space-2xs);
  font-size: var(--text-xs);
  font-weight: var(--weight-regular);
  line-height: var(--leading-ui);
  color: var(--color-muted-gray);
}
.ck .ck-factor-age[data-age="stale"] {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2xs);
  font-weight: var(--weight-semibold);
  color: var(--color-caution-text);
}
.ck .ck-vs-cell .ck-factor-age { margin-top: var(--space-2xs); }
/* The same reading in the fleet, as the cell's own note. */
.ck-table .ck-cell-note[data-age="stale"] { color: var(--color-caution-text); font-weight: var(--weight-semibold); }
/* A READING IS NOT A REFUSAL, AND USED TO BE PAINTED LIKE ONE. This note
   took the caution ground and a caution edge, which is what the rule card
   above takes to say "you cannot do this". The two then differed by the
   weight of a border -- 2px against 1px -- and a border weight is not a
   difference a reader can name. A hard requirement and a suggestion read
   as the same kind of thing, which is the failure the close-call zone was
   already fixed for a few hundred lines up: caution is spent on exactly
   one thing, a rule refusing a truck, and this note is not one. The row
   keeps its Assign and what the sentence asks for is a check.

   So it takes the ground the decisive rows in the comparison below it
   take: white, raised on the close call's muted-light, which is this
   card's own idiom for lifting something out of the page rather than
   flagging it. The hairline is the same one every raised surface here
   carries.

   THE CAUTION INK STAYS, on the clock and on the phrase that names the
   age. That is not a leftover: staleness is written in caution ink
   everywhere else on the screen -- the age line under a factor's name, the
   fleet cell's note -- and the ink is the reading of the figure while the
   ground is the system's verdict on the action. Ink says "this number is
   old"; ground says "you cannot do this". Only one of those is true here.
   Caution-text on white is 6.45, charcoal on it 15.32. */
.ck .ck-fresh {
  display: flex;
  align-items: flex-start;
  gap: var(--space-xs);
  margin: var(--space-md) 0 0;
  padding: var(--space-sm) var(--space-md);
  border: 1px solid var(--rule-hairline);
  border-radius: var(--radius-xl);
  background: var(--color-white);
  font-size: var(--text-sm);
  font-weight: var(--weight-regular);
  line-height: var(--leading-body);
  color: var(--color-charcoal);
}
/* THE MEASURE, ON THE PROSE. Every block of running text in the cockpit
   is held to --measure the way the page's own paragraphs are: the note,
   the status line, the key under the factor bars, the outcomes card and
   the stored reason. On a monitor the note ran 148 characters to the line
   and the status line 150, which is a bar, not a sentence. Where the block
   is a flex box with an icon in front, the cap goes on the text span --
   the element the prose's own size resolves on, which is the rule SPACING.md
   gives -- and a box with a ground hugs what it holds, so the note's
   surface does not run on past its last word as a band of empty white. */
.ck .ck-fresh { width: fit-content; max-width: 100%; }
.ck .ck-fresh > span { max-width: var(--measure); }
.ck .ck-fresh .ck-icon { flex-shrink: 0; color: var(--color-caution-text); }
.ck .ck-fresh strong { font-weight: var(--weight-semibold); color: var(--color-caution-text); }

/* The key sits with the bars; the disclaimer stays under it. The sample is
   a real .ck-factor-bar with fixed custom properties, so it cannot drift
   from the thing it explains -- only its grid placement and width are
   overridden here. */
.ck .ck-factor-key {
  display: flex;
  align-items: flex-start;
  gap: var(--space-xs);
  margin: var(--space-md) 0 0;
  font-size: var(--text-xs);
  line-height: var(--leading-ui);
  color: var(--color-muted-gray);
}
.ck .ck-factor-key > span:last-child { max-width: var(--measure); }
.ck .ck-key-sample {
  grid-column: auto;
  flex: 0 0 auto;
  width: 3.5rem;
  /* Centred on the first line of the sentence it explains. The bar is 4px of
     ink rather than a glyph in a box, so it cannot take the 1lh box the icons
     above use; half the difference between the line and the bar is the same
     arithmetic by hand. 0.45em was 1.1px high, and wrong again whenever the
     bar's height or this row's leading moves. */
  margin-top: calc((1lh - 4px) / 2);
}
.ck .ck-factor-note {
  margin: var(--space-xs) 0 0;
  font-size: var(--text-xs);
  line-height: var(--leading-ui);
  color: var(--color-muted-gray);
}

/* ---------- Where the truck stands, as a bar ----------
   Two real elements, the track and the mark. The fleet's middle and the zone
   that still counts as level are the track's two pseudo-elements, which is
   not a trick to save bytes: curves.mjs counts ELEMENTS, and four marks a row
   across five rows and two cards would move that count by sixty for drawing
   that carries no text and no border of its own.

   THE MIDDLE AND THE BAND SIT ON TOP OF THE MARK, NOT UNDER IT. Drawn
   underneath they vanish, because the mark is a fill from the left edge and
   a truck ahead of the fleet covers the very band it is being compared to --
   which is every helping factor, that is, most of them. Painted over the
   fill they read as calipers around the middle: two hairlines saying where
   level stops and a heavier tick saying where the middle is.

   The band is LEVEL rescaled to this factor's own spread, so a mark inside
   the calipers is exactly a factor the word calls neutral. On this fleet
   that band runs from 9% to 16% of a track, wide enough that leaving it out
   would put a mark a quarter of the way clear of the middle under the word
   "neutral". */
.ck-factor-bar {
  grid-column: 1 / -1;
  /* Block, not the span's default inline: in the factor list it is a grid
     item and gets this for free, and in a comparison cell and in the key it
     is neither, where an inline box would drop the 4px height on the floor. */
  display: block;
  position: relative;
  /* 4, not 6. Five of these under five rows of figures is a lot of ink for
     a reference mark, and the figures are what finding 1 just made the thing
     you land on. Thin enough to read as a rule under the row. */
  height: 4px;
  margin-top: var(--space-2xs);
  border-radius: 2px;
  background: var(--color-tag-border);
}
/* accent-deep, not accent-text. color.css draws the line by what sits ON the
   fill rather than by the fill itself, and says so in as many words: a sage
   fill carrying no text -- a rule, a bar, an icon -- takes accent-deep. This
   is that. 4.51 on the white card and 3.57 against its own track, both over
   the 3:1 a non-text mark answers to, and a step lighter than the text sage
   that was here, which was reading as heavy against five rows of figures. */
.ck-factor-mark {
  position: absolute;
  top: 0;
  bottom: 0;
  left: 0;
  width: var(--pos);
  /* Under both marks below. Positioned siblings paint in tree order and a
     pseudo-element counts as a child, so ::before -- the band -- was painting
     UNDER this fill and vanishing behind it on every factor where the truck
     leads the band. That is most of them, and it included the one case the
     band exists for: a mark that is ahead of the middle and still called
     neutral showed the band's right edge and not its left. */
  z-index: 0;
  border-radius: 2px;
  background: var(--color-accent-deep);
}
/* The zone that still counts as level with the fleet. Charcoal, not
   muted-gray: over the fill, muted-gray is 1.43:1 and simply is not there.
   Charcoal is 3.40 on the fill and 12.13 on the track, so the caliper reads
   wherever the mark happens to be. */
.ck-factor-bar::before {
  content: "";
  position: absolute;
  z-index: 1;
  top: -1px;
  bottom: -1px;
  left: var(--band-l);
  width: var(--band-w);
  border-left: 1px solid var(--color-charcoal);
  border-right: 1px solid var(--color-charcoal);
}
/* The fleet's middle. Same ink as the calipers on purpose -- what separates
   them is weight and reach, 2px and taller against 1px and shorter, so the
   middle reads as the reference and the calipers as the tolerance around it
   rather than as three marks of equal standing. */
.ck-factor-bar::after {
  content: "";
  position: absolute;
  z-index: 2;
  top: -3px;
  bottom: -3px;
  left: var(--med);
  width: 2px;
  margin-left: -1px;
  background: var(--color-charcoal);
}

/* The rest of what the note used to say, folded. The summary borrows the
   disclosure the misses list already uses rather than inventing a second
   one; grouping the selectors keeps it one rule, so the state count does not
   move for a pattern the page already had. */
.ck-note { margin-top: var(--space-xs); }
.ck-note-body { padding-bottom: var(--space-xs); }
.ck .ck-note-body p {
  margin: var(--space-xs) 0 0;
  font-size: var(--text-xs);
  line-height: var(--leading-ui);
  color: var(--color-muted-gray);
}

/* The three card heads carried a 20px glyph each for one release, as the
   audit's answer to a screen with twenty-two annotating icons and no
   landmarks. The diagnosis was right and this was the wrong fix: a glyph that
   size beside a four-word heading competes with the heading instead of
   locating it, and the heading was already the landmark. The audit's other
   four findings -- the value sizes, the one raised surface, the folded note,
   the fleet bars -- are what actually gave the card places to land.

   Sub-heads inside the panel: a rung under the recommendation's h3. */
.ck .ck-h {
  display: flex;
  align-items: center;
  gap: var(--space-2xs);
  margin: 0 0 var(--space-xs);
  font-family: var(--font-sans);
  font-size: var(--text-sm);
  font-weight: var(--weight-semibold);
  line-height: var(--leading-ui);
  letter-spacing: var(--tracking-normal);
  color: var(--color-charcoal);
}

/* The record. A count, what "like this one" means, and the misses behind a
   disclosure, because the pattern in the misses is the part a dispatcher
   can act on. */
/* NOT A CARD ANY MORE, ON PURPOSE. Until now this and .ck-also were white
   cards with a --color-rule edge, exactly like .ck-card beside them: three
   identical objects, one of which is the recommendation and two of which are
   the history behind it, with nothing on the screen saying which was which.
   Border, fill and radius each say "separate object", and spending them on
   all three flattened the hierarchy they were supposed to build.

   The ground was already here. .ck-lead is --color-tea-light and both
   columns sit on it, so the way to put the evidence on the tint is to stop
   painting white over it -- no new colour enters the palette and the one
   already there starts carrying rank. What is left is one raised white
   surface, the card with the Assign button on it, and one tinted region
   beside it to consult. The inset stays so nothing shifts; only the fill and
   the edge go. Every ink here clears its floor on tea-light: charcoal at
   12.90, accent-text at 4.90, and accent-hover is darker than accent-text. */
.ck-confidence {
  padding: var(--space-lg) var(--space-xl);
  background: none;
  border: 0;
  border-radius: 0;
}
.ck .ck-conf-line {
  margin: 0;
  max-width: var(--measure);
  font-size: var(--text-base);
  line-height: var(--leading-body);
  color: var(--color-charcoal);
}
.ck .ck-conf-line strong { font-weight: var(--weight-semibold); }
.ck .ck-conf-like {
  margin: var(--space-xs) 0 0;
  max-width: var(--measure);
  font-size: var(--text-sm);
  line-height: var(--leading-ui);
  color: var(--color-charcoal);
}
/* What to watch for on this load: the one line per miss that changes what
   the dispatcher checks, on the card rather than behind the disclosure
   under it. Same size and ink as the lines above it; the label is the
   card's own small-caps label, and the list is numbered because the
   disclosure below lists the loads they came from in the same order. */
.ck-conf-watch { margin-top: var(--space-md); }
/* The label's own size, said again here, because the page's paragraph rule
   outranks .ck-label on a <p> and would set this at body size. */
.ck .ck-conf-watch-h { margin: 0; font-size: var(--text-xs); line-height: var(--leading-ui); color: var(--color-accent-text); }
.ck-conf-watch-list {
  margin: var(--space-2xs) 0 0;
  padding: 0 0 0 var(--space-lg);
  display: grid;
  gap: var(--space-2xs);
  max-width: var(--measure);
  font-size: var(--text-sm);
  line-height: var(--leading-ui);
  color: var(--color-charcoal);
}
/* A disclosure that looks like one. It was sage underlined text, which is
   this site's link, so the one control on the card that expands in place
   read as a control that navigates away -- and its hit area was the 20px
   of the words themselves. It is now a full-width row: label left, chevron
   right, a rule above it, and the whole row clickable at 44px. The chevron
   turns to point down when it is open, which is the only thing on this page
   that moves, and the site's reduced-motion blanket stops it. */
.ck-misses { margin-top: var(--space-md); border-top: 1px solid var(--rule-hairline); }
.ck-misses summary,
.ck-note summary {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-sm);
  min-height: 2.75rem;
  padding: var(--space-xs) 0;
  cursor: pointer;
  font-size: var(--text-sm);
  font-weight: var(--weight-semibold);
  line-height: var(--leading-ui);
  color: var(--color-accent-text);
  transition: color var(--motion-state) var(--ease);
}
/* Safari draws its own triangle on a summary with any display but list-item;
   both of these are needed to be rid of it. */
.ck-misses summary::-webkit-details-marker,
.ck-note summary::-webkit-details-marker { display: none; }
.ck-misses summary::marker,
.ck-note summary::marker { content: ''; }
.ck-misses summary:hover,
.ck-note summary:hover { color: var(--color-accent-hover); }
.ck .ck-misses-chev {
  flex-shrink: 0;
  transform: rotate(-90deg);
  transition: transform var(--motion-state) var(--ease);
}
.ck-misses[open] .ck-misses-chev,
.ck-note[open] .ck-misses-chev { transform: rotate(0deg); }
.ck-miss-list {
  margin: 0 0 var(--space-sm);
  padding: 0 0 0 var(--space-lg);
  display: grid;
  gap: var(--space-sm);
}
.ck .ck-miss-what,
.ck .ck-miss-tell {
  margin: 0;
  max-width: var(--measure);
  font-size: var(--text-sm);
  line-height: var(--leading-ui);
  color: var(--color-charcoal);
}
.ck .ck-miss-tell { margin-top: var(--space-2xs); }
.ck .ck-miss-load { font-weight: var(--weight-semibold); }

/* Also considered: rank, then the one line. */
/* The second half of the same region, so it loses its card for the same
   reason. The hairline is what still divides the two, and the radius has to
   go with the fill rather than merely being unused: a top border on a
   surface that kept its corner is a partial border on a curve, which is the
   one thing curves.mjs exists to refuse. */
.ck-also {
  padding: var(--space-lg) var(--space-xl);
  background: none;
  border: 0;
  border-top: 1px solid var(--rule-hairline);
  border-radius: 0;
}
.ck-also-list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  gap: var(--space-xs);
}
.ck-also-list li {
  display: grid;
  grid-template-columns: 2.5rem minmax(0, 1fr);
  gap: var(--space-xs);
  font-size: var(--text-sm);
  line-height: var(--leading-ui);
  color: var(--color-charcoal);
}
.ck .ck-also-rank { font-weight: var(--weight-semibold); }
.ck .ck-also-body strong { font-weight: var(--weight-semibold); }

/* ---------- The status line ----------
   A live region, always in the document, on the feature ground so an update
   is somewhere the eye already goes. */
.ck .ck-status {
  display: flex;
  align-items: flex-start;
  gap: var(--space-xs);
  margin: 0;
  padding: var(--space-sm) var(--space-xl);
  border-radius: var(--radius-xl);
  background: var(--color-muted-light);
  font-size: var(--text-sm);
  font-weight: var(--weight-semibold);
  line-height: var(--leading-ui);
  color: var(--color-charcoal);
}
/* Tinted, not filled: a filled sage line was tried on 2026-09-11 and read
   as a second button. The line keeps the muted ground for everything the
   cockpit can do and takes the caution ground for the one thing it cannot --
   a truck a rule refuses. A close call used to be painted here too, which
   put "the two are level" in the same colour as "this is not allowed".
   Charcoal on muted-light 12.10, on caution-light 12.44. */
.ck .ck-status[data-tone="refused"] { background: var(--color-caution-light); }
.ck .ck-status:empty { display: none; }
/* Hugs its text, held to the measure, like .ck-fresh above: a pill that
   runs the width of the panel with thirty words at its left end is a bar. */
.ck .ck-status { width: fit-content; max-width: 100%; }
.ck .ck-status > span { max-width: var(--measure); }
.ck .ck-status .ck-icon { flex-shrink: 0; color: var(--color-accent-text); }
.ck .ck-status[data-tone="refused"] .ck-icon { color: var(--color-caution-text); }
.ck .ck-status[data-tone="close"] .ck-icon { color: var(--color-charcoal); }
.ck .ck-status[data-tone="note"] .ck-icon { color: var(--color-muted-gray); }

/* ---------- The optional question ----------
   Cheap by construction: it appears after the assignment, not before it;
   nothing in it is required; Skip is a button of the same weight as Save. */
.ck-why { padding: var(--space-lg) var(--space-xl); }
.ck .ck-why-head {
  margin: 0 0 var(--space-sm);
  font-size: var(--text-base);
  font-weight: var(--weight-semibold);
  line-height: var(--leading-tight);
  color: var(--color-charcoal);
}
.ck .ck-why-opt { font-weight: var(--weight-regular); color: var(--color-muted-gray); }
.ck-why-set {
  border: 0;
  margin: 0;
  padding: 0;
  display: grid;
  gap: var(--space-xs);
}
.ck-radio {
  display: flex;
  align-items: center;
  gap: var(--space-xs);
  font-size: var(--text-sm);
  line-height: var(--leading-ui);
  color: var(--color-charcoal);
  cursor: pointer;
}
.ck-radio input {
  accent-color: var(--color-accent-text);
  width: 1rem; height: 1rem;
  margin: 0;
  flex-shrink: 0;
}
.ck-why-text { display: block; margin-top: var(--space-2xs); }
.ck-why-text textarea {
  display: block;
  width: 100%;
  max-width: var(--measure);
  padding: var(--space-xs) var(--space-sm);
  border: 1px solid var(--color-muted-gray);
  border-radius: 4px;
  background: var(--color-white);
  font-family: var(--font-sans);
  font-size: var(--text-sm);
  line-height: var(--leading-ui);
  color: var(--color-charcoal);
  resize: vertical;
}
.ck-why-text textarea::placeholder { color: var(--color-muted-gray); opacity: 1; }
.ck .ck-why-what {
  margin: var(--space-md) 0 0;
  max-width: var(--measure);
  font-size: var(--text-sm);
  line-height: var(--leading-ui);
  color: var(--color-charcoal);
}
.ck .ck-why-act {
  margin: var(--space-md) 0 0;
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-xs);
}
.ck .ck-why-done {
  margin: 0;
  max-width: var(--measure);
  font-size: var(--text-sm);
  line-height: var(--leading-ui);
  color: var(--color-charcoal);
}

/* ---------- Buttons ----------
   The site's two shapes: a filled sage and a quiet outline, both pills.
   The fill is accent-text, not accent-deep, for the reason color.css gives:
   warm on accent-text is 5.32:1 and on accent-deep 4.12:1, and a ground
   carrying text answers to the text floor. */
.ck .ck-btn {
  appearance: none;
  display: inline-flex;
  align-items: center;
  gap: var(--space-2xs);
  padding: var(--space-xs) var(--space-md);
  border: 1px solid transparent;
  border-radius: var(--radius-pill);
  background: none;
  font-family: var(--font-sans);
  font-size: var(--text-sm);
  font-weight: var(--weight-semibold);
  line-height: var(--leading-ui);
  color: var(--color-charcoal);
  cursor: pointer;
  white-space: nowrap;
  transition: background-color var(--motion-state) var(--ease), color var(--motion-state) var(--ease), border-color var(--motion-state) var(--ease);
}
.ck .ck-btn-primary {
  background: var(--color-accent-text);
  border-color: var(--color-accent-text);
  color: var(--color-warm);
}
.ck .ck-btn-primary:hover {
  background: var(--color-accent-hover);
  border-color: var(--color-accent-hover);
}
.ck .ck-btn-quiet {
  border-color: var(--color-muted-gray);
  color: var(--color-charcoal);
}
.ck .ck-btn-quiet:hover { background: var(--wash-on-light-hover); }
/* Not disabled in the DOM, so it stays in the tab order and can be read;
   aria-disabled says what it is, the copy says why. Muted-gray on white is
   6.47:1 as text and as the border. */
.ck .ck-btn[aria-disabled="true"] {
  color: var(--color-muted-gray);
  border-color: var(--color-muted-gray);
  cursor: not-allowed;
}
.ck .ck-btn[aria-disabled="true"]:hover { background: none; }
.ck table .ck-btn { padding: var(--space-2xs) var(--space-sm); border-color: var(--color-muted-gray); }
/* THE WASH IS FOR THE QUIET BUTTONS, AND IT USED TO ERASE THE LOUD ONE.
   `table` is a type selector, so `.ck table .ck-btn:hover` scores (0,3,1)
   against `.ck .ck-btn-primary:hover`'s (0,3,0) and wins. The comparison is a
   <table class="ck-vs">, and the button it offers for each option is a primary
   -- near-white ink on the accent green. Hovering it therefore kept the ink
   and swapped the green for a 6%-opacity wash over a light ground: measured on
   a real pointer, 5.32:1 at rest and 1.29:1 under the cursor. The label
   vanished at the moment it was being pressed.
   :not() rather than raising the primary's specificity, because the intent is
   what wants saying -- this wash belongs to the plain row buttons. */
.ck table .ck-btn:not(.ck-btn-primary):hover { background: var(--wash-on-light-hover); }
.ck table .ck-btn[aria-disabled="true"]:hover { background: none; }

/* ---------- The fleet ----------
   Every truck and every column the recommendation weighed, sortable, never
   collapsed. The wrapper scrolls sideways on its own; the page does not.

   THE HEAD IS THE DARK BAND. Until #69 the head was muted-gray text on the
   same white as the rows, with a wrapped label wherever the browser chose
   and a text glyph on every column, so the row that names the columns was
   the quietest thing on the table. It sits on charcoal now, COLOR.md's own
   dark band, in the tokens that band already uses: warm for the sorted
   column (14.02), ink-on-dark-secondary for the rest (8.49), ink-on-dark-
   muted for a unit line (5.26), accent-on-dark for the sort chevron (7.47).
   Muted-gray never appears on it. Every head is a label on one line and,
   where a number needs one, a unit on the line under it, so nothing wraps
   where it was not told to.

   A SORT INDICATOR IS EARNED. The sorted column shows one chevron, in sage,
   the direction it is sorted. The others show nothing at rest and a
   two-way chevron under the pointer or the focus ring, so the eye finds the
   one column that is ordered instead of ten that could be. On a right-
   aligned column the chevron sits before the label, so the label's right
   edge lines up with the numbers under it.

   The action column is right-aligned, head and buttons together, so the
   buttons' edge is the table's edge and the head sits over the buttons
   rather than a padding's width to the left of them. The buttons carry the
   quiet outline in the table, not only when disabled; a bold word with no
   edge read as a caption. */
.ck-table-wrap {
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;
}
.ck-table {
  width: 100%;
  min-width: 60rem;
  border-collapse: collapse;
}
/* 12 down, 8 across. The vertical inset is the row's rhythm and does not
   move; the horizontal one is column width, ten columns of it, and 4px a
   side is 80px of table -- which is what the fleet was overflowing its wrap
   by once the frame came in to the content's width. A data table is allowed
   to be denser across than a card is; what it is not allowed to be is
   cut off. The outer inset at the two ends stays --space-md, so the table
   still starts and ends on the screen's own margin. */
.ck-table th,
.ck-table td {
  padding: var(--space-sm) var(--space-xs);
  text-align: left;
  vertical-align: middle;
  font-size: var(--text-sm);
  line-height: var(--leading-ui);
  color: var(--color-charcoal);
  border-bottom: 1px solid var(--rule-hairline);
}
.ck-table tbody th:first-child,
.ck-table tbody td:first-child { padding-left: var(--space-md); }
.ck-table tbody th:last-child,
.ck-table tbody td:last-child { padding-right: var(--space-md); }
.ck-table tbody tr:last-child th,
.ck-table tbody tr:last-child td { border-bottom: 0; }
.ck-table .ck-num { text-align: right; font-variant-numeric: tabular-nums; }
.ck-table tbody th { font-weight: var(--weight-regular); white-space: nowrap; }
.ck-table td:nth-child(2) { font-weight: var(--weight-semibold); }
.ck-table .ck-cell-text { white-space: nowrap; }
.ck-table .ck-cell-act { text-align: right; white-space: nowrap; }
.ck-table tbody tr:not(.is-lead):not(.is-assigned):hover th,
.ck-table tbody tr:not(.is-lead):not(.is-assigned):hover td { background: var(--color-warm); }

/* The head. The cell carries no padding of its own; the button or the span
   inside it does, so the whole cell is the sort target. */
.ck-table thead th {
  padding: 0;
  background: var(--color-charcoal);
  color: var(--ink-on-dark-secondary);
  font-size: var(--text-xs);
  font-weight: var(--weight-semibold);
  border-bottom: 0;
  vertical-align: top;
}
.ck-table th[aria-sort="ascending"],
.ck-table th[aria-sort="descending"] { color: var(--ink-on-dark); }
/* The head cell carries padding: 0 and this is what insets it, so it takes
   the same 12-and-8 as a body cell or the head sits proud of its column. */
.ck .ck-th {
  display: flex;
  align-items: flex-start;
  gap: var(--space-2xs);
  width: 100%;
  padding: var(--space-sm) var(--space-xs);
  text-align: inherit;
}
.ck-table thead th:first-child .ck-th { padding-left: var(--space-md); }
.ck-table thead th:last-child .ck-th { padding-right: var(--space-md); }
.ck-table thead th.ck-num .ck-th,
.ck-table thead th.ck-cell-act .ck-th { justify-content: flex-end; }
.ck .ck-th-text { display: block; min-width: 0; }
.ck .ck-th-label { display: block; white-space: nowrap; }
.ck .ck-th-unit {
  display: block;
  font-weight: var(--weight-regular);
  color: var(--ink-on-dark-muted);
  white-space: nowrap;
}
.ck .ck-sort {
  appearance: none;
  margin: 0;
  border: 0;
  background: none;
  font: inherit;
  color: inherit;
  cursor: pointer;
  transition: color var(--motion-state) var(--ease);
}
.ck .ck-sort:hover { color: var(--ink-on-dark); }
/* Sized by the group above, not nudged: the column head is a top-aligned
   flex row so the arrow stays on the first line when "At pickup by" wraps to
   two, and 0.125em put it 1.2px above that line's centre. */
.ck .ck-sort-icon {
  color: var(--color-accent-on-dark);
  opacity: 0;
  transition: opacity var(--motion-state) var(--ease);
}
.ck-table thead th.ck-num .ck-sort-icon { order: -1; }
.ck-table th[aria-sort="ascending"] .ck-sort-icon,
.ck-table th[aria-sort="descending"] .ck-sort-icon,
.ck .ck-sort:hover .ck-sort-icon,
.ck .ck-sort:focus-visible .ck-sort-icon { opacity: 1; }

/* Row states. Each is a ground AND a word in the rank cell.
   Lead: the feature ground, tea-light; charcoal 12.90, muted-gray 5.44.
   Assigned: the alternate ground, muted-light; charcoal 12.10.
   Blocked: caution-light, charcoal 12.44, the rank in the caution ink at
   5.23 with a stop glyph.
   Hover, on a row that is neither: warm; charcoal 14.02, muted-gray 5.91. */
.ck-table .ck-row.is-lead th,
.ck-table .ck-row.is-lead td { background: var(--color-tea-light); }
.ck-table .ck-row.is-assigned th,
.ck-table .ck-row.is-assigned td { background: var(--color-muted-light); font-weight: var(--weight-semibold); }
.ck-table .ck-row.is-blocked th,
.ck-table .ck-row.is-blocked td { background: var(--color-caution-light); }
.ck-table .ck-row.is-blocked td:nth-child(2) { font-weight: var(--weight-regular); }
/* style.css makes every svg a block, which put the stop glyph on its own
   line above the words; inline-flex keeps them on one. */
/* "Over hours" is allowed to take two lines, and the column is given a
   width narrow enough that it does. Held on one line it was the widest thing
   in the rank column in the blocked situation and pushed the fleet past its
   wrapper -- on the one screen whose whole argument is that it fits. The
   words are their own span so the text has something to wrap inside; a bare
   text node next to the glyph is one anonymous flex item and wraps nowhere.

   The width is a preference, not a cap: auto table layout will still take
   more if a row genuinely needs it, which is what keeps "Over hours" from
   being clipped if the copy ever grows. */
.ck-table thead th:first-child { width: 4.5rem; }
.ck .ck-rank-rule {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-start;
  gap: var(--space-2xs);
  font-weight: var(--weight-semibold);
  color: var(--color-caution-text);
}
.ck .ck-rank-rule .ck-icon { margin-top: 0.15em; }
/* The rank cell, stacked: ordinal over marks.

   NOT WITH display:flex ON THE CELL. A th given a flex display stops being a
   table-cell, and a box that is not a table-cell does not stretch to its
   row: this one sized to its own content and sat at the top of the row,
   carrying its border-bottom up there with it. Every row whose other cells
   wrapped to two lines therefore drew the rank column's hairline 10px or
   17px above the one running across the rest of the row, and the ordinal sat
   a line higher than the truck id beside it. Two visible faults from one
   declaration, and neither is anything the four checks can see -- they read
   colour, type and borders-on-curves, and this is a box model.

   The stack is a block one instead. The cell stays a table-cell, so it
   stretches, its border meets its neighbours' and vertical-align:middle puts
   the ordinal on the same line as everything else in the row. */
.ck-table .ck-cell-rank { white-space: normal; }
.ck .ck-rank-n { display: block; }
/* The marks stack too, rather than running along one line. A row can carry
   two of them -- "assigned" and a moved marker, or "option A" and a moved
   marker -- and side by side those two set the whole column to 106px in the
   override situation, which was the last thing standing between the fleet
   and its wrapper. */
.ck .ck-rank-marks {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 2px;
  margin-top: 2px;   /* was the cell flex's gap, before the cell stopped being one */
}
.ck .ck-rank-tag {
  display: inline-flex;
  align-items: center;
  gap: 0.2em;
  padding: 0 var(--space-xs);
  border: 1px solid var(--color-accent-deep);
  border-radius: var(--radius-pill);
  background: var(--color-white);
  font-size: var(--text-2xs);
  font-weight: var(--weight-semibold);
  line-height: var(--leading-ui);
  color: var(--color-accent-text);
  vertical-align: 0.1em;
}
/* The assigned row's state word, out of the button and in with the row's
   other tags. White ground, accent-text on it 5.82. */
.ck .ck-tag-lead {
  background: var(--color-accent-text);
  border-color: var(--color-accent-text);
  color: var(--color-warm);
}
.ck .ck-cell-note {
  display: block;
  font-size: var(--text-xs);
  line-height: var(--leading-ui);
  font-weight: var(--weight-regular);
  color: var(--color-muted-gray);
}

.ck .ck-why-done:focus-visible {
  outline: 2px solid var(--color-accent-deep);
  outline-offset: 4px;
  border-radius: 4px;
}

/* ---------- Focus ----------
   style.css rings links and buttons. These are the controls it does not
   name. The ring is the fill sage: 4.51 on white, 4.12 on warm, 3.80 on
   tea-light, all over the 3:1 a focus indicator answers to. The sort
   buttons fill their cell in the charcoal head, so they ring inward, 3.40
   on charcoal, where the wrapper's rounded overflow cannot clip it. */
/* The walkthrough's disclosures sit outside .ck and are the same control, so
   they take the same ring rather than falling through to style.css, which
   rings links and buttons and does not name a summary. */
.ck input:focus-visible,
.ck textarea:focus-visible,
.ck summary:focus-visible,
.ckw-more summary:focus-visible {
  outline: 2px solid var(--color-accent-deep);
  outline-offset: 2px;
  border-radius: 4px;
}
.ck .ck-sort:focus-visible { outline-offset: -3px; }

/* ======================= THE CLOSE CALL, COMPARED =========================
   Two recommendation cards side by side were two READINGS, not a comparison.
   The same five factors in the same order in two boxes means the reader does
   the comparing: find the fourth row on the left, hold 5.8, find the fourth
   row on the right, subtract. Five times. And on a phone the cards stack, so
   the two halves of each comparison ended up about nine hundred pixels apart,
   which is not a comparison at all -- it is a memory test.

   It is a <table> now, and the markup is most of the fix: <th scope="col"> on
   each option and <th scope="row"> on each factor is what lets a screen
   reader say "Hours of service left, Option B, 8.4 h" from a single cell.
   The pair of cards could not produce that sentence in any order.

   THE TWO DECISIVE ROWS SORT TO THE TOP and take the white raised surface,
   which is this cockpit's existing grammar for "the thing to act on". The
   rest keep the zone's muted ground. Row order is the argument.

   FIXED LAYOUT, so the two option columns are exactly equal: a comparison
   whose columns are different widths is one the eye reads as weighted. ==== */
.ck .ck-vs {
  width: 100%;
  margin: var(--space-lg) 0 0;
  border-collapse: collapse;
  table-layout: fixed;
}
.ck .ck-vs th,
.ck .ck-vs td {
  padding: var(--space-sm) var(--space-md);
  text-align: left;
  vertical-align: top;
  border-bottom: 1px solid var(--rule-hairline);
}
.ck .ck-vs thead th,
.ck .ck-vs thead td { border-bottom: 1px solid var(--color-rule); }
.ck .ck-vs tfoot td { border-bottom: 0; }
.ck .ck-vs-corner { width: 30%; border-bottom-color: transparent; }

/* The option head: what it is, which truck, and who is driving it. */
.ck .ck-vs-opt { width: 35%; }
.ck .ck-vs-opt-label { display: block; color: var(--color-accent-text); font-size: var(--text-xs); line-height: var(--leading-ui); }
.ck .ck-vs-opt-id {
  display: block;
  margin-top: var(--space-2xs);
  font-size: var(--text-lg);
  font-weight: var(--weight-semibold);
  line-height: var(--leading-tight);
  color: var(--color-charcoal);
}
.ck .ck-vs-opt-who {
  display: block;
  font-size: var(--text-sm);
  font-weight: var(--weight-regular);
  line-height: var(--leading-ui);
  color: var(--color-muted-gray);
}
.ck .ck-vs-opt.is-assigned .ck-vs-opt-label { color: var(--color-charcoal); font-weight: var(--weight-semibold); }

/* The factor, as the row's head. */
.ck .ck-vs-factor { font-weight: var(--weight-regular); }
.ck .ck-vs-factor-name {
  display: block;
  font-size: var(--text-sm);
  line-height: var(--leading-ui);
  color: var(--color-charcoal);
}
.ck .ck-vs-tag {
  display: inline-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);
}
.ck .ck-vs-note {
  display: block;
  margin-top: var(--space-2xs);
  font-size: var(--text-xs);
  line-height: var(--leading-ui);
  color: var(--color-muted-gray);
}

/* A cell: the figure, the verdict under it, the fleet bar under that. The
   two bars for one factor now sit on one line, which is the arrangement that
   makes them worth drawing at all. */
.ck .ck-vs-value {
  display: block;
  font-size: var(--text-lg);
  font-weight: var(--weight-semibold);
  line-height: var(--leading-ui);
  font-variant-numeric: tabular-nums;
  color: var(--color-charcoal);
}
.ck .ck-vs-dir {
  justify-content: flex-start;
  min-width: 0;
  margin-top: var(--space-2xs);
  text-align: left;
}
.ck .ck-vs-cell .ck-factor-bar { margin-top: var(--space-xs); }

/* The two rows that separate them, raised onto white. Forced by states.mjs
   onto every row, which is harmless: all four inks clear on white. */
.ck .ck-vs-row.is-decisive th,
.ck .ck-vs-row.is-decisive td { background: var(--color-white); }

/* The derived reading, last and marked as derived. It is figured from the
   miles the ranking weighed; it is not a sixth factor and must not read as
   one, so it sits below the five with the words saying so. */
.ck .ck-vs-derived .ck-vs-value { font-size: var(--text-base); }
.ck .ck-vs-win .ck-vs-dir { color: var(--color-muted-gray); }
.ck .ck-vs-win[data-window="tight"] .ck-vs-dir,
.ck .ck-vs-win[data-window="misses"] .ck-vs-dir { color: var(--color-caution-text); font-weight: var(--weight-semibold); }
.ck .ck-vs-act { padding-top: var(--space-lg); }

/* ===================== THE FLEET'S HEAD, AND ITS DENSITY ==================
   The fleet was the one region of the cockpit with no visible heading at all
   -- a hidden <caption> and nothing else -- so a reader scrolling past a
   thousand pixels of interface arrived at the data table with nothing saying
   what it was. The heading is the landmark; the switch beside it is the
   other half of the argument the table makes.

   WHY A DENSITY SWITCH IS NOT A GIMMICK HERE. A dispatch floor runs denser
   than a portfolio page. A prototype that only ever shows the comfortable end
   is quietly proposing a screen nobody would ship, and the page's fourth
   decision -- keep the whole fleet in reach -- is exactly the claim that gets
   harder as rows get shorter. Both ends are on screen, and the reader can
   see the tradeoff rather than take my word for it. ======================== */
.ck .ck-fleet-bar {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-sm);
  margin-bottom: var(--space-sm);
}
.ck .ck-fleet-h { margin: 0; }
.ck .ck-density {
  display: flex;
  align-items: center;
  gap: 2px;
  padding: 2px;
  border: 1px solid var(--color-rule);
  border-radius: var(--radius-pill);
  background: var(--color-white);
}
.ck .ck-density-btn {
  appearance: none;
  border: 0;
  border-radius: var(--radius-pill);
  padding: var(--space-2xs) var(--space-sm);
  background: none;
  font-family: var(--font-sans);
  font-size: var(--text-xs);
  font-weight: var(--weight-medium);
  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);
}
.ck .ck-density-btn[aria-pressed="false"]:hover { background: var(--wash-on-light-hover); }
/* The selected end takes the tabs' own idiom: charcoal under warm, 14.02. */
.ck .ck-density-btn[aria-pressed="true"] {
  background: var(--color-charcoal);
  color: var(--color-warm);
  font-weight: var(--weight-semibold);
}

/* ======================= A ROW THAT OPENS IN PLACE ========================
   "Also considered" explained why second and third lost and stopped there;
   the other four kept their figures and never got a reason. This is the same
   open-in-place disclosure the misses list and the comparisons note already
   use -- one idiom for "there is more here", not a third invention.

   It is also what answers the phone. Under 48rem the stylesheet drops six of
   the eleven columns and this row is where they go, so nothing is lost and
   what is left fits in 292px instead of scrolling 1104px of table behind an
   invisible scrollbar. ==================================================== */
/* "Can't assign" takes two lines in the fleet. It is the widest control in
   the table and one blocked row sets the whole action column: 138px against
   the 74 an enabled row needs. The reason it can afford to wrap here and
   nowhere else is that the blocked row already says "Over hours" where its
   rank would be, so the button is the second telling, not the first. */
.ck-table .ck-btn[aria-disabled="true"] { white-space: normal; }

/* "Assign" alone in the fleet, "Assign T-118" still in its accessible name:
   the id is the row's own second cell, and spelling it out again cost the
   action column 141px of a table with 1118 to spend. */
.ck .ck-table .ck-cell-act .ck-btn-id {
  position: absolute;
  width: 1px; height: 1px;
  padding: 0; margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}
.ck-table .ck-cell-truck { padding: 0; }
.ck .ck-row-more {
  appearance: none;
  display: flex;
  align-items: center;
  gap: var(--space-2xs);
  width: 100%;
  min-height: 2.75rem;
  padding: var(--space-xs) var(--space-2xs) var(--space-xs) var(--space-xs);
  border: 0;
  background: none;
  font-family: var(--font-sans);
  font-size: var(--text-sm);
  font-weight: var(--weight-semibold);
  line-height: var(--leading-ui);
  color: var(--color-charcoal);
  text-align: left;
  /* The id is the label and must not break: the button is narrower than the
     cell was, and "T-118" came back as "T-" over "118" on every row. */
  white-space: nowrap;
  cursor: pointer;
  transition: color var(--motion-state) var(--ease);
}
.ck .ck-row-more:hover { color: var(--color-accent-hover); }
.ck .ck-row-chev {
  flex-shrink: 0;
  width: 0.875rem;
  height: 0.875rem;
  color: var(--color-muted-gray);
  transform: rotate(-90deg);
  transition: transform var(--motion-state) var(--ease);
}
.ck .ck-row-more[aria-expanded="true"] .ck-row-chev { transform: rotate(0deg); }
.ck .ck-row-more:focus-visible { outline: 2px solid var(--color-accent-deep); outline-offset: -3px; border-radius: 4px; }

/* The detail row takes the warm ground, so an opened row is visibly a note
   about the row above rather than another truck. Charcoal 14.02 on it. */
.ck-table .ck-row-detail > td { padding: 0; background: var(--color-warm); }
.ck .ck-detail {
  display: grid;
  gap: 0;
  padding: var(--space-md) var(--space-md) var(--space-lg);
  max-width: 34rem;
}
.ck .ck-detail-who {
  margin: 0;
  font-size: var(--text-sm);
  line-height: var(--leading-ui);
  color: var(--color-charcoal);
}
.ck .ck-detail-why {
  margin: var(--space-md) 0 0;
  font-size: var(--text-sm);
  line-height: var(--leading-ui);
  color: var(--color-charcoal);
}
.ck .ck-why-rank-rule { display: inline-flex; align-items: baseline; gap: var(--space-2xs); color: var(--color-caution-text); font-weight: var(--weight-semibold); }
.ck .ck-detail-act { margin: var(--space-md) 0 0; }
/* The detail is a panel, not a dense row, so its button takes the site's
   full 44 rather than the 30 a fleet row can afford. */
.ck .ck-detail-act .ck-btn { min-height: 2.75rem; padding-inline: var(--space-md); }
.ck .ck-detail .ck-factors { margin-top: var(--space-md); }

/* ---------- Where a row came from ----------
   Switching situations re-ranks seven rows silently, and which ones moved is
   the first thing anyone flicking between four situations wants to know. A
   direction, a number of places, and the words in the row for a reader who
   cannot see the glyph. Cleared by the reader's next action rather than by a
   timer: a mark that leaves on its own leaves while it is being read.
   muted-gray clears on all four row grounds -- 6.47 white, 5.44 tea-light,
   5.11 muted-light, 5.25 caution-light. */
.ck .ck-rank-moved {
  display: inline-flex;
  align-items: center;
  gap: 0.1em;
  font-size: var(--text-xs);
  font-weight: var(--weight-semibold);
  line-height: var(--leading-ui);
  color: var(--color-muted-gray);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}
.ck .ck-rank-moved .ck-icon { width: 0.75em; height: 0.75em; }

/* ---------- The window, in the data table ---------- */
.ck-table .ck-cell-win { white-space: nowrap; }
.ck-table .ck-cell-win .ck-cell-note { color: var(--color-muted-gray); }
.ck-table .ck-cell-win[data-window="tight"] .ck-cell-note,
.ck-table .ck-cell-win[data-window="misses"] .ck-cell-note { color: var(--color-caution-text); font-weight: var(--weight-semibold); }

/* ---------- Assign, as a target ----------
   30px in a 55px row cleared the 24px the success criterion asks for and
   missed the 44px every other round control on this site holds itself to.
   The button keeps its size and the TARGET grows to 44 through a pseudo-
   element, so the row's rhythm does not change and curves.mjs counts no new
   element. In compact the extender comes off, because a 44px target in a
   38px row is a target that overlaps the row above. */
.ck table .ck-btn { position: relative; }
.ck .ck-fleet:not(.is-compact) table .ck-btn::after {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  top: 50%;
  height: 2.75rem;
  transform: translateY(-50%);
}

/* ---------- Compact ----------

   PADDING-BLOCK, NOT THE SHORTHAND, AND NOT ON thead.

   This was `padding: var(--space-2xs) var(--space-xs)` on every th and td in
   the fleet, and it did three things where it meant to do one. The horizontal
   half was already what the base rule sets -- both are --space-xs -- so the
   only real change was ever the vertical; the rest was collateral.

   It reset `thead th { padding: 0 }`. The head cell is deliberately empty of
   padding so the .ck-th inside can carry the same 12-and-8 a body cell has,
   which is the comment at that rule. Adding 8px to the cell put it on top of
   the 8px already on the button, so in compact every header label sat 8px
   further into its column than the values under it -- right on the left-hand
   columns, left on the right-aligned ones, and 16px on Rank, which has the
   first-child inset too. It also made the head TALLER in compact than in
   comfortable, 4+12 a side against 12.

   And it flattened the first and last columns' outer inset, because
   `.ck .ck-fleet.is-compact .ck-table th` outranks `.ck-table tbody
   th:first-child`, so the table stopped starting on the screen's own margin.

   padding-block changes the one thing compact is about and leaves the
   horizontal rhythm, the head's zero and the outer insets alone. */
.ck .ck-fleet.is-compact .ck-table tbody th,
.ck .ck-fleet.is-compact .ck-table tbody td { padding-block: var(--space-2xs); }
.ck .ck-fleet.is-compact .ck-table thead .ck-th { padding-block: var(--space-2xs); }
/* The truck id is a button filling a cell with no padding of its own, so this
   padding IS the column's left inset and has to stay on --space-xs like every
   other cell's. At --space-2xs the id sat 4px left of the word "Truck" above
   it -- the one column in compact still out of line once the head stopped
   being padded twice. Only the vertical compresses. */
.ck .ck-fleet.is-compact .ck-row-more { min-height: 0; padding: var(--space-2xs) var(--space-md) var(--space-2xs) var(--space-xs); }
.ck .ck-fleet.is-compact .ck-table .ck-cell-note { display: none; }
.ck .ck-fleet.is-compact .ck-table .ck-rank-tag { font-size: var(--text-2xs); }

/* ---------- Narrow ----------
   The four ramps bottom out at 400px, which is the width this is built to.
   Cards give back the inset a panel takes; the table keeps its width and
   scrolls in its wrapper. */
/* ============== THE FLEET, UNDER 48rem: FEWER COLUMNS, NOT LESS DATA ======
   At 390px the wrapper is 292px and the table authors 960, so a phone reader
   got Rank, Truck and Driver and a silent 812px of horizontal scroll holding
   every figure and every Assign button. The blocked situation's own nudge
   asks the reader to assign T-114 from the data table, which on a phone was
   an instruction to find a control that nothing said was there.

   Seven columns come off and the row disclosure carries them, so the fleet
   is still whole -- one tap per truck instead of a scroll with no bar on it.
   What stays is the smallest set a phone reader can triage from: the rank,
   the truck, when it would reach the pickup, and the button. That is the
   page's "keep the whole fleet in reach" honoured rather than repeated,
   because a column nobody can find is not in reach.

   HOURS LEFT IS THE ONE THAT HURT TO CUT, and it is cut on arithmetic
   rather than taste. Five columns wanted 325px of a 292px wrapper even after
   every tag, inset and gutter had been squeezed; four want 264. The hours
   are not gone from the phone -- the blocked row still says "Over hours"
   where its rank would be, the rule card above still spells out the figure
   and the limit, and the row disclosure carries the factor with its bar. */
@media (max-width: 47.99rem) {
  .ck-table { min-width: 0; }
  .ck-table th:nth-child(3),  .ck-table td:nth-child(3),
  .ck-table th:nth-child(4),  .ck-table td:nth-child(4),
  .ck-table th:nth-child(5),  .ck-table td:nth-child(5),
  .ck-table th:nth-child(7),  .ck-table td:nth-child(7),
  .ck-table th:nth-child(8),  .ck-table td:nth-child(8),
  .ck-table th:nth-child(9),  .ck-table td:nth-child(9),
  .ck-table th:nth-child(10), .ck-table td:nth-child(10) { display: none; }
  .ck-table th, .ck-table td { padding-inline: var(--space-2xs); }
  .ck-table tbody th:first-child, .ck-table tbody td:first-child { padding-left: var(--space-xs); }
  .ck-table tbody th:last-child, .ck-table tbody td:last-child { padding-right: var(--space-xs); }
  .ck-table thead th:first-child .ck-th { padding-left: var(--space-xs); }
  .ck-table thead th:last-child .ck-th { padding-right: var(--space-xs); }
  /* The pick and option tags go under the ordinal rather than beside it:
     beside it, the rank column alone wanted 67px of a 292px table. display
     is flex and not inline-flex on purpose -- an inline box sits back on the
     same line and saves nothing. */
  /* A head is allowed two lines here. The rule that keeps every label on one
     line is what stops the browser wrapping them where IT chooses on a wide
     table; at 292px the choice is a two-line head or a column that does not
     fit at all, and five columns of "Hours left" over one line is 391px of
     table in a 292px wrapper. */
  .ck .ck-th-label { white-space: normal; }
  .ck .ck-th { align-items: flex-start; }
  /* The last sixty pixels, taken off the furniture rather than off a column.
     Every number below is the width of something that is not data: a tag's
     padding, a button's inset, the gap beside a chevron, the gutter between
     cells. Five columns of truck, clock, hours and a button fit 292px once
     the furniture stops asking for 352. */
  .ck-table th, .ck-table td { padding-inline: 2px; }
  .ck-table tbody th:first-child, .ck-table tbody td:first-child { padding-left: var(--space-2xs); }
  .ck-table tbody th:last-child, .ck-table tbody td:last-child { padding-right: var(--space-2xs); }
  .ck-table thead th:first-child .ck-th { padding-left: var(--space-2xs); }
  .ck-table thead th:last-child .ck-th { padding-right: var(--space-2xs); }
  .ck .ck-rank-tag { font-size: var(--text-2xs); padding: 0 var(--space-2xs); }
  .ck-table .ck-btn { padding-inline: var(--space-xs); }
  .ck .ck-row-more { gap: 2px; padding-left: var(--space-2xs); }
  .ck .ck-row-chev { width: 0.75rem; height: 0.75rem; }
  /* The head's unit line is a second line in a 60px column here, and every
     unit it carries is in the row disclosure underneath. */
  .ck .ck-th-unit { display: none; }
  .ck .ck-th { padding-inline: var(--space-2xs); }
  .ck .ck-detail { padding-inline: var(--space-sm); }
}

@media (max-width: 599px) {
  /* Frame, screen, zone, card: four insets stack on a phone, and at 390px
     they left a card 238px wide. The screen and the zone give back most of
     theirs; the cards keep a readable inset. */
  .ck { padding: var(--space-md); }
  .ck-lead { padding: var(--space-sm); }
  .ck-card, .ck-load, .ck-why, .ck-rule, .ck-confidence, .ck-also { padding: var(--space-md); }
  .ck .ck-status { padding: var(--space-sm) var(--space-md); }
  .ck .ck-reco-h { font-size: var(--text-xl); }
  .ck-load-facts { grid-template-columns: minmax(0, 1fr); }
  /* THE FACTOR ROW, IN THREE LINES RATHER THAN FOUR. The verdict used to
     take the full width on its own line UNDER the bar's row, so every factor
     was name / value / verdict / bar and a five-factor card was twenty lines
     of phone. The verdict belongs under the NAME -- it is judging the thing
     the name names -- and the value spans both rows beside them, which puts
     the figure and the word about it on the same block of the card. */
  .ck-factor { grid-template-columns: minmax(0, 1fr) auto; row-gap: 0; column-gap: var(--space-sm); }
  .ck .ck-factor-name { grid-column: 1; grid-row: 1; }
  .ck .ck-factor-value { grid-column: 2; grid-row: 1 / span 2; align-self: center; }
  .ck .ck-factor-dir { grid-column: 1; grid-row: 2; justify-content: flex-start; text-align: left; min-width: 0; }
  .ck-factor-bar { grid-row: 3; }
  /* The comparison keeps three columns on a phone -- stacking it would put
     it back where the two cards were -- and buys the room from the padding
     and one step of the value. */
  .ck .ck-vs th, .ck .ck-vs td { padding: var(--space-sm) var(--space-2xs); }
  .ck .ck-vs-corner { width: 32%; }
  .ck .ck-vs-opt { width: 34%; }
  .ck .ck-vs-value { font-size: var(--text-base); }
  .ck .ck-vs-opt-id { font-size: var(--text-base); }
  .ck .ck-vs-dir { font-size: var(--text-xs); }
  /* The two Assign buttons sit in columns about 99px wide and "Assign T-131"
     needs 111, so the pair collided and the first one clipped. The id goes
     quiet here for the same reason it is quiet in the fleet -- the column it
     sits under is headed with the truck it assigns -- and each button fills
     its own column, which is what makes that association unmistakable. The
     accessible name still reads "Assign T-131". */
  .ck .ck-vs-act .ck-btn-id {
    position: absolute;
    width: 1px; height: 1px;
    padding: 0; margin: -1px;
    overflow: hidden;
    clip: rect(0, 0, 0, 0);
    white-space: nowrap;
    border: 0;
  }
  .ck .ck-vs-act .ck-btn { width: 100%; justify-content: center; }
  .ck .ck-try { padding: var(--space-sm); }
  /* The disc does not shrink -- it is the case studies' mark at every width
     there too -- so what a phone buys back is the gap beside it, not the
     column. */
  .ckw-decision-copy { padding-left: calc(var(--ck-num) + var(--space-xs)); }
  /* Four cards inside a card: the compare sides, the question cards and the
     callout keep a readable inset at the width the rest of the page gives
     back. */
  .ckw-compare-side, .ckw-questions > li, .ckw-callout { padding: var(--space-md); }
  .case-section .ckw-question { padding: var(--space-md) var(--space-lg); }
}
