/**
 * CANDYBOX MOMENTUM: the dashboard a client is given (docs/26).
 *
 * TWO SURFACES, ONE STYLESHEET, and that is deliberate rather than lazy. The
 * builder an account manager works in and the page a client reads are the same
 * board with the same cards, drawn from the same reduction; the only difference
 * is a row of controls that is not rendered for a reader. A second stylesheet
 * for the client page would be the place the two quietly stop matching, and the
 * first person to notice would be the client.
 *
 * ── WHAT THIS FILE IS ALLOWED TO INVENT ─────────────────────────────────────
 *
 * Almost nothing. Every card body is built from `note-parts`, `charts-time` and
 * `trend-plot`, which already carry their own rules about colour, scale, hover
 * and reduced motion. What is here is the BOARD (a four-column grid whose
 * placement comes from the shared packer rather than from auto-flow), the
 * chrome around a tile, and the one mark this console has never needed before:
 * the line that says a figure was typed rather than measured.
 *
 * ── THE ONE NEW MARK, AND WHY IT IS NOT A COLOUR ────────────────────────────
 *
 * `.cb-mom-mark` is a manual card's source line, and it is drawn as a rule and
 * a quiet italic rather than as a coloured badge. Two reasons and both are
 * rules of this codebase. A colour has two jobs and two bars (rule 19), so a
 * tinted sentence would have to clear 4.5:1 on the console's near-black, the
 * client page's white and paper, in three themes; and one candy-motif touch per
 * surface is the brand's limit, spent here on the name rather than on a badge.
 * A rule above a line of italic reads as a footnote in every one of those
 * grounds without asking any of them a contrast question.
 *
 * ── AND WHY THE BOARD IS PLACED EXPLICITLY ──────────────────────────────────
 *
 * `--mom-col` comes off `packBoard` in shared/src/momentum-shape.ts, which has
 * unit tests. Grid auto-flow would agree with it today and is a second
 * implementation of one arithmetic across three renderings (this console, the
 * print stylesheet, and the client page when it ships). One function with tests
 * beats three browsers' reading of one shorthand.
 */

/* ---------------------------------------------------------------------------
   The screens: the list of a client's dashboards, and the builder's chrome.
   ------------------------------------------------------------------------ */

.cb-mom-head,
.cb-mom-build-head {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: var(--cb-space-3xl);
  margin-bottom: var(--cb-space-4xl);
  flex-wrap: wrap;
}

.cb-mom-head h1 {
  margin: 0 0 var(--cb-space-md);
  font-size: var(--cb-type-2xl-size);
  font-weight: var(--cb-font-weight-semibold);
  color: var(--cbc-ink);
}

/**
 * A LINE LENGTH IS A MEASURE, NOT A SPACING STEP, and this is the cross-scale
 * fault CLAUDE.md rule 13 names: a spacing token in a typographic slot passes
 * every guard, because `check:tokens` asks "is this a raw value" and never "is
 * this the right family".
 *
 * The first version of this rule was `max-width: var(--cb-space-11xl)`, which
 * is 160 pixels. It looked like a token and it was one; it was also a quarter
 * of the measure a sentence wants, so the screen's own subtitle wrapped after
 * three words down the left edge of an otherwise empty page.
 *
 * `ch` IS THE UNIT A MEASURE IS WRITTEN IN, and the scale this token set does
 * not model. Sixty-eight characters is the middle of the readable band and it
 * moves with the type rather than against it, which is the whole reason not to
 * express it in pixels of any kind.
 */
.cb-mom-sub {
  margin: 0;
  max-width: 68ch;
  font-size: var(--cb-type-sm-size);
  line-height: var(--cb-type-sm-line-height);
  color: var(--cbc-ink-muted);
}

/* The dashboard's name, edited in place. It is a heading that happens to be a
   field, so it is sized as one rather than looking like a form. */
.cb-mom-name {
  /* A title's own field, so its basis is how many characters a name is, not a
     spacing step. Sixty is the schema's ceiling on the name (momentum.ts). */
  flex: 1 1 30ch;
  min-width: 0;
  font-size: var(--cb-type-xl-size);
  font-weight: var(--cb-font-weight-semibold);
}

