/* ==========================================================================
   app.css — the dashboard shell and the screen-level components.

   WHAT: everything the logged-in product needs that the brand system does not
   already ship: the app frame (top bar, navigation, page header), the wizard
   step rail, the prompt x engine matrix, the action queue, the copy control.

   WHY a second stylesheet instead of extending components.css: components.css
   is embedded inside white-labelled PDFs and pages we do not own, so it must
   stay free of anything app-shaped. This file is only ever served to a logged-in
   customer at /static/css/app.css.

   RULES this file obeys (BRAND.md 3.5 / 4.6):
     * only LAYER 2 semantic tokens (--cp-color-*) and LAYER 3 system tokens are
       referenced. No raw hex, no primitive scale.
     * mobile-first: the base rules ARE the 390px rules; media queries only add.
     * every interactive target is at least --cp-tap-min (44px).
     * no data is drawn as the hatch (--cp-pattern-nodata), never as a zero.
     * motion is opacity/transform only, 90-320ms, disabled by reduced-motion.
   Load order: fonts.css -> tokens.css -> components.css -> app.css
   ========================================================================== */

/* ==========================================================================
   1. APP FRAME
   Phone: a fixed top bar, the page, and a fixed bottom tab bar (thumb reach).
   Desktop (>=960px): the tab bar becomes a left rail and the top bar keeps the
   workspace switcher, so the primary navigation is visible without a menu tap.
   ========================================================================== */

/* Keyboard-only escape hatch past the navigation. Parked off-screen until it is
   focused — never `.cp-visually-hidden`, which would leave a 1px interactive
   target behind and fail the 44px tap-target gate for a real reason. */
.cp-skip {
  position: absolute;
  left: var(--cp-space-2);
  top: -100px;
  z-index: var(--cp-z-modal);
  display: inline-flex;
  align-items: center;
  min-height: var(--cp-tap-min);
  padding: 0 var(--cp-space-4);
  border-radius: var(--cp-radius-md);
  background: var(--cp-color-surface-inverse);
  color: var(--cp-color-text-inverse);
  font-size: var(--cp-text-sm);
  font-weight: var(--cp-weight-medium);
  text-decoration: none;
  transition: top var(--cp-duration-fast) var(--cp-ease-out);
}
.cp-skip:focus { top: var(--cp-space-2); }

.cp-app {
  min-height: 100dvh;
  display: flex;
  flex-direction: column;
  background: var(--cp-color-bg);
}

.cp-app__main {
  flex: 1 1 auto;
  width: 100%;
  /* Clear the fixed tab bar + the iOS home indicator. Measured: the bar is 71px
     at 390px, so 72px left exactly 1px of daylight under the last card — the
     extra space is the difference between "technically not covered" and
     "obviously not covered". */
  padding-bottom: calc(72px + var(--cp-space-5) + env(safe-area-inset-bottom, 0px));
}

/* ---- top bar ---- */

.cp-topbar {
  position: sticky;
  top: 0;
  z-index: var(--cp-z-sticky);
  display: flex;
  align-items: center;
  /* The switcher takes its own full-width row on a phone — see .cp-switcher. */
  flex-wrap: wrap;
  gap: var(--cp-space-2) var(--cp-space-3);
  min-height: 56px;
  padding: var(--cp-space-2) var(--cp-gutter);
  background: var(--cp-color-surface);
  border-bottom: var(--cp-hairline) solid var(--cp-color-border);
}

.cp-topbar__brand {
  display: inline-flex;
  align-items: center;
  gap: var(--cp-space-2);
  min-height: var(--cp-tap-min);
  min-width: var(--cp-tap-min);
  text-decoration: none;
  color: var(--cp-color-text);
  flex: none;
}
/* Size only. `display` is DELIBERATELY not set here: components.css hides the
   wrong-theme mark with `.cp-logo--dark { display: none }` (specificity 0-1-0),
   and an element selector like `.cp-topbar__brand img` (0-1-1) in a later sheet
   would beat it and paint BOTH marks. Proved in the browser: two .cp-logo nodes
   both computed `display: block` at 390px, so the inverse mark's paper brackets
   vanished into the page and its cobalt tick floated beside the real logo. */
.cp-topbar__brand img { width: 28px; height: 28px; }
.cp-topbar__brand span {
  font-weight: var(--cp-weight-semibold);
  letter-spacing: var(--cp-tracking-tight);
  font-size: var(--cp-text-base);
}

.cp-topbar__spacer { flex: 1 1 auto; }

/* The workspace switcher is the single most-used control for an agency account
   manager, so it is a real <select> — native, keyboard-safe, 44px, no JS menu. */
/* Full width on its own row below 640px. Measured at 390px it was 66px wide and
   printed "Nor" — a switcher that cannot tell you which brand you are looking at
   is worse than no switcher, and this is the control an agency uses most. */
.cp-switcher {
  position: relative;
  display: flex;
  align-items: center;
  min-width: 0;
  order: 10;
  flex: 1 0 100%;
}
.cp-switcher select {
  width: 100%;
  min-height: var(--cp-tap-min);
  padding: 0 var(--cp-space-8) 0 var(--cp-space-3);
  font-size: var(--cp-text-sm);
  font-weight: var(--cp-weight-medium);
  border-radius: var(--cp-radius-md);
}
@media (min-width: 640px) {
  .cp-switcher { order: 0; flex: 0 1 auto; }
  .cp-switcher select { width: auto; max-width: 44vw; }
}
@media (min-width: 960px) {
  .cp-switcher select { max-width: 320px; }
}

