/* BonBonBot Console: the business dossier.
   ===================================================================
   THE IDEA. Every other screen in this console is a set of panels
   about a subject. This one is a brief about a company, written to be
   read top to bottom by somebody who is about to phone them, and its
   layout says so: one masthead carrying the verdict at the largest
   size on the page, then chapters with names, then the paperwork last.

   The whole sheet resolves to --cb-* tokens through the console's own
   --cbc-* layer. The exceptions are the ones the token scale
   deliberately does not model: hairlines, 100%/0, opacity and
   colour-mix percentages, and breakpoint literals in media queries,
   each of which names the token it mirrors.

   TIMINGS COME FROM THE TOKENS TOO, and nine transitions in here did
   not: the map's pins and controls, the who-they-are rows and their
   copy button, and the share tabs all carried a hand-typed 120ms or
   160ms with a `linear` easing. Two costs. The times were nobody's
   decision, so this sheet was a hundred and fifty milliseconds quicker
   than the rest of the console for no reason anybody could name; and
   `linear` starts and stops at the same speed, which is the one shape
   nothing physical moves in, so a hover here answered differently from
   an identical hover one screen over. All nine are now
   --cb-motion-fast and --cbc-spring, which is what the rest of the
   console uses to say the same thing. */

/* ==================================================================
   THE MASTHEAD
   Who they are, what the report decided, and the size of the gap.

   The headline is the company. A dossier is about a business, so its
   first line is the business: name, trade, and their own sentence about
   what they do. The verdict is the report's opinion of their website,
   which is the second thing, so it sits beside as a quoted line rather
   than above as the title of the page. */

.cb-dossier-head {
  padding: var(--cb-space-4xl);
  border: 1px solid var(--cbc-line);
  border-radius: var(--cb-radius-4xl);
  background: var(--cbc-surface);
  display: grid;
  gap: var(--cb-space-4xl);
  animation: cbc-rise var(--cb-motion-slow) var(--cbc-spring) backwards;
}
/* The identity row: mark, name, one line of facts, actions. Full width,
   as it has always been. */
.cb-dossier-id {
  display: flex;
  align-items: center;
  gap: var(--cb-space-xl);
}
/* The mark is the site's own icon, drawn a size up from every list it
   appears in: this is the one screen that is about this one business. */
.cb-dossier-id > .cb-site-icon {
  inline-size: var(--cb-space-6xl);
  block-size: var(--cb-space-6xl);
  border-radius: var(--cb-radius-xl);
  font-size: var(--cb-type-lg-size);
  flex: none;
}
.cb-dossier-names {
  min-width: 0;
  flex: 1 1 var(--cb-width-xs);
}
.cb-dossier-names h1 {
  font-size: var(--cb-type-3xl-size);
  line-height: var(--cb-type-3xl-line-height);
  letter-spacing: var(--cb-type-3xl-letter-spacing);
  font-weight: var(--cb-font-weight-semibold);
  overflow-wrap: anywhere;
}
/* One line of identity, separated by dots rather than by rules: six facts
   in six boxes reads as a form, and this is a sentence. */
.cb-dossier-meta {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: var(--cb-space-md);
  margin-block-start: var(--cb-space-xs);
  font-size: var(--cb-type-sm-size);
  color: var(--cbc-ink-faint);
}
.cb-dossier-trade {
  margin-block-start: var(--cb-space-xxs);
  font-size: var(--cb-type-sm-size);
  font-weight: var(--cb-font-weight-medium);
  color: var(--cbc-accent);
}
.cb-dossier-dot {
  color: var(--cbc-line-strong);
}
.cb-dossier-domain {
  color: var(--cbc-ink-muted);
  text-decoration: none;
}
.cb-dossier-domain:hover {
  color: var(--cbc-accent);
  text-decoration: underline;
}
.cb-dossier-stars {
  display: inline-flex;
  align-items: center;
  gap: var(--cb-space-xs);
}
.cb-dossier-stars .cb-icon {
  color: var(--cbc-warn-text);
  inline-size: var(--cb-space-xl);
}
.cb-dossier-quiet {
  color: var(--cbc-line-strong);
}
/* Already ours to look after. It sits on the fact line with the rest, and it
   is the one item there carrying a badge, so it gets the gap a badge needs
   and nothing else: a fact that shouted would push the whole line into
   reading as a warning, which this is not. */
.cb-dossier-client {
  display: inline-flex;
  align-items: center;
  gap: var(--cb-space-xs);
  color: var(--cbc-ink-muted);
  font-weight: var(--cb-font-weight-medium);
}
.cb-dossier-actions {
  margin-inline-start: auto;
  display: flex;
  gap: var(--cb-space-md);
  flex-wrap: wrap;
  flex: none;
}

/* ---- The lede ----
   Two blocks on one baseline. The left is the display type this band has
   always carried and it says what the company does. The right is the
   report's verdict on their website, which is a different subject and a
   smaller one, so it is set a size down and aligned to the bottom of the
   block beside it rather than to the top. */
.cb-dossier-lede {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  gap: var(--cb-space-4xl);
  align-items: end;
}
.cb-dossier-about {
  font-size: var(--cb-type-2xl-size);
  line-height: var(--cb-type-2xl-line-height);
  letter-spacing: var(--cb-type-3xl-letter-spacing);
  font-weight: var(--cb-font-weight-medium);
  text-wrap: balance;
}
.cb-dossier-verdict {
  font-size: var(--cb-type-md-size);
  line-height: var(--cb-type-md-line-height);
  color: var(--cbc-ink-muted);
  text-wrap: pretty;
}

/* ---- The gap ---- */
.cb-dossier-open {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  align-items: center;
  gap: var(--cb-space-5xl);
  padding-block-start: var(--cb-space-3xl);
  border-block-start: 1px solid var(--cbc-line);
}
/* The ring fills to what they score and keeps going, quieter, to what
   the plan says they could score. Two numbers a reader would otherwise
   subtract become one picture of how far short of themselves they are. */
.cb-dossier-score {
  display: grid;
  justify-items: center;
  gap: var(--cb-space-lg);
}
.cb-dossier-dial {
  position: relative;
  display: grid;
  place-items: center;
  inline-size: var(--cb-space-11xl);
  block-size: var(--cb-space-11xl);
  flex: none;
}
.cb-dossier-ring {
  position: absolute;
  inset: 0;
  border-radius: var(--cb-radius-full);
  background: conic-gradient(
    var(--cb-ring-colour, var(--cbc-ink-faint)) calc(var(--cb-score) * 1%),
    var(--cb-ring-rest) calc(var(--cb-score) * 1%) calc(var(--cb-score-potential) * 1%),
    var(--cbc-line) calc(var(--cb-score-potential) * 1%)
  );
  /* The hole, so it reads as a ring rather than a pie. */
  mask: radial-gradient(
    farthest-side,
    transparent calc(100% - var(--cb-space-lg)),
    var(--cb-color-black) calc(100% - var(--cb-space-lg))
  );
  /* Sweeps round rather than appearing whole. The arc and the number
     inside it are the same claim, so they arrive together. */
  animation: cbc-sweep var(--cb-motion-slow) var(--cbc-spring) both;
}
.cb-dossier-dial {
  --cb-ring-rest: color-mix(in srgb, var(--cbc-good) 30%, transparent);
}
.cb-dossier-dial[data-tone="good"] {
  --cb-ring-colour: var(--cbc-good);
}
.cb-dossier-dial[data-tone="warn"] {
  --cb-ring-colour: var(--cbc-warn);
}
.cb-dossier-dial[data-tone="poor"] {
  --cb-ring-colour: var(--cbc-poor);
}
.cb-dossier-big {
  font-family: var(--cb-font-heading);
  font-size: var(--cb-type-4xl-size);
  line-height: 1;
  font-weight: var(--cb-font-weight-bold);
  font-variant-numeric: tabular-nums;
}
.cb-dossier-dial-label {
  max-inline-size: var(--cb-space-11xl);
  text-align: center;
  text-wrap: balance;
  line-height: var(--cb-type-xs-line-height);
  font-size: var(--cb-type-xs-size);
  color: var(--cbc-ink-faint);
  text-transform: uppercase;
  letter-spacing: var(--cb-tracking-xxs);
  font-weight: var(--cb-font-weight-semibold);
}

/* Four readouts, and not one of them is a cost to us. What is on the
   table, what is on fire, who is beating them, and whether they have
   ever opened what we sent. */
.cb-dossier-readouts {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: var(--cb-space-3xl);
}
.cb-dossier-readout {
  display: grid;
  gap: var(--cb-space-xxs);
  align-content: start;
}
.cb-dossier-readout-label {
  font-size: var(--cb-type-xs-size);
  text-transform: uppercase;
  letter-spacing: var(--cb-tracking-xxs);
  font-weight: var(--cb-font-weight-semibold);
  color: var(--cbc-ink-faint);
}
.cb-dossier-readout-value {
  font-size: var(--cb-type-2xl-size);
  line-height: var(--cb-type-2xl-line-height);
  font-weight: var(--cb-font-weight-semibold);
  font-variant-numeric: tabular-nums;
}
.cb-dossier-readout[data-tone="good"] .cb-dossier-readout-value {
  color: var(--cbc-good-text);
}
.cb-dossier-readout[data-tone="warn"] .cb-dossier-readout-value {
  color: var(--cbc-warn-text);
}
.cb-dossier-readout[data-tone="poor"] .cb-dossier-readout-value {
  color: var(--cbc-poor-text);
}
.cb-dossier-readout-note {
  font-size: var(--cb-type-xs-size);
  line-height: var(--cb-type-sm-line-height);
  color: var(--cbc-ink-muted);
}

/* 1024px mirrors tokens.breakpoint.lg */
@media (max-width: 1024px) {
  .cb-dossier-lede {
    grid-template-columns: minmax(0, 1fr);
    align-items: start;
  }
  .cb-dossier-open {
    grid-template-columns: minmax(0, 1fr);
    justify-items: start;
  }
  .cb-dossier-readouts {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
}
/* 480px mirrors tokens.breakpoint.sm */
@media (max-width: 480px) {
  .cb-dossier-readouts {
    grid-template-columns: minmax(0, 1fr);
  }
}

/* ==================================================================
   THE CHAPTER RAIL
   A floating segmented control that says where in the brief you are.
   Buttons rather than anchors: the console routes on the hash, so an
   href of "#pitch" is an address the router would try to resolve. */

.cb-chapter-rail {
  position: sticky;
  inset-block-start: var(--cb-space-xl);
  z-index: 5;
  margin-block: var(--cb-space-3xl) var(--cb-space-none);
  display: flex;
}
.cb-rail-inner {
  display: flex;
  gap: var(--cb-space-xxs);
  padding: var(--cb-space-xs);
  border: 1px solid var(--cbc-line);
  border-radius: var(--cb-radius-full);
  background: color-mix(in srgb, var(--cbc-raised) 88%, transparent);
  backdrop-filter: blur(var(--cb-space-lg));
  box-shadow: var(--cbc-shadow);
  overflow-x: auto;
  scrollbar-width: none;
  max-inline-size: 100%;
}
.cb-rail-link {
  flex: none;
  padding: var(--cb-space-md) var(--cb-space-xl);
  border: 0;
  border-radius: var(--cb-radius-full);
  background: transparent;
  color: var(--cbc-ink-muted);
  font-family: var(--cb-font-body);
  font-size: var(--cb-type-sm-size);
  font-weight: var(--cb-font-weight-medium);
  cursor: pointer;
  white-space: nowrap;
  transition:
    background var(--cb-motion-fast) var(--cb-motion-ease),
    color var(--cb-motion-fast) var(--cb-motion-ease);
}
.cb-rail-link:hover {
  background: var(--cbc-hover);
  color: var(--cbc-ink);
}
/* The one you are in holds the ink; the rest are held back rather than
   the current one shouting. */
.cb-rail-link[aria-current] {
  background: var(--cbc-accent-wash);
  color: var(--cbc-ink);
}

/* ==================================================================
   CHAPTERS */

.cb-dossier-body {
  display: grid;
  gap: var(--cb-space-7xl);
  margin-block-start: var(--cb-space-6xl);
}
.cb-chapter {
  display: grid;
  gap: var(--cb-space-3xl);
  scroll-margin-block-start: var(--cb-space-8xl);
}
.cb-chapter-head {
  display: flex;
  align-items: flex-end;
  gap: var(--cb-space-2xl);
  flex-wrap: wrap;
}
.cb-chapter-title {
  min-width: 0;
}
.cb-chapter-title h2 {
  font-size: var(--cb-type-xl-size);
  line-height: var(--cb-type-xl-line-height);
  letter-spacing: var(--cb-type-xl-letter-spacing);
  font-weight: var(--cb-font-weight-semibold);
}
.cb-chapter-title p {
  margin-block-start: var(--cb-space-xs);
  font-size: var(--cb-type-sm-size);
  line-height: var(--cb-type-sm-line-height);
  color: var(--cbc-ink-faint);
  max-inline-size: var(--cb-layout-paragraph-max-width);
}
.cb-chapter-actions {
  margin-inline-start: auto;
  display: flex;
  gap: var(--cb-space-md);
}

/* A sub-heading inside a chapter. Smaller than the chapter and quieter
   than the body, so a two-column chapter has two labelled halves
   rather than two headings competing with the one above them. */
.cb-sub {
  font-size: var(--cb-type-xs-size);
  text-transform: uppercase;
  letter-spacing: var(--cb-tracking-xxs);
  font-weight: var(--cb-font-weight-semibold);
  color: var(--cbc-ink-faint);
  margin-block-end: var(--cb-space-xl);
}

/* ==================================================================
   WHAT TO OPEN WITH */

/* The read, across the measure. It was a column beside the three lines,
   which put a paragraph in a third of the screen and left a hole under
   the cards exactly as tall as the paragraph was. */
.cb-talk-read {
  font-size: var(--cb-type-md-size);
  line-height: var(--cb-type-md-line-height);
  color: var(--cbc-ink-muted);
  max-inline-size: var(--cb-layout-paragraph-max-width);
}
/* Three across. They are short, they are alternatives rather than a
   sequence, and stacked they read as a list to work through. */
.cb-talk-lines {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(var(--cb-width-xxs), 1fr));
  gap: var(--cb-space-xl);
}
.cb-talk-line {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  grid-template-rows: auto auto;
  align-content: start;
  gap: var(--cb-space-lg);
  padding: var(--cb-space-2xl);
  border: 1px solid var(--cbc-line);
  border-radius: var(--cb-radius-2xl);
  background: var(--cbc-surface);
  transition:
    border-color var(--cb-motion-fast) var(--cb-motion-ease),
    background var(--cb-motion-fast) var(--cb-motion-ease);
}
.cb-talk-line:hover {
  border-color: var(--cbc-line-strong);
  background: var(--cbc-raised);
}
.cb-talk-line p {
  font-size: var(--cb-type-sm-size);
  line-height: var(--cb-type-base-line-height);
}
.cb-talk-index {
  inline-size: var(--cb-space-3xl);
  block-size: var(--cb-space-3xl);
  display: grid;
  place-items: center;
  border-radius: var(--cb-radius-full);
  background: var(--cbc-accent-quiet);
  color: var(--cbc-accent);
  font-size: var(--cb-type-xs-size);
  font-weight: var(--cb-font-weight-semibold);
  font-variant-numeric: tabular-nums;
}
/* The copy shows itself when the line is approached, not before: three
   copy buttons sitting out at once read as a toolbar, and only one of
   them is ever wanted. It stays for a keyboard, which cannot hover. */