.cb-mom-build-acts {
  display: flex;
  gap: var(--cb-space-md);
  align-items: center;
  flex-wrap: wrap;
}

/* WHERE A MANUAL CARD'S FIGURES COME FROM (docs/26 §3.3). One block at the top
   of the card's dialog, because choosing a sheet or a file FILLS the fields
   below it: a source control under a table somebody has just typed out is a
   control that overwrites their work. */
.cb-mom-source {
  display: flex;
  flex-direction: column;
  gap: var(--cb-space-sm);
  padding: var(--cb-space-md);
  border-radius: var(--cb-radius-lg);
  background: var(--cbc-sunken);
}

/* The Try button sits under the address rather than beside it, so a long
   published link keeps the whole width of the dialog. */
.cb-mom-source-try {
  display: flex;
  justify-content: flex-start;
}

/* THE SHARING GROUP, KEPT TOGETHER AND SET APART FROM THE REST OF THE ROW.
   Add, Delete and Save are about what is ON the board; these three are about
   who can read it, which is a different decision with a different seat behind
   it. The divider is what says so without a heading. */
.cb-mom-share {
  display: flex;
  gap: var(--cb-space-xs);
  align-items: center;
  padding-right: var(--cb-space-md);
  border-right: 1px solid var(--cbc-line);
}

.cb-mom-controls {
  display: flex;
  gap: var(--cb-space-md);
  margin-bottom: var(--cb-space-3xl);
  flex-wrap: wrap;
}

.cb-mom-controls .cb-input {
  width: auto;
  /* Wide enough for the longest option ("Since we started", and a domain), so
     the two menus do not resize as somebody changes them. A measure again. */
  min-width: 20ch;
}

/* ---------------------------------------------------------------------------
   The list of dashboards.
   ------------------------------------------------------------------------ */

.cb-mom-list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: var(--cb-space-md);
}

.cb-mom-row {
  display: flex;
  align-items: center;
  gap: var(--cb-space-3xl);
  padding: var(--cb-space-2xl) var(--cb-space-3xl);
  border: 1px solid var(--cbc-line);
  border-radius: var(--cb-radius-xl);
  background: var(--cbc-surface);
  cursor: pointer;
  /* Fast out and slow to settle. Hover answers immediately and moves nothing. */
  transition: background var(--cbc-grace) var(--cbc-spring);
}

.cb-mom-row:hover,
.cb-mom-row:focus-visible {
  background: var(--cbc-hover);
}

.cb-mom-row:focus-visible {
  outline: 2px solid var(--cbc-focus);
  outline-offset: 2px;
}

.cb-mom-row > div {
  flex: 1 1 auto;
  min-width: 0;
}

.cb-mom-row h2 {
  margin: 0;
  font-size: var(--cb-type-base-size);
  font-weight: var(--cb-font-weight-medium);
  color: var(--cbc-ink);
}

.cb-mom-row-note,
.cb-mom-when {
  margin: 0;
  font-size: var(--cb-type-xs-size);
  color: var(--cbc-ink-faint);
}

/* Which kind of dashboard, in words rather than a colour code. The tint is a
   reinforcement of a word that is already there, never the only signal. */
.cb-mom-kind {
  flex: 0 0 auto;
  padding: var(--cb-space-xxs) var(--cb-space-md);
  border-radius: var(--cb-radius-full);
  font-size: var(--cb-type-xs-size);
  background: var(--cbc-stand);
  color: var(--cbc-ink-muted);
  white-space: nowrap;
}

.cb-mom-kind[data-kind="shareable"] {
  background: var(--cbc-accent-quiet);
  color: var(--cbc-accent-text);
}

/* ---------------------------------------------------------------------------
   The empty state: the six templates, which is what this screen opens on.
   ------------------------------------------------------------------------ */