.cp-topbar__link {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--cp-space-2);
  min-height: var(--cp-tap-min);
  min-width: var(--cp-tap-min);
  padding: 0 var(--cp-space-2);
  border-radius: var(--cp-radius-md);
  color: var(--cp-color-text-muted);
  text-decoration: none;
  transition: var(--cp-transition-colors);
}
.cp-topbar__link:hover { color: var(--cp-color-text); background: var(--cp-color-bg-subtle); }
.cp-topbar__link svg { width: 20px; height: 20px; flex: none; }

/* ---- navigation ---- */

.cp-nav {
  position: fixed;
  left: 0; right: 0; bottom: 0;
  z-index: var(--cp-z-sticky);
  display: flex;
  align-items: stretch;
  background: var(--cp-color-surface);
  border-top: var(--cp-hairline) solid var(--cp-color-border);
  padding-bottom: env(safe-area-inset-bottom, 0px);
}

.cp-nav__link {
  flex: 1 1 0;
  min-width: 0;
  min-height: 60px;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 3px;
  padding: var(--cp-space-1) 2px;
  text-decoration: none;
  color: var(--cp-color-text-subtle);
  font-size: var(--cp-text-2xs);
  font-weight: var(--cp-weight-medium);
  letter-spacing: var(--cp-tracking-normal);
  border-top: 2px solid transparent;
  transition: var(--cp-transition-colors);
}
.cp-nav__link svg { width: 22px; height: 22px; flex: none; }
.cp-nav__label { max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.cp-nav__link:hover { color: var(--cp-color-text); }
.cp-nav__link--active {
  color: var(--cp-color-primary-text);
  border-top-color: var(--cp-color-primary);
  background: var(--cp-color-primary-bg);
}

/* A count rides the nav item so "how much work is waiting" is answerable
   without opening the screen. It is omitted entirely when zero — a "0" badge
   is noise. */
.cp-nav__count {
  font-family: var(--cp-font-mono);
  font-size: var(--cp-text-2xs);
  font-weight: var(--cp-weight-semibold);
  line-height: 1;
  padding: 2px 5px;
  border-radius: var(--cp-radius-full);
  background: var(--cp-color-primary);
  color: var(--cp-color-text-on-primary);
}

@media (min-width: 960px) {
  .cp-app { flex-direction: column; }
  .cp-app__body { display: flex; align-items: flex-start; gap: 0; }
  .cp-app__main { padding-bottom: var(--cp-space-16); min-width: 0; flex: 1 1 auto; }

  .cp-nav {
    position: sticky;
    top: 56px;
    bottom: auto;
    left: auto; right: auto;
    flex-direction: column;
    align-items: stretch;
    width: 232px;
    flex: none;
    height: calc(100dvh - 56px);
    padding: var(--cp-space-4) var(--cp-space-3);
    gap: var(--cp-space-px);
    border-top: 0;
    border-right: var(--cp-hairline) solid var(--cp-color-border);
    background: var(--cp-color-bg-subtle);
  }
  .cp-nav__link {
    flex: none;
    flex-direction: row;
    justify-content: flex-start;
    gap: var(--cp-space-3);
    min-height: var(--cp-tap-min);
    padding: 0 var(--cp-space-3);
    font-size: var(--cp-text-sm);
    border-top: 0;
    border-radius: var(--cp-radius-md);
  }
  .cp-nav__link--active { background: var(--cp-color-primary-bg); }
  .cp-nav__count { margin-left: auto; }
  .cp-nav__group {
    margin-top: var(--cp-space-5);
    padding: 0 var(--cp-space-3) var(--cp-space-2);
    font-size: var(--cp-text-2xs);
    font-weight: var(--cp-weight-semibold);
    letter-spacing: var(--cp-tracking-caps);
    text-transform: uppercase;
    color: var(--cp-color-text-subtle);
  }
}
@media (max-width: 959px) {
  .cp-nav__group { display: none; }
}

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

.cp-page {
  width: 100%;
  max-width: var(--cp-container);
  margin: 0 auto;
  padding: var(--cp-space-5) var(--cp-gutter) var(--cp-space-10);
}
.cp-page--wide { max-width: var(--cp-container-wide); }
.cp-page--narrow { max-width: var(--cp-container-narrow); }

.cp-page__head {
  display: flex;
  flex-direction: column;
  gap: var(--cp-space-2);
  margin-bottom: var(--cp-space-5);
}
.cp-page__title { font-size: var(--cp-text-2xl); line-height: var(--cp-leading-tight); letter-spacing: var(--cp-tracking-tight); margin: 0; }
.cp-page__sub { color: var(--cp-color-text-muted); font-size: var(--cp-text-sm); margin: 0; }
@media (min-width: 960px) {
  .cp-page__head { flex-direction: row; align-items: flex-end; justify-content: space-between; gap: var(--cp-space-5); }
  .cp-page__title { font-size: var(--cp-text-3xl); }
}

/* The demo banner is deliberately loud: fixture numbers must never be mistaken
   for a customer's measurement. */
.cp-demo-banner {
  display: flex;
  align-items: center;
  gap: var(--cp-space-2);
  padding: var(--cp-space-2) var(--cp-gutter);
  background: var(--cp-color-warn-bg);
  border-bottom: var(--cp-hairline) solid var(--cp-color-warn-border);
  color: var(--cp-color-warn-text);
  font-family: var(--cp-font-mono);
  font-size: var(--cp-text-2xs);
  font-weight: var(--cp-weight-semibold);
  letter-spacing: var(--cp-tracking-caps);
  text-transform: uppercase;
}

/* ==========================================================================
   2. OVERVIEW — the five-second read
   One headline reading, its interval, its sample size, one verdict, one next
   action. Everything else is below the fold by construction.
   ========================================================================== */

.cp-hero {
  display: flex;
  flex-direction: column;
  gap: var(--cp-space-4);
  padding: var(--cp-space-5);
  background: var(--cp-color-surface);
  border: var(--cp-hairline) solid var(--cp-color-border);
  border-radius: var(--cp-radius-lg);
  box-shadow: var(--cp-shadow-xs);
}
.cp-hero__label {
  font-size: var(--cp-text-2xs);
  font-weight: var(--cp-weight-semibold);
  letter-spacing: var(--cp-tracking-caps);
  text-transform: uppercase;
  color: var(--cp-color-text-subtle);
}
.cp-hero__row { display: flex; flex-wrap: wrap; align-items: flex-end; gap: var(--cp-space-4); }
.cp-hero__facts { display: flex; flex-direction: column; gap: var(--cp-space-1); }
.cp-hero__fact { font-family: var(--cp-font-mono); font-size: var(--cp-text-xs); color: var(--cp-color-text-muted); }
.cp-hero__reason {
  max-width: var(--cp-measure);
  font-size: var(--cp-text-sm);
  line-height: var(--cp-leading-normal);
  color: var(--cp-color-text-muted);
}

.cp-engine-name { font-family: var(--cp-font-mono); font-size: var(--cp-text-sm); white-space: nowrap; }

/* ---- trend chart (server-rendered SVG, no library) ---- */

.cp-chart { width: 100%; }
.cp-chart__svg { display: block; width: 100%; height: auto; overflow: visible; }
.cp-chart__grid { stroke: var(--cp-color-border-subtle); stroke-width: 1; }
.cp-chart__line { fill: none; stroke: var(--cp-color-primary); stroke-width: 2.5; stroke-linejoin: round; stroke-linecap: round; }
.cp-chart__dot { fill: var(--cp-color-surface); stroke: var(--cp-color-primary); stroke-width: 2.5; }
/* A period we could not read.
   `fill` is DELIBERATELY not declared here. The template paints the band with
   fill="url(#cp-hatch-trend)" as a presentation attribute, and ANY fill in CSS
   beats a presentation attribute — this rule used to set a flat colour, which
   erased the hatch and turned "no reading was taken" into what looks like a
   measured void. That is the exact lie this product is sold against, rendered
   in our own UI. `color` is set because the pattern's strokes use currentColor. */
.cp-chart__band {
  color: var(--cp-color-nodata-hatch);
  stroke: var(--cp-color-nodata-border);
  stroke-width: 1;
  stroke-dasharray: 3 3;
}
/* Period labels are HTML, one column per period, so they hold ONE readable size
   at every viewport instead of scaling with the viewBox. */
.cp-chart__ticks {
  display: grid;
  grid-auto-flow: column;
  grid-auto-columns: 1fr;
  gap: var(--cp-space-1);
  margin-top: var(--cp-space-2);
}
.cp-chart__tick {
  font-family: var(--cp-font-mono);
  font-size: var(--cp-text-2xs);
  color: var(--cp-color-text-subtle);
  text-align: center;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.cp-chart__tick--nodata { color: var(--cp-color-nodata-text); }
.cp-chart__axis { fill: var(--cp-color-text-subtle); font-family: var(--cp-font-mono); font-size: 10px; }
.cp-chart__legend {
  display: flex;
  flex-wrap: wrap;
  gap: var(--cp-space-4);
  margin-top: var(--cp-space-3);
  font-size: var(--cp-text-xs);
  color: var(--cp-color-text-muted);
}
.cp-chart__key { display: inline-flex; align-items: center; gap: var(--cp-space-2); }
.cp-chart__swatch { width: 16px; height: 10px; border-radius: 2px; background: var(--cp-color-primary); flex: none; }
.cp-chart__swatch--nodata { background: var(--cp-pattern-nodata); border: var(--cp-hairline) dashed var(--cp-color-nodata-border); }

/* ==========================================================================
   3. CRAWLER ACCESS (Tier-0)
   The retrieval/training distinction is the reason to buy us, so it is spelled
   out on every row rather than collapsed into one "blocked" badge.
   ========================================================================== */

.cp-bot { font-family: var(--cp-font-mono); font-size: var(--cp-text-sm); white-space: nowrap; }
.cp-bot-class {
  font-family: var(--cp-font-mono);
  font-size: var(--cp-text-2xs);
  letter-spacing: var(--cp-tracking-caps);
  text-transform: uppercase;
  color: var(--cp-color-text-subtle);
}
.cp-state { display: inline-flex; align-items: center; gap: var(--cp-space-2); font-size: var(--cp-text-sm); }
.cp-state__dot { width: 10px; height: 10px; border-radius: var(--cp-radius-full); flex: none; }
.cp-state--reachable .cp-state__dot { background: var(--cp-color-proof); }
.cp-state--blocked .cp-state__dot { background: var(--cp-color-negative); }
.cp-state--unknown .cp-state__dot { background: var(--cp-pattern-nodata-dense); border: var(--cp-hairline) dashed var(--cp-color-nodata-border); }

/* ==========================================================================
   4. ACTIONS — the queue and the Action Package
   Each row is a <details>: the package opens in place with no JS and no route
   change, so an account manager never loses the queue.
   ========================================================================== */

.cp-queue { display: flex; flex-direction: column; gap: var(--cp-space-3); }

.cp-action {
  background: var(--cp-color-surface);
  border: var(--cp-hairline) solid var(--cp-color-border);
  border-radius: var(--cp-radius-lg);
  box-shadow: var(--cp-shadow-xs);
  overflow: hidden;
}
.cp-action[open] { border-color: var(--cp-color-border-strong); box-shadow: var(--cp-shadow-sm); }

/* Anti-waste findings read as an instruction to STOP, not as another task. */
.cp-action--anti-waste { border-style: dashed; background: var(--cp-color-bg-subtle); }

.cp-action__summary {
  display: flex;
  gap: var(--cp-space-3);
  align-items: flex-start;
  padding: var(--cp-space-4);
  min-height: var(--cp-tap-min);
  cursor: pointer;
  list-style: none;
  transition: var(--cp-transition-colors);
}
.cp-action__summary::-webkit-details-marker { display: none; }
.cp-action__summary:hover { background: var(--cp-color-bg-subtle); }
.cp-action__summary:focus-visible { outline: none; box-shadow: var(--cp-shadow-focus); }

.cp-action__chevron {
  flex: none;
  width: 20px; height: 20px;
  margin-top: 2px;
  color: var(--cp-color-text-subtle);
  transition: transform var(--cp-duration-fast) var(--cp-ease-out);
}
.cp-action[open] .cp-action__chevron { transform: rotate(90deg); }

.cp-action__head { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; gap: var(--cp-space-2); }
.cp-action__title {
  font-size: var(--cp-text-base);
  font-weight: var(--cp-weight-semibold);
  line-height: var(--cp-leading-snug);
  letter-spacing: var(--cp-tracking-tight);
  color: var(--cp-color-text);
  margin: 0;
}
.cp-action__meta {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--cp-space-2) var(--cp-space-3);
  font-size: var(--cp-text-xs);
  color: var(--cp-color-text-muted);
}
.cp-action__meta-item { display: inline-flex; align-items: center; gap: var(--cp-space-1); white-space: nowrap; }
.cp-action__meta-item svg { width: 14px; height: 14px; flex: none; color: var(--cp-color-text-subtle); }

.cp-action__body {
  padding: 0 var(--cp-space-4) var(--cp-space-4);
  border-top: var(--cp-hairline) solid var(--cp-color-border-subtle);
  animation: cp-reveal var(--cp-duration-base) var(--cp-ease-out);
}
@keyframes cp-reveal { from { opacity: 0; transform: translateY(-4px); } to { opacity: 1; transform: none; } }

.cp-action__section { padding-top: var(--cp-space-5); }
.cp-action__section-title {
  display: flex;
  align-items: baseline;
  gap: var(--cp-space-2);
  font-size: var(--cp-text-2xs);
  font-weight: var(--cp-weight-semibold);
  letter-spacing: var(--cp-tracking-caps);
  text-transform: uppercase;
  color: var(--cp-color-text-subtle);
  margin: 0 0 var(--cp-space-2);
}

/* The status rail. Four fixed states; "verified" is never clickable because it
   is earned by a re-measurement. */
.cp-flow { display: flex; align-items: center; gap: var(--cp-space-1); flex-wrap: wrap; }
.cp-flow__step {
  display: inline-flex;
  align-items: center;
  gap: var(--cp-space-1);
  font-family: var(--cp-font-mono);
  font-size: var(--cp-text-2xs);
  letter-spacing: var(--cp-tracking-wide);
  text-transform: uppercase;
  color: var(--cp-color-text-subtle);
}
.cp-flow__dot {
  width: 8px; height: 8px;
  border-radius: var(--cp-radius-full);
  border: var(--cp-hairline) solid var(--cp-color-border-strong);
  background: var(--cp-color-surface);
  flex: none;
}
.cp-flow__step--done { color: var(--cp-color-text-muted); }
.cp-flow__step--done .cp-flow__dot { background: var(--cp-color-text-muted); border-color: var(--cp-color-text-muted); }
.cp-flow__step--current { color: var(--cp-color-primary-text); font-weight: var(--cp-weight-semibold); }
.cp-flow__step--current .cp-flow__dot { background: var(--cp-color-primary); border-color: var(--cp-color-primary); }
.cp-flow__sep { color: var(--cp-color-border-strong); }

/* ---- code + copy ---- */

.cp-code {
  position: relative;
  border: var(--cp-hairline) solid var(--cp-color-border);
  border-radius: var(--cp-radius-md);
  background: var(--cp-color-surface-sunken);
  overflow: hidden;
}
.cp-code__bar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--cp-space-2);
  padding: var(--cp-space-2) var(--cp-space-2) var(--cp-space-2) var(--cp-space-3);
  border-bottom: var(--cp-hairline) solid var(--cp-color-border-subtle);
  background: var(--cp-color-bg-subtle);
}
.cp-code__label {
  font-family: var(--cp-font-mono);
  font-size: var(--cp-text-2xs);
  letter-spacing: var(--cp-tracking-caps);
  text-transform: uppercase;
  color: var(--cp-color-text-subtle);
}
.cp-code__body { margin: 0; padding: var(--cp-space-3); overflow-x: auto; }
.cp-code__body pre { margin: 0; }