.cb-talk-line .cb-btn {
  grid-column: 2;
  justify-self: start;
  opacity: 0;
  transition: opacity var(--cb-motion-fast) var(--cb-motion-ease);
}
.cb-talk-line:hover .cb-btn,
.cb-talk-line:focus-within .cb-btn {
  opacity: 1;
}

.cb-talk-foot {
  display: grid;
  grid-template-columns: minmax(0, 3fr) minmax(0, 2fr);
  gap: var(--cb-space-4xl);
  padding-block-start: var(--cb-space-2xl);
  border-block-start: 1px solid var(--cbc-line);
}
.cb-talk-quiet {
  font-size: var(--cb-type-sm-size);
  line-height: var(--cb-type-base-line-height);
  color: var(--cbc-ink-faint);
  font-style: italic;
}
.cb-talk-good {
  list-style: none;
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(var(--cb-width-xxs), 1fr));
  gap: var(--cb-space-lg) var(--cb-space-3xl);
}
.cb-talk-good li {
  position: relative;
  padding-inline-start: var(--cb-space-2xl);
  font-size: var(--cb-type-sm-size);
  line-height: var(--cb-type-sm-line-height);
  color: var(--cbc-ink-muted);
}
.cb-talk-good li::before {
  content: "";
  position: absolute;
  inset-block-start: var(--cb-space-md);
  inset-inline-start: 0;
  inline-size: var(--cb-space-sm);
  block-size: var(--cb-space-sm);
  border-radius: var(--cb-radius-full);
  background: var(--cbc-good);
}

/* 1024px mirrors tokens.breakpoint.lg */
@media (max-width: 1024px) {
  .cb-talk-foot {
    grid-template-columns: minmax(0, 1fr);
  }
}

/* ==================================================================
   WHERE THEIR SITE LOSES
   A category to a row, one open at a time. Closed it is the bar it always
   was; open it is what the report actually said. How many rows there are is
   the kind's business, not this stylesheet's: the website audit scores eight
   and a focused kind scores a handful of its own. */

.cb-weak {
  border: 1px solid var(--cbc-line);
  border-radius: var(--cb-radius-2xl);
  background: var(--cbc-surface);
  overflow: hidden;
}
.cb-weak-row + .cb-weak-row {
  border-block-start: 1px solid var(--cbc-line);
}
.cb-weak-row > summary {
  display: grid;
  /* Six, one per child including the chevron in ::after. With five the
     chevron was placed into an implicit second row and every category was
     twice as tall as it needed to be. */
  grid-template-columns: auto minmax(var(--cb-width-xxs), 1.4fr) minmax(0, 2fr) auto auto auto;
  align-items: center;
  gap: var(--cb-space-xl);
  padding: var(--cb-space-xl) var(--cb-space-2xl);
  cursor: pointer;
  list-style: none;
  transition: background var(--cb-motion-fast) var(--cb-motion-ease);
}
.cb-weak-row > summary::-webkit-details-marker {
  display: none;
}
.cb-weak-row > summary:hover {
  background: var(--cbc-hover);
}
.cb-weak-row[open] > summary {
  background: var(--cbc-hover);
}
/* THE CATEGORY'S OWN COLOUR, HANDED DOWN BY THE ROW AS --tint.
   This was eight rules, one per category id, which is a stylesheet keeping a
   second copy of a list that belongs to the token set. The copy stopped being
   true the moment the focused audit kinds added eight more ids
   (docs/14-audit-kinds.md): a row for crawlability, aiReadiness or security
   matched none of the eight and drew with no fill at all. Not a wrong colour,
   which somebody would query, but no colour, which reads as a rendering
   glitch. The two screens that draw these rows build the name from the id
   instead (report-scores.ts and business-weakness.ts), the way weight-bar.ts
   and settings-scoring.ts already do, so the set can grow again and this rule
   needs nothing. The fallback covers the one case left, a row drawn with no
   tint at all, which is a fault rather than a state: grey says so quietly
   instead of leaving a hole. */
.cb-weak-swatch {
  inline-size: var(--cb-space-md);
  block-size: var(--cb-space-md);
  border-radius: var(--cb-radius-xs);
  background: var(--tint, var(--cbc-ink-faint));
}
.cb-weak-name {
  font-size: var(--cb-type-sm-size);
  font-weight: var(--cb-font-weight-medium);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.cb-weak-track {
  block-size: var(--cb-space-md);
  border-radius: var(--cb-radius-full);
  background: var(--cbc-sunken);
  overflow: hidden;
}
.cb-weak-fill {
  display: block;
  inline-size: var(--w);
  block-size: 100%;
  border-radius: var(--cb-radius-full);
  transform-origin: left center;
  animation: cbc-grow-x var(--cb-motion-slow) var(--cbc-spring) backwards;
  animation-delay: var(--cbc-inside);
}
.cb-weak-fill[data-band="good"] {
  background: var(--cbc-good);
}
.cb-weak-fill[data-band="warn"] {
  background: var(--cbc-warn);
}
.cb-weak-fill[data-band="poor"] {
  background: var(--cbc-poor);
}
.cb-weak-score {
  font-size: var(--cb-type-md-size);
  font-weight: var(--cb-font-weight-semibold);
  font-variant-numeric: tabular-nums;
  min-inline-size: var(--cb-space-5xl);
  text-align: end;
}
.cb-weak-score[data-band="good"] {
  color: var(--cbc-good-text);
}
.cb-weak-score[data-band="warn"] {
  color: var(--cbc-warn-text);
}
.cb-weak-score[data-band="poor"] {
  color: var(--cbc-poor-text);
}
.cb-weak-count {
  font-size: var(--cb-type-xs-size);
  color: var(--cbc-ink-faint);
  min-inline-size: var(--cb-space-9xl);
  text-align: end;
}
.cb-weak-count[data-tone="poor"] {
  color: var(--cbc-poor-text);
}
/* The chevron, lucide's own path as a mask so it takes currentColor.
   It turns rather than swapping, so opening reads as one movement. */
.cb-weak-row > summary::after {
  content: "";
  inline-size: var(--cb-space-xl);
  block-size: var(--cb-space-xl);
  background: currentColor;
  color: var(--cbc-ink-faint);
  mask: var(--cbc-chevron) center / contain no-repeat;
  transition: rotate var(--cb-motion-base) var(--cbc-spring);
}
.cb-weak-row[open] > summary::after {
  rotate: 180deg;
}

.cb-weak-body {
  padding: var(--cb-space-3xl) var(--cb-space-2xl) var(--cb-space-3xl) var(--cb-space-5xl);
  display: grid;
  gap: var(--cb-space-2xl);
  background: var(--cbc-sunken);
  border-block-start: 1px solid var(--cbc-line);
  animation: cbc-emerge var(--cb-motion-slow) var(--cbc-spring) backwards;
}
/* The report's read on the category, and what it costs them. One block,
   so the sentence and the number under it are one statement rather than
   two paragraphs that happen to be adjacent. */
.cb-weak-read {
  display: grid;
  gap: var(--cb-space-md);
}
.cb-weak-headline {
  font-size: var(--cb-type-md-size);
  line-height: var(--cb-type-md-line-height);
  font-weight: var(--cb-font-weight-medium);
  max-inline-size: var(--cb-layout-paragraph-max-width);
  text-wrap: pretty;
}
/* What the category costs them, in the report's own words.
   This was a capsule, which is the right shape for "+8 points" and the
   wrong one for what the field actually holds: three hundred characters
   about a fourteen-second mobile load and the share of visitors that
   leave at that speed, set bold, at twelve pixels, inside a pill. It is
   a sentence, so it is set as one. */
.cb-weak-cost {
  max-inline-size: var(--cb-layout-paragraph-max-width);
  color: var(--cbc-warn-text);
  font-size: var(--cb-type-sm-size);
  line-height: var(--cb-type-base-line-height);
  text-wrap: pretty;
}
.cb-weak-none {
  font-size: var(--cb-type-sm-size);
  color: var(--cbc-ink-faint);
}

.cb-finds {
  display: grid;
  gap: var(--cb-space-lg);
  list-style: none;
}
/* A finding is a heading, a sentence and its evidence, stacked. It was a
   two-column grid with the severity in the first column, which made the
   sentence start a hundred pixels in from the title above it and left a
   ragged left edge down the whole list. */
.cb-find {
  display: grid;
  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);
  animation: cbc-emerge var(--cb-motion-slow) var(--cbc-spring) backwards;
  animation-delay: min(calc(var(--i, 0) * var(--cb-motion-fast) / 3), var(--cb-motion-base));
}
.cb-find-head {
  display: flex;
  align-items: baseline;
  gap: var(--cb-space-lg);
  flex-wrap: wrap;
}
/* The severity is a word in a capsule rather than a coloured edge on the
   block: "critical" is a claim somebody repeats out loud, and a colour
   with no word beside it is not repeatable. */
.cb-find-sev {
  padding: var(--cb-space-xxs) var(--cb-space-md);
  border-radius: var(--cb-radius-full);
  font-size: var(--cb-type-xs-size);
  font-weight: var(--cb-font-weight-semibold);
  white-space: nowrap;
  background: color-mix(in srgb, var(--cbc-ink-faint) 18%, transparent);
  color: var(--cbc-ink-muted);
}
.cb-find[data-severity="critical"] .cb-find-sev {
  background: color-mix(in srgb, var(--cbc-poor) 18%, transparent);
  color: var(--cbc-poor-text);
}
.cb-find[data-severity="major"] .cb-find-sev {
  background: color-mix(in srgb, var(--cbc-warn) 18%, transparent);
  color: var(--cbc-warn-text);
}
.cb-find-title {
  font-size: var(--cb-type-base-size);
  font-weight: var(--cb-font-weight-semibold);
  min-width: 0;
}
.cb-find-why {
  font-size: var(--cb-type-sm-size);
  line-height: var(--cb-type-base-line-height);
  color: var(--cbc-ink-muted);
  max-inline-size: var(--cb-layout-paragraph-max-width);
  text-wrap: pretty;
}
.cb-find-where {
  display: flex;
  flex-wrap: wrap;
  gap: var(--cb-space-md);
  align-items: center;
}
.cb-find-page {
  display: inline-flex;
  align-items: center;
  gap: var(--cb-space-xs);
  padding: var(--cb-space-xs) var(--cb-space-lg);
  border-radius: var(--cb-radius-full);
  border: 1px solid var(--cbc-line);
  font-size: var(--cb-type-xs-size);
  color: var(--cbc-ink-faint);
  overflow-wrap: anywhere;
  text-decoration: none;
}
.cb-find-page .cb-icon {
  inline-size: var(--cb-space-lg);
  flex: none;
}
a.cb-find-page:hover {
  color: var(--cbc-accent);
  border-color: var(--cbc-accent);
}

/* ---- The measurement, read rather than printed ----
   The report writes free text here and it arrives as things like
   "gbpExists: false". Set in a monospace face that is a variable name on
   a sales screen. Taken apart, it is a labelled reading with a yes or a
   no in the colour that answer deserves. See views/evidence.ts. */
.cb-ev {
  display: inline-flex;
  align-items: center;
  gap: var(--cb-space-md);
  padding: var(--cb-space-xs) var(--cb-space-lg);
  border-radius: var(--cb-radius-full);
  background: var(--cbc-sunken);
  border: 1px solid var(--cbc-line);
  font-size: var(--cb-type-xs-size);
}
.cb-ev-mark {
  inline-size: var(--cb-space-xl);
  flex: none;
  color: var(--cbc-ink-faint);
}
.cb-ev-label {
  color: var(--cbc-ink-faint);
}
.cb-ev-value {
  font-weight: var(--cb-font-weight-semibold);
  color: var(--cbc-ink);
}
.cb-ev[data-tone="good"] {
  border-color: color-mix(in srgb, var(--cbc-good) 40%, transparent);
}
.cb-ev[data-tone="good"] .cb-ev-mark,
.cb-ev[data-tone="good"] .cb-ev-value {
  color: var(--cbc-good-text);
}
.cb-ev[data-tone="poor"] {
  border-color: color-mix(in srgb, var(--cbc-poor) 40%, transparent);
}
.cb-ev[data-tone="poor"] .cb-ev-mark,
.cb-ev[data-tone="poor"] .cb-ev-value {
  color: var(--cbc-poor-text);
}

/* 768px mirrors tokens.breakpoint.md */
@media (max-width: 768px) {
  .cb-weak-row > summary {
    grid-template-columns: auto minmax(0, 1fr) auto auto;
  }
  .cb-weak-track {
    display: none;
  }
  .cb-weak-count {
    display: none;
  }
}

/* ==================================================================
   WHAT TO SELL THEM

   This was two lists side by side, services left and the plan right,
   and reading it meant doing a join by eye: every step names the
   service it bills to, and the only way to see which was to hold four
   names in your head while scrolling a second column. So the plan is
   grouped under the service that sells it. One subject, one block. */