.cb-mom-empty h2 {
  margin: 0 0 var(--cb-space-md);
  font-size: var(--cb-type-lg-size);
  font-weight: var(--cb-font-weight-semibold);
  color: var(--cbc-ink);
}

.cb-mom-templates {
  list-style: none;
  margin: var(--cb-space-3xl) 0 0;
  padding: 0;
  display: grid;
  /* Three across at a comfortable width, two on a laptop, one on a phone. The
     minimum is a MEASURE in `ch` rather than a spacing step: what decides it is
     how many characters of a template's blurb fit on a line, which moves with
     the type. A spacing token here is the cross-scale fault the subtitle rule
     above sets out. */
  grid-template-columns: repeat(auto-fill, minmax(28ch, 1fr));
  gap: var(--cb-space-xl);
}

.cb-mom-template {
  display: flex;
  flex-direction: column;
  gap: var(--cb-space-md);
  padding: var(--cb-space-2xl);
  border: 1px solid var(--cbc-line);
  border-radius: var(--cb-radius-xl);
  background: var(--cbc-surface);
}

.cb-mom-template h3 {
  margin: 0;
  font-size: var(--cb-type-base-size);
  font-weight: var(--cb-font-weight-medium);
  color: var(--cbc-ink);
}

.cb-mom-template p {
  margin: 0;
  font-size: var(--cb-type-sm-size);
  line-height: var(--cb-type-sm-line-height);
  color: var(--cbc-ink-muted);
}

.cb-mom-template .cb-btn {
  align-self: flex-start;
  margin-top: auto;
}

/* ---------------------------------------------------------------------------
   The board. Four columns, placed by the shared packer.
   ------------------------------------------------------------------------ */

/**
 * THE BOARD'S CONTAINER, WHICH HOLDS ITS HEIGHT WHILE THE FIGURES ARE RE-READ.
 *
 * Changing a card's level asks the server again (that is what makes a level a
 * reduction rather than a filter), and the answer takes a moment. Without a
 * floor the board would collapse to nothing and the coverage note would jump up
 * the page and back down, which is the page moving under somebody who has just
 * pressed something. Content settles into a container that has already arrived.
 */
.cb-mom-stage {
  min-height: var(--cb-space-11xl);
}

.cb-mom-board {
  display: grid;
  grid-template-columns: repeat(var(--mom-cols, 4), minmax(0, 1fr));
  /**
   * A row is a MINIMUM rather than a fixed height, so a card asking for one row
   * gets at least this and grows if its contents need it, and the row grows
   * with it so its neighbours stay aligned.
   *
   * It was a third larger and every text card had a void under it: a two-row
   * default on a card holding four lines left half the tile empty, on a page
   * whose whole job is being read at a glance. The cards that need the height
   * (a plot, a table, a list of months) now ask for it, and the ones that do
   * not take one row and grow.
   */
  grid-auto-rows: minmax(var(--cb-space-8xl), auto);
  gap: var(--cb-space-xl);
  align-items: stretch;
}

.cb-mom-tile {
  grid-column: var(--mom-col, auto) / span var(--mom-w, 2);
  grid-row: var(--mom-row, auto) / span var(--mom-h, 1);
  display: flex;
  flex-direction: column;
  gap: var(--cb-space-lg);
  min-width: 0;
  padding: var(--cb-space-2xl);
  border: 1px solid var(--cbc-line);
  border-radius: var(--cb-radius-2xl);
  background: var(--cbc-surface);
  color: var(--cbc-ink);
}

.cb-mom-tile-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--cb-space-md);
}

.cb-mom-tile-head h3 {
  margin: 0;
  font-size: var(--cb-type-xs-size);
  font-weight: var(--cb-font-weight-medium);
  /* The instrument label above a reading, which is the one piece of chrome
     every card on this board shares. It is what makes a screen of different
     charts read as one instrument rather than as a folder of widgets. */
  letter-spacing: var(--cb-tracking-xxs);
  text-transform: uppercase;
  color: var(--cbc-ink-faint);
}