.cp-copy {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--cp-space-2);
  min-height: var(--cp-tap-min);
  min-width: var(--cp-tap-min);
  padding: 0 var(--cp-space-3);
  border: var(--cp-hairline) solid var(--cp-color-border-strong);
  border-radius: var(--cp-radius-md);
  background: var(--cp-color-surface);
  color: var(--cp-color-text);
  font: inherit;
  font-size: var(--cp-text-xs);
  font-weight: var(--cp-weight-medium);
  cursor: pointer;
  transition: var(--cp-transition-colors);
}
.cp-copy:hover { background: var(--cp-color-bg-subtle); }
.cp-copy svg { width: 15px; height: 15px; flex: none; }
.cp-copy[data-cp-copied="1"] {
  border-color: var(--cp-color-proof-border);
  background: var(--cp-color-proof-bg);
  color: var(--cp-color-proof-text);
}

/* ---- evidence ---- */

.cp-kv { display: flex; flex-wrap: wrap; gap: var(--cp-space-2); margin: 0; }
.cp-kv__item {
  display: inline-flex;
  align-items: baseline;
  gap: var(--cp-space-2);
  padding: var(--cp-space-1) var(--cp-space-3);
  border: var(--cp-hairline) solid var(--cp-color-border);
  border-radius: var(--cp-radius-sm);
  background: var(--cp-color-bg-subtle);
  font-family: var(--cp-font-mono);
  font-size: var(--cp-text-xs);
}
.cp-kv__key { color: var(--cp-color-text-subtle); }
.cp-kv__val { color: var(--cp-color-text); font-weight: var(--cp-weight-medium); }