/* The argument in three numbers, above the line items. */
.cb-climb {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr) auto;
  align-items: center;
  gap: var(--cb-space-4xl);
  padding: var(--cb-space-3xl);
  border: 1px solid var(--cbc-line);
  border-radius: var(--cb-radius-2xl);
  background: var(--cbc-surface);
}
.cb-climb-label {
  font-size: var(--cb-type-xs-size);
  text-transform: uppercase;
  letter-spacing: var(--cb-tracking-xxs);
  font-weight: var(--cb-font-weight-semibold);
  color: var(--cbc-ink-faint);
}
.cb-climb-figure {
  font-size: var(--cb-type-3xl-size);
  line-height: var(--cb-type-3xl-line-height);
  letter-spacing: var(--cb-type-3xl-letter-spacing);
  font-weight: var(--cb-font-weight-bold);
  font-variant-numeric: tabular-nums;
}
.cb-climb-figure[data-good] {
  color: var(--cbc-good-text);
}
.cb-climb-mid {
  display: grid;
  gap: var(--cb-space-md);
}
/* One track, two runs: what they already have, and what the blocks
   below add to it. The join between them is the whole point. */
.cb-climb-track {
  display: flex;
  block-size: var(--cb-space-lg);
  border-radius: var(--cb-radius-full);
  background: var(--cbc-sunken);
  overflow: hidden;
}
.cb-climb-have,
.cb-climb-add {
  inline-size: var(--w);
  transform-origin: left center;
  animation: cbc-grow-x var(--cb-motion-slow) var(--cbc-spring) backwards;
}
.cb-climb-have {
  background: var(--cbc-ink-faint);
}
.cb-climb-add {
  background: var(--cbc-good);
  animation-delay: var(--cb-motion-fast);
}
.cb-climb-note {
  display: flex;
  align-items: baseline;
  gap: var(--cb-space-md);
  font-size: var(--cb-type-xs-size);
  color: var(--cbc-ink-muted);
}
.cb-climb-gain {
  font-size: var(--cb-type-md-size);
  font-weight: var(--cb-font-weight-bold);
  color: var(--cbc-good-text);
  font-variant-numeric: tabular-nums;
}

/* One block per service: what it is, why it was picked, what it is
   worth, and the work inside it. */
.cb-blocks {
  display: grid;
  gap: var(--cb-space-2xl);
}
.cb-block {
  padding: var(--cb-space-3xl);
  border: 1px solid var(--cbc-line);
  border-radius: var(--cb-radius-2xl);
  background: var(--cbc-surface);
  display: grid;
  gap: var(--cb-space-xl);
}
.cb-block-head {
  display: flex;
  align-items: center;
  gap: var(--cb-space-xl);
  flex-wrap: wrap;
}
.cb-block-title {
  min-width: 0;
  flex: 1 1 var(--cb-width-xxs);
}
.cb-block-title h3 {
  font-size: var(--cb-type-lg-size);
  line-height: var(--cb-type-lg-line-height);
  font-weight: var(--cb-font-weight-semibold);
}
.cb-block-pitch {
  margin-block-start: var(--cb-space-xxs);
  font-size: var(--cb-type-xs-size);
  line-height: var(--cb-type-sm-line-height);
  color: var(--cbc-ink-faint);
}
/* What the block is worth, as a figure rather than a badge. It is the
   number the block exists to justify. */
.cb-block-worth {
  display: grid;
  justify-items: end;
  line-height: 1;
  color: var(--cbc-good-text);
}
.cb-block-worth strong {
  font-size: var(--cb-type-xl-size);
  font-weight: var(--cb-font-weight-bold);
  font-variant-numeric: tabular-nums;
}
.cb-block-worth span {
  font-size: var(--cb-type-xs-size);
  color: var(--cbc-ink-faint);
  margin-block-start: var(--cb-space-xxs);
}
.cb-block-link {
  color: var(--cbc-ink-faint);
  display: inline-flex;
  opacity: 0;
  transition: opacity var(--cb-motion-fast) var(--cb-motion-ease);
}
.cb-block:hover .cb-block-link,
.cb-block:focus-within .cb-block-link {
  opacity: 1;
}
.cb-block-link:hover {
  color: var(--cbc-accent);
}
.cb-block-why {
  font-size: var(--cb-type-sm-size);
  line-height: var(--cb-type-base-line-height);
  max-inline-size: var(--cb-layout-paragraph-max-width);
  text-wrap: pretty;
}
.cb-block-none {
  font-size: var(--cb-type-xs-size);
  color: var(--cbc-ink-faint);
}

/* The work inside a service. Rows against a rule rather than cards in a
   card: these are already inside a container, and a box in a box is a
   border for the sake of one. */
.cb-steps {
  list-style: none;
  display: grid;
}
.cb-step {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr) auto;
  align-items: start;
  gap: var(--cb-space-lg) var(--cb-space-xl);
  padding-block: var(--cb-space-xl);
  border-block-start: 1px solid var(--cbc-line);
}
.cb-step-order {
  inline-size: var(--cb-space-3xl);
  block-size: var(--cb-space-3xl);
  display: grid;
  place-items: center;
  border-radius: var(--cb-radius-full);
  border: 1px solid var(--cbc-line-strong);
  font-size: var(--cb-type-xs-size);
  font-weight: var(--cb-font-weight-semibold);
  color: var(--cbc-ink-muted);
  font-variant-numeric: tabular-nums;
}
.cb-step-text {
  min-width: 0;
  display: grid;
  gap: var(--cb-space-xxs);
}
.cb-step-title {
  font-size: var(--cb-type-sm-size);
  font-weight: var(--cb-font-weight-semibold);
}
.cb-step-why {
  font-size: var(--cb-type-xs-size);
  line-height: var(--cb-type-sm-line-height);
  color: var(--cbc-ink-muted);
}
.cb-step-tail {
  display: flex;
  align-items: center;
  gap: var(--cb-space-lg);
}
.cb-step-effort {
  display: inline-flex;
  align-items: center;
  gap: var(--cb-space-xs);
  padding: var(--cb-space-xxs) var(--cb-space-md);
  border-radius: var(--cb-radius-full);
  font-size: var(--cb-type-xs-size);
  white-space: nowrap;
  background: color-mix(in srgb, var(--cbc-ink-faint) 14%, transparent);
  color: var(--cbc-ink-muted);
}
.cb-step-effort[data-effort="quick win"] {
  background: color-mix(in srgb, var(--cbc-good) 16%, transparent);
  color: var(--cbc-good-text);
}
.cb-step-effort .cb-icon {
  inline-size: var(--cb-space-lg);
}
.cb-step-points {
  font-size: var(--cb-type-md-size);
  font-weight: var(--cb-font-weight-bold);
  color: var(--cbc-good-text);
  font-variant-numeric: tabular-nums;
  min-inline-size: var(--cb-space-4xl);
  text-align: end;
}