/* A card the agency typed, marked at the top as well as at the bottom. */
.cb-mom-typed {
  font-size: var(--cb-type-xs-size);
  letter-spacing: var(--cb-tracking-xxs);
  text-transform: uppercase;
  color: var(--cbc-warn-text);
}

/* ---------------------------------------------------------------------------
   The controls, which arrive when you approach and reserve their own space.
   ------------------------------------------------------------------------ */

.cb-mom-tools {
  display: flex;
  flex-wrap: wrap;
  gap: var(--cb-space-xs);
  margin-top: auto;
  padding-top: var(--cb-space-md);
  border-top: 1px solid var(--cbc-line);
  /* IN THE FLOW AND ONLY FADED, never display:none. A control that appears on
     hover and pushes the card's contents about is a card that moves under the
     pointer, and one that is display:none is unreachable by a keyboard until
     something focuses it, which nothing can. */
  opacity: 0;
  transition: opacity var(--cbc-grace) var(--cbc-spring);
}

.cb-mom-tile:hover .cb-mom-tools,
.cb-mom-tile:focus-within .cb-mom-tools {
  opacity: 1;
}

@media (prefers-reduced-motion: reduce) {
  /* Nothing fades. The controls are simply always there, which is the honest
     reduced-motion answer: an affordance that depends on an animation is an
     affordance somebody with motion turned off never learns about. */
  .cb-mom-tools {
    opacity: 1;
    transition: none;
  }
  .cb-mom-row {
    transition: none;
  }
}

.cb-mom-tool {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: var(--cb-space-xs);
  border: 0;
  border-radius: var(--cb-radius-sm);
  background: transparent;
  color: var(--cbc-ink-muted);
  cursor: pointer;
}

.cb-mom-tool:hover {
  background: var(--cbc-hover);
  color: var(--cbc-ink);
}

.cb-mom-tool:focus-visible {
  outline: 2px solid var(--cbc-focus);
  outline-offset: 1px;
}

.cb-mom-tool[aria-disabled="true"],
.cb-mom-tools .cb-btn[aria-disabled="true"] {
  /* Turned off, never removed (rule 15), and still hoverable so it can carry
     the sentence saying why. `pressable()` is what stops it acting. */
  opacity: 0.45;
  cursor: default;
}

/* ---------------------------------------------------------------------------
   Inside a card. Everything below is composed from note-parts; these are the
   few wrappers those parts sit in.
   ------------------------------------------------------------------------ */

.cb-mom-move,
.cb-mom-detail,
.cb-mom-stack,
.cb-mom-manual,
.cb-mom-inside,
.cb-mom-headline,
.cb-mom-lines {
  display: flex;
  flex-direction: column;
  gap: var(--cb-space-md);
  min-width: 0;
}

/* The opening line of a card: the sentence, before the number. */
.cb-mom-said {
  margin: 0;
  font-size: var(--cb-type-md-size);
  font-weight: var(--cb-font-weight-medium);
  color: var(--cbc-ink);
}

/* The page's own opening line, which is the sentence the product is named
   after. Larger than any figure on the board on purpose (decision 4): every
   other reporting product puts the number first, which is why a client reads
   one and cannot tell whether it was a good quarter. */
.cb-mom-lead {
  margin: 0;
  font-size: var(--cb-type-2xl-size);
  line-height: var(--cb-type-2xl-line-height, 1.2);
  font-weight: var(--cb-font-weight-semibold);
  color: var(--cbc-ink);
}

/* A DIRECTION IS TONED AND A FIGURE IS NOT. The tone is on the sentence, where
   the word "Up" or "Down" is already carrying the meaning, so the colour is a
   reinforcement rather than the only signal. Each uses the -text sibling
   because a sentence is TEXT and the bar is 4.5:1 (rule 19). */
.cb-mom-said[data-tone="better"],
.cb-mom-lead[data-tone="better"] {
  color: var(--cbc-good-text);
}

.cb-mom-said[data-tone="worse"],
.cb-mom-lead[data-tone="worse"] {
  color: var(--cbc-poor-text);
}