/* ---- filters ---- */

.cp-filters {
  display: flex;
  gap: var(--cp-space-2);
  margin-bottom: var(--cp-space-4);
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;
  scrollbar-width: none;
  padding-bottom: 2px;
}
.cp-filters::-webkit-scrollbar { display: none; }
.cp-chip {
  display: inline-flex;
  align-items: center;
  gap: var(--cp-space-2);
  min-height: var(--cp-tap-min);
  padding: 0 var(--cp-space-4);
  border: var(--cp-hairline) solid var(--cp-color-border);
  border-radius: var(--cp-radius-full);
  background: var(--cp-color-surface);
  color: var(--cp-color-text-muted);
  font-size: var(--cp-text-sm);
  font-weight: var(--cp-weight-medium);
  text-decoration: none;
  white-space: nowrap;
  flex: none;
  cursor: pointer;
  transition: var(--cp-transition-colors);
}
.cp-chip:hover { background: var(--cp-color-bg-subtle); color: var(--cp-color-text); }
.cp-chip--active {
  background: var(--cp-color-surface-inverse);
  border-color: var(--cp-color-surface-inverse);
  color: var(--cp-color-text-inverse);
}
.cp-chip__count { font-family: var(--cp-font-mono); font-size: var(--cp-text-xs); opacity: 0.75; }