/* 768px mirrors tokens.breakpoint.md */
@media (max-width: 768px) {
  .cb-climb {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
  .cb-climb-mid {
    grid-column: 1 / -1;
    order: 1;
  }
  .cb-step {
    grid-template-columns: auto minmax(0, 1fr);
  }
  .cb-step-tail {
    grid-column: 2;
  }
}

/* ==================================================================
   AGAINST THE MARKET

   A bar per business is four pictures of the same axis, and it answers
   "how does each one score" rather than "where do they sit". This is
   one axis with everybody plotted on it: the distribution is the shape,
   and the distance to the leader is a distance on the screen. */

/* The competitive field: one axis with everybody plotted on it. Named
   cb-market rather than cb-field because dom.ts's field() helper had already
   claimed .cb-field for a labelled form control, and this sheet loads after
   console-forms.css, so being second it won: every form field in every dialog
   came out as a padded bordered card. The retired advisor's .cb-ask hit the
   same collision. Two components, one class, one of them silently restyled. */
.cb-market {
  padding: var(--cb-space-3xl);
  border: 1px solid var(--cbc-line);
  border-radius: var(--cb-radius-2xl);
  background: var(--cbc-surface);
  display: grid;
  gap: var(--cb-space-2xl);
}
.cb-market-head {
  display: grid;
  gap: var(--cb-space-xxs);
}
.cb-market-verdict {
  font-size: var(--cb-type-xl-size);
  line-height: var(--cb-type-xl-line-height);
  font-weight: var(--cb-font-weight-semibold);
}
.cb-market-verdict[data-tone="warn"] {
  color: var(--cbc-warn-text);
}
.cb-market-verdict[data-tone="good"] {
  color: var(--cbc-good-text);
}
.cb-market-sub {
  font-size: var(--cb-type-xs-size);
  color: var(--cbc-ink-faint);
}

/* Room above the axis for the markers and their scores to sit in. */
.cb-market-plot {
  position: relative;
  block-size: var(--cb-space-8xl);
  margin-inline: var(--cb-space-3xl);
}
.cb-market-axis {
  position: absolute;
  inset-inline: calc(var(--cb-space-3xl) * -1);
  inset-block-end: 0;
  block-size: var(--cb-space-xs);
  border-radius: var(--cb-radius-full);
  background: var(--cbc-sunken);
}
/* The stretch they have to cover to lead, drawn as that stretch. */
.cb-market-gap {
  position: absolute;
  inset-block-end: 0;
  inset-inline-start: var(--from);
  inline-size: var(--w);
  block-size: var(--cb-space-xs);
  border-radius: var(--cb-radius-full);
  background: color-mix(in srgb, var(--cbc-warn) 60%, transparent);
  transform-origin: left center;
  transform: scaleX(0);
  transition: transform var(--cb-motion-slow) var(--cbc-spring) var(--cb-motion-fast);
}
.cb-market-plot[data-drawn] .cb-market-gap {
  transform: scaleX(1);
}

/* One business, standing on the axis at its score. */
.cb-market-mark {
  position: absolute;
  inset-block-end: 0;
  inset-inline-start: var(--at);
  translate: -50% 0;
  display: grid;
  justify-items: center;
  gap: var(--cb-space-xs);
  padding-block-end: var(--cb-space-lg);
  cursor: default;
  opacity: 0;
  transition:
    opacity var(--cb-motion-base) var(--cb-motion-ease),
    translate var(--cb-motion-slow) var(--cbc-spring);
}
.cb-market-plot[data-drawn] .cb-market-mark {
  opacity: 1;
}
.cb-market-plot:not([data-drawn]) .cb-market-mark {
  translate: -50% var(--cb-space-lg);
}
.cb-market-mark::after {
  content: "";
  position: absolute;
  inset-block-end: 0;
  inline-size: 1px;
  block-size: var(--cb-space-lg);
  background: var(--cbc-line-strong);
}
.cb-market-mark .cb-site-icon {
  inline-size: var(--cb-space-4xl);
  block-size: var(--cb-space-4xl);
  border-radius: var(--cb-radius-md);
  font-size: var(--cb-type-xs-size);
  /* A ring, so a marker standing on the axis reads as a token on a board
     rather than as an icon floating above a line. */
  box-shadow: 0 0 0 var(--cb-space-xxs) var(--cbc-surface);
}
.cb-market-score {
  font-size: var(--cb-type-xs-size);
  font-weight: var(--cb-font-weight-semibold);
  font-variant-numeric: tabular-nums;
  color: var(--cbc-ink-faint);
}
/* Theirs is the marked point: larger, in the accent, and the only score
   on the axis written at full strength. */
.cb-market-mark[data-mine] {
  z-index: 1;
}
.cb-market-mark[data-mine] .cb-site-icon {
  inline-size: var(--cb-space-5xl);
  block-size: var(--cb-space-5xl);
  box-shadow: 0 0 0 var(--cb-space-xxs) var(--cbc-accent);
}
.cb-market-mark[data-mine] .cb-market-score {
  color: var(--cbc-accent);
  font-size: var(--cb-type-sm-size);
}
.cb-market-mark[data-mine]::after {
  background: var(--cbc-accent);
}
.cb-market-scale {
  margin-inline: var(--cb-space-3xl);
  display: flex;
  justify-content: space-between;
  font-size: var(--cb-type-xs-size);
  color: var(--cbc-line-strong);
  font-variant-numeric: tabular-nums;
}

/* ---- One rival at a time ----
   Every competitor's wins printed at once is four lists nobody reads.
   Picking one is how the question is actually asked in a room. */
.cb-versus {
  padding: var(--cb-space-3xl);
  border: 1px solid var(--cbc-line);
  border-radius: var(--cb-radius-2xl);
  background: var(--cbc-surface);
  display: grid;
  gap: var(--cb-space-xl);
}
.cb-versus-head {
  display: flex;
  align-items: center;
  gap: var(--cb-space-xl);
  flex-wrap: wrap;
}
.cb-versus-head .cb-sub {
  margin-block-end: 0;
}
.cb-versus-tabs {
  margin-inline-start: auto;
  display: flex;
  gap: var(--cb-space-xxs);
  padding: var(--cb-space-xs);
  border-radius: var(--cb-radius-full);
  background: var(--cbc-sunken);
  overflow-x: auto;
  scrollbar-width: none;
}
.cb-versus-tab {
  flex: none;
  padding: var(--cb-space-sm) var(--cb-space-xl);
  border: 0;
  border-radius: var(--cb-radius-full);
  background: transparent;
  color: var(--cbc-ink-faint);
  font-family: var(--cb-font-body);
  font-size: var(--cb-type-xs-size);
  font-weight: var(--cb-font-weight-medium);
  cursor: pointer;
  white-space: nowrap;
  transition:
    background var(--cb-motion-fast) var(--cb-motion-ease),
    color var(--cb-motion-fast) var(--cb-motion-ease);
}
.cb-versus-tab:hover {
  color: var(--cbc-ink);
}
.cb-versus-tab[aria-pressed="true"] {
  background: var(--cbc-surface);
  color: var(--cbc-ink);
}
/* What they are better at. Rows with a mark, not chips: these are
   sentences, and a sentence in a pill is a pill the width of the card. */
.cb-wins {
  list-style: none;
  display: grid;
  gap: var(--cb-space-lg);
}
.cb-wins li {
  position: relative;
  padding-inline-start: var(--cb-space-3xl);
  font-size: var(--cb-type-sm-size);
  line-height: var(--cb-type-base-line-height);
  color: var(--cbc-ink-muted);
  animation: cbc-emerge var(--cb-motion-slow) var(--cbc-spring) backwards;
  animation-delay: min(calc(var(--i, 0) * var(--cb-motion-fast) / 3), var(--cb-motion-base));
}
.cb-wins li::before {
  content: "";
  position: absolute;
  inset-block-start: var(--cb-space-md);
  inset-inline-start: var(--cb-space-md);
  inline-size: var(--cb-space-md);
  block-size: var(--cb-space-md);
  border-radius: var(--cb-radius-full);
  background: var(--cbc-warn);
}

/* Six questions asked of two businesses. This genuinely is a table. */
.cb-channels {
  border: 1px solid var(--cbc-line);
  border-radius: var(--cb-radius-2xl);
  background: var(--cbc-surface);
  overflow: hidden;
}
.cb-channel-head,
.cb-channel {
  display: grid;
  grid-template-columns: minmax(0, 2fr) minmax(0, 1fr) minmax(0, 1fr);
  gap: var(--cb-space-xl);
  padding: var(--cb-space-xl) var(--cb-space-2xl);
  align-items: center;
}
.cb-channel-head {
  background: var(--cbc-sunken);
  font-size: var(--cb-type-xs-size);
  text-transform: uppercase;
  letter-spacing: var(--cb-tracking-xxs);
  font-weight: var(--cb-font-weight-semibold);
  color: var(--cbc-ink-faint);
}
.cb-channel-head > span {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.cb-channel + .cb-channel {
  border-block-start: 1px solid var(--cbc-line);
}
.cb-channel-name {
  min-width: 0;
  font-size: var(--cb-type-sm-size);
  font-weight: var(--cb-font-weight-medium);
}
.cb-channel-why {
  margin-block-start: var(--cb-space-xxs);
  font-size: var(--cb-type-xs-size);
  line-height: var(--cb-type-sm-line-height);
  font-weight: var(--cb-font-weight-regular);
  color: var(--cbc-ink-faint);
}
.cb-channel-state {
  display: inline-flex;
  align-items: center;
  gap: var(--cb-space-md);
  font-size: var(--cb-type-xs-size);
  color: var(--cbc-ink-muted);
}
.cb-channel-dot {
  inline-size: var(--cb-space-md);
  block-size: var(--cb-space-md);
  border-radius: var(--cb-radius-full);
  background: var(--cbc-line-strong);
  flex: none;
}
.cb-channel-state[data-state="active"] .cb-channel-dot {
  background: var(--cbc-good);
}
.cb-channel-state[data-state="detected"] .cb-channel-dot {
  background: var(--cbc-cat-design);
}
.cb-channel-state[data-state="absent"] .cb-channel-dot {
  background: var(--cbc-poor);
}

/* 768px mirrors tokens.breakpoint.md */
@media (max-width: 768px) {
  .cb-versus-tabs {
    margin-inline-start: 0;
    max-inline-size: 100%;
  }
}

.cb-market-read {
  font-size: var(--cb-type-sm-size);
  line-height: var(--cb-type-base-line-height);
  color: var(--cbc-ink-muted);
  max-inline-size: var(--cb-layout-paragraph-max-width);
}

/* ==================================================================
   CAN ANYONE FIND THEM */

.cb-found {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(var(--cb-width-xs), 1fr));
  gap: var(--cb-space-2xl);
}
.cb-found-card {
  padding: var(--cb-space-3xl);
  border: 1px solid var(--cbc-line);
  border-radius: var(--cb-radius-2xl);
  background: var(--cbc-surface);
}
.cb-found-answers {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: var(--cb-space-lg);
}
.cb-found-answer {
  padding: var(--cb-space-xl);
  border-radius: var(--cb-radius-xl);
  background: var(--cbc-sunken);
  display: grid;
  gap: var(--cb-space-xs);
}
.cb-found-who {
  font-size: var(--cb-type-sm-size);
  font-weight: var(--cb-font-weight-semibold);
}
.cb-found-verdict {
  font-size: var(--cb-type-xs-size);
  color: var(--cbc-poor-text);
}
.cb-found-answer[data-known] .cb-found-verdict {
  color: var(--cbc-good-text);
}
.cb-found-versus {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: var(--cb-space-lg);
}
.cb-mapstat {
  padding: var(--cb-space-xl);
  border-radius: var(--cb-radius-xl);
  background: var(--cbc-sunken);
  display: grid;
  gap: var(--cb-space-xxs);
}
.cb-mapstat-label {
  font-size: var(--cb-type-xs-size);
  text-transform: uppercase;
  letter-spacing: var(--cb-tracking-xxs);
  font-weight: var(--cb-font-weight-semibold);
  color: var(--cbc-ink-faint);
}
.cb-mapstat-mine {
  font-size: var(--cb-type-xl-size);
  line-height: var(--cb-type-xl-line-height);
  font-weight: var(--cb-font-weight-semibold);
  font-variant-numeric: tabular-nums;
}
.cb-mapstat-theirs {
  font-size: var(--cb-type-xs-size);
  color: var(--cbc-ink-faint);
}
.cb-found-flag {
  margin-block-start: var(--cb-space-xl);
  font-size: var(--cb-type-sm-size);
  font-weight: var(--cb-font-weight-medium);
  color: var(--cbc-warn-text);
}
.cb-found-read {
  margin-block-start: var(--cb-space-xl);
  font-size: var(--cb-type-sm-size);
  line-height: var(--cb-type-base-line-height);
  color: var(--cbc-ink-muted);
}

/* ==================================================================
   THE RELATIONSHIP
   Last, because a phone number is what somebody wants once they have
   decided to act.

   Rebuilt twice. It was nine rows of a definition list, which put a
   number to dial and a model-spend figure at the same weight in the
   same grey; then two panels holding leftovers with a browser-default
   button under forty monospace addresses. The rule now: every card has
   one lead, the largest thing in it and the thing it is about, and
   anything that would bury that lead is behind a fold. */

.cb-accts {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: var(--cb-space-2xl);
  align-items: stretch;
}
/* One shape, three times. Written once so three cards cannot drift into
   three different paddings, which is what happened when each was
   assembled by hand. */
/* Three cards to one height, with the body taking the slack and the
   fold pinned to the bottom edge. A row of cards ending at three
   different heights reads as three things that happened to be put next
   to each other; one line along the bottom reads as a set. */
.cb-acct {
  display: grid;
  grid-template-rows: auto minmax(0, 1fr) auto;
  border: 1px solid var(--cbc-line);
  border-radius: var(--cb-radius-2xl);
  background: var(--cbc-surface);
  overflow: hidden;
  block-size: 100%;
}
.cb-acct-head {
  display: flex;
  align-items: baseline;
  gap: var(--cb-space-lg);
  padding: var(--cb-space-2xl) var(--cb-space-2xl) var(--cb-space-xl);
  border-block-end: 1px solid var(--cbc-line);
}
.cb-acct-count {
  margin-inline-start: auto;
  font-size: var(--cb-type-xs-size);
  color: var(--cbc-ink-faint);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}
.cb-acct-body {
  padding: var(--cb-space-2xl);
  display: grid;
  gap: var(--cb-space-2xl);
  align-content: start;
}
.cb-acct-foot {
  padding: var(--cb-space-xl) var(--cb-space-2xl);
  border-block-start: 1px solid var(--cbc-line);
  background: var(--cbc-sunken);
}

/* The eyebrow every block in this chapter is titled with. */
.cb-eyebrow {
  font-size: var(--cb-type-xs-size);
  text-transform: uppercase;
  letter-spacing: var(--cb-tracking-xxs);
  font-weight: var(--cb-font-weight-semibold);
  color: var(--cbc-ink-faint);
}

/* ---- The lead ----
   The largest thing in a card and the thing the card is about. A number
   to dial, the platform, how many people asked. */
.cb-lead {
  display: flex;
  align-items: center;
  gap: var(--cb-space-xl);
}
.cb-lead-mark {
  inline-size: var(--cb-space-5xl);
  block-size: var(--cb-space-5xl);
  flex: none;
  display: grid;
  place-items: center;
  border-radius: var(--cb-radius-xl);
  background: var(--cbc-accent-quiet);
  color: var(--cbc-accent);
}
.cb-lead-mark .cb-icon {
  inline-size: var(--cb-space-3xl);
}
.cb-lead-mark .cb-platform-mark {
  inline-size: var(--cb-space-3xl);
  block-size: var(--cb-space-3xl);
}
.cb-lead-text {
  min-width: 0;
  display: grid;
  gap: var(--cb-space-xxs);
}
.cb-lead-value {
  font-size: var(--cb-type-xl-size);
  line-height: var(--cb-type-xl-line-height);
  font-weight: var(--cb-font-weight-semibold);
  font-variant-numeric: tabular-nums;
  overflow-wrap: anywhere;
  color: var(--cbc-ink);
  text-decoration: none;
}
a.cb-lead-dial:hover {
  color: var(--cbc-accent);
}
.cb-lead-note {
  font-size: var(--cb-type-xs-size);
  line-height: var(--cb-type-sm-line-height);
  color: var(--cbc-ink-faint);
}

/* ---- Supporting rows ---- */
.cb-lines {
  display: grid;
  gap: var(--cb-space-lg);
}
.cb-line {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  gap: var(--cb-space-lg);
  align-items: center;
  font-size: var(--cb-type-sm-size);
}
.cb-line-glyph {
  inline-size: var(--cb-space-2xl);
  color: var(--cbc-ink-faint);
  flex: none;
}
.cb-line a,
.cb-line span {
  color: var(--cbc-ink-muted);
  text-decoration: none;
  overflow-wrap: anywhere;
}
.cb-line a:hover {
  color: var(--cbc-accent);
}
.cb-line-dial {
  font-variant-numeric: tabular-nums;
}

.cb-pairs {
  display: grid;
  gap: var(--cb-space-lg);
}
.cb-pair {
  display: flex;
  align-items: baseline;
  gap: var(--cb-space-lg);
  font-size: var(--cb-type-sm-size);
}
.cb-pair dt {
  color: var(--cbc-ink-faint);
}
.cb-pair dd {
  margin: 0;
  margin-inline-start: auto;
  text-align: end;
  font-weight: var(--cb-font-weight-medium);
  overflow-wrap: anywhere;
}
.cb-pair dd[data-tone="warn"] {
  color: var(--cbc-warn-text);
}

/* ---- Tags ----
   Not .cb-chip: that is the console's monospace value chip, and a
   product name is not a value to be read character by character. */
.cb-tools,
.cb-socials {
  display: grid;
  gap: var(--cb-space-lg);
}
.cb-tags {
  display: flex;
  flex-wrap: wrap;
  gap: var(--cb-space-md);
}
/* The base moved to console-panels.css, which is the earlier of the two files
   that dress this shared class, so a variant here can still override it. These
   values are unchanged: they are the ones that were winning. */
a.cb-tag-mail {
  text-decoration: none;
}
a.cb-tag-mail:hover {
  color: var(--cbc-accent);
  border-color: var(--cbc-accent);
}
.cb-flagline {
  font-size: var(--cb-type-sm-size);
  line-height: var(--cb-type-base-line-height);
  color: var(--cbc-warn-text);
}

.cb-social-row {
  display: flex;
  flex-wrap: wrap;
  gap: var(--cb-space-md);
}
.cb-social {
  inline-size: var(--cb-space-5xl);
  block-size: var(--cb-space-5xl);
  display: grid;
  place-items: center;
  border-radius: var(--cb-radius-lg);
  border: 1px solid var(--cbc-line);
  color: var(--cbc-ink-muted);
  transition:
    color var(--cb-motion-fast) var(--cb-motion-ease),
    border-color var(--cb-motion-fast) var(--cb-motion-ease),
    background var(--cb-motion-fast) var(--cb-motion-ease);
}
.cb-social:hover {
  color: var(--cbc-accent);
  border-color: var(--cbc-accent);
  background: var(--cbc-accent-quiet);
}
.cb-social-mark {
  display: block;
  inline-size: var(--cb-space-3xl);
  block-size: var(--cb-space-3xl);
}
.cb-social-mark > svg {
  inline-size: 100%;
  block-size: 100%;
  display: block;
}

/* ---- Who asked, grouped by where they came from ---- */
.cb-origins {
  display: grid;
  gap: var(--cb-space-lg);
}
.cb-origin {
  padding: var(--cb-space-xl);
  border-radius: var(--cb-radius-xl);
  background: var(--cbc-sunken);
  display: flex;
  align-items: center;
  gap: var(--cb-space-lg);
  flex-wrap: wrap;
}
/* An address at the company being sold to is the only one on the list
   worth writing to, so it is the one that is marked. */
.cb-origin[data-theirs] {
  background: var(--cbc-accent-quiet);
  border: 1px solid color-mix(in srgb, var(--cbc-accent) 34%, transparent);
}
.cb-origin-who {
  min-width: 0;
  flex: 1 1 auto;
  display: grid;
  gap: var(--cb-space-xxs);
}
.cb-origin-name {
  font-size: var(--cb-type-sm-size);
  font-weight: var(--cb-font-weight-medium);
  color: var(--cbc-ink);
  text-decoration: none;
  overflow-wrap: anywhere;
}
a.cb-origin-name:hover {
  color: var(--cbc-accent);
}
.cb-origin-tag {
  font-size: var(--cb-type-xs-size);
  color: var(--cbc-ink-faint);
}
.cb-origin .cb-more {
  margin-inline-start: auto;
  flex: none;
}

/* ---- The fold ----
   cb-reveal was an ::after chevron with no base rule anywhere, so what
   shipped under a carefully set panel was a browser default button. */
.cb-more {
  display: inline-flex;
  align-items: center;
  gap: var(--cb-space-md);
  padding: var(--cb-space-sm) var(--cb-space-lg);
  border: 1px solid var(--cbc-line);
  border-radius: var(--cb-radius-full);
  background: transparent;
  color: var(--cbc-ink-muted);
  font-family: var(--cb-font-body);
  font-size: var(--cb-type-xs-size);
  font-weight: var(--cb-font-weight-medium);
  cursor: pointer;
  white-space: nowrap;
  transition:
    color var(--cb-motion-fast) var(--cb-motion-ease),
    border-color var(--cb-motion-fast) var(--cb-motion-ease),
    background var(--cb-motion-fast) var(--cb-motion-ease);
}
.cb-more:hover {
  color: var(--cbc-ink);
  border-color: var(--cbc-line-strong);
  background: var(--cbc-hover);
}
/* lucide's chevron as a mask, so it takes currentColor and turns rather
   than swapping, and opening reads as one movement. */
.cb-more::after {
  content: "";
  inline-size: var(--cb-space-xl);
  block-size: var(--cb-space-xl);
  background: currentColor;
  mask: var(--cbc-chevron) center / contain no-repeat;
  transition: rotate var(--cb-motion-base) var(--cbc-spring);
}
.cb-more[aria-expanded="true"]::after {
  rotate: 180deg;
}
.cb-fold-body {
  animation: cbc-emerge var(--cb-motion-slow) var(--cbc-spring) backwards;
}
.cb-acct-body > .cb-fold-body {
  display: grid;
  gap: var(--cb-space-lg);
}

/* ---- The history, and our own ledger on its header ---- */
.cb-history {
  padding: var(--cb-space-3xl);
  border: 1px solid var(--cbc-line);
  border-radius: var(--cb-radius-2xl);
  background: var(--cbc-surface);
  display: grid;
  gap: var(--cb-space-2xl);
}
.cb-history-head {
  display: flex;
  align-items: baseline;
  gap: var(--cb-space-2xl);
  flex-wrap: wrap;
}
.cb-ledger {
  margin-inline-start: auto;
  display: flex;
  flex-wrap: wrap;
  gap: var(--cb-space-lg);
  font-size: var(--cb-type-xs-size);
  color: var(--cbc-ink-faint);
  font-variant-numeric: tabular-nums;
}
.cb-ledger > span + span::before {
  content: "·";
  margin-inline-end: var(--cb-space-lg);
  color: var(--cbc-line-strong);
}
/* Which audit the line is drawn from, and every other audit this website has
   been scanned by, beside it.
   The row is the whole answer to "what has been run against this site", so an
   audit with a single run stays in it and is turned off rather than taken away
   (rule 15, and business-trend.ts argues the chart itself). Left rather than
   right: it is a control on the chart under it, not a figure in the ledger
   above it. */
.cb-history-kinds {
  justify-self: start;
  flex-wrap: wrap;
  max-inline-size: 100%;
}
.cb-history-kinds .cb-view[aria-disabled="true"] {
  color: var(--cbc-ink-faint);
  cursor: not-allowed;
}
.cb-history-kinds .cb-view[aria-disabled="true"]:hover {
  background: none;
}
/* Capped rather than left to the drawing's own ratio: full width and
   unbounded it came out a card and a half tall for a line that says one
   thing. */
.cb-history-plot {
  display: grid;
}
.cb-history .cb-chart-plot {
  block-size: calc(var(--cb-space-11xl) + var(--cb-space-3xl));
}

/* 1024px mirrors tokens.breakpoint.lg */
@media (max-width: 1024px) {
  .cb-accts {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
  .cb-ledger {
    margin-inline-start: 0;
  }
}
/* 768px mirrors tokens.breakpoint.md */
@media (max-width: 768px) {
  .cb-accts {
    grid-template-columns: minmax(0, 1fr);
  }
}

/* ==================================================================
   THE LIST POPOVER
   A long list, opened beside the thing that counts it. Forty rows
   unfolding inside a card grew it by two thousand pixels and shoved
   every chapter under it down the page; here nothing on the page moves
   and the list scrolls inside its own height. See views/list-popover.ts. */

.cb-listpop {
  position: fixed;
  inset: auto auto auto 0;
  margin: 0;
  padding: 0;
  border: 1px solid var(--cbc-line-strong);
  border-radius: var(--cb-radius-2xl);
  background: var(--cbc-raised);
  box-shadow: var(--cbc-shadow);
  color: inherit;
  inline-size: min(var(--cb-width-sm), calc(100vw - var(--cb-space-4xl)));
  overflow: hidden;
  translate: var(--x, 0) var(--y, 0);
  display: grid;
  grid-template-rows: auto minmax(0, 1fr);
  /* Capped, so a domain with four hundred addresses is a scrolling panel
     rather than a column the height of the screen. */
  max-block-size: min(var(--cb-width-xs), calc(100vh - var(--cb-space-8xl)));
  animation: cbc-pop var(--cb-motion-fast) var(--cbc-spring) backwards;
}
/* Older engines with no popover support: the panel still works, it just
   is not in the top layer. */
.cb-listpop:not(:popover-open):not([data-open]) {
  display: none;
}

.cb-listpop-head {
  display: flex;
  align-items: baseline;
  gap: var(--cb-space-lg);
  padding: var(--cb-space-xl) var(--cb-space-2xl);
  border-block-end: 1px solid var(--cbc-line);
  background: var(--cbc-sunken);
}
.cb-listpop-title {
  font-size: var(--cb-type-sm-size);
  font-weight: var(--cb-font-weight-semibold);
  overflow-wrap: anywhere;
}
.cb-listpop-count {
  margin-inline-start: auto;
  font-size: var(--cb-type-xs-size);
  color: var(--cbc-ink-faint);
  font-variant-numeric: tabular-nums;
}
.cb-listpop-body {
  overflow-y: auto;
  overscroll-behavior: contain;
  padding: var(--cb-space-md);
  display: grid;
  gap: var(--cb-space-xxs);
}
.cb-listpop-row {
  padding: var(--cb-space-md) var(--cb-space-lg);
  border-radius: var(--cb-radius-md);
  font-size: var(--cb-type-xs-size);
  font-family: var(--cb-font-mono);
  color: var(--cbc-ink-muted);
  text-decoration: none;
  overflow-wrap: anywhere;
}
a.cb-listpop-row:hover {
  background: var(--cbc-hover);
  color: var(--cbc-accent);
}

/* ==================================================================
   WHY A SERVICE FIRED
   The rule that fired it, read out loud. This panel printed the rule
   itself, `gbpExists == false` in a monospace face on a card headed
   "Services to pitch": the machine's own notation shown to a marketer.
   See views/rule-words.ts. */

/* One row per service: the rank, what it is, why it fired, and how
   heavily it counted. It was a card per service inside a card inside a
   chapter, which is three borders to say "here are five things". */
.cb-fired {
  grid-template-columns: auto minmax(0, 1fr) minmax(0, var(--cb-width-xxs));
  align-items: start;
  gap: var(--cb-space-xl);
}
.cb-fired-rank {
  inline-size: var(--cb-space-3xl);
  block-size: var(--cb-space-3xl);
  flex: none;
  display: grid;
  place-items: center;
  border-radius: var(--cb-radius-md);
  background: var(--cbc-accent-quiet);
  color: var(--cbc-accent);
  font-size: var(--cb-type-xs-size);
  font-weight: var(--cb-font-weight-bold);
  font-variant-numeric: tabular-nums;
}
.cb-fired-what {
  min-inline-size: 0;
  display: grid;
  gap: var(--cb-space-lg);
}
.cb-fired-name {
  font-size: var(--cb-type-base-size);
  font-weight: var(--cb-font-weight-semibold);
}
/* The number that decided the order these are in. An ordered list whose
   ordering is invisible is a list somebody reorders in their head. */
/* The whole rule. The width and the self-alignment had been in
   console-submission.css, which loads afterwards and named no property this one
   did, so both always applied and the split only cost a class two files defined.
   Here because the entire .cb-fired-* family is here: name, rank, what, weight
   and weight-value. The responsive override below stays exactly where it is. */
.cb-fired-weight {
  display: grid;
  gap: var(--cb-space-sm);
  align-content: start;
  inline-size: var(--cb-space-9xl);
  justify-self: end;
}
.cb-fired-weight-value {
  font-size: var(--cb-type-xs-size);
  color: var(--cbc-ink-faint);
  font-variant-numeric: tabular-nums;
  justify-self: end;
}

/* 768px mirrors tokens.breakpoint.md */
@media (max-width: 768px) {
  .cb-fired {
    grid-template-columns: auto minmax(0, 1fr);
  }
  .cb-fired-weight {
    grid-column: 2;
  }
  .cb-fired-weight-value {
    justify-self: start;
  }
}

/* Every clause of the rule, one line each: a rule joined with && is
   several conditions that all have to hold, and they read as several
   claims rather than as one string with an ampersand in it. */
.cb-reasons {
  list-style: none;
  display: grid;
  gap: var(--cb-space-md);
}
.cb-reason {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  gap: var(--cb-space-md);
  align-items: baseline;
}
.cb-reason-mark {
  inline-size: var(--cb-space-xl);
  color: var(--cbc-good-text);
  transform: translateY(var(--cb-space-xxs));
}
.cb-reason-text {
  display: inline-flex;
  flex-wrap: wrap;
  gap: var(--cb-space-sm);
  align-items: baseline;
  font-size: var(--cb-type-sm-size);
  line-height: var(--cb-type-sm-line-height);
}
.cb-reason-signal {
  color: var(--cbc-ink);
  font-weight: var(--cb-font-weight-medium);
}
.cb-reason-op {
  color: var(--cbc-ink-faint);
}
.cb-reason-value {
  padding: 0 var(--cb-space-md);
  border-radius: var(--cb-radius-full);
  background: var(--cbc-hover);
  color: var(--cbc-ink);
  font-weight: var(--cb-font-weight-semibold);
  font-variant-numeric: tabular-nums;
}
/* A rule nobody could read is shown exactly as written rather than
   guessed at: it is the reason a service is being pitched, and a reason
   nobody can check is worse than an ugly one. */
.cb-reason[data-raw] .cb-reason-mark {
  color: var(--cbc-warn-text);
}
.cb-reason[data-raw] .cb-reason-text {
  font-family: var(--cb-font-mono);
  color: var(--cbc-ink-muted);
}

/* ==================================================================
   WHAT IT LOOKS LIKE
   Every capture, as a capture. This panel listed fourteen text links
   reading "Screenshot 1" through "Screenshot 10", and under that sat a
   real bug: the server labels the homepage `hero` and the share card
   `og`, while the panel only drew images for `screenshot` and
   `annotated`, so the two most useful pictures on the screen rendered
   as ghost buttons next to "Report PDF". */

/* Each scanned page is a row: what it is called, then everything the scan
   captured of it. Ten captions reading "Screenshot 1" through "Screenshot
   10" describe five pages photographed twice each, and the pairing is the
   whole reason to look at them. */

.cb-page-row {
  display: grid;
  gap: var(--cb-space-md);
  padding-block-end: var(--cb-space-xl);
  border-block-end: 1px solid var(--cbc-line);
}
.cb-page-row:last-child {
  border-block-end: 0;
  padding-block-end: 0;
}

/* This was an unscoped `.cb-page-head`, so it restyled every page header in the
   console rather than the dossier's. Its values are the ones that were winning
   and they have moved into console.css's base unchanged. */
.cb-page-name {
  margin: 0;
  color: var(--cbc-ink);
  font-weight: var(--cb-font-weight-semibold);
}
.cb-page-url {
  color: var(--cbc-ink-faint);
  font-size: var(--cb-type-xs-size);
  text-decoration: none;
  overflow-wrap: anywhere;
}
.cb-page-url:hover {
  color: var(--cbc-accent);
  text-decoration: underline;
}

/* One row that scrolls sideways rather than a wrapping grid: as a grid,
   forty captures cost more of the page than the report does, and one row
   costs the same whether there are three or forty. */
.cb-page-shots {
  display: grid;
  grid-auto-flow: column;
  grid-auto-columns: var(--cb-width-xxs);
  gap: var(--cb-space-lg);
  overflow-x: auto;
  overscroll-behavior-x: contain;
  padding-block-end: var(--cb-space-sm);
  scroll-snap-type: x proximity;
}

.cb-plate {
  position: relative;
  display: grid;
  gap: var(--cb-space-sm);
  padding: 0;
  border: 0;
  background: none;
  color: inherit;
  font: inherit;
  text-align: start;
  cursor: zoom-in;
  scroll-snap-align: start;
}
.cb-plate-frame {
  position: relative;
  display: block;
}
.cb-plate img {
  inline-size: 100%;
  display: block;
  /* Captures are full-page and very tall. Cropped to the top, which is the
     part anybody is looking at, rather than shrunk to a sliver. */
  aspect-ratio: 4 / 3;
  object-fit: cover;
  object-position: top center;
  border-radius: var(--cb-radius-xl);
  border: 1px solid var(--cbc-line);
  background: var(--cbc-sunken);
  transition:
    border-color var(--cb-motion-fast) var(--cb-motion-ease),
    opacity var(--cb-motion-fast) var(--cb-motion-ease);
}
/* A phone capture drawn at a desktop's proportions is a lie about what was
   measured. It gets a phone's shape and the row stays the same height. */
.cb-plate[data-view="mobile"] img {
  aspect-ratio: 3 / 4;
}
.cb-plate[data-kind="hero"] img {
  aspect-ratio: 16 / 10;
}
.cb-plate:hover img,
.cb-plate:focus-visible img {
  border-color: var(--cbc-accent);
}
.cb-plate-name {
  display: flex;
  align-items: center;
  gap: var(--cb-space-xs);
  font-size: var(--cb-type-xs-size);
  color: var(--cbc-ink-faint);
  overflow-wrap: anywhere;
}
.cb-plate[data-kind="annotated"] .cb-plate-name {
  color: var(--cbc-accent);
}
/* The affordance appears on approach, in the corner, moving nothing. */
.cb-plate-zoom {
  position: absolute;
  inset-block-start: var(--cb-space-md);
  inset-inline-end: var(--cb-space-md);
  inline-size: var(--cb-space-4xl);
  block-size: var(--cb-space-4xl);
  display: grid;
  place-items: center;
  border-radius: var(--cb-radius-full);
  background: var(--cbc-raised);
  color: var(--cbc-ink);
  box-shadow: var(--cbc-shadow);
  opacity: 0;
  transition: opacity var(--cb-motion-fast) var(--cb-motion-ease);
}
.cb-plate:hover .cb-plate-zoom,
.cb-plate:focus-visible .cb-plate-zoom {
  opacity: 1;
}

/* ---- The viewer ----
   A thumbnail is too small to read an annotation on, and an annotation
   is what somebody screen-shares on a call.

   Not --cbc-veil, and on purpose: this is the only full-screen surface in the
   console where the dimming is not behind the thing, it IS the thing. There is
   no panel floating in it, so the ground has to be dark enough to read a
   screenshot against on somebody else's monitor. At the veil's own strength
   the dashboard shows through around the picture being presented. */
.cb-lightbox {
  position: fixed;
  inset: 0;
  margin: 0;
  padding: 0;
  max-inline-size: 100%;
  max-block-size: 100%;
  inline-size: 100%;
  block-size: 100%;
  border: 0;
  background: color-mix(in srgb, var(--cb-color-black) 88%, transparent);
  backdrop-filter: blur(var(--cb-space-md));
  color: var(--cb-color-ceramic-grey);
  /* A DARK ISLAND IN BOTH THEMES, so the ring cannot follow the page's accent:
     the light theme's accent-600 measures 2.5:1 on this ground and 1.4.11 asks
     3:1. Scoped to the island rather than patched onto each button, because
     every accent inside here has the same problem. accent-400 is the step of
     the official set that clears it, which is the same move --cbc-accent-text
     already makes on the dark theme's ground. */
  --cbc-accent: var(--cb-color-accent-400);
  display: grid;
  grid-template-rows: auto minmax(0, 1fr);
  animation: cbc-fade var(--cb-motion-fast) var(--cb-motion-ease) backwards;
}
.cb-lightbox:not(:popover-open):not([data-open]) {
  display: none;
}
.cb-lightbox-bar {
  display: flex;
  align-items: center;
  gap: var(--cb-space-2xl);
  padding: var(--cb-space-2xl) var(--cb-space-3xl);
}
.cb-lightbox-caption {
  font-size: var(--cb-type-sm-size);
  font-weight: var(--cb-font-weight-medium);
}
.cb-lightbox-count {
  margin-inline-start: auto;
  font-size: var(--cb-type-xs-size);
  opacity: 0.7;
  font-variant-numeric: tabular-nums;
}
.cb-lightbox-shut,
.cb-lightbox-step {
  inline-size: var(--cb-space-5xl);
  block-size: var(--cb-space-5xl);
  flex: none;
  display: grid;
  place-items: center;
  border: 1px solid color-mix(in srgb, var(--cb-color-ceramic-grey) 24%, transparent);
  border-radius: var(--cb-radius-full);
  background: transparent;
  color: inherit;
  cursor: pointer;
  transition: background var(--cb-motion-fast) var(--cb-motion-ease);
}
.cb-lightbox-shut:hover,
.cb-lightbox-step:hover {
  background: color-mix(in srgb, var(--cb-color-ceramic-grey) 16%, transparent);
}
.cb-lightbox-stage {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr) auto;
  align-items: center;
  gap: var(--cb-space-2xl);
  padding: var(--cb-space-none) var(--cb-space-3xl) var(--cb-space-4xl);
  min-block-size: 0;
}
.cb-lightbox-image {
  max-inline-size: 100%;
  max-block-size: 100%;
  justify-self: center;
  object-fit: contain;
  border-radius: var(--cb-radius-lg);
  /* The captures are on a white page, so a hairline keeps the edge of the
     picture off the ground behind it. */
  border: 1px solid color-mix(in srgb, var(--cb-color-ceramic-grey) 18%, transparent);
  animation: cbc-emerge var(--cb-motion-slow) var(--cbc-spring) backwards;
}
/* 768px mirrors tokens.breakpoint.md */
@media (max-width: 768px) {
  .cb-lightbox-stage {
    grid-template-columns: minmax(0, 1fr);
  }
  .cb-lightbox-step {
    display: none;
  }
}

/* ==================================================================
   THE REPORT, ON THE SUBMISSION SCREEN
   Nothing left here. The verdict, the summary, the strengths, the plan,
   the services and the opening lines were six classes that each drew a
   bordered box, inside a card, inside a chapter. They are parts, rows
   and figures on the page now: see console-submission.css. */

/* ==================================================================
   HOW THIS SCAN RAN
   The machine's half, last and shut. It was interleaved with the
   report, which put twelve JSON dumps on a screen whose job is
   checking English prose. */

.cb-run {
  border: 1px solid var(--cbc-line);
  border-radius: var(--cb-radius-2xl);
  background: var(--cbc-surface);
  overflow: hidden;
}
.cb-run-summary {
  display: flex;
  align-items: center;
  gap: var(--cb-space-lg);
  padding: var(--cb-space-2xl);
  cursor: pointer;
  list-style: none;
  transition: background var(--cb-motion-fast) var(--cb-motion-ease);
}
.cb-run-summary::-webkit-details-marker {
  display: none;
}
.cb-run-summary:hover {
  background: var(--cbc-hover);
}
.cb-run-dot {
  inline-size: var(--cb-space-lg);
  block-size: var(--cb-space-lg);
  flex: none;
  border-radius: var(--cb-radius-full);
  background: var(--cbc-ink-faint);
}
.cb-run-dot[data-tone="good"] {
  background: var(--cbc-good);
}
.cb-run-dot[data-tone="warn"] {
  background: var(--cbc-warn);
}
.cb-run-dot[data-tone="poor"] {
  background: var(--cbc-poor);
}
.cb-run-line {
  font-size: var(--cb-type-sm-size);
  font-weight: var(--cb-font-weight-medium);
}
.cb-run-more {
  margin-inline-start: auto;
  font-size: var(--cb-type-xs-size);
  color: var(--cbc-ink-faint);
}
.cb-run-summary::after {
  content: "";
  flex: none;
  inline-size: var(--cb-space-xl);
  block-size: var(--cb-space-xl);
  background: currentColor;
  color: var(--cbc-ink-faint);
  mask: var(--cbc-chevron) center / contain no-repeat;
  transition: rotate var(--cb-motion-base) var(--cbc-spring);
}
.cb-run[open] .cb-run-summary::after {
  rotate: 180deg;
}
.cb-run-body {
  padding: var(--cb-space-2xl);
  border-block-start: 1px solid var(--cbc-line);
  background: var(--cbc-sunken);
  display: grid;
  gap: var(--cb-space-2xl);
  animation: cbc-emerge var(--cb-motion-slow) var(--cbc-spring) backwards;
}
/* The panels in here are already cards; inside a card they become plain
   blocks, or the chapter reads as boxes in a box in a box. */
.cb-run-body > .cb-card {
  border-color: var(--cbc-line);
  background: var(--cbc-surface);
}

/* ==================================================================
   WHO THEY ARE, ON THE SUBMISSION SCREEN */

.cb-source-note {
  font-size: var(--cb-type-xs-size);
  line-height: var(--cb-type-sm-line-height);
  color: var(--cbc-ink-faint);
  max-inline-size: var(--cb-layout-paragraph-max-width);
}
/* The platform gets its own logo and its own line. It was a chip in a
   row of chips, so "WordPress" sat between "Microsoft Clarity" and
   "424 pages" at one weight, and one of those three is not software. */
.cb-built {
  display: flex;
  align-items: center;
  gap: var(--cb-space-xl);
  padding: var(--cb-space-xl);
  border-radius: var(--cb-radius-xl);
  background: var(--cbc-sunken);
}
.cb-built-mark {
  inline-size: var(--cb-space-5xl);
  block-size: var(--cb-space-5xl);
  flex: none;
  display: grid;
  place-items: center;
  border-radius: var(--cb-radius-lg);
  background: var(--cbc-accent-quiet);
  color: var(--cbc-accent);
}
.cb-built-mark .cb-platform-mark {
  inline-size: var(--cb-space-3xl);
  block-size: var(--cb-space-3xl);
}
.cb-built-name {
  font-size: var(--cb-type-md-size);
  font-weight: var(--cb-font-weight-semibold);
}
.cb-built-note {
  font-size: var(--cb-type-xs-size);
  color: var(--cbc-ink-faint);
}
.cb-built-pages {
  margin-inline-start: auto;
  display: grid;
  justify-items: end;
  line-height: 1;
}
.cb-built-pages strong {
  font-size: var(--cb-type-xl-size);
  font-weight: var(--cb-font-weight-bold);
  font-variant-numeric: tabular-nums;
}
.cb-built-pages span {
  margin-block-start: var(--cb-space-xxs);
  font-size: var(--cb-type-xs-size);
  color: var(--cbc-ink-faint);
}

/* ==================================================================
   WHAT THE ASSISTANTS SAID
   Quoted verbatim, which is about the words rather than the notation.
   These arrived as one unbroken block each, in the form system's faint
   caption class, carrying the model's own markdown citations in the
   middle of every sentence. See views/answer-text.ts. */

.cb-engines {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(var(--cb-width-md), 1fr));
  gap: var(--cb-space-2xl);
  align-items: start;
}
.cb-engine {
  padding: var(--cb-space-2xl);
  border: 1px solid var(--cbc-line);
  border-radius: var(--cb-radius-2xl);
  background: var(--cbc-sunken);
  display: grid;
  gap: var(--cb-space-2xl);
  align-content: start;
}
.cb-engine-head {
  display: flex;
  align-items: center;
  gap: var(--cb-space-lg);
}
.cb-engine-mark {
  inline-size: var(--cb-space-4xl);
  block-size: var(--cb-space-4xl);
  flex: none;
  display: grid;
  place-items: center;
  border-radius: var(--cb-radius-lg);
  background: var(--cbc-surface);
  color: var(--cbc-ink);
}
.cb-engine-name {
  font-size: var(--cb-type-md-size);
  font-weight: var(--cb-font-weight-semibold);
}
.cb-engine-head .cb-badge {
  margin-inline-start: auto;
}
.cb-engine-aside {
  display: grid;
  gap: var(--cb-space-lg);
  margin-block-start: var(--cb-space-2xl);
}