.cb-mom-said[data-tone="unknown"],
.cb-mom-lead[data-tone="unknown"] {
  color: var(--cbc-ink-muted);
}

/**
 * The change beside a figure, on a reading card.
 *
 * A BADGE RATHER THAN A SENTENCE, because the Direction card at the top of the
 * board already owns the sentence and five cards saying "Up 9 since July 2026"
 * is a page that stutters. The tone is on the badge and never on the number:
 * a figure coloured red reads as an error rather than as a fall.
 */
.cb-mom-change {
  margin: 0;
  font-size: var(--cb-type-sm-size);
  font-weight: var(--cb-font-weight-medium);
  color: var(--cbc-ink-muted);
}

.cb-mom-change[data-tone="better"] {
  color: var(--cbc-good-text);
}

.cb-mom-change[data-tone="worse"] {
  color: var(--cbc-poor-text);
}

.cb-mom-under,
.cb-mom-caption {
  margin: 0;
  font-size: var(--cb-type-xs-size);
  line-height: var(--cb-type-xs-line-height);
  color: var(--cbc-ink-muted);
}

.cb-mom-title {
  margin: 0;
  font-size: var(--cb-type-base-size);
  font-weight: var(--cb-font-weight-medium);
  color: var(--cbc-ink);
}

.cb-mom-words {
  margin: 0;
  font-size: var(--cb-type-sm-size);
  line-height: var(--cb-type-sm-line-height);
  color: var(--cbc-ink);
}

/* An absence, and it must not look like a caption. A gap is a thing the page is
   telling you it does not have, so it is set apart rather than tucked under. */
.cb-mom-gap {
  margin: 0;
  font-size: var(--cb-type-sm-size);
  line-height: var(--cb-type-sm-line-height);
  color: var(--cbc-ink-muted);
  font-style: italic;
}

/* An icon and a sentence on one line. The tone colours the ICON only, so the
   words never have to clear a contrast bar they were not designed against. */
.cb-mom-flag {
  display: flex;
  align-items: flex-start;
  gap: var(--cb-space-md);
  margin: 0;
  font-size: var(--cb-type-sm-size);
  line-height: var(--cb-type-sm-line-height);
  color: var(--cbc-ink);
}

.cb-mom-flag .cb-icon {
  flex: 0 0 auto;
  color: var(--cbc-ink-muted);
}

.cb-mom-flag[data-tone="good"] .cb-icon {
  color: var(--cbc-good);
}

.cb-mom-flag[data-tone="warn"] .cb-icon {
  color: var(--cbc-warn);
}

.cb-mom-flag[data-tone="poor"] .cb-icon {
  color: var(--cbc-poor);
}

/* Two halves of one card, side by side where there is room. */
/* Two halves side by side while each still holds a readable line, one under the
   other below that. A measure again, for the reason the subtitle rule gives. */
.cb-mom-halves {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(18ch, 1fr));
  gap: var(--cb-space-xl);
}

.cb-mom-half {
  display: flex;
  flex-direction: column;
  gap: var(--cb-space-md);
  min-width: 0;
}

/* noteHead was written for the hover-note popover. On a card face it needs to
   be quieter than the card's own instrument label, so the pip goes and the
   title drops a step. */
.cb-mom-half .cb-note-head {
  margin: 0;
}

.cb-mom-half .cb-note-pip {
  display: none;
}

.cb-mom-strip,
.cb-mom-plot {
  min-width: 0;
}

/**
 * THE SPARKLINE'S OWN STRIP, and it has to draw its own marks.
 *
 * `.cb-spark` in console-charts.css is the stat strip's wrapper: absolutely
 * positioned along the bottom of a tile at 30% opacity, which is right for a
 * texture behind a number and wrong for a card that gives the line its own
 * band. But the STROKES are styled under that class (`.cb-spark .cb-chart-line`
 * and `.cb-chart-area`), so a wrapper that is not one draws an SVG with no
 * paint in it: the first version of this file had every sparkline present in
 * the DOM, correctly shaped, and completely invisible.
 *
 * So the strip carries both classes and puts back the three properties it does
 * not want. Restated rather than overridden by specificity, because a rule that
 * depends on winning a cascade it did not write is a rule somebody breaks by
 * reordering two stylesheets.
 */