/* ==========================================================================
   5. PROMPT x ENGINE MATRIX
   Desktop: a grid. Phone: one record per prompt with a row per engine — never a
   side-scrolling grid, because reading the answer IS the feature.
   ========================================================================== */

.cp-matrix { display: flex; flex-direction: column; gap: var(--cp-space-3); }

.cp-prompt {
  background: var(--cp-color-surface);
  border: var(--cp-hairline) solid var(--cp-color-border);
  border-radius: var(--cp-radius-lg);
  box-shadow: var(--cp-shadow-xs);
  overflow: hidden;
}
.cp-prompt__head { padding: var(--cp-space-4); display: flex; flex-direction: column; gap: var(--cp-space-2); }
.cp-prompt__text {
  font-family: var(--cp-font-mono);
  font-size: var(--cp-text-sm);
  line-height: var(--cp-leading-snug);
  color: var(--cp-color-text);
  margin: 0;
  overflow-wrap: anywhere;
}
.cp-prompt__meta { display: flex; flex-wrap: wrap; align-items: center; gap: var(--cp-space-2) var(--cp-space-3); font-size: var(--cp-text-xs); color: var(--cp-color-text-muted); }
.cp-prompt__cells { display: flex; flex-direction: column; border-top: var(--cp-hairline) solid var(--cp-color-border-subtle); }

.cp-cell { border-bottom: var(--cp-hairline) solid var(--cp-color-border-subtle); }
.cp-cell:last-child { border-bottom: 0; }
.cp-cell__summary {
  display: flex;
  align-items: center;
  gap: var(--cp-space-3);
  min-height: var(--cp-tap-min);
  padding: var(--cp-space-2) var(--cp-space-4);
  cursor: pointer;
  list-style: none;
  transition: var(--cp-transition-colors);
}
.cp-cell__summary::-webkit-details-marker { display: none; }
/* A cell with no answer has nothing to open: same row, no pointer, no hover. */
.cp-cell__summary--static { cursor: default; }
.cp-cell__summary--static:hover { background: transparent; }
.cp-cell__summary:hover { background: var(--cp-color-bg-subtle); }
.cp-cell__summary:focus-visible { outline: none; box-shadow: var(--cp-shadow-focus); }
/* `min-width: 0` alone let this shrink below its content: a mono engine name has
   no break opportunity, so "ChatGPT" painted straight over the state text beside
   it and "Google AI Mode" broke into three lines. The glyphs spilled while the
   BOXES stayed apart, which is why a geometry check missed it. A minimum in ch
   plus a break opportunity fixes the cause, not the symptom. */