/* One question and the answer to it. Named cb-said rather than cb-ask because
   the advisor panel that used to live further down this sheet had also claimed
   .cb-ask, and being second it won: every quoted answer was drawn in the
   advisor's bordered panel. The advisor is gone and the name stays, because
   the collision is why it is called this and renaming it now would delete the
   reason. */
.cb-said {
  display: grid;
  gap: var(--cb-space-md);
  justify-items: start;
}
.cb-said-none {
  font-size: var(--cb-type-sm-size);
  color: var(--cbc-ink-faint);
}

.cb-answer {
  display: grid;
  gap: var(--cb-space-lg);
}
.cb-answer-line {
  font-size: var(--cb-type-sm-size);
  line-height: var(--cb-type-base-line-height);
  color: var(--cbc-ink-muted);
  text-wrap: pretty;
}
/* Clamped rather than cut. These run to a thousand characters and two of
   them side by side is most of a screen, but reading what was said is
   the reason to open the panel, so the whole of it is one press away. */
.cb-answer[data-clamped] {
  display: -webkit-box;
  -webkit-line-clamp: 5;
  -webkit-box-orient: vertical;
  overflow: hidden;
}
/* A citation, as the site it was pointing at. */
.cb-answer-cite {
  display: inline-flex;
  align-items: baseline;
  padding: 0 var(--cb-space-md);
  border-radius: var(--cb-radius-full);
  background: var(--cbc-hover);
  color: var(--cbc-ink);
  font-size: var(--cb-type-xs-size);
  text-decoration: none;
  overflow-wrap: anywhere;
}
.cb-answer-cite:hover {
  color: var(--cbc-accent);
  background: var(--cbc-accent-quiet);
}