.cb-mom-strip {
  /* A sparkline is a texture rather than a chart: it says the shape of a run
     and the card's own figure says the value. */
  position: static;
  block-size: var(--cb-space-5xl);
  opacity: 1;
}

.cb-mom-lines {
  gap: var(--cb-space-lg);
}

.cb-mom-line {
  display: flex;
  flex-direction: column;
  gap: var(--cb-space-xxs);
}

.cb-mom-why {
  margin: 0;
  font-size: var(--cb-type-sm-size);
  line-height: var(--cb-type-sm-line-height);
  color: var(--cbc-ink);
}

/* A staff card saying, on its own face, that it never reaches a client. */
.cb-mom-private {
  display: flex;
  align-items: center;
  gap: var(--cb-space-sm);
  margin: 0;
  font-size: var(--cb-type-xs-size);
  color: var(--cbc-ink-faint);
}

.cb-mom-private-glyph {
  color: var(--cbc-ink-faint);
}

.cb-mom-account {
  display: flex;
  flex-direction: column;
  gap: var(--cb-space-xs);
}

/* ---------------------------------------------------------------------------
   The manual mark. The one thing this console has never had to say before.
   ------------------------------------------------------------------------ */

.cb-mom-mark {
  margin: auto 0 0;
  padding-top: var(--cb-space-md);
  border-top: 1px solid var(--cbc-line);
  font-size: var(--cb-type-xs-size);
  line-height: var(--cb-type-xs-line-height);
  font-style: italic;
  color: var(--cbc-ink-muted);
}

/* ---------------------------------------------------------------------------
   A manual table. It scrolls inside itself; the page never scrolls sideways.
   ------------------------------------------------------------------------ */

.cb-mom-tablewrap {
  overflow-x: auto;
  min-width: 0;
}

.cb-mom-table {
  width: 100%;
  border-collapse: collapse;
  font-size: var(--cb-type-sm-size);
}

.cb-mom-table th,
.cb-mom-table td {
  padding: var(--cb-space-sm) var(--cb-space-md);
  border-bottom: 1px solid var(--cbc-line);
  text-align: left;
  color: var(--cbc-ink);
}

.cb-mom-table th {
  font-weight: var(--cb-font-weight-medium);
  color: var(--cbc-ink-muted);
}

/* ---------------------------------------------------------------------------
   The card library, and the dialog that starts a dashboard.
   ------------------------------------------------------------------------ */

.cb-mom-lib + .cb-mom-lib,
.cb-mom-lib-note {
  margin-top: var(--cb-space-4xl);
}

.cb-mom-lib h3,
.cb-mom-lib-note h3 {
  margin: 0 0 var(--cb-space-xs);
  font-size: var(--cb-type-base-size);
  font-weight: var(--cb-font-weight-semibold);
  color: var(--cbc-ink);
}

.cb-mom-lib-blurb,
.cb-mom-lib-note p,
.cb-mom-lib-levels {
  margin: 0;
  font-size: var(--cb-type-xs-size);
  line-height: var(--cb-type-xs-line-height);
  color: var(--cbc-ink-muted);
}

.cb-mom-lib-list {
  list-style: none;
  margin: var(--cb-space-lg) 0 0;
  padding: 0;
  display: flex;
  flex-direction: column;
}

.cb-mom-lib-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--cb-space-xl);
  padding: var(--cb-space-lg) 0;
  border-bottom: 1px solid var(--cbc-line);
}

.cb-mom-lib-row h4 {
  margin: 0;
  font-size: var(--cb-type-sm-size);
  font-weight: var(--cb-font-weight-medium);
  color: var(--cbc-ink);
}

.cb-mom-lib-row p {
  margin: 0;
  font-size: var(--cb-type-xs-size);
  color: var(--cbc-ink-muted);
}