.cp-cell__engine {
  flex: 1 1 auto;
  font-family: var(--cp-font-mono);
  font-size: var(--cp-text-sm);
  min-width: 9ch;
  overflow-wrap: anywhere;
}
.cp-cell__state { display: inline-flex; align-items: center; gap: var(--cp-space-2); font-size: var(--cp-text-xs); color: var(--cp-color-text-muted); white-space: nowrap; }

/* At 390px a long state ("NOT ENOUGH DATA — no answer") is nowrap and was
   squeezing the engine name to four characters: "Google AI Mode" broke across
   three lines and one row collided with the state text. Below 640px the state
   drops to its own line under the engine, aligned past the glyph. */
@media (max-width: 639px) {
  .cp-cell__summary { flex-wrap: wrap; padding-top: var(--cp-space-3); padding-bottom: var(--cp-space-3); }
  .cp-cell__summary .cp-action__chevron { order: 2; margin-left: auto; }
  .cp-cell__state {
    order: 3;
    flex: 1 0 100%;
    padding-left: calc(22px + var(--cp-space-3));
    white-space: normal;
  }
}
.cp-cell__body { padding: 0 var(--cp-space-4) var(--cp-space-4); }

/* The three states, one glyph each. Shape carries the meaning, colour only
   reinforces it — colour is never the sole indicator. */
.cp-glyph {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 22px; height: 22px;
  flex: none;
  border-radius: var(--cp-radius-sm);
  font-family: var(--cp-font-mono);
  font-size: 13px;
  line-height: 1;
  border: var(--cp-hairline) solid transparent;
}
.cp-glyph--cited { background: var(--cp-color-proof-bg); border-color: var(--cp-color-proof-border); color: var(--cp-color-proof-text); }
.cp-glyph--absent { background: var(--cp-color-surface-sunken); border-color: var(--cp-color-border); color: var(--cp-color-text-subtle); }
.cp-glyph--nodata { background: var(--cp-pattern-nodata); border-color: var(--cp-color-nodata-border); border-style: dashed; color: var(--cp-color-nodata-text); }

/* The raw answer. Verbatim, monospaced, with the brand match highlighted —
   this transparency is the anti-black-box trust feature. */
.cp-answer {
  max-height: 22rem;
  overflow: auto;
  padding: var(--cp-space-3);
  border: var(--cp-hairline) solid var(--cp-color-border);
  border-radius: var(--cp-radius-md);
  background: var(--cp-color-surface-sunken);
  font-family: var(--cp-font-mono);
  font-size: var(--cp-text-xs);
  line-height: var(--cp-leading-relaxed);
  white-space: pre-wrap;
  overflow-wrap: anywhere;
}

.cp-citation {
  display: flex;
  gap: var(--cp-space-2);
  align-items: baseline;
  padding: var(--cp-space-2) 0;
  border-bottom: var(--cp-hairline) solid var(--cp-color-border-subtle);
  font-size: var(--cp-text-sm);
}
.cp-citation:last-child { border-bottom: 0; }
.cp-citation__pos { font-family: var(--cp-font-mono); font-size: var(--cp-text-xs); color: var(--cp-color-text-subtle); flex: none; min-width: 2ch; }
.cp-citation__link { overflow-wrap: anywhere; }
/* The domain always sits on its own line under the title. Left inline it landed
   beside short titles and under long ones, so a column of citations read as if
   the rows were structured differently from one another. */
.cp-citation__link > .cp-small { display: block; }

@media (min-width: 960px) {
  .cp-prompt { display: grid; grid-template-columns: minmax(0, 1fr) 420px; align-items: start; }
  .cp-prompt__head { border-right: var(--cp-hairline) solid var(--cp-color-border-subtle); height: 100%; }
  .cp-prompt__cells { border-top: 0; }
}

/* ==========================================================================
   6. ONBOARDING WIZARD
   Three steps, every default pre-accepted. The rail states where you are and
   how many steps remain; it is not clickable forward, because step 2 needs the
   crawl that step 1 starts.
   ========================================================================== */

.cp-steps {
  /* The markup is an <ol>, so without these the UA draws its own "1." and "2." on top of
     the numbered circles. The offenders are the two <li class="cp-steps__rule">
     connectors: .cp-steps__item is inline-flex and therefore loses its marker, but the
     rules keep display:list-item and each renders one. Seen at 390px on the first screen
     of onboarding — a "1." struck through the word DOMAIN and a "2." over circle 2. */
  list-style: none;
  padding-inline-start: 0;
  display: flex;
  align-items: center;
  gap: var(--cp-space-2);
  margin-bottom: var(--cp-space-5);
  font-family: var(--cp-font-mono);
  font-size: var(--cp-text-2xs);
  letter-spacing: var(--cp-tracking-caps);
  text-transform: uppercase;
  color: var(--cp-color-text-subtle);
}
.cp-steps__item { display: inline-flex; align-items: center; gap: var(--cp-space-2); }
.cp-steps__num {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 22px; height: 22px;
  border-radius: var(--cp-radius-full);
  border: var(--cp-hairline) solid var(--cp-color-border-strong);
  font-size: 11px;
  flex: none;
}
.cp-steps__item--done .cp-steps__num { background: var(--cp-color-text-muted); border-color: var(--cp-color-text-muted); color: var(--cp-color-text-inverse); }
.cp-steps__item--current { color: var(--cp-color-primary-text); }
.cp-steps__item--current .cp-steps__num { background: var(--cp-color-primary); border-color: var(--cp-color-primary); color: var(--cp-color-text-on-primary); }
.cp-steps__rule { flex: 1 1 auto; height: var(--cp-hairline); background: var(--cp-color-border); min-width: var(--cp-space-2); }
@media (max-width: 479px) {
  .cp-steps__text { display: none; }
  .cp-steps__item--current .cp-steps__text { display: inline; }
}