/* ── The lead map ──────────────────────────────────────────────────────────
   A real map, because the profile has held coordinates for months and no
   screen drew them. The surface is a canvas; the pins are buttons on top of
   it so they can carry a tooltip and be reached by a keyboard, which a shape
   painted into a canvas cannot.                                            */

.cb-map-card {
  display: grid;
  gap: var(--cb-space-md);
  min-inline-size: 0;
  border: 1px solid var(--cbc-line);
  border-radius: var(--cb-radius-lg);
  background: var(--cbc-surface);
  overflow: hidden;
}

.cb-map-stage {
  position: relative;
  /* Aspect only, and min-inline-size: 0 with it. A grid item's automatic
     minimum is its min-content width, and with a height floor beside an
     aspect ratio that minimum is computed from the height: the stage refused
     to go under 427 pixels inside a 348-pixel column, overflowed it, and took
     the fit with it, so the office sat off the edge of its own map. */
  aspect-ratio: 16 / 10;
  min-inline-size: 0;
  background: var(--cbc-map-wash);
  cursor: grab;
  touch-action: pan-y;
  isolation: isolate;
}

.cb-map-stage[data-dragging] {
  cursor: grabbing;
}

.cb-map-surface {
  display: block;
  width: 100%;
  height: 100%;
}

.cb-map-pins {
  position: absolute;
  inset: 0;
  pointer-events: none;
}

/* The dot sits exactly on the coordinate. The name arrives on approach,
   because a pill carrying a company name is wider than this card and a pin
   pressed against the border claims a location it is not at. Both names are
   on the readout underneath in any case. */
/* The DOT is what sits on the coordinate, not the pin. The label is laid out
   even while it is invisible, so centring the whole pin put a 164-pixel-wide
   element over the point and left the dot eighty pixels west of the place it
   claimed to mark. The shift is half a dot, and the label hangs off whichever
   side has room. */
.cb-map-pin {
  position: absolute;
  left: var(--x);
  top: var(--y);
  transform: translate(calc(var(--cb-space-3xl) / -2), -50%);
  display: inline-flex;
  align-items: center;
  gap: var(--cb-space-xs);
  padding: 0;
  border: none;
  background: none;
  color: var(--cbc-ink);
  font: var(--cb-font-body);
  font-size: var(--cb-type-xs-size);
  font-weight: var(--cb-font-weight-semibold);
  white-space: nowrap;
  pointer-events: auto;
  cursor: default;
}

.cb-map-dot {
  display: grid;
  place-items: center;
  inline-size: var(--cb-space-3xl);
  block-size: var(--cb-space-3xl);
  border-radius: var(--cb-radius-full);
  border: 2px solid var(--cbc-surface);
  background: var(--cbc-ink);
  color: var(--cbc-surface);
  box-shadow: var(--cbc-shadow);
  transition: transform var(--cb-motion-fast) var(--cbc-spring);
}

.cb-map-pin[data-kind="lead"] .cb-map-dot {
  background: var(--cbc-accent);
  color: var(--cbc-on-accent);
}

.cb-map-pin:hover .cb-map-dot,
.cb-map-pin:focus-visible .cb-map-dot {
  transform: scale(1.12);
}

.cb-map-dot .cb-icon {
  inline-size: var(--cb-space-lg);
  block-size: var(--cb-space-lg);
}

/* The name is laid out but not painted, so revealing it moves nothing. */
.cb-map-tag {
  padding: var(--cb-space-xxs) var(--cb-space-sm);
  border-radius: var(--cb-radius-full);
  background: var(--cbc-surface);
  box-shadow: var(--cbc-shadow);
  opacity: 0;
  transition: opacity var(--cb-motion-fast) var(--cbc-spring);
  pointer-events: none;
}