.cb-mom-lib-note {
  padding: var(--cb-space-xl);
  border: 1px solid var(--cbc-line);
  border-radius: var(--cb-radius-xl);
  background: var(--cbc-sunken);
}

.cb-mom-kinds {
  display: flex;
  flex-direction: column;
  gap: var(--cb-space-md);
}

.cb-mom-kind-choice {
  display: flex;
  align-items: flex-start;
  gap: var(--cb-space-md);
  padding: var(--cb-space-lg);
  border: 1px solid var(--cbc-line);
  border-radius: var(--cb-radius-lg);
  cursor: pointer;
}

.cb-mom-kind-choice:hover {
  background: var(--cbc-hover);
}

.cb-mom-kind-choice:has(input:checked) {
  border-color: var(--cbc-accent);
  background: var(--cbc-accent-quiet);
}

.cb-mom-kind-choice b {
  display: block;
  font-size: var(--cb-type-sm-size);
  font-weight: var(--cb-font-weight-medium);
  color: var(--cbc-ink);
}

.cb-mom-kind-choice i {
  display: block;
  margin-top: var(--cb-space-xxs);
  font-style: normal;
  font-size: var(--cb-type-xs-size);
  line-height: var(--cb-type-xs-line-height);
  color: var(--cbc-ink-muted);
}

/* ---------------------------------------------------------------------------
   The coverage note. Never behind a disclosure, and it prints.
   ------------------------------------------------------------------------ */

.cb-mom-coverage {
  margin-top: var(--cb-space-5xl);
  padding-top: var(--cb-space-3xl);
  border-top: 1px solid var(--cbc-line);
}

.cb-mom-coverage h2 {
  margin: 0 0 var(--cb-space-md);
  font-size: var(--cb-type-xs-size);
  letter-spacing: var(--cb-tracking-xxs);
  text-transform: uppercase;
  color: var(--cbc-ink-faint);
}

.cb-mom-coverage ul {
  margin: 0;
  padding-left: var(--cb-space-2xl);
  display: flex;
  flex-direction: column;
  gap: var(--cb-space-xs);
}

.cb-mom-coverage li {
  font-size: var(--cb-type-xs-size);
  line-height: var(--cb-type-xs-line-height);
  color: var(--cbc-ink-muted);
}

/* ---------------------------------------------------------------------------
   Narrow. The board collapses to one column before the cards stop being
   readable, because a four-column grid on a phone is four unreadable columns.
   ------------------------------------------------------------------------ */

/* 720px, which the spacing scale does not model: it is the width below which a
   two-column card holds fewer than about thirty characters a line. */
@media (max-width: 720px) {
  .cb-mom-board {
    grid-template-columns: minmax(0, 1fr);
  }

  .cb-mom-tile {
    /* The packer's own column and row are meaningless in one column, so every
       card takes the whole of it and keeps its ORDER, which is the editorial
       decision the packer was preserving in the first place. */
    grid-column: 1 / -1;
    grid-row: auto;
  }
}

/* ---------------------------------------------------------------------------
   PRINT IS THE PDF (decision 16). No generated file and no download button: a
   real print stylesheet and the browser's own Save as PDF.
   ------------------------------------------------------------------------ */

@media print {
  /* The controls, the crumb and the chrome go. The board and the coverage note
     are the document. */
  .cb-mom-tools,
  .cb-mom-build-acts,
  .cb-mom-controls,
  .cb-mom-name {
    display: none !important;
  }

  .cb-mom-tile {
    /* A card split across a page break is a card nobody can read. */
    break-inside: avoid;
    border-color: var(--cbc-line);
  }

  /* THE COVERAGE NOTE PRINTS. It is the whole point of building it on the
     server: a caveat computed by a screen travels nowhere, and a total that
     leaves the building without its qualification is the number somebody
     quotes in a meeting. */
  .cb-mom-coverage {
    break-before: auto;
    break-inside: avoid;
  }

  /* And so does the mark on a manual card, for the same reason. */
  .cb-mom-mark {
    break-inside: avoid;
  }
}