.cp-chips { display: flex; flex-wrap: wrap; gap: var(--cp-space-2); }
.cp-tag {
  display: inline-flex;
  align-items: center;
  gap: var(--cp-space-2);
  padding: var(--cp-space-1) var(--cp-space-3);
  border: var(--cp-hairline) solid var(--cp-color-border);
  border-radius: var(--cp-radius-sm);
  background: var(--cp-color-bg-subtle);
  font-size: var(--cp-text-sm);
}
.cp-tag--negative { border-style: dashed; color: var(--cp-color-text-muted); }

.cp-intent-group { padding-top: var(--cp-space-4); }
.cp-intent-group__title {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--cp-space-3);
  font-size: var(--cp-text-2xs);
  font-weight: var(--cp-weight-semibold);
  letter-spacing: var(--cp-tracking-caps);
  text-transform: uppercase;
  color: var(--cp-color-text-subtle);
  padding-bottom: var(--cp-space-2);
  border-bottom: var(--cp-hairline) solid var(--cp-color-border-subtle);
  margin: 0 0 var(--cp-space-1);
}

/* A sticky action bar so "Run" is always in thumb reach on a long list. */
.cp-sticky-bar {
  position: sticky;
  bottom: calc(72px + env(safe-area-inset-bottom, 0px));
  z-index: var(--cp-z-raised);
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--cp-space-3);
  margin-top: var(--cp-space-5);
  padding: var(--cp-space-3) var(--cp-space-4);
  background: var(--cp-color-surface);
  border: var(--cp-hairline) solid var(--cp-color-border-strong);
  border-radius: var(--cp-radius-lg);
  box-shadow: var(--cp-shadow-md);
}
.cp-sticky-bar__facts { flex: 1 1 200px; font-family: var(--cp-font-mono); font-size: var(--cp-text-xs); color: var(--cp-color-text-muted); }
@media (min-width: 960px) {
  .cp-sticky-bar { bottom: var(--cp-space-4); }
}

/* ==========================================================================
   7. REPORTS / SETTINGS
   ========================================================================== */

.cp-report {
  display: flex;
  flex-direction: column;
  gap: var(--cp-space-3);
  padding: var(--cp-space-4);
  border: var(--cp-hairline) solid var(--cp-color-border);
  border-radius: var(--cp-radius-lg);
  background: var(--cp-color-surface);
}
.cp-report__row { display: flex; flex-wrap: wrap; align-items: center; gap: var(--cp-space-2) var(--cp-space-3); }
.cp-share {
  display: flex;
  gap: var(--cp-space-2);
  align-items: stretch;
  flex-wrap: wrap;
}
.cp-share input { flex: 1 1 200px; min-width: 0; }

/* The sharing switch — one bounded block per report, so "on" and "off" read as a single
   decision rather than as loose controls scattered under the download button. */
.cp-sharing {
  padding-top: var(--cp-space-3);
  border-top: var(--cp-hairline) solid var(--cp-color-border);
}

.cp-swatch {
  display: inline-block;
  width: 28px; height: 28px;
  border-radius: var(--cp-radius-sm);
  border: var(--cp-hairline) solid var(--cp-color-border);
  flex: none;
}
.cp-colour-field { display: flex; align-items: center; gap: var(--cp-space-3); }
.cp-colour-field input[type="color"] {
  width: var(--cp-tap-min);
  height: var(--cp-tap-min);
  padding: 2px;
  border: var(--cp-hairline) solid var(--cp-color-border);
  border-radius: var(--cp-radius-sm);
  background: var(--cp-color-surface);
  cursor: pointer;
  flex: none;
}

/* ==========================================================================
   8. FEEDBACK
   ========================================================================== */

/* Copy confirmation. Announced to screen readers via aria-live in the markup. */
.cp-toast {
  position: fixed;
  left: 50%;
  bottom: calc(84px + env(safe-area-inset-bottom, 0px));
  transform: translateX(-50%) translateY(8px);
  z-index: var(--cp-z-toast);
  max-width: calc(100vw - 2 * var(--cp-gutter));
  padding: var(--cp-space-3) var(--cp-space-4);
  border-radius: var(--cp-radius-md);
  background: var(--cp-color-surface-inverse);
  color: var(--cp-color-text-inverse);
  font-size: var(--cp-text-sm);
  box-shadow: var(--cp-shadow-lg);
  opacity: 0;
  pointer-events: none;
  transition: opacity var(--cp-duration-fast) var(--cp-ease-out),
              transform var(--cp-duration-fast) var(--cp-ease-out);
}
.cp-toast[data-cp-show="1"] { opacity: 1; transform: translateX(-50%) translateY(0); }
@media (min-width: 960px) {
  .cp-toast { bottom: var(--cp-space-6); }
}

/* A running measurement. The bar is indeterminate on purpose: we do not know
   how long an engine will take, and a fake percentage is a fabricated number. */