.cb-map-pin:hover .cb-map-tag,
.cb-map-pin:focus-visible .cb-map-tag {
  opacity: 1;
}

/* Near the right edge the name would run off the card, so it opens the other
   way. The dot does not move: only the side the words come out of. */
.cb-map-pin[data-side="left"] {
  flex-direction: row-reverse;
  transform: translate(calc(-100% + var(--cb-space-3xl) / 2), -50%);
}

.cb-map-pin[data-off] {
  display: none;
}

/* Only up while somebody has tried to zoom without the modifier. */
.cb-map-hint {
  position: absolute;
  inset: auto 0 0 0;
  margin: 0;
  padding: var(--cb-space-sm);
  text-align: center;
  background: color-mix(in srgb, var(--cbc-base) 82%, transparent);
  color: var(--cbc-ink);
  font-size: var(--cb-type-xs-size);
  opacity: 0;
  transition: opacity var(--cb-motion-fast) var(--cbc-spring);
}

.cb-map-stage[data-hint] .cb-map-hint {
  opacity: 1;
}

.cb-map-read {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: var(--cb-space-sm);
  margin: 0;
  padding: var(--cb-space-none) var(--cb-space-lg);
  color: var(--cbc-ink-muted);
  font-size: var(--cb-type-sm-size);
}

.cb-map-read strong {
  color: var(--cbc-ink);
  font-size: var(--cb-type-lg-size);
  font-weight: var(--cb-font-weight-semibold);
}

.cb-map-read .cb-icon {
  color: var(--cbc-accent);
}

.cb-map-read-empty {
  align-items: flex-start;
}

/* Wraps rather than overflowing. This card lives in a 22rem column and the
   row of controls is wider than that, so without a wrap the map ran past the
   edge of its own column and took the fit with it. */
.cb-map-controls {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: var(--cb-space-sm);
  padding: var(--cb-space-none) var(--cb-space-lg) var(--cb-space-lg);
}

.cb-map-zoom {
  display: inline-flex;
  border: 1px solid var(--cbc-line);
  border-radius: var(--cb-radius-md);
  overflow: hidden;
}

.cb-map-btn,
.cb-map-fit {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--cb-space-xs);
  padding: var(--cb-space-xs) var(--cb-space-sm);
  border: none;
  background: transparent;
  color: var(--cbc-ink-muted);
  font: inherit;
  font-size: var(--cb-type-xs-size);
  cursor: pointer;
  transition:
    background var(--cb-motion-fast) var(--cbc-spring),
    color var(--cb-motion-fast) var(--cbc-spring);
}

.cb-map-btn:hover,
.cb-map-fit:hover {
  background: var(--cbc-hover);
  color: var(--cbc-ink);
}

.cb-map-btn + .cb-map-btn {
  border-left: 1px solid var(--cbc-line);
}

.cb-map-fit {
  border: 1px solid var(--cbc-line);
  border-radius: var(--cb-radius-md);
}

.cb-map-out {
  margin-inline-start: auto;
  color: var(--cbc-ink-faint);
  font-size: var(--cb-type-xs-size);
  text-decoration: none;
}

.cb-map-out:hover {
  color: var(--cbc-accent);
  text-decoration: underline;
}

/* ── Who they are ──────────────────────────────────────────────────────────
   A page about a company, not a definition list. The masthead names them,
   their own words are the lede, and the map answers the question a rep
   actually has before dialling: is this a drive or a call.               */

.cb-who {
  display: grid;
  gap: var(--cb-space-xl);
}

.cb-who-source {
  margin: 0;
  color: var(--cbc-ink-faint);
  font-size: var(--cb-type-xs-size);
}

.cb-who-top {
  display: grid;
  gap: var(--cb-space-xl);
  align-items: start;
}

/* Two columns once there is room for the map to be worth drawing.

   900 IS NOT A TOKEN AND THE SCALE DOES NOT MODEL IT. This said "Mirrors
   --cb-width-4xl", which is 1440px, so the comment named a value 540px from
   the one beside it. The exemption a query prelude gets is paid for by this
   comment being true, and a guard satisfied by a comment naming the wrong
   token is one somebody satisfies that way again. The width scale steps 768
   then 1024 and the breakpoints are 480, 768 and 1024, so this is a measured
   place where the map earns its column, sitting between two steps. Moving it
   to 1024 is a real layout change and a separate decision. */
@media (min-width: 900px) {
  .cb-who-top {
    grid-template-columns: minmax(0, 1fr) minmax(0, 22rem);
  }
}

.cb-who-left,
.cb-who-right {
  display: grid;
  gap: var(--cb-space-lg);
  align-content: start;
  min-width: 0;
}

.cb-who-head {
  display: flex;
  align-items: center;
  gap: var(--cb-space-md);
}

.cb-who-mark .cb-site-icon {
  width: var(--cb-space-6xl);
  height: var(--cb-space-6xl);
  font-size: var(--cb-type-lg-size);
}

.cb-who-titles {
  min-width: 0;
}

.cb-who-name {
  margin: 0;
  font-family: var(--cb-font-heading);
  font-size: var(--cb-type-2xl-size);
  line-height: var(--cb-type-2xl-line-height);
  letter-spacing: var(--cb-type-2xl-letter-spacing);
  font-weight: var(--cb-font-weight-semibold);
  color: var(--cbc-ink);
}

.cb-who-trade {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: var(--cb-space-sm);
  margin: var(--cb-space-xxs) var(--cb-space-none) var(--cb-space-none);
  color: var(--cbc-ink-muted);
  font-size: var(--cb-type-sm-size);
}

.cb-who-domain {
  color: var(--cbc-ink-faint);
  text-decoration: none;
}

.cb-who-domain:hover {
  color: var(--cbc-accent);
  text-decoration: underline;
}

.cb-who-legal {
  display: flex;
  align-items: center;
  gap: var(--cb-space-xs);
  margin: var(--cb-space-xxs) var(--cb-space-none) var(--cb-space-none);
  color: var(--cbc-ink-faint);
  font-size: var(--cb-type-xs-size);
}

/* Their own sentence about themselves, which is the only line on the screen
   written by the person about to be called. No accent rail: the size and the
   ink already say it is a quotation. */
.cb-who-lede {
  margin: 0;
  padding: 0;
}

.cb-who-lede p {
  margin: 0;
  color: var(--cbc-ink);
  font-family: var(--cb-font-heading);
  font-size: var(--cb-type-lg-size);
  line-height: var(--cb-type-lg-line-height);
}

.cb-who-lede cite {
  display: flex;
  align-items: center;
  gap: var(--cb-space-xs);
  margin-top: var(--cb-space-sm);
  color: var(--cbc-ink-faint);
  font-size: var(--cb-type-xs-size);
  font-style: normal;
}

.cb-who-reach {
  display: grid;
  gap: var(--cb-space-xxs);
}

.cb-reach-row {
  display: flex;
  align-items: center;
  gap: var(--cb-space-sm);
  padding: var(--cb-space-xs) var(--cb-space-sm);
  border-radius: var(--cb-radius-md);
  transition: background var(--cb-motion-fast) var(--cbc-spring);
}

.cb-reach-row:hover {
  background: var(--cbc-hover);
}

.cb-reach-row > .cb-icon {
  color: var(--cbc-ink-faint);
}

.cb-reach-value {
  color: var(--cbc-ink);
  font-weight: var(--cb-font-weight-medium);
  text-decoration: none;
  overflow-wrap: anywhere;
}

.cb-reach-value:hover {
  color: var(--cbc-accent);
  text-decoration: underline;
}

.cb-reach-where {
  color: var(--cbc-ink-faint);
  font-size: var(--cb-type-xs-size);
}

/* The copy button appears when the row is approached. One affordance, at the
   end of the row it belongs to, and it never moves the layout. */
.cb-reach-copy {
  margin-left: auto;
  display: inline-flex;
  padding: var(--cb-space-xxs);
  border: none;
  border-radius: var(--cb-radius-sm);
  background: transparent;
  color: var(--cbc-ink-faint);
  cursor: pointer;
  opacity: 0;
  transition:
    opacity var(--cb-motion-fast) var(--cbc-spring),
    color var(--cb-motion-fast) var(--cbc-spring);
}

.cb-reach-row:hover .cb-reach-copy,
.cb-reach-copy:focus-visible,
.cb-reach-copy[data-done] {
  opacity: 1;
}

.cb-reach-copy:hover {
  color: var(--cbc-ink);
}

.cb-reach-copy[data-done] {
  color: var(--cbc-good-text);
}

.cb-who-socials {
  display: flex;
  flex-wrap: wrap;
  gap: var(--cb-space-xs);
}

.cb-who-social {
  display: inline-flex;
  align-items: center;
  gap: var(--cb-space-xs);
  padding: var(--cb-space-xs) var(--cb-space-md) var(--cb-space-xs) var(--cb-space-sm);
  border: 1px solid var(--cbc-line);
  border-radius: var(--cb-radius-full);
  color: var(--cbc-ink-muted);
  font-size: var(--cb-type-xs-size);
  text-decoration: none;
  transition:
    border-color var(--cb-motion-fast) var(--cbc-spring),
    color var(--cb-motion-fast) var(--cbc-spring);
}

.cb-who-social:hover {
  border-color: var(--cbc-line-strong);
  color: var(--cbc-ink);
}

.cb-who-social .cb-social-mark {
  width: var(--cb-space-lg);
  height: var(--cb-space-lg);
}

.cb-who-where {
  display: grid;
  gap: var(--cb-space-xs);
}

.cb-who-where-main {
  display: flex;
  align-items: flex-start;
  gap: var(--cb-space-xs);
  margin: 0;
  color: var(--cbc-ink);
  font-size: var(--cb-type-sm-size);
}

.cb-who-where-main > .cb-icon {
  color: var(--cbc-ink-faint);
  flex: none;
}

.cb-who-missing {
  color: var(--cbc-ink-faint);
}

.cb-who-where-more {
  display: grid;
  gap: var(--cb-space-xxs);
  margin: 0;
  color: var(--cbc-ink-faint);
  font-size: var(--cb-type-xs-size);
}

.cb-who-alt {
  color: var(--cbc-ink-muted);
}

.cb-who-blocks {
  display: grid;
  gap: var(--cb-space-lg);
  /* Each block is as tall as its own contents. Stretched to the row, the one
     holding a single chip became a box the height of a paragraph with nothing
     in it, which reads as a panel that failed to render. */
  align-items: start;
}

/* The same measured 900 as .cb-who-top, and not a token: see the note there.
   This one carried no comment at all, which is the exemption taken without
   even the claim. */
@media (min-width: 900px) {
  .cb-who-blocks {
    grid-template-columns: repeat(auto-fit, minmax(18rem, 1fr));
  }
}

.cb-who-block {
  display: grid;
  gap: var(--cb-space-md);
  align-content: start;
  padding: var(--cb-space-lg);
  border: 1px solid var(--cbc-line);
  border-radius: var(--cb-radius-lg);
  background: var(--cbc-surface);
}

.cb-who-block-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--cb-space-sm);
  flex-wrap: wrap;
}

.cb-who-block-title {
  display: flex;
  align-items: center;
  gap: var(--cb-space-xs);
  margin: 0;
  color: var(--cbc-ink-muted);
  font-size: var(--cb-type-xs-size);
  font-weight: var(--cb-font-weight-semibold);
  letter-spacing: var(--cb-tracking-xxs);
  text-transform: uppercase;
}

.cb-who-block-title .cb-social-mark {
  width: var(--cb-space-lg);
  height: var(--cb-space-lg);
}

.cb-tool-grid {
  display: flex;
  flex-wrap: wrap;
  gap: var(--cb-space-xs);
}

.cb-tool {
  display: inline-flex;
  align-items: center;
  gap: var(--cb-space-xs);
  padding: var(--cb-space-xxs) var(--cb-space-sm);
  border: 1px solid var(--cbc-line);
  border-radius: var(--cb-radius-full);
  color: var(--cbc-ink-muted);
  font-size: var(--cb-type-xs-size);
}

.cb-tool-name {
  white-space: nowrap;
}

.cb-tool-mark {
  width: var(--cb-space-lg);
  height: var(--cb-space-lg);
  flex: none;
}

.cb-tool-initials {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: var(--cb-space-lg);
  height: var(--cb-space-lg);
  border-radius: var(--cb-radius-xs);
  background: var(--cbc-hover-strong);
  color: var(--cbc-ink-muted);
  font-size: var(--cb-type-xs-size);
  font-weight: var(--cb-font-weight-semibold);
  flex: none;
}

.cb-built {
  display: flex;
  align-items: center;
  gap: var(--cb-space-md);
}

.cb-built-mark {
  display: inline-flex;
  padding: var(--cb-space-sm);
  border-radius: var(--cb-radius-md);
  background: var(--cbc-hover);
  color: var(--cbc-ink);
}

.cb-built-mark .cb-tool-mark,
.cb-built-mark .cb-tool-initials {
  width: var(--cb-space-2xl);
  height: var(--cb-space-2xl);
}

.cb-built-words {
  min-width: 0;
}

.cb-built-name {
  margin: 0;
  color: var(--cbc-ink);
  font-weight: var(--cb-font-weight-semibold);
}

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

.cb-built-pages {
  margin: 0 0 0 auto;
  text-align: right;
  color: var(--cbc-ink-faint);
  font-size: var(--cb-type-xs-size);
}

.cb-built-pages strong {
  display: block;
  color: var(--cbc-ink);
  font-size: var(--cb-type-lg-size);
}

.cb-tube-name {
  margin: 0;
  color: var(--cbc-ink);
  font-weight: var(--cb-font-weight-semibold);
}

.cb-tube-figures {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: var(--cb-space-sm);
}

.cb-tube-figure strong {
  display: block;
  color: var(--cbc-ink);
  font-family: var(--cb-font-heading);
  font-size: var(--cb-type-xl-size);
  font-variant-numeric: tabular-nums;
}

.cb-tube-figure span {
  color: var(--cbc-ink-faint);
  font-size: var(--cb-type-xs-size);
}

.cb-tube-figure[data-empty] strong {
  color: var(--cbc-ink-faint);
  font-size: var(--cb-type-md-size);
}