.cp-running {
  position: relative;
  height: 4px;
  border-radius: var(--cp-radius-full);
  background: var(--cp-color-surface-sunken);
  overflow: hidden;
}
.cp-running::after {
  content: "";
  position: absolute;
  inset: 0 auto 0 0;
  width: 35%;
  border-radius: inherit;
  background: var(--cp-color-primary);
  animation: cp-slide 1.4s var(--cp-ease-in-out) infinite;
}
@keyframes cp-slide {
  0%   { transform: translateX(-100%); }
  100% { transform: translateX(300%); }
}

.cp-stack-gap { display: flex; flex-direction: column; gap: var(--cp-space-4); }

/* ==========================================================================
   9. TEXT LINKS AND PROSE
   ========================================================================== */

/* A link inside a sentence. It stays underlined — colour is never the only
   signal. The vertical padding is not decoration: measured at 390px these links
   were 18px tall, under the 24x24 minimum target size (WCAG 2.2 AA, 2.5.8).
   Inline padding grows the hit box without moving a single glyph. */
.cp-link {
  color: var(--cp-color-link);
  text-decoration: underline;
  text-underline-offset: 2px;
  padding-block: 6px;
  border-radius: var(--cp-radius-xs);
}
.cp-link:hover { color: var(--cp-color-link-hover); }
.cp-link:focus-visible { outline: none; box-shadow: var(--cp-shadow-focus); }

/* Rendered Markdown from an Action Package. The width limit is the reason a
   worked example is readable on a 27-inch monitor. */
.cp-prose { max-width: var(--cp-measure); color: var(--cp-color-text); }
.cp-prose > *:first-child { margin-top: 0; }
.cp-prose > *:last-child { margin-bottom: 0; }
.cp-prose p { margin: 0 0 var(--cp-space-3); line-height: var(--cp-leading-relaxed); }
.cp-prose ul, .cp-prose ol { margin: 0 0 var(--cp-space-3); padding-left: var(--cp-space-5); }
.cp-prose li { margin-bottom: var(--cp-space-2); line-height: var(--cp-leading-relaxed); }
.cp-prose strong { font-weight: var(--cp-weight-semibold); }
.cp-prose code {
  font-family: var(--cp-font-mono);
  font-size: 0.92em;
  background: var(--cp-color-surface-sunken);
  border: var(--cp-hairline) solid var(--cp-color-border-subtle);
  border-radius: var(--cp-radius-xs);
  padding: 0.1em 0.35em;
  overflow-wrap: anywhere;
}
.cp-prose pre {
  margin: 0 0 var(--cp-space-3);
  padding: var(--cp-space-4);
  background: var(--cp-color-surface-sunken);
  border: var(--cp-hairline) solid var(--cp-color-border);
  border-radius: var(--cp-radius-md);
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;
}
.cp-prose pre code { background: none; border: 0; padding: 0; font-size: var(--cp-text-sm); }
.cp-prose a { color: var(--cp-color-link); text-underline-offset: 2px; padding-block: 4px; }

.cp-break { overflow-wrap: anywhere; }
.cp-negative { color: var(--cp-color-negative-text); }

/* components.css sets `svg { display: block }` for layout icons, which forces a
   line break before any icon that sits INSIDE a sentence — "Source ↗" put its
   arrow on a line of its own even with white-space: nowrap, because a block box
   cannot share a line. Icons inside a text link or a nowrap run go back to
   inline. */
.cp-link svg,
.cp-nowrap svg,
.cp-prose svg { display: inline-block; vertical-align: -0.15em; }

/* The evidence line: a 22px grade square, the sentence it means, and the source
   link, aligned rather than run together as inline text. */
.cp-grade-line {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: var(--cp-space-2) var(--cp-space-3);
  margin-top: var(--cp-space-2);
}

/* Code stays readable on a phone: wrap long lines instead of hiding them behind a
   horizontal scroll the thumb has to find. The COPY button still hands over the
   exact bytes, so wrapping the display costs nothing. */
@media (max-width: 639px) {
  .cp-code__body pre,
  .cp-prose pre {
    white-space: pre-wrap;
    overflow-wrap: anywhere;
  }
}

/* A <details> summary that still LOOKS openable. Setting `display: flex` on a
   summary removes the browser's disclosure triangle — the affordance vanishes and
   the row reads as plain text (caught by looking at the trend card, where "Read
   the periods as a table" looked like a sentence nobody could click). The chevron
   is drawn explicitly and rotated by the open state. */
.cp-disclosure {
  display: flex;
  align-items: center;
  gap: var(--cp-space-2);
  min-height: var(--cp-tap-min);
  cursor: pointer;
  list-style: none;
  color: var(--cp-color-text-muted);
  font-size: var(--cp-text-sm);
}
.cp-disclosure::-webkit-details-marker { display: none; }
.cp-disclosure:hover { color: var(--cp-color-text); }
.cp-disclosure:focus-visible { outline: none; box-shadow: var(--cp-shadow-focus); }
.cp-disclosure svg { flex: none; transition: transform var(--cp-duration-fast) var(--cp-ease-out); }
details[open] > .cp-disclosure svg { transform: rotate(90deg); }
@media (prefers-reduced-motion: reduce) { .cp-disclosure svg { transition: none; } }

@media (prefers-reduced-motion: reduce) {
  .cp-action__body { animation: none; }
  .cp-running::after { animation: none; width: 100%; opacity: 0.35; }
  .cp-action__chevron { transition: none; }
}