.cb-tube-since {
  margin: 0;
  color: var(--cbc-ink-faint);
  font-size: var(--cb-type-xs-size);
}

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

.cb-record-marks {
  display: flex;
  flex-wrap: wrap;
  gap: var(--cb-space-xs);
}

.cb-record-link {
  color: var(--cbc-accent);
  font-size: var(--cb-type-xs-size);
  text-decoration: none;
}

.cb-record-link:hover {
  text-decoration: underline;
}

.cb-gap-row {
  display: flex;
  flex-wrap: wrap;
  gap: var(--cb-space-xs);
}

.cb-gap {
  padding: var(--cb-space-xxs) var(--cb-space-sm);
  border: 1px dashed var(--cbc-line-strong);
  border-radius: var(--cb-radius-full);
  color: var(--cbc-ink-faint);
  font-size: var(--cb-type-xs-size);
}

/* The cover on the profile is a card in a column, not a bleed across the top
   of one. cb-cover carries negative margins for the card it was written for,
   and outside that card they pull it over whatever sits above it. */
.cb-who-cover {
  margin: 0;
  border: 1px solid var(--cbc-line);
  border-radius: var(--cb-radius-lg);
  block-size: auto;
  aspect-ratio: 16 / 10;
}

.cb-who-cover[data-empty] {
  block-size: auto;
  aspect-ratio: 16 / 10;
}

/* ── Share ─────────────────────────────────────────────────────────────────
   The card drawn inside the frame it will actually appear in. The one screen
   in the console whose point is seeing something the way somebody outside
   Candybox will see it.                                                   */

.cb-share {
  display: grid;
  gap: var(--cb-space-xl);
  align-items: start;
}

/* The same measured 900 as .cb-who-top above, and not a token: see the note
   there for why the scale does not model it. */
@media (min-width: 900px) {
  .cb-share {
    grid-template-columns: minmax(0, 1fr) minmax(0, 24rem);
  }
}

.cb-share-preview {
  display: grid;
  gap: var(--cb-space-md);
  min-width: 0;
}

.cb-share-tabs {
  display: flex;
  flex-wrap: wrap;
  gap: var(--cb-space-xs);
}

.cb-share-tab {
  display: inline-flex;
  align-items: center;
  gap: var(--cb-space-xs);
  padding: var(--cb-space-xs) var(--cb-space-md);
  border: 1px solid var(--cbc-line);
  border-radius: var(--cb-radius-full);
  background: transparent;
  color: var(--cbc-ink-faint);
  font: inherit;
  font-size: var(--cb-type-xs-size);
  cursor: pointer;
  transition:
    border-color var(--cb-motion-fast) var(--cbc-spring),
    color var(--cb-motion-fast) var(--cbc-spring),
    background var(--cb-motion-fast) var(--cbc-spring);
}

.cb-share-tab:hover {
  color: var(--cbc-ink);
  border-color: var(--cbc-line-strong);
}

/* The selected frame holds still and the rest step back, rather than the
   selected one shouting. */
.cb-share-tab[aria-selected="true"] {
  background: var(--cbc-hover-strong);
  border-color: var(--cbc-line-strong);
  color: var(--cbc-ink);
}

.cb-share-tab .cb-social-mark {
  width: var(--cb-space-lg);
  height: var(--cb-space-lg);
}

.cb-unfurl {
  max-inline-size: var(--cb-width-lg);
  border: 1px solid var(--cbc-line-strong);
  border-radius: var(--cb-radius-lg);
  background: var(--cbc-surface);
  overflow: hidden;
}

.cb-unfurl[data-surface="whatsapp"] {
  border-radius: var(--cb-radius-md);
}

.cb-unfurl-card {
  display: block;
  inline-size: 100%;
  aspect-ratio: 1200 / 630;
  object-fit: cover;
  background: var(--cbc-sunken);
  border-block-end: 1px solid var(--cbc-line);
}

.cb-unfurl-card[data-empty] {
  display: grid;
  place-items: center;
  align-content: center;
  gap: var(--cb-space-sm);
  padding: var(--cb-space-xl);
  text-align: center;
  color: var(--cbc-ink-faint);
  font-size: var(--cb-type-xs-size);
}

.cb-unfurl-words {
  display: grid;
  gap: var(--cb-space-xxs);
  padding: var(--cb-space-md) var(--cb-space-lg) var(--cb-space-lg);
}

.cb-unfurl-domain {
  margin: 0;
  color: var(--cbc-ink-faint);
  font-size: var(--cb-type-xs-size);
  letter-spacing: var(--cb-type-xs-letter-spacing);
}

.cb-unfurl-title {
  margin: 0;
  color: var(--cbc-ink);
  font-weight: var(--cb-font-weight-semibold);
  font-size: var(--cb-type-md-size);
}

.cb-unfurl-text {
  margin: 0;
  color: var(--cbc-ink-muted);
  font-size: var(--cb-type-sm-size);
  line-height: var(--cb-type-sm-line-height);
  /* Every one of these surfaces truncates. A preview that shows the whole
     description is a preview of something nobody will ever see. */
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}

.cb-share-side {
  display: grid;
  gap: var(--cb-space-lg);
  align-content: start;
  min-width: 0;
}

.cb-share-link {
  display: grid;
  gap: var(--cb-space-xs);
  min-width: 0;
}

.cb-share-link-label {
  display: flex;
  align-items: center;
  gap: var(--cb-space-xs);
  margin: 0;
  color: var(--cbc-ink-muted);
  font-size: var(--cb-type-xs-size);
  font-weight: var(--cb-font-weight-semibold);
  text-transform: uppercase;
  letter-spacing: var(--cb-tracking-xxs);
}

.cb-share-link-row {
  display: flex;
  align-items: center;
  gap: var(--cb-space-xs);
  padding: var(--cb-space-xxs) var(--cb-space-xs) var(--cb-space-xxs) var(--cb-space-sm);
  border: 1px solid var(--cbc-line);
  border-radius: var(--cb-radius-md);
  background: var(--cbc-sunken);
}

.cb-share-link-value {
  flex: 1;
  min-width: 0;
  border: none;
  background: transparent;
  color: var(--cbc-ink);
  font-family: var(--cb-font-mono);
  font-size: var(--cb-type-xs-size);
  text-overflow: ellipsis;
}

.cb-share-link-value:focus-visible {
  outline: none;
}

/* The copy button on a link row is always there: unlike a contact row, this
   is the whole reason the row exists. */
.cb-share-link-row .cb-reach-copy {
  opacity: 1;
  margin-left: 0;
}

.cb-share-open {
  display: inline-flex;
  padding: var(--cb-space-xxs);
  border-radius: var(--cb-radius-sm);
  color: var(--cbc-ink-faint);
}

.cb-share-open:hover {
  color: var(--cbc-ink);
}

.cb-share-link-note {
  margin: 0;
  color: var(--cbc-ink-faint);
  font-size: var(--cb-type-xs-size);
}

.cb-share-card-open {
  justify-self: start;
  padding: var(--cb-space-xs) var(--cb-space-md);
  border: 1px solid var(--cbc-line);
  border-radius: var(--cb-radius-md);
  background: transparent;
  color: var(--cbc-ink-muted);
  font: inherit;
  font-size: var(--cb-type-xs-size);
  cursor: pointer;
  transition:
    border-color var(--cb-motion-fast) var(--cbc-spring),
    color var(--cb-motion-fast) var(--cbc-spring);
}

.cb-share-card-open:hover {
  border-color: var(--cbc-line-strong);
  color: var(--cbc-ink);
}

/* A capture that will not load. It happens for ordinary reasons: a signed link
   expires within the hour, a raw capture ages out at ninety days, and a scan
   can write a file with nothing in it. Any of those drawn as a torn-page icon
   reads as a bug in this screen rather than as a fact about the scan. */
.cb-plate[data-gone] {
  cursor: default;
}
.cb-plate-gone {
  display: grid;
  place-items: center;
  align-content: center;
  gap: var(--cb-space-sm);
  aspect-ratio: 4 / 3;
  padding: var(--cb-space-md);
  text-align: center;
  border: 1px dashed var(--cbc-line-strong);
  border-radius: var(--cb-radius-xl);
  background: var(--cbc-sunken);
  color: var(--cbc-ink-faint);
  font-size: var(--cb-type-xs-size);
}
.cb-plate[data-view="mobile"] .cb-plate-gone {
  aspect-ratio: 3 / 4;
}
.cb-plate[data-gone] .cb-plate-name {
  color: var(--cbc-ink-faint);
}

/* ---- Today's look ----
   Two plates side by side, or one with the changed blocks painted over it.
   The frame holds its aspect ratio so the difference grid, which is absolutely
   positioned inside it, cannot drift out of register with the picture: the
   grid is 24 by 15 cells of the SAME box the image fills, so as long as they
   share a container they scale together for free. */
.cb-look-plates {
  display: grid;
  /* A width token, because this is a minimum COLUMN WIDTH rather than a gap.
     It named `--cb-space-14xl`, which the scale stops short of, so the whole
     declaration was dropped and the two plates never had a wrapping point:
     they simply sat side by side however narrow the panel got. */
  grid-template-columns: repeat(auto-fit, minmax(var(--cb-width-xxs), 1fr));
  gap: var(--cb-space-3xl);
}
.cb-look-plate {
  margin: 0;
  display: grid;
  gap: var(--cb-space-md);
}
.cb-look-frame {
  position: relative;
  aspect-ratio: 16 / 10;
  overflow: hidden;
  border: 1px solid var(--cbc-line);
  border-radius: var(--cb-radius-lg);
  background: var(--cbc-sunken);
}
.cb-look-image {
  inline-size: 100%;
  block-size: 100%;
  object-fit: cover;
  object-position: top;
  display: block;
}

/* The changed blocks. A grid of cells over the picture rather than a canvas:
   it scales with the plate for free and needs no second drawing surface to
   keep in step with an image whose size the layout decides. */
.cb-look-diff {
  position: absolute;
  inset: 0;
  display: grid;
  grid-template-columns: repeat(24, 1fr);
  grid-template-rows: repeat(15, 1fr);
  pointer-events: none;
}
/* Washed rather than solid: the point is to see WHERE the change is on the
   page, which needs the page underneath to still be readable. */
.cb-look-diff span[data-changed] {
  background: color-mix(in srgb, var(--cbc-accent) 45%, transparent);
  outline: 1px solid var(--cbc-accent);
}
.cb-look-caption {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--cb-space-lg);
  font-size: var(--cb-type-sm-size);
  font-weight: var(--cb-font-weight-medium);
  color: var(--cbc-ink);
}
.cb-look-when {
  font-weight: var(--cb-font-weight-regular);
  color: var(--cbc-ink-faint);
}

/* ---- The QBR brief ----
   Built to be PRINTED, which is a different thing from built to be looked at.
   Nothing here collapses, nothing hides behind a hover, and the coverage block
   is plain text in the flow of the page: a caveat that has to be clicked open
   travels nowhere with the number it qualifies. */
/* Three across, not three down. The minimum is the width of the widest
   figure's own note rather than a guess: too large and auto-fit gives up and
   stacks them, which is what the first version did. */
.cb-qbr-headline {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(var(--cb-space-11xl), 1fr));
  gap: var(--cb-space-4xl);
}
/* The one sentence on the page whose job is to stop somebody sending it on.
   In the flow rather than in the page head, where the blurb clamps: a
   truncated warning is a warning that did not work. */
.cb-qbr-internal {
  padding: var(--cb-space-lg) var(--cb-space-2xl);
  border-radius: var(--cb-radius-md);
  background: var(--cbc-sunken);
  font-size: var(--cb-type-sm-size);
  color: var(--cbc-ink-muted);
}
.cb-qbr-internal strong {
  color: var(--cbc-ink);
}
.cb-qbr-figure {
  display: grid;
  gap: var(--cb-space-xs);
}
.cb-qbr-label {
  font-size: var(--cb-type-xs-size);
  letter-spacing: var(--cb-tracking-xxs);
  text-transform: uppercase;
  color: var(--cbc-ink-faint);
}
.cb-qbr-value {
  font-size: var(--cb-type-3xl-size);
  line-height: var(--cb-type-3xl-line-height);
  font-weight: var(--cb-font-weight-semibold);
  font-variant-numeric: tabular-nums;
  color: var(--cbc-ink);
}
.cb-qbr-note {
  font-size: var(--cb-type-sm-size);
  color: var(--cbc-ink-muted);
}

/* A dash that says why. On a printed page there is nothing to hover, so the
   reason is also the element's own title: a dash with no account of itself is
   the thing somebody reads as a zero. */
.cb-qbr-blank {
  text-decoration: none;
  border-block-end: 1px dotted var(--cbc-line-strong);
  color: var(--cbc-ink-faint);
  cursor: help;
}

.cb-qbr-coverage {
  display: grid;
  gap: var(--cb-space-md);
}
.cb-qbr-coverage h2 {
  font-size: var(--cb-type-md-size);
  font-weight: var(--cb-font-weight-semibold);
  color: var(--cbc-ink);
}
.cb-qbr-coverage p {
  font-size: var(--cb-type-sm-size);
  color: var(--cbc-ink-muted);
}

@media print {
  /* The one control on the page is the browser's own Save as PDF, and it does
     not belong on the paper it produces. */
  .cb-qbr ~ * .cb-btn,
  .cb-page-head .cb-btn {
    display: none;
  }
  /* Never split a figure or the block that qualifies it across a page. */
  .cb-qbr-figure,
  .cb-qbr-coverage {
    break-inside: avoid;
  }
}

/* ---- The day's looks ----
   One card per site, with its own comparison on it. Behind a click this screen
   would be a list of twenty links, and the question it exists to answer is
   answered by looking rather than by reading a number. */
.cb-look-row {
  display: grid;
  gap: var(--cb-space-lg);
  padding: var(--cb-space-2xl) 0;
}
.cb-look-row + .cb-look-row {
  border-block-start: 1px solid var(--cbc-line);
}
.cb-look-row-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--cb-space-lg);
  flex-wrap: wrap;
}
.cb-look-numbers {
  display: flex;
  flex-wrap: wrap;
  gap: var(--cb-space-md) var(--cb-space-3xl);
  font-size: var(--cb-type-sm-size);
  color: var(--cbc-ink-muted);
}
.cb-look-numbers strong {
  color: var(--cbc-ink);
  font-variant-numeric: tabular-nums;
}
