@layer reset, tokens, base, shell, components, views, phone;
/* GENERATED from deploy/app/css: edit the partials, then run python bin/build_app_css.py. Do not edit app.css by hand. */

/* ---- css/00-tokens.css ---- */
/* 00-tokens: the ONLY place a colour or a font size is written as a literal.
   bin/build_app_css.py fails the build on a hex, rgb() or hsl() colour, or a
   font-size literal, anywhere else. Spec: Sprint 178 build spec section 2.

   Light values on :root. Dark values on :root[data-theme="dark"], which the
   head script stamps (and removes for Light). Nothing is defined twice. */
@layer tokens {
  :root {
    color-scheme: light;

    /* ---- colour: ground and surfaces (zero-chroma greys) ---- */
    --bg: #FAFAFA;
    --frame: #FFFFFF;
    --surface: #FFFFFF;
    --surface-2: #F5F5F5;
    --surface-3: #EBEBEB;
    --border: #E5E5E5;
    --border-strong: #D4D4D4;
    --border-control: #858585;

    /* ---- colour: text ---- */
    --text: #171717;
    --text-2: #525252;
    --text-3: #666666;
    /* Sprint 187 lane B: the "Google Maps" attribution - one of Google's three allowed colours (Places policies). */
    --gmaps-text: #5E5E5E;

    /* ---- colour: the one accent (press, focus, link, "you are here") ---- */
    --accent: #5B3FBF;
    --accent-hover: #4A31A3;
    --on-accent: #FFFFFF;
    --accent-text: #5B3FBF;
    --accent-wash: #F3F0FC;

    /* ---- colour: data only, never decoration ---- */
    --good: #1A7F37;
    --warn: #8A5A00;
    --warn-mark: #B07A00;
    --bad: #B42318;
    --changed: #0969DA;
    --neutral-mark: #858585;
    --good-wash: #EDF7F0;
    --warn-wash: #FBF5E6;
    --bad-wash: #FDEEEF;
    --changed-wash: #EAF3FD;

    /* ---- colour: inverse toast, scrim ---- */
    --toast-bg: #171717;
    --toast-text: #FFFFFF;
    --toast-2: #A3A3A3;
    --scrim: rgba(0, 0, 0, .40);

    /* ---- the "not comparable" signature: a diagonal hatch in neutral-mark.
       Only ever a FILL behind no text (rule 9). ---- */
    --hatch: repeating-linear-gradient(135deg, var(--neutral-mark) 0 1.5px, transparent 1.5px 4.5px);

    /* ---- type ---- */
    --sans: "Geist", system-ui, "Segoe UI", sans-serif;
    --mono: "Geist Mono", ui-monospace, Consolas, monospace;
    --fs-11: 11px;  --lh-11: 14px;
    --fs-12: 12px;  --lh-12: 16px;
    --fs-13: 13px;  --lh-13: 20px;
    --fs-14: 14px;  --lh-14: 20px;
    --fs-16: 16px;  --lh-16: 24px;
    --fs-20: 20px;  --lh-20: 28px;
    --fs-28: 28px;  --lh-28: 32px;
    --lh-mono: 18px;

    /* ---- space ---- */
    --s-1: 4px;  --s-2: 8px;  --s-3: 12px; --s-4: 16px; --s-5: 20px;
    --s-6: 24px; --s-7: 32px; --s-8: 40px; --s-9: 48px; --s-10: 64px;

    /* ---- radius ---- */
    --r-sm: 6px;
    --r-md: 8px;
    --r-lg: 12px;
    --r-full: 9999px;

    /* ---- elevation (menus, toasts; dialogs). Cards have none. ---- */
    --e1: 0 1px 2px rgba(0, 0, 0, .05), 0 8px 24px -8px rgba(0, 0, 0, .14);
    --e2: 0 24px 48px -12px rgba(0, 0, 0, .22);

    /* ---- motion ---- */
    --dur-1: 120ms;
    --dur-2: 160ms;
    --dur-3: 200ms;
    --ease: cubic-bezier(.2, 0, 0, 1);
  }

  :root[data-theme="dark"] {
    color-scheme: dark;

    --bg: #0E0E0E;
    --frame: #0E0E0E;
    --surface: #1B1B1B;
    --surface-2: #242424;
    --surface-3: #2E2E2E;
    --border: #2B2B2B;
    --border-strong: #3A3A3A;
    --border-control: #707070;

    --text: #EDEDED;
    --text-2: #B4B4B4;
    --text-3: #9A9A9A;
    --gmaps-text: #FFFFFF;

    --accent: #6D4FE6;
    --accent-hover: #5E40D6;
    --on-accent: #FFFFFF;
    --accent-text: #B4A3FF;
    --accent-wash: #262140;

    --good: #3FB950;
    --warn: #E3B341;
    --warn-mark: #E3B341;
    --bad: #FF7B72;
    --changed: #58A6FF;
    --neutral-mark: #8A8A8A;
    --good-wash: #15291C;
    --warn-wash: #2E2612;
    --bad-wash: #341B1B;
    --changed-wash: #12233A;

    --toast-bg: #EDEDED;
    --toast-text: #171717;
    --toast-2: #525252;
    --scrim: rgba(0, 0, 0, .60);

    --e1: 0 0 0 1px #3A3A3A, 0 8px 24px -8px rgba(0, 0, 0, .6);
    --e2: 0 0 0 1px #3A3A3A, 0 24px 48px -12px rgba(0, 0, 0, .7);
  }

  /* Reduced motion: every duration collapses; the pulses stop in 20-components. */
  @media (prefers-reduced-motion: reduce) {
    :root {
      --dur-1: .01ms;
      --dur-2: .01ms;
      --dur-3: .01ms;
    }
  }
}

/* ---- css/05-reset.css ---- */
/* 05-reset: first in the @layer order, so its !important declarations beat
   every other layer's (important declarations reverse layer order). That is
   the point: nothing anywhere can out-rank a hide. !important is refused by
   the build in every other layer. */
@layer reset {
  *, *::before, *::after { box-sizing: border-box; }
  html { -webkit-text-size-adjust: 100%; text-size-adjust: 100%; }
  body { margin: 0; }
  h1, h2, h3, h4, h5, h6, p, figure, blockquote, dl, dd, pre { margin: 0; }
  /* Only CLASSED lists lose their bullets; a bare list in prose keeps them. */
  ul[class], ol[class] { list-style: none; margin: 0; padding: 0; }
  /* Not display:block - an icon inline with a number (ringOf beside a score)
     must stay on the number's line. */
  img, svg, video { vertical-align: middle; max-width: 100%; }
  img, video { height: auto; }
  button, input, select, textarea { font: inherit; color: inherit; margin: 0; }
  button { background: none; border: 0; padding: 0; cursor: pointer; }
  a { color: inherit; }
  table { border-collapse: collapse; }

  /* `hidden` always wins. */
  [hidden] { display: none !important; }

  /* The views: only DIRECT children of .page that declare data-view are
     hidden. `~=`, so one element can belong to several views (#hero and
     .pinned are "audit home"). #pbModal declares none and is never hidden by
     these. Sixteen rules: the eleven views, the website overview, and the
     four IA_SPEC 2.1 views (area overview, tool page, not-available page,
     site section). */
  .page[data-view="home"] > [data-view]:not([data-view~="home"]) { display: none !important; }
  .page[data-view="audit"] > [data-view]:not([data-view~="audit"]) { display: none !important; }
  .page[data-view="playbooks"] > [data-view]:not([data-view~="playbooks"]) { display: none !important; }
  .page[data-view="sites"] > [data-view]:not([data-view~="sites"]) { display: none !important; }
  .page[data-view="history"] > [data-view]:not([data-view~="history"]) { display: none !important; }
  .page[data-view="keywords"] > [data-view]:not([data-view~="keywords"]) { display: none !important; }
  .page[data-view="runs"] > [data-view]:not([data-view~="runs"]) { display: none !important; }
  .page[data-view="aeo"] > [data-view]:not([data-view~="aeo"]) { display: none !important; }
  .page[data-view="reports"] > [data-view]:not([data-view~="reports"]) { display: none !important; }
  .page[data-view="plan"] > [data-view]:not([data-view~="plan"]) { display: none !important; }
  .page[data-view="account"] > [data-view]:not([data-view~="account"]) { display: none !important; }
  .page[data-view="website"] > [data-view]:not([data-view~="website"]) { display: none !important; }
  .page[data-view="area"] > [data-view]:not([data-view~="area"]) { display: none !important; }
  .page[data-view="tool"] > [data-view]:not([data-view~="tool"]) { display: none !important; }
  .page[data-view="connect"] > [data-view]:not([data-view~="connect"]) { display: none !important; }
  .page[data-view="section"] > [data-view]:not([data-view~="section"]) { display: none !important; }
}

/* ---- css/10-base.css ---- */
/* 10-base: element defaults for every page that links app.css (the app, the
   sign-in pages, later the public report page). Spec sections 1, 2.2, 2.3. */
@layer base {
  html { background: var(--bg); }
  body {
    background: var(--bg);
    color: var(--text);
    font-family: var(--sans);
    font-size: var(--fs-14);
    line-height: var(--lh-14);
    font-weight: 400;
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
    text-rendering: optimizeLegibility;
  }

  h1, h2, h3, h4, h5, h6 { font-weight: 600; color: var(--text); }
  h1 { font-size: var(--fs-20); line-height: var(--lh-20); letter-spacing: -.01em; }
  h2 { font-size: var(--fs-20); line-height: var(--lh-20); letter-spacing: -.01em; }
  h3 { font-size: var(--fs-14); line-height: var(--lh-14); }
  h4, h5, h6 { font-size: var(--fs-14); line-height: var(--lh-14); }
  b, strong { font-weight: 600; }

  a { color: var(--accent-text); text-decoration: none; }
  a:hover { text-decoration: underline; text-underline-offset: 2px; }

  /* Mono only for measured values, evidence, code, keys and IPs (rule 5). */
  code, kbd, samp, pre, .mono {
    font-family: var(--mono);
    font-size: var(--fs-12);
    line-height: var(--lh-mono);
  }

  ::selection { background: var(--accent-wash); color: var(--text); }

  /* One focus ring everywhere: 2px accent-text, offset 2px. */
  :focus { outline: none; }
  :focus-visible { outline: 2px solid var(--accent-text); outline-offset: 2px; }

  /* Form controls: 13px (smoke:1590 reads 13px), 1px border-control, r-md.
     :where() keeps this at element specificity (0,0,1): with bare :not()s it
     was (0,3,1) and beat `.field input { min-height: 40px }` in the same layer
     (CLAUDE.md 5.1 - measured: the sign-in inputs rendered 32px, not 40). */
  input:where(:not([type="checkbox"]):not([type="radio"]):not([type="range"])),
  select, textarea {
    font-size: var(--fs-13);
    line-height: var(--lh-13);
    color: var(--text);
    background: var(--surface-2);
    border: 1px solid var(--border-control);
    border-radius: var(--r-md);
    min-height: 32px;
    padding: 0 var(--s-3);
  }
  textarea { padding: var(--s-2) var(--s-3); }
  input::placeholder, textarea::placeholder { color: var(--text-3); opacity: 1; }
  input:focus-visible, select:focus-visible, textarea:focus-visible {
    outline: 2px solid var(--accent-text);
    outline-offset: 0;
    border-color: var(--accent-text);
  }
  input:disabled, select:disabled, textarea:disabled {
    color: var(--text-3);
    background: var(--surface-2);
    border-color: var(--border);
    cursor: not-allowed;
  }

  hr { border: 0; border-top: 1px solid var(--border); margin: 0; }

  /* Words for screen readers only (the theme switch's labels, section 4). */
  .sr-only {
    position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
    overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
  }
}

/* Rule 10: at 767px and below every interactive element is at least 44px
   tall. Keyed on WIDTH, not pointer, because touch_targets runs with a fine
   pointer. In the phone layer so no component height can undercut it. */
@layer phone {
  @media (max-width: 767px) {
    button, select, summary, [role="button"], [role="menuitem"],
    input:not([type="checkbox"]):not([type="radio"]):not([type="range"]):not([type="hidden"]) {
      min-height: 44px;
    }
  }
}

/* ---- css/15-auth.css ---- */
/* 15-auth: the sign-in and sign-up pages (body.auth), plus .err, which the
   app's own error boxes share. These pages link the same app.css as the app,
   so this partial is all that styles them. */
@layer base {
  body.auth { background: var(--bg); color: var(--text); }

  .auth-wrap {
    min-height: 100dvh;
    display: grid;
    place-items: center;
    padding: var(--s-7) var(--s-4);
  }
  .auth-card {
    width: min(400px, 100%);
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: var(--r-lg);
    padding: var(--s-7);
  }
  .auth-card .brand {
    display: inline-flex;
    align-items: center;
    gap: var(--s-2);
    margin-bottom: var(--s-6);
    min-height: 44px;   /* S184 MST-17: every control on these pages is 44px tall */
    color: var(--text);
    text-decoration: none;
  }
  .auth-card .brand b { font-size: var(--fs-14); line-height: var(--lh-14); font-weight: 600; }
  .brand-q { width: 32px; height: 32px; flex: none; }
  .brand-q rect { fill: var(--accent); }
  .brand-q text {
    fill: var(--on-accent);
    font-family: var(--sans);
    font-size: var(--fs-20);
    font-weight: 600;
  }

  .auth-card h1 { font-size: var(--fs-20); line-height: var(--lh-20); font-weight: 600; letter-spacing: -.01em; }
  .auth-card .sub { margin-top: var(--s-2); color: var(--text-2); font-size: var(--fs-13); line-height: var(--lh-13); }

  .field { margin-top: var(--s-4); }
  .field label {
    display: block;
    margin-bottom: 6px;
    font-size: var(--fs-13);
    line-height: var(--lh-13);
    font-weight: 500;
    color: var(--text);
  }
  .field input { width: 100%; min-height: 44px; background: var(--surface-2); }
  .hint { margin-top: 6px; font-size: var(--fs-12); line-height: var(--lh-12); color: var(--text-3); }

  /* The sign-in pages' one button: the primary, full width, 44px. */
  .btn {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 100%;
    min-height: 44px;
    margin-top: var(--s-6);
    padding: 0 var(--s-4);
    border: 0;
    border-radius: var(--r-md);
    background: var(--accent);
    color: var(--on-accent);
    font-size: var(--fs-13);
    line-height: var(--lh-13);
    font-weight: 500;
    cursor: pointer;
    transition: background-color var(--dur-1) var(--ease);
  }
  .btn:hover:not(:disabled) { background: var(--accent-hover); }
  /* Disabled: a fill and a text colour, never opacity (design_guard does not
     composite opacity, so a faded button reads as passing when it is not). */
  .btn:disabled { background: var(--surface-2); color: var(--text-3); cursor: not-allowed; }

  .alt { margin-top: var(--s-5); text-align: center; font-size: var(--fs-13); line-height: var(--lh-13); color: var(--text-2); }
  /* The links under the form were 17px tall text; a 44px box around the same words. */
  .alt a { display: inline-flex; align-items: center; min-height: 44px; padding: 0 var(--s-1); }

  .err {
    margin-top: var(--s-3);
    padding: var(--s-2) var(--s-3);
    border: 1px solid var(--bad);
    border-radius: var(--r-md);
    background: var(--bad-wash);
    color: var(--bad);
    font-size: var(--fs-13);
    line-height: var(--lh-13);
  }
  .err:empty { display: none; }
}

@layer phone {
  @media (max-width: 767px) {
    .auth-card { padding: var(--s-6) var(--s-4); }
  }
}

/* ---- css/20-components.css ---- */
/* 20-components: the shared parts every view is built from. Spec section 3.
   A component that needs a view-specific tweak gets it in that view's own
   partial (40-90), never by editing this file from a view chunk.

   FLEX AND INLINE TAGS (CLAUDE.md 5.2): several components below are flex
   containers. Each child element becomes its own flex item, so a text run with
   an inline tag in the middle (<li>a <em>b</em> c</li>) breaks apart. Put one
   text run in one element (.banner-x, .mi-l, .es-p ...). */
@layer components {

  /* ============================================ panels (section 4) ===== */
  /* A view root is transparent: the .cc, .kpis and .card panels inside it
     carry the surfaces. .card stays on #result, #fixes, #fuCard, #hubCard,
     #watchCard and #evCard. Cards have no shadow and never move (rule 6). */
  .view { display: grid; gap: var(--s-4); align-content: start; min-width: 0; }
  .card {
    min-width: 0;
    padding: var(--s-5);
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: var(--r-lg);
  }

  /* ====================================================== 3.1 buttons ===== */
  .btn-p, .btn-2, .btn-t, .btn-d, .btn-i {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 6px;
    min-height: 32px;
    padding: 0 var(--s-3);
    border: 1px solid transparent;
    border-radius: var(--r-md);
    font-family: var(--sans);
    font-size: var(--fs-13);
    line-height: var(--lh-13);
    font-weight: 500;
    white-space: nowrap;
    text-decoration: none;
    cursor: pointer;
    transition: background-color var(--dur-1) var(--ease), border-color var(--dur-1) var(--ease), color var(--dur-1) var(--ease);
  }
  :is(.btn-p, .btn-2, .btn-t, .btn-d, .btn-i):hover { text-decoration: none; }
  :is(.btn-p, .btn-2, .btn-t, .btn-d, .btn-i) > svg { width: 16px; height: 16px; flex: none; }

  .btn-p { background: var(--accent); color: var(--on-accent); }
  .btn-p:hover, .btn-p:active { background: var(--accent-hover); }

  .btn-2 { background: var(--surface); color: var(--text); border-color: var(--border-strong); }
  .btn-2:hover { background: var(--surface-2); }
  .btn-2:active { background: var(--surface-3); }

  .btn-t { background: transparent; color: var(--text-2); padding: 0 var(--s-2); }
  .btn-t:hover { background: var(--surface-2); }
  .btn-t.is-link { color: var(--accent-text); }

  .btn-d { background: var(--surface); color: var(--bad); border-color: var(--bad); }
  .btn-d:hover { background: var(--bad-wash); }

  .btn-i { width: 32px; padding: 0; background: transparent; color: var(--text-2); }
  .btn-i:hover { background: var(--surface-2); color: var(--text); }
  .btn-i > svg { width: 16px; height: 16px; }

  .sz-sm { min-height: 28px; }
  .btn-i.sz-sm { width: 28px; }
  .sz-lg { min-height: 40px; padding: 0 var(--s-4); }

  /* Disabled: surface-2 fill, text-3, never opacity. The reason is shown
     beside it by the caller (rule 8: a control with no backend is absent). */
  :is(.btn-p, .btn-2, .btn-t, .btn-d, .btn-i):is(:disabled, [aria-disabled="true"]) {
    background: var(--surface-2);
    color: var(--text-3);
    border-color: var(--border);
    cursor: not-allowed;
  }

  /* =================================================== 3.2 status chips ===== */
  /* A chip WRAPS rather than clip: its words carry the meaning (rule 2 -
     colour is never the only cue), so "Older scori…" is not allowed. */
  .chip {
    display: inline-block;
    max-width: 100%;
    min-height: 20px;
    padding: 0 var(--s-2);
    border: 1px solid transparent;
    border-radius: var(--r-sm);
    background: var(--surface-2);
    color: var(--text-2);
    font-size: var(--fs-12);
    line-height: 18px;
    font-weight: 500;
    white-space: normal;
    vertical-align: middle;
    font-variant-numeric: tabular-nums;
    justify-self: start;   /* in a .tbl grid cell a chip is its own width, never stretched */
  }
  /* the 8x8 swatch that leads every toned chip */
  .chip:is(.t-neutral, .t-good, .t-warn, .t-bad, .t-changed, .t-accent, .t-nm)::before {
    content: "";
    display: inline-block;
    width: 8px;
    height: 8px;
    margin-right: 6px;
    border-radius: 2px;
    background: currentColor;
  }
  .chip.t-neutral { background: var(--surface-2); color: var(--text-2); }
  .chip.t-neutral::before { background: var(--neutral-mark); }
  .chip.t-good { background: var(--good-wash); color: var(--good); }
  .chip.t-warn { background: var(--warn-wash); color: var(--warn); }
  .chip.t-warn::before { background: var(--warn-mark); }
  .chip.t-bad { background: var(--bad-wash); color: var(--bad); }
  .chip.t-changed { background: var(--changed-wash); color: var(--changed); }
  .chip.t-accent { background: var(--accent-wash); color: var(--accent-text); }
  .chip.t-accent::before { background: var(--accent); }
  /* a category or mode: an outline, no swatch - it is not a data state */
  .chip.t-mode { background: transparent; color: var(--text-2); border-color: var(--border-strong); }
  /* NOT COMPARABLE: solid border, a hatch swatch, then "≠ ". The swatch is a
     real 8x8 box with its own 1px outline (::after, pinned left), so it reads
     as a swatch and not as a stray "/"; the glyph sits beside it, never on it
     (rule 9). The "≠" stays in CSS so the chip's textContent is unchanged. */
  .chip.t-nc {
    position: relative;
    padding-left: 22px;
    background: transparent;
    color: var(--text-3);
    border-color: var(--text-3);
  }
  .chip.t-nc::before { content: "\2260\00a0"; }
  .chip.t-nc::after {
    content: "";
    position: absolute;
    left: 7px;
    top: 5px;
    width: 8px;
    height: 8px;
    border: 1px solid var(--neutral-mark);
    border-radius: 1px;
    background: var(--hatch);
  }
  /* NOT MEASURED: dashed border, an empty dashed swatch */
  .chip.t-nm { background: transparent; color: var(--text-3); border: 1px dashed var(--border-control); }
  .chip.t-nm::before { background: none; border: 1px dashed var(--border-control); }

  /* ========================================== 3.2 filter chips (kept) ===== */
  .pb-chip {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    min-height: 32px;
    padding: 0 var(--s-3);
    border: 1px solid var(--border-strong);
    border-radius: var(--r-md);
    background: var(--surface);
    color: var(--text-2);
    font-size: var(--fs-13);
    line-height: var(--lh-13);
    font-weight: 500;
    white-space: nowrap;
    cursor: pointer;
    transition: background-color var(--dur-1) var(--ease), color var(--dur-1) var(--ease);
  }
  .pb-chip:hover { background: var(--surface-2); color: var(--text); }
  .pb-chip i { font-style: normal; font-size: var(--fs-12); line-height: var(--lh-12); color: var(--text-3); font-variant-numeric: tabular-nums; }
  .pb-chip.on { background: var(--accent-wash); color: var(--accent-text); border-color: var(--accent-text); }
  .pb-chip.on i { color: var(--accent-text); }
  /* a passed check: a static good chip, not a control */
  .pb-chip.on-pass { background: var(--good-wash); color: var(--good); border-color: transparent; cursor: default; }

  /* ======================================= 3.3 score cell: the only N/100 ===== */
  .sc {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    white-space: nowrap;
    vertical-align: middle;
    font-variant-numeric: tabular-nums;
    justify-self: start;
  }
  .sc-r { width: 16px; height: 16px; flex: none; }
  .sc-t { fill: none; stroke: var(--surface-3); stroke-width: 2.5; }
  .sc-v { fill: none; stroke-width: 2.5; stroke-linecap: butt; }
  .sc-hi .sc-v { stroke: var(--good); }
  .sc-mid .sc-v { stroke: var(--warn-mark); }
  .sc-lo .sc-v { stroke: var(--bad); }
  /* the number is never coloured: 22 is ink everywhere */
  .sc b { font-size: var(--fs-14); line-height: var(--lh-14); font-weight: 600; color: var(--text); }
  .sc i { margin-left: -5px; font-style: normal; font-size: var(--fs-12); line-height: var(--lh-12); color: var(--text-3); }
  .sc-na { color: var(--text-3); font-weight: 500; }
  .sc-lg { gap: 10px; }
  .sc-lg .sc-r { width: 40px; height: 40px; }
  .sc-lg b { font-size: var(--fs-28); line-height: var(--lh-28); letter-spacing: -.02em; }
  .sc-lg i { margin-left: -8px; font-size: var(--fs-14); line-height: var(--lh-14); }

  /* ================================================= 3.4 KPI strip ===== */
  .kpis {
    --n: 4;
    display: grid;
    grid-template-columns: repeat(var(--n), minmax(0, 1fr));
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: var(--r-lg);
    overflow: hidden;
  }
  .kpi {
    display: flex;
    flex-direction: column;
    gap: var(--s-1);
    min-width: 0;
    min-height: 96px;
    padding: var(--s-4) var(--s-5);
    background: var(--surface);   /* opaque: theme.mjs and live_audit read it */
  }
  .kpi + .kpi { border-left: 1px solid var(--border); }
  .kpi-l {
    font-size: var(--fs-12);
    line-height: var(--lh-12);
    font-weight: 500;
    text-transform: uppercase;
    letter-spacing: .04em;
    color: var(--text-3);
  }
  .kpi-v {
    display: flex;
    align-items: baseline;
    gap: 2px;
    font-size: var(--fs-28);
    line-height: var(--lh-28);
    font-weight: 600;
    letter-spacing: -.02em;
    color: var(--text);
    font-variant-numeric: tabular-nums;
  }
  .kpi-v > .sc { align-self: center; }
  .kpi-d { font-size: var(--fs-14); line-height: var(--lh-14); font-weight: 400; letter-spacing: 0; color: var(--text-3); }
  /* only ever a fraction of a quota, and neutral: a quota is not a verdict */
  .kpi-bar { width: 96px; height: 4px; margin-top: 2px; border-radius: 2px; background: var(--surface-3); overflow: hidden; }
  .kpi-bar > i { display: block; height: 100%; background: var(--text-2); }
  .kpi-delta { font-size: var(--fs-12); line-height: var(--lh-12); font-weight: 600; font-variant-numeric: tabular-nums; }
  .kd-up { color: var(--good); }
  .kd-down { color: var(--bad); }
  /* text-wrap: pretty keeps a last word off a line of its own (round 3: the
     phone Credits tile ended on "left" alone) */
  .kpi-s { font-size: var(--fs-12); line-height: var(--lh-12); color: var(--text-3); overflow-wrap: anywhere; text-wrap: pretty; }

  /* ================================================= 3.5 page header ===== */
  .ph {
    display: grid;
    grid-template-columns: minmax(0, 1fr) auto;
    align-items: end;
    column-gap: var(--s-4);
    row-gap: var(--s-2);
    margin: 0 0 var(--s-6);
  }
  .page > .ph { margin-bottom: var(--s-2); }   /* + the page's 16px gap = 24 */
  .ph-m { min-width: 0; }
  .ph-c {
    display: inline-block;
    margin-bottom: var(--s-1);
    font-size: var(--fs-12);
    line-height: var(--lh-12);
    font-weight: 500;
    color: var(--text-3);
  }
  a.ph-c:hover, button.ph-c:hover { color: var(--text-2); }
  .ph-t {
    margin: 0;
    font-size: var(--fs-20);
    line-height: var(--lh-20);
    font-weight: 600;
    letter-spacing: -.01em;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
  }
  .ph-s { margin-top: var(--s-1); font-size: var(--fs-13); line-height: var(--lh-13); color: var(--text-3); }
  .ph-a { display: flex; flex-wrap: wrap; align-items: center; justify-content: flex-end; gap: var(--s-2); }

  /* ====================================================== 3.5 banner ===== */
  .banner {
    display: flex;
    align-items: flex-start;
    gap: 10px;
    min-height: 40px;
    padding: 10px 14px;
    border: 1px solid var(--border-strong);
    border-radius: var(--r-md);
    background: var(--surface);
    color: var(--text);
    font-size: var(--fs-13);
    line-height: var(--lh-13);
  }
  .banner-i { width: 16px; height: 16px; flex: none; margin-top: 2px; color: var(--text-2); }
  .banner-x { flex: 1; min-width: 0; }
  .banner-x a { color: var(--accent-text); }
  .banner-a { flex: none; display: flex; align-items: center; gap: var(--s-2); margin: -4px 0; }
  .b-warn { background: var(--warn-wash); }
  .b-warn .banner-i { color: var(--warn); }
  .b-info { background: var(--changed-wash); }
  .b-info .banner-i { color: var(--changed); }
  .b-nc { background: var(--surface-2); }
  /* the hatch lives in its own swatch, never behind the words */
  .banner-sw {
    width: 12px;
    height: 12px;
    flex: none;
    margin-top: 4px;
    border: 1px solid var(--text-3);
    border-radius: 2px;
    background: var(--hatch);
  }

  /* ======================================================= 3.7 table ===== */
  .tbl { --cols: minmax(0, 1fr) auto; display: block; }
  .tbl-h, .tbl-r {
    display: grid;
    grid-template-columns: var(--cols);
    align-items: center;
    column-gap: var(--s-4);
    padding: 0 var(--s-4);
    border-bottom: 1px solid var(--border);
  }
  .tbl-h {
    min-height: 32px;
    font-size: var(--fs-12);
    line-height: var(--lh-12);
    font-weight: 500;
    text-transform: uppercase;
    letter-spacing: .04em;
    color: var(--text-3);
  }
  .tbl-r {
    min-height: 48px;
    font-size: var(--fs-13);
    line-height: var(--lh-13);
    color: var(--text-2);
  }
  .tbl > :last-child { border-bottom: 0; }
  a.tbl-r, button.tbl-r {
    width: 100%;
    text-align: left;
    background: none;
    border-width: 0 0 1px;
    border-style: solid;
    border-color: var(--border);
    color: var(--text-2);
    text-decoration: none;
    cursor: pointer;
  }
  a.tbl-r:hover, button.tbl-r:hover { background: var(--surface-2); text-decoration: none; }
  a.tbl-r:focus-visible, button.tbl-r:focus-visible { outline-offset: -2px; }
  .tc-p { min-width: 0; font-size: var(--fs-14); line-height: var(--lh-14); font-weight: 500; color: var(--text); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
  .tc-s { min-width: 0; color: var(--text-2); }
  .tc-n { justify-self: end; text-align: right; color: var(--text); font-variant-numeric: tabular-nums; white-space: nowrap; }
  .tbl-g {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--s-1) var(--s-3);
    min-height: 48px;
    padding: 0 var(--s-4);
    border-bottom: 1px solid var(--border);
    background: var(--surface-2);
    font-size: var(--fs-14);
    line-height: var(--lh-14);
    font-weight: 600;
    color: var(--text);
  }
  .tbl-g .tg-s { font-size: var(--fs-13); font-weight: 400; color: var(--text-3); }
  .tbl-g .tg-a { margin-left: auto; display: flex; align-items: center; gap: var(--s-2); }
  /* rows past a cap stay in the DOM; the list shows them once it is .is-all */
  .tbl:not(.is-all) > .is-more { display: none; }
  .tbl-more { display: flex; justify-content: flex-start; padding: var(--s-2) var(--s-2); }

  /* ======================================================== 3.8 menu ===== */
  .menu {
    position: fixed;
    z-index: 60;
    min-width: 240px;
    max-width: 280px;
    padding: var(--s-1);
    background: var(--surface);
    border: 1px solid var(--border-strong);
    border-radius: var(--r-lg);
    box-shadow: var(--e1);
    animation: q-menu-in var(--dur-2) var(--ease);
  }
  .menu-l {
    padding: var(--s-2) 10px var(--s-1);
    font-size: var(--fs-12);
    line-height: var(--lh-12);
    font-weight: 500;
    color: var(--text-3);
  }
  .menu-sep { height: 1px; margin: var(--s-1) 0; background: var(--border); }
  .mi {
    display: flex;
    align-items: center;
    gap: 10px;
    width: 100%;
    min-height: 36px;
    padding: 0 10px;
    border: 0;
    border-radius: var(--r-md);
    background: none;
    color: var(--text);
    font-size: var(--fs-13);
    line-height: var(--lh-13);
    font-weight: 500;
    text-align: left;
    text-decoration: none;
    cursor: pointer;
  }
  .mi:hover, .mi:focus-visible { background: var(--surface-2); text-decoration: none; }
  .mi:focus-visible { outline-offset: -2px; }
  .mi-i { width: 16px; height: 16px; flex: none; color: var(--text-2); }
  .mi-l { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  .mi-h { flex: none; margin-left: auto; font-size: var(--fs-12); line-height: var(--lh-12); font-weight: 400; color: var(--text-3); }

  /* ====================================================== 3.8 dialog ===== */
  .dlg-scrim {
    position: fixed;
    inset: 0;
    z-index: 70;
    display: grid;
    place-items: center;
    padding: var(--s-4);
    background: var(--scrim);
    animation: q-fade-in var(--dur-3) var(--ease);
  }
  .dlg {
    display: flex;
    flex-direction: column;
    width: min(560px, 100vw - 32px);
    max-height: 85dvh;
    overflow: hidden;
    background: var(--surface);
    border: 1px solid var(--border-strong);
    border-radius: var(--r-lg);
    box-shadow: var(--e2);
    animation: q-dlg-in var(--dur-3) var(--ease);
  }
  .dlg-h { display: flex; align-items: center; gap: var(--s-3); padding: var(--s-5) var(--s-6) 0; }
  .dlg-t { flex: 1; min-width: 0; font-size: var(--fs-16); line-height: var(--lh-16); font-weight: 600; }
  .dlg-b { flex: 1; overflow: auto; padding: var(--s-4) var(--s-6); font-size: var(--fs-13); line-height: var(--lh-13); color: var(--text-2); }
  .dlg-f {
    position: sticky;
    bottom: 0;
    display: flex;
    justify-content: flex-end;
    gap: var(--s-2);
    padding: var(--s-4) var(--s-6);
    border-top: 1px solid var(--border);
    background: var(--surface);
  }

  /* ========================================= 3.8 disclosure (kept) ===== */
  details.basis { font-size: var(--fs-13); line-height: var(--lh-13); }
  details.basis > summary {
    display: inline-flex;
    align-items: center;
    gap: var(--s-2);
    min-height: 32px;
    list-style: none;
    font-weight: 500;
    color: var(--text-2);
    cursor: pointer;
  }
  details.basis > summary::-webkit-details-marker { display: none; }
  details.basis > summary::before {
    content: "";
    width: 6px;
    height: 6px;
    margin: 0 2px;
    border-right: 1.5px solid currentColor;
    border-bottom: 1.5px solid currentColor;
    transform: rotate(-45deg);
    transition: transform var(--dur-1) var(--ease);
  }
  details.basis[open] > summary::before { transform: rotate(45deg); }
  details.basis > summary:hover { color: var(--text); }
  details.basis > :not(summary) { max-width: 72ch; margin-top: var(--s-1); color: var(--text-2); }

  /* ======================================================= 3.8 toast ===== */
  /* Centred by left/right 0 + auto margins, NOT left:50% + translate: with
     left:50% the toast shrink-wraps into the half of the viewport right of
     its left edge (measured 260px at 375, the link field cut off). */
  .toast {
    position: fixed;
    left: 0;
    right: 0;
    width: fit-content;
    margin-inline: auto;
    bottom: var(--s-6);
    z-index: 80;
    display: flex;
    align-items: flex-start;
    gap: 10px;
    min-width: 240px;
    max-width: min(400px, 100vw - 32px);
    padding: 10px 14px;
    border-radius: var(--r-lg);
    background: var(--toast-bg);
    color: var(--toast-text);
    box-shadow: var(--e1);
    font-size: var(--fs-13);
    line-height: var(--lh-13);
    animation: q-toast-in var(--dur-2) var(--ease);
  }
  .toast-m { flex: 1; min-width: 0; }
  .toast-2 { display: block; color: var(--toast-2); }
  .toast-f {
    display: block;
    width: 100%;
    margin-top: var(--s-2);
    font-family: var(--mono);
    font-size: var(--fs-12);
    color: var(--toast-text);
    background: transparent;
    border-color: var(--toast-2);
  }
  /* The close button sits on the INVERSE surface: .btn-i:hover's surface-2
     fill would put a toast-text icon on a near-white square (1.09:1 light,
     1.15:1 dark - the X vanished). Hover brightens the icon instead:
     toast-2 -> toast-text, 17.9:1 light / 15.3:1 dark on toast-bg. */
  .toast-c { flex: none; min-height: 20px; color: var(--toast-2); }
  .toast-c:hover, .toast-c:active { background: transparent; color: var(--toast-text); }
  /* the global ring is accent-text: 2.48:1 / 1.86:1 on toast-bg. Use toast-text. */
  .toast :focus-visible { outline-color: var(--toast-text); }
  .toast-f:focus-visible { border-color: var(--toast-text); }

  /* ================================================== 3.8 empty state ===== */
  .es {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 6px;
    min-height: 100%;
    padding: var(--s-6) var(--s-4);
    text-align: center;
  }
  .es-i {
    flex: none;             /* a short plot must not squash the circle into an oval */
    display: grid;
    place-items: center;
    width: 40px;
    height: 40px;
    margin-bottom: var(--s-1);
    border-radius: 50%;
    background: var(--surface-2);
    color: var(--text-2);
    font-size: var(--fs-16);
    line-height: var(--lh-16);
    font-weight: 600;
  }
  .es-i > svg { width: 20px; height: 20px; }
  /* rule 3: not measured, not read, not recorded - one empty dashed outline */
  :is(.es-nm, .es-not-recorded, .es-never-read) .es-i { background: transparent; border: 1px dashed var(--border-control); }
  .es-t { font-size: var(--fs-14); line-height: var(--lh-14); font-weight: 600; color: var(--text); }
  .es-p { max-width: 48ch; font-size: var(--fs-13); line-height: var(--lh-13); color: var(--text-2); }
  .es > .btn-2 { margin-top: var(--s-2); }

  /* =================================================== skeleton (kept) ===== */
  .sk {
    display: block;
    min-height: 12px;
    border-radius: var(--r-sm);
    background: var(--surface-2);
    animation: q-pulse 1.2s ease-in-out infinite alternate;
  }

  /* ============================================================ motion ===== */
  @keyframes q-menu-in { from { opacity: 0; transform: translateY(4px); } to { opacity: 1; transform: none; } }
  @keyframes q-fade-in { from { opacity: 0; } to { opacity: 1; } }
  @keyframes q-dlg-in { from { opacity: 0; transform: scale(.98); } to { opacity: 1; transform: none; } }
  @keyframes q-toast-in { from { opacity: 0; transform: translateY(8px); } to { opacity: 1; transform: none; } }
  @keyframes q-pulse { from { opacity: .55; } to { opacity: 1; } }

  @media (prefers-reduced-motion: reduce) {
    .sk { animation: none; }
  }
}

@layer phone {
  @media (max-width: 767px) {
    .btn-p, .btn-2, .btn-t, .btn-d, .pb-chip, .mi, .sz-sm, .sz-lg,
    details.basis > summary { min-height: 44px; }
    .btn-i, .btn-i.sz-sm { width: 44px; min-height: 44px; }

    .card { padding: var(--s-4); }
    .kpis { grid-template-columns: repeat(2, minmax(0, 1fr)); }
    .kpi:nth-child(odd) { border-left: 0; }
    .kpi:nth-child(n+3) { border-top: 1px solid var(--border); }

    /* rule 10 for LINK controls: the base phone rule covers buttons, not <a> */
    a.ph-c { display: inline-flex; align-items: center; min-height: 44px; margin-bottom: 0; }

    .ph { grid-template-columns: minmax(0, 1fr); }
    .ph-a { justify-content: flex-start; }

    .tbl-h { display: none; }
    .tbl-r {
      display: flex;
      flex-wrap: wrap;
      align-items: center;
      column-gap: var(--s-3);
      row-gap: 2px;
      padding: var(--s-2) var(--s-4);
    }
    .tbl-r > :first-child { flex: 1 0 100%; }
    .tc-n { text-align: left; }
    /* The row display above sits in a later layer than the components' cap rule,
       so it re-showed every capped row on phones (C5/C6 measured 50 of 50). */
    .tbl:not(.is-all) > .is-more { display: none; }
    .tbl-g { padding: var(--s-2) var(--s-4); }
    /* rule 10 for LINK cells: a bare "/" path was a 7px target */
    .tbl-r > a.tc-p { display: flex; align-items: center; min-height: 44px; }
    a.t-url, a.rep-u { min-width: 44px; }
    .ph-c { min-width: 44px; }

    .dlg-scrim { place-items: end center; padding: 0; }
    .dlg { width: 100%; max-height: 90dvh; border-radius: var(--r-lg) var(--r-lg) 0 0; }
  }
}

/* ---- css/25-charts.css ---- */
/* 25-charts: the chart card and the marks the chart helpers draw. Spec 3.6.

   THE THREE SIGNATURES (rule 3), one class each, used by bars, slices,
   legend swatches and bar-track fills alike:
     .mk-good .mk-warn .mk-bad .mk-changed .mk-neutral   measured: solid
     .mk-nc    not comparable: diagonal hatch (the "≠" is printed in the label)
     .mk-nm    not measured / not read / not recorded: empty dashed outline
   A dashed line means nothing else. Chart marks sit only on --surface. */
@layer components {

  /* ==================================================== chart card ===== */
  .cc {
    display: flex;
    flex-direction: column;
    gap: var(--s-3);
    min-width: 0;
    padding: var(--s-4) var(--s-5) var(--s-5);
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: var(--r-lg);
  }
  .cc-h { display: flex; align-items: flex-start; gap: var(--s-3); }
  .cc-hm { flex: 1; min-width: 0; }
  .cc-t { margin: 0; font-size: var(--fs-14); line-height: var(--lh-14); font-weight: 600; color: var(--text); }
  .cc-s { margin-top: 2px; font-size: var(--fs-12); line-height: var(--lh-12); color: var(--text-3); }
  .cc-h > .btn-t { flex: none; margin: -6px -8px 0 0; }
  /* FIXED heights: an empty or loading plot never moves the layout (spec 3.6:
     200 full width, 180 half, 128 a donut row, 28 per hbars row). The donut
     and hbars heights key on the helper's own root (.dn / .hb) with :has(), so
     they hold for every caller, not only one that remembers a class.
     inline-size containment: the plot takes its card's width, never its
     content's, and the narrow-card query below can ask how wide it is. */
  .cc-plot { position: relative; height: 200px; min-width: 0; container-type: inline-size; }
  .cc-half .cc-plot { height: 180px; }
  /* 128px ring; a legend longer than the ring (7 outcome slices) may grow it */
  .cc-plot:has(> .dn) { height: auto; min-height: 128px; }
  .cc-plot:has(> .hb) { height: auto; }
  .cc-plot > .es, .cc-plot > .sk { height: 100%; min-height: 0; }
  .cc-f { font-size: var(--fs-12); line-height: var(--lh-12); color: var(--text-3); }
  .cc-table { border-top: 1px solid var(--border); }

  /* ============================================ the three signatures ===== */
  .mk-good { background: var(--good); }
  .mk-warn { background: var(--warn-mark); }
  .mk-bad { background: var(--bad); }
  .mk-changed { background: var(--changed); }
  .mk-neutral { background: var(--neutral-mark); }
  /* round 4: a re-reading where nothing moved (Page changes) - the neutral
     mark, lighter, so "first read" and "unchanged" are told apart */
  .mk-same { background: color-mix(in srgb, var(--neutral-mark) 45%, var(--surface)); box-shadow: inset 0 0 0 1px var(--neutral-mark); }
  .mk-nc { background: var(--hatch); box-shadow: inset 0 0 0 1px var(--neutral-mark); }
  .mk-nm { background: transparent; border: 1px dashed var(--border-control); }
  /* the scoring-change rule as a legend swatch: the plot's own mark */
  .mk-rule { background: linear-gradient(var(--border-control), var(--border-control)) center / 2px 100% no-repeat; }

  /* ======================================================== legend ===== */
  .legend { display: flex; flex-wrap: wrap; gap: 6px var(--s-4); font-size: var(--fs-12); line-height: var(--lh-12); }
  .legend.is-v { flex-direction: column; flex-wrap: nowrap; gap: 6px; }
  .lg { display: inline-flex; align-items: center; gap: 6px; min-width: 0; color: var(--text-2); }
  .lg-l { min-width: 0; }
  .lg-n { font-weight: 600; color: var(--text); font-variant-numeric: tabular-nums; }
  .legend.is-v .lg-n { margin-left: auto; padding-left: var(--s-3); }
  .lg.is-zero .lg-n { color: var(--text-3); }
  .lg-sub { padding-left: var(--s-4); color: var(--text-3); }
  .lg-subs { color: var(--text-3); font-variant-numeric: tabular-nums; }
  .sw { display: inline-block; width: 10px; height: 10px; flex: none; border-radius: 2px; }

  /* ================================================ columns (3.6) ===== */
  .cols {
    display: grid;
    grid-template-rows: minmax(0, 1fr) auto;
    height: 100%;
    min-width: calc(var(--n) * 72px);   /* narrower than this, the plot scrolls sideways */
  }
  .cols-plot { position: relative; min-height: 0; }
  .cols-area { position: absolute; inset: 20px 0 0; }
  .cols.has-break .cols-area { top: 38px; }
  .cols-grid > i {
    position: absolute;
    left: 0;
    right: 0;
    height: 0;
    border-top: 1px solid var(--border);
  }
  .cols-grid > i > span {
    position: absolute;
    left: 0;
    bottom: 1px;
    font-style: normal;
    font-size: var(--fs-12);
    line-height: var(--lh-12);
    color: var(--text-3);
    font-variant-numeric: tabular-nums;
  }
  .cols-bars, .cols-x { display: grid; grid-template-columns: repeat(var(--n), minmax(0, 1fr)); }
  .cols-bars { position: absolute; inset: 0; }
  .col { position: relative; display: flex; align-items: flex-end; justify-content: center; min-width: 0; }
  .col-stack {
    position: relative;
    display: flex;
    flex-direction: column-reverse;
    gap: 1.5px;
    width: 56%;
    min-height: 1px;
  }
  .col-stack > i { display: block; min-height: 1px; flex: 1 1 0; }
  .col-v {
    position: absolute;
    bottom: 100%;
    left: 50%;
    padding-bottom: 2px;
    transform: translateX(-50%);
    font-size: var(--fs-12);
    line-height: var(--lh-12);
    font-weight: 600;
    color: var(--text);
    white-space: nowrap;
    font-variant-numeric: tabular-nums;
  }
  /* not read: a 16px empty dashed stub, no number */
  .col-nr { position: relative; width: 56%; height: 16px; border: 1px dashed var(--border-control); border-bottom: 0; }
  .col-nr > .col-v { font-weight: 400; color: var(--text-3); }
  /* not comparable: a 16px hatched stub, its "≠" above it, never a bare 0 */
  .col-nc { position: relative; width: 56%; height: 16px; }
  .col-nc > .col-v { font-weight: 400; color: var(--text-3); }
  /* our scoring changed before this slot: a solid rule (dashed means "not
     measured") from the top gridline down, lighter than any bar, with its
     label above the plot */
  .col.is-break::before {
    content: "";
    position: absolute;
    left: -1px;
    top: 0;
    bottom: 0;
    border-left: 1.5px solid var(--border-control);
  }
  .col-brk {
    position: absolute;
    top: -38px;
    left: 4px;
    font-size: var(--fs-12);
    line-height: var(--lh-12);
    color: var(--text-3);
    white-space: nowrap;
  }
  /* A break before the LAST slot labels to the left of its rule: to the right
     it ran past the card edge and was clipped (measured at 375 and in half-width
     cards). Safe unless the slot before it is also a break, which a stamped
     engine history does not produce in consecutive weeks. */
  .col.is-break:last-child:not(:first-child) > .col-brk { left: auto; right: calc(100% + 4px); }
  .cols-x { padding-top: 6px; border-top: 1px solid var(--border-strong); }
  .col-x { display: flex; flex-direction: column; align-items: center; min-width: 0; padding: 0 2px; text-align: center; }
  .col-x b { font-size: var(--fs-12); line-height: var(--lh-12); font-weight: 500; color: var(--text-2); white-space: nowrap; }
  .col-x small { font-size: var(--fs-12); line-height: var(--lh-12); color: var(--text-3); }
  .cc-plot:has(> .cols) { overflow-x: auto; overflow-y: hidden; }

  /* ================================================== donut (3.6) ===== */
  .dn { display: flex; align-items: center; gap: var(--s-5); height: 100%; min-width: 0; }
  .dn-c { position: relative; width: 128px; height: 128px; flex: none; }
  .dn-c > svg { width: 128px; height: 128px; }
  .dn-t { position: absolute; inset: 0; display: grid; place-content: center; text-align: center; }
  .dn-t b { font-size: var(--fs-20); line-height: var(--lh-20); font-weight: 600; color: var(--text); font-variant-numeric: tabular-nums; }
  .dn-t span { font-size: var(--fs-12); line-height: var(--lh-12); color: var(--text-3); }
  .dn .legend { flex: 1; min-width: 0; }
  .dn-a { fill: none; stroke-width: 14; }
  .dn-a.mk-good { stroke: var(--good); }
  .dn-a.mk-warn { stroke: var(--warn-mark); }
  .dn-a.mk-bad { stroke: var(--bad); }
  .dn-a.mk-changed { stroke: var(--changed); }
  .dn-a.mk-neutral { stroke: var(--neutral-mark); }
  /* the SVG arcs take their signature from stroke/fill, not background */
  .dn-a, .dn-o, .dn-h { background: none; box-shadow: none; border: 0; }
  .dn-o { fill: none; stroke: var(--border-control); stroke-width: 1; stroke-dasharray: 3 2; }
  .dn-h { stroke: var(--neutral-mark); stroke-width: 1; }
  .dn-hl { fill: var(--neutral-mark); }
  /* a total under 2 is a list, not a ring */
  .dn.is-list { display: block; height: auto; }
  .dn.is-list .dn-lt { margin-bottom: var(--s-2); font-size: var(--fs-13); line-height: var(--lh-13); color: var(--text-2); }

  /* ================================================== hbars (3.6) ===== */
  /* The value column is as wide as the widest value, and every row shares it
     through subgrid, so the tracks line up whether a value reads "7 of 11" or
     "6 of 6 pages · 9 findings". A bare count ("2") takes only its own width;
     the 88px floor is for "n of m" text only (.is-of, set by hbars()). */
  .hb {
    display: grid;
    grid-template-columns: minmax(0, 40%) minmax(0, 1fr) max-content;
    column-gap: var(--s-3);
  }
  .hb.is-of { grid-template-columns: minmax(0, 40%) minmax(0, 1fr) minmax(88px, max-content); }
  .hb-r {
    display: grid;
    grid-column: 1 / -1;
    grid-template-columns: subgrid;
    align-items: center;
    min-height: 28px;
  }
  .hb-l { min-width: 0; font-size: var(--fs-13); line-height: var(--lh-13); color: var(--text); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
  .hb-t { height: 8px; border-radius: 2px; background: var(--surface-3); overflow: hidden; }
  .hb-t > i { display: block; height: 100%; border-radius: 2px; }
  .hb-v { text-align: right; font-size: var(--fs-12); line-height: var(--lh-12); color: var(--text-2); font-variant-numeric: tabular-nums; white-space: nowrap; }
  .hb:not(.is-all) > .is-more { display: none; }
  .hb-all { margin-top: var(--s-1); }
  /* A narrow card (a third-width column) stacks the label over the track, as
     the phone layout does, instead of squeezing the track to a stub. */
  @container (max-width: 320px) {
    .hb, .hb.is-of { grid-template-columns: minmax(0, 1fr) max-content; }
    .hb-r { row-gap: 2px; padding: 4px 0; }
    .hb-l { grid-column: 1 / -1; }
  }

  /* ================================================== spark (3.6) ===== */
  .spk { width: 120px; height: 28px; flex: none; }
  .spk-l { fill: none; stroke: var(--text-2); stroke-width: 1.5; stroke-linecap: round; stroke-linejoin: round; }
  .spk-d { stroke: var(--surface); stroke-width: 1; }
  .spk-h { fill: var(--surface); stroke: var(--text-2); stroke-width: 1.25; }
  .spk-p { fill: var(--text-2); }
  .spk-b { stroke: var(--text-3); stroke-width: 1; }
  .spk-hi { fill: var(--good); }
  .spk-mid { fill: var(--warn-mark); }
  .spk-lo { fill: var(--bad); }
}

@layer phone {
  @media (max-width: 767px) {
    .dn { gap: var(--s-4); }
    /* five weeks fit a 375px card (5 x 56 = 280 of ~303px); at 72 the last
       column and its label were cut off behind a sideways scroll */
    .cols { min-width: calc(var(--n) * 56px); }
    /* a 56px slot has no room for the words: the rule keeps its "≠", and the
       legend's "≠ Scoring changed" names it */
    .col-brk-w { display: none; }
    .hb, .hb.is-of { grid-template-columns: minmax(0, 1fr) max-content; }
    .hb-r { row-gap: 2px; padding: 4px 0; }
    .hb-l { grid-column: 1 / -1; }
    /* rule 10: a page link in a bar label is a 44px target */
    .hb-l > a { display: block; padding-block: calc((44px - var(--lh-13)) / 2); overflow: hidden; text-overflow: ellipsis; }
  }
}

/* ---- css/30-shell.css ---- */
/* 30-shell: the frame every view sits in. Build spec section 4 (chunk C1):
   the rail, the second-level panel (nav2), the top bar and .page.

   LAYER ORDER: shell comes BEFORE components, so a component class on a shell
   element (.btn-2 on #siteSel and .credits, .btn-i on #bell) keeps the
   component's own declarations - this file only adds what the component does
   not set (max-width, order, flex). It never restates a component property.

   What the tests hold this file to:
   - smoke:2416  #out and .rail-logo visible, and the rail NOT overflowing, at
                 1340 x 900 / 700 / 600: logo and foot are pinned, only
                 .rail-scroll scrolls.
   - palette.mjs #cmdk wider than 200px, left edge past #creditChip's right
                 edge, right edge before #who's left edge; >200 wide and 44 tall
                 at 375 with no sideways scroll.
   - theme.mjs   #themeSeg visible and >= 44px tall at 375 and 720.
   - sheet.mjs   nav2 is a column on desktop (top 0, full height) and a bottom
                 sheet on phones (<= 86dvh, 12px top radius, a grip, a 44px
                 close, a body::after scrim). */
@layer shell {

  /* ============================================================ shell ===== */
  .shell {
    display: grid;
    grid-template-columns: 72px minmax(0, 1fr);
    min-height: 100dvh;
  }
  body.nav2-open .shell { grid-template-columns: 72px 240px minmax(0, 1fr); }
  .shell > div { min-width: 0; }            /* Bugs/49: a grid item's min-width is auto */

  /* S184 FJ1: the line (then the could-not-open card) shown while the shell is
     hidden behind /me, so a slow or failing API is never a blank white page. */
  .boot { max-width: 520px; margin: 18vh auto 0; padding: 0 var(--s-4); }
  .boot-l { margin-top: var(--s-3); color: var(--text-2); font-size: var(--fs-13); line-height: var(--lh-13); text-align: center; }

  /* ============================================================= rail ===== */
  .rail {
    position: sticky;
    top: 0;
    z-index: 30;
    display: flex;
    flex-direction: column;
    align-items: center;
    height: 100dvh;
    padding: var(--s-2) var(--s-1);
    background: var(--frame);
    border-right: 1px solid var(--border);
  }
  /* The Q monogram (the robot is gone): white on the accent square. */
  .rail-logo {
    flex: none;
    display: grid;
    place-items: center;
    width: 40px;
    height: 40px;
    margin-bottom: var(--s-2);
    border-radius: var(--r-md);
  }
  .rail-logo svg { width: 32px; height: 32px; }
  .rl-bg { fill: var(--accent); }
  .rl-q { fill: none; stroke: var(--on-accent); stroke-width: 2.75; stroke-linecap: round; }

  /* Only the middle scrolls; its scrollbar is hidden so the 64px column keeps
     its width for the labels (a wheel, a trackpad and touch still scroll it). */
  .rail-scroll {
    flex: 1;
    min-height: 0;
    width: 100%;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 2px;
    overflow-x: hidden;
    overflow-y: auto;
    overscroll-behavior: contain;
    scrollbar-width: none;
  }
  .rail-scroll::-webkit-scrollbar { display: none; }
  .rail-foot {
    flex: none;
    width: 100%;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 2px;
  }

  .rail button {
    flex: none;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 3px;
    width: 100%;
    min-height: 52px;
    padding: 6px 2px;
    border-radius: var(--r-md);
    color: var(--text-3);
    transition: background-color var(--dur-1) var(--ease), color var(--dur-1) var(--ease);
  }
  .rail button:hover { background: var(--surface-2); color: var(--text-2); }
  /* The one "you are here" rule (it replaces nine). */
  .rail button[aria-current="page"] { background: var(--accent-wash); color: var(--accent-text); }
  .rail button:focus-visible { outline-offset: -2px; }
  .rail-i {
    flex: none;
    width: 20px;
    height: 20px;
    fill: none;
    stroke: currentColor;
    stroke-width: 1.75;
    stroke-linecap: round;
    stroke-linejoin: round;
  }
  .rail-l {
    max-width: 100%;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    font-size: var(--fs-11);
    line-height: var(--lh-11);
    font-weight: 500;
  }
  .rail-sep {
    flex: none;
    width: 32px;
    margin: var(--s-2) auto;
    border: 0;
    border-top: 1px solid var(--border);
  }
  /* Short windows. The rail is 9 places + a 3-button foot (IA_SPEC 1.2, down
     from 17 + foot): at 52px each it measures about 761px, so a 795px window
     (Search Atlas's viewport) keeps the full size and only windows shorter
     than 780px tighten, to about 555px - #out and the logo stay in view at
     600px. Below that the middle scrolls; the foot and logo never move. */
  @media (max-height: 779px) {
    .rail-scroll, .rail-foot { gap: 1px; }
    .rail button { min-height: 38px; gap: 1px; padding: 2px; }
    .rail-i { width: 18px; height: 18px; }
    .rail-sep { margin: 4px auto; }
    .rail-logo { margin-bottom: var(--s-1); }
  }

  /* ========================================================= top bar ===== */
  .top {
    position: sticky;
    top: 0;
    z-index: 20;
    display: flex;
    align-items: center;
    gap: var(--s-3);
    height: 56px;
    padding: 0 var(--s-6);
    background: var(--frame);
    border-bottom: 1px solid var(--border);
  }

  /* 1. The site selector: a letter tile (we store no favicons), the host,
        the worst page's score cell, a chevron. */
  .site-sel { flex: 0 1 auto; min-width: 0; max-width: 280px; }
  .ss-tile {
    flex: none;
    display: grid;
    place-items: center;
    width: 20px;
    height: 20px;
    border-radius: var(--r-sm);
    background: var(--surface-3);
    color: var(--text-2);
    font-size: var(--fs-11);
    line-height: var(--lh-11);
    font-weight: 600;
  }
  .ss-tile svg { width: 14px; height: 14px; }
  .ss-host {
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    color: var(--text-2);
  }
  .site-sel.is-open-site .ss-host { color: var(--text); }
  .ss-sc { flex: none; display: inline-flex; }
  .ss-sc:empty { display: none; }
  .ss-chev { fill: none; stroke: var(--text-3); stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; }

  /* 2. The credits pill: the plan, a hairline, the balance. */
  .credits { flex: none; }
  .credits:has(.cr-plan:empty):has(.cr-n:empty) { visibility: hidden; }
  .cr-plan { color: var(--text-2); font-weight: 400; }
  .cr-plan b { color: var(--text); font-weight: 500; }
  .cr-n {
    padding-left: var(--s-2);
    border-left: 1px solid var(--border-strong);
    color: var(--text-2);
    font-weight: 400;
    font-variant-numeric: tabular-nums;
  }
  .cr-n b { color: var(--text); font-weight: 600; }
  .cr-plan:empty, .cr-n:empty { display: none; }
  .cr-plan:empty + .cr-n { padding-left: 0; border-left: 0; }

  /* 3. Search. The space after it is the bar's only flexible gap, so the
        account controls sit at the right edge. */
  .cmdk {
    position: relative;
    flex: 1 1 220px;
    min-width: 220px;
    max-width: 520px;
    margin-right: auto;
  }
  .cmdk-i {
    position: absolute;
    left: 10px;
    top: 50%;
    width: 16px;
    height: 16px;
    margin-top: -8px;
    color: var(--text-3);
    stroke-width: 1.75;
    pointer-events: none;
  }
  .cmdk input {
    width: 100%;
    height: 32px;
    padding: 0 64px 0 32px;
    background: var(--surface-2);
  }
  .cmdk input:focus-visible { background: var(--surface); }
  .cmdk input::-webkit-search-cancel-button { -webkit-appearance: none; appearance: none; }
  .cmdk-k {
    position: absolute;
    right: 8px;
    top: 50%;
    margin-top: -10px;
    padding: 0 6px;
    border: 1px solid var(--border-strong);
    border-radius: var(--r-sm);
    background: var(--surface);
    color: var(--text-3);
    font-family: var(--sans);
    font-size: var(--fs-11);
    line-height: 18px;
    font-weight: 500;
    pointer-events: none;
  }
  .cmdk-panel {
    position: absolute;
    top: calc(100% + 4px);
    left: 0;
    right: 0;
    z-index: 60;
    min-width: 320px;
    max-height: min(420px, 70vh);
    overflow-y: auto;
    padding: var(--s-1);
    background: var(--surface);
    border: 1px solid var(--border-strong);
    border-radius: var(--r-lg);
    box-shadow: var(--e1);
    animation: q-menu-in var(--dur-2) var(--ease);
  }
  .cmdk-list li[data-n] {
    display: grid;
    grid-template-columns: 88px minmax(0, 1fr) auto;
    align-items: center;
    column-gap: var(--s-3);
    min-height: 36px;
    padding: var(--s-1) 10px;
    border-radius: var(--r-md);
    cursor: pointer;
  }
  .cmdk-list li[data-n]:hover, .cmdk-list li.on { background: var(--surface-2); }
  .cmdk-kind {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    font-size: var(--fs-12);
    line-height: var(--lh-12);
    color: var(--text-3);
  }
  .cmdk-label {
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    font-size: var(--fs-13);
    line-height: var(--lh-13);
    font-weight: 500;
    color: var(--text);
  }
  .cmdk-label .chip { margin-left: 6px; white-space: nowrap; }
  .cmdk-meta {
    white-space: nowrap;
    font-size: var(--fs-12);
    line-height: var(--lh-12);
    color: var(--text-3);
    font-variant-numeric: tabular-nums;
  }
  .cmdk-none { padding: var(--s-2) 10px; font-size: var(--fs-13); line-height: var(--lh-13); color: var(--text-2); }
  /* The audit form, filled from search but NOT submitted (it spends credits):
     the Run button is ringed so the customer sees what to press. No motion. */
  .run-armed { outline: 2px solid var(--accent-text); outline-offset: 2px; }

  /* 4. What changed. The count is the accent (news); unread is a muted dash
        on surface-3 - never the accent, an unread state is not news. */
  .bell { position: relative; flex: none; }
  /* On the icon's top-right CORNER, outside the glyph: at top:1px/right:0 a
     two-digit pill covered the 20px bell and the control read as a stray
     number. The count is capped at "9+" (the full count is in the label). */
  .bell-n {
    position: absolute;
    top: 2px;
    right: 2px;
    transform: translate(35%, -35%);
    box-shadow: 0 0 0 2px var(--frame);
    display: block;
    min-width: 16px;
    height: 16px;
    padding: 0 4px;
    border-radius: var(--r-full);
    background: var(--accent);
    color: var(--on-accent);
    font-size: var(--fs-11);
    line-height: 16px;
    font-weight: 600;
    text-align: center;
    font-variant-numeric: tabular-nums;
    pointer-events: none;
  }
  .bell-n.bell-unknown { background: var(--surface-3); color: var(--text-2); }

  /* 5. Who you are. textContent is the email (account deletion compares it);
        the avatar letter and the chevron are pseudo-elements, not text. */
  .acct { position: relative; flex: 0 1 auto; min-width: 0; display: flex; }
  .who {
    position: relative;
    display: block;
    min-width: 0;
    max-width: 180px;
    height: 32px;
    padding: 0 26px 0 36px;
    border-radius: var(--r-md);
    color: var(--text-2);
    font-size: var(--fs-13);
    line-height: 32px;
    font-weight: 500;
    text-align: left;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    transition: background-color var(--dur-1) var(--ease), color var(--dur-1) var(--ease);
  }
  /* the email had ~150px of free bar beside it and was cut to "demo@quinndatu…" */
  @media (min-width: 1280px) { .who { max-width: 240px; } }
  .who:hover, .who[aria-expanded="true"] { background: var(--surface-2); color: var(--text); }
  .who::before {
    content: attr(data-initial);
    position: absolute;
    left: 4px;
    top: 50%;
    width: 24px;
    height: 24px;
    margin-top: -12px;
    border-radius: var(--r-full);
    background: var(--accent-wash);
    color: var(--accent-text);
    font-size: var(--fs-12);
    line-height: 24px;
    font-weight: 600;
    text-align: center;
  }
  .who::after {
    content: "";
    position: absolute;
    right: 11px;
    top: 50%;
    width: 6px;
    height: 6px;
    margin-top: -5px;
    border-right: 1.5px solid var(--text-3);
    border-bottom: 1.5px solid var(--text-3);
    transform: rotate(45deg);
  }

  /* 6. The theme: three icon buttons on a track; the words are .sr-only and
        aria-pressed carries the STORED choice. */
  .theme-seg {
    flex: none;
    display: inline-flex;
    align-items: center;
    gap: 2px;
    height: 32px;
    padding: 1px;
    background: var(--surface-2);
    border: 1px solid var(--border);
    border-radius: var(--r-md);
  }
  .theme-seg button {
    display: grid;
    place-items: center;
    width: 28px;
    height: 28px;
    border-radius: var(--r-sm);
    color: var(--text-3);
    transition: background-color var(--dur-1) var(--ease), color var(--dur-1) var(--ease);
  }
  .theme-seg button:hover { color: var(--text); }
  .theme-seg button[aria-pressed="true"] {
    background: var(--surface);
    color: var(--text);
    box-shadow: 0 0 0 1px var(--border-strong);
  }
  .theme-seg svg {
    width: 16px;
    height: 16px;
    fill: none;
    stroke: currentColor;
    stroke-width: 1.75;
    stroke-linecap: round;
    stroke-linejoin: round;
  }

  /* The site selector's menu: the worst page's score cell beside each host. */
  .menu-sites .mi > .sc { flex: none; }

  /* ============================================================ page ===== */
  .page {
    display: grid;
    gap: var(--s-4);
    align-content: start;
    width: 100%;
    max-width: 1248px;
    margin: 0 auto;
    padding: var(--s-7) var(--s-7) 80px;
  }
  .page > * { min-width: 0; }
  /* Anything scrolled to (a route's &at= target, a finding, a report opened
     from a list) lands BELOW the sticky 56px bar - the top bar, or the rail
     row on phones - not under it: a heading behind the bar reads as the
     wrong card. The document is the scroller, so this sits on html. */
  html { scroll-padding-top: calc(56px + var(--s-4)); }

  /* ============================================ nav2: the second level ===== */
  .nav2 {
    position: sticky;
    top: 0;
    width: 240px;
    height: 100dvh;
    overflow-y: auto;
    overscroll-behavior: contain;
    padding: 0 var(--s-3) var(--s-6);
    background: var(--frame);
    border-right: 1px solid var(--border);
    color: var(--text);
    scrollbar-width: thin;
    scrollbar-color: var(--border-strong) transparent;
  }
  .n2-grip { display: none; }
  .n2-head {
    position: sticky;
    top: 0;
    z-index: 1;
    display: flex;
    align-items: center;
    gap: var(--s-2);
    height: 56px;
    margin: 0 calc(-1 * var(--s-3));
    padding: 0 var(--s-3) 0 var(--s-4);
    background: var(--frame);
    border-bottom: 1px solid var(--border);
  }
  .n2-head h2 { font-size: var(--fs-14); line-height: var(--lh-14); font-weight: 600; letter-spacing: 0; }
  .n2-close { flex: none; }                 /* a .btn-i; sheet.mjs measures it at 44px on phones */
  /* .n2-count ("N entries") is gone from the panel head (R2, IA_SPEC 1.6). */
  .n2-conv {
    margin: var(--s-3) var(--s-2) 0;
    font-size: var(--fs-12);
    line-height: var(--lh-12);
    color: var(--text-3);
  }
  .nav2 h4 {
    margin: var(--s-4) var(--s-2) var(--s-1);
    font-size: var(--fs-12);
    line-height: var(--lh-12);
    font-weight: 500;
    color: var(--text-3);
  }
  .nav2 ul { display: flex; flex-direction: column; gap: 1px; margin: 0; padding: 0; list-style: none; }
  /* icon | label, with a state chip (when there is one) on its own line
     under the label - beside it, the chip squeezed labels to four lines. */
  .nav2 li button {
    display: grid;
    grid-template-columns: 16px minmax(0, 1fr);
    align-items: start;
    column-gap: var(--s-2);
    row-gap: var(--s-1);
    width: 100%;
    min-height: 32px;
    padding: 7px var(--s-2);
    border-radius: var(--r-md);
    color: var(--text-2);
    font-size: var(--fs-13);
    line-height: 18px;
    font-weight: 500;
    text-align: left;
    transition: background-color var(--dur-1) var(--ease), color var(--dur-1) var(--ease);
  }
  .nav2 li button:hover { background: var(--surface-2); color: var(--text); }
  .nav2 li button[aria-current] { background: var(--surface-3); color: var(--accent-text); }
  .nav2 li button:focus-visible { outline-offset: -2px; }
  .nav2 li button svg { width: 16px; height: 16px; margin-top: 1px; stroke-width: 1.75; color: var(--text-3); }
  .nav2 li button:hover svg, .nav2 li button[aria-current] svg { color: inherit; }
  .n2-label { min-width: 0; }
  .nav2 li .n2-state { grid-column: 2; justify-self: start; white-space: nowrap; }
  /* .n2-note is gone with #n2Note (IA_SPEC 1.6): no entry ends in a note;
     its reasons are the not-available pages. */

  /* ============================================ tablet 768 - 1099 ===== */
  @media (max-width: 1099px) {
    .top { gap: var(--s-2); padding: 0 var(--s-4); }
    .page { padding: var(--s-6) var(--s-6) 80px; }
    .site-sel { max-width: 200px; }
    .cmdk { min-width: 160px; }
    .cr-plan { display: none; }
    .cr-plan + .cr-n { padding-left: 0; border-left: 0; }
    /* The email stays the button's text (and its accessible name); only
       the avatar shows. */
    .who { width: 32px; padding: 0; text-indent: 200%; text-overflow: clip; }
    .who::before { text-indent: 0; }
    .who::after { display: none; }
  }
}

/* ======================================================= phones <= 767 ===== */
@layer phone {
  @media (max-width: 767px) {
    .shell, body.nav2-open .shell { grid-template-columns: minmax(0, 1fr); }

    /* The rail is a 56px row that scrolls sideways, and STAYS at the top: on
       a 7,987px Home the nav otherwise scrolled away with no way back. The
       right edge fades, so a cut label reads as "more this way". */
    .rail {
      position: sticky;
      top: 0;
      z-index: 20;
      -webkit-mask-image: linear-gradient(to right, var(--bg) calc(100% - 28px), transparent);
      mask-image: linear-gradient(to right, var(--bg) calc(100% - 28px), transparent);
      flex-direction: row;
      gap: 2px;
      height: 56px;
      padding: 0 var(--s-2);
      border-right: 0;
      border-bottom: 1px solid var(--border);
      overflow-x: auto;
      overflow-y: hidden;
      scrollbar-width: none;
    }
    .rail::-webkit-scrollbar { display: none; }
    .rail-logo { width: 44px; height: 44px; margin: 0 var(--s-1) 0 0; }
    .rail-scroll, .rail-foot { flex: none; width: auto; flex-direction: row; overflow: visible; }
    .rail button { width: 64px; min-height: 48px; padding: var(--s-1) 2px; }
    .rail-sep { width: 0; height: 32px; margin: 0 var(--s-1); border-top: 0; border-left: 1px solid var(--border); }

    /* The top bar on TWO rows (three plus the rail took ~225px of 812):
         site selector ........... bell  you
         search .............. theme
       The credits pill is left out here: at 375 it squeezed the site
       selector to "Choo..."; the balance is Home's CREDITS tile and the Plan
       view, both one tap away on the rail. */
    .top {
      position: static;
      display: grid;
      grid-template-columns: minmax(0, 1fr) auto 44px 44px;
      grid-template-areas: "site site bell who" "cmdk theme theme theme";
      gap: var(--s-2);
      height: auto;
      /* 12px sides and a gapless theme track keep search over 200px wide at
         375 beside the three 44px theme buttons (palette.mjs) */
      padding: var(--s-2) var(--s-3);
    }
    .theme-seg { gap: 0; }
    .credits { display: none; }
    .cmdk-k { display: none; }   /* a keyboard shortcut on a touch layout */
    .bell { grid-area: bell; }
    .acct { grid-area: who; justify-self: end; }
    .site-sel { grid-area: site; justify-self: stretch; max-width: none; }
    .theme-seg { grid-area: theme; justify-self: end; height: auto; }
    .cmdk { grid-area: cmdk; min-width: 0; max-width: none; margin-right: 0; align-self: center; }
    .cmdk input { padding-right: 12px; }
    .cmdk-panel { min-width: 0; }
    .theme-seg button { width: 44px; height: 44px; }
    .who { width: 44px; height: 44px; line-height: 44px; }
    .who::before { left: 10px; line-height: 24px; }

    .page { padding: var(--s-4) var(--s-4) var(--s-10); }

    /* nav2 is a bottom SHEET: anchored low, capped so the page shows above
       it, rounded at the top, over a scrim that closes it on tap. The grip
       is the only drag surface (JS sets --n2-drag). */
    body.nav2-open { overflow: hidden; }
    body.nav2-open::after {
      content: "";
      position: fixed;
      inset: 0;
      z-index: 39;
      background: var(--scrim);
    }
    .nav2 {
      --n2-drag: 0px;
      position: fixed;
      left: 0;
      right: 0;
      bottom: 0;
      top: auto;
      z-index: 40;
      width: auto;
      height: auto;
      max-height: 86dvh;
      padding: 0 var(--s-4) calc(var(--s-5) + env(safe-area-inset-bottom, 0px));
      border-right: 0;
      border-top: 1px solid var(--border);
      border-radius: var(--r-lg) var(--r-lg) 0 0;
      box-shadow: var(--e2);
      transform: translateY(var(--n2-drag));
      transition: transform var(--dur-3) var(--ease);
    }
    .nav2.n2-dragging { transition: none; }
    .n2-grip {
      display: block;
      position: sticky;
      top: 0;
      z-index: 2;
      margin: 0 calc(-1 * var(--s-4));
      padding: 10px 0 8px;
      border-radius: var(--r-lg) var(--r-lg) 0 0;
      background: var(--frame);
      touch-action: none;
      cursor: grab;
    }
    .n2-grip:active { cursor: grabbing; }
    .n2-grip span {
      display: block;
      width: 40px;
      height: 4px;
      margin: 0 auto;
      border-radius: var(--r-full);
      background: var(--border-control);
    }
    .n2-head { top: 22px; margin: 0 calc(-1 * var(--s-4)); padding: 0 var(--s-2) 0 var(--s-4); }
  }
}

/* ---- css/32-nav2.css ---- */
/* 32-nav2: the second-level panel's entries (Sprint 178 part 2, IA_SPEC 1.3-1.6).
   30-shell.css keeps the panel's frame (column, head, sheet, grip); this file
   styles what goes inside it: the site context block, one-line entries with
   an optional right-aligned chip or badge, disabled entries with their reason,
   and the collapsible "Not available yet" group. Same layer as 30-shell and
   later in the build, so an equal selector here wins. */
@layer shell {
  /* The current site, carried into every area. */
  .n2-head .n2-close { margin-left: auto; }
  .n2-ctx {
    margin: 0 calc(-1 * var(--s-3)) var(--s-2);
    padding: var(--s-2) var(--s-3) var(--s-3);
    border-bottom: 1px solid var(--border);
  }
  /* A .btn-2: the components layer outranks this one, so only properties the
     button family does not set are set here (width, height; the host grows). */
  .n2-site { width: 100%; height: 36px; }
  .n2-site .ss-host { flex: 1 1 auto; text-align: left; color: var(--text); }
  /* round 4: at 240px the host was cut ("quintarth..." beside "74/100"); the
     score keeps its ring and number here, the scale is in the button's label */
  .n2-site .sc > i { display: none; }
  .n2-ctx-s {
    margin-top: var(--s-2);
    font-size: var(--fs-12);
    line-height: var(--lh-12);
    color: var(--text-3);
  }

  /* Group headings: 12/500 text-3, sentence case. */
  .nav2 h4 { margin: var(--s-4) var(--s-3) var(--s-1); }

  /* One entry, one line: icon, label (ellipsis), then a chip or a badge
     pushed right. 1-3 word labels, so nothing wraps at 240px. */
  .nav2 li button {
    display: flex;
    align-items: center;
    gap: var(--s-2);
    height: 32px;
    min-height: 32px;
    padding: 0 var(--s-2);
    white-space: nowrap;
  }
  .nav2 li button svg { flex: none; margin-top: 0; }
  .n2-label { flex: 1 1 auto; overflow: hidden; text-overflow: ellipsis; }
  .nav2 li .n2-state, .nav2 li .n2-badge { flex: none; margin-left: auto; }
  .n2-badge { min-width: 20px; text-align: center; }

  /* You are here: Search Atlas's left bar, in our accent. */
  .nav2 li button[aria-current] {
    background: var(--surface-3);
    color: var(--accent-text);
    box-shadow: inset 2px 0 0 var(--accent-text);
  }

  /* Needs a site: focusable and announced, text-3, no hover fill. The reason
     is printed once under the group heading (.n2-need), never hover-only. */
  .nav2 li button[aria-disabled="true"],
  .nav2 li button[aria-disabled="true"]:hover { background: transparent; color: var(--text-3); cursor: default; }
  .nav2 li button[aria-disabled="true"] svg { color: var(--text-3); }
  .n2-need {
    margin: 0 var(--s-3) var(--s-1);
    font-size: var(--fs-12);
    line-height: var(--lh-12);
    color: var(--text-3);
  }

  /* "Not available yet (n)": the last group, collapsed by default. */
  .n2-grp {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--s-2);
    width: 100%;
    min-height: 32px;
    border-radius: var(--r-md);
    text-align: left;
  }
  .n2-grp:hover { color: var(--text); }
  .n2-grp:focus-visible { outline-offset: -2px; }
  .n2-grp svg {
    flex: none;
    width: 16px;
    height: 16px;
    stroke-width: 1.75;
    transition: transform var(--dur-1) var(--ease);
  }
  .n2-grp[aria-expanded="true"] svg { transform: rotate(180deg); }
  .nav2 h4:has(> .n2-grp) { margin-bottom: 0; }
  /* Inside it, each reason once, as a chip over the rows it applies to: a
     chip beside each label does not fit at 240px. */
  .n2-why { margin: var(--s-2) var(--s-2) var(--s-1); }
  .nav2 .n2-conv { margin-top: var(--s-6); }
}

@layer phone {
  @media (max-width: 767px) {
    .nav2 li button { height: auto; min-height: 44px; }
    .n2-site { height: auto; }
    .n2-grp { min-height: 44px; }
    /* rule 10 for the reason lines' links */
    .n2-need a, .n2-ctx-s a { display: inline-flex; align-items: center; min-height: 44px; }
  }
}

/* ---- css/40-home.css ---- */
/* 40-home: Home (#hero + #overview + #hubCard + #tourCard + .pinned) and the
   Audit form (#hero on the audit view). Sprint 178 build spec section 5
   (chunk C2) and IA spec section 4 (chunk A1, Home as a launcher). Tokens
   only: the build refuses colour and font-size literals.

   Contracts this file keeps (IA spec section 7, A1 row):
   - #hero is visible on Home; #intents (one "All playbooks" link since the
     final repair: the Audit view is a quick action, not a second library) is
     HIDDEN on Home. #hubCard lives INSIDE #hero, directly under the audit box
     (final repair: the cards first, the KPIs and "Your sites" after them), so
     the view rules cannot reach it: it is hidden here off Home.
   - KPI tiles are .kpi (C0); .ov-t/.ov-v/.ov-s are hooks, styled only as .kpi*.
     2 per row at 375 comes from C0's phone rule on .kpis.
   - "Your sites": every .ov-proj li is in the DOM (= hosts); the first five
     show. .hc-grid is 3/2/1 columns (>=1100 / 768-1099 / phone).
   FLEX AND INLINE TAGS (CLAUDE.md 5.2): .hc-h, .hc-item and .hc-f
   are flex; every piece in them is its own element on purpose (renderHomeCards
   emits each value as its own span/a/chip). .ov-path/.tour-steps items and
   .pinned are blocks, so their inline <b> stays inside the sentence. */
@layer views {

  /* =========================================== #hero: header and ask ===== */
  /* S184 FJ8: an explicit minmax(0, 1fr) track. The implicit auto track grew to the home
     cards' min-content (nowrap actions) and pushed 320px screens 7-15px sideways. */
  .hero { display: grid; grid-template-columns: minmax(0, 1fr); gap: var(--s-4); min-width: 0; }
  .hero-ph { margin: 0; }
  /* reserve the sub-line so the header does not jump when /trend answers */
  #heroSub { min-height: var(--lh-13); }

  .ask { display: flex; align-items: center; gap: var(--s-2); max-width: 680px; }
  .ask input { flex: 1; min-width: 0; max-width: 560px; min-height: 40px; }
  .ask .btn-p { flex: none; }

  /* The ask's state, said before Run is pressed. #gate carries a <b> and a
     sentence from gateRun(): a BLOCK banner, not the flex one, or the two
     would split into side-by-side columns. */
  #gate.banner { display: block; }
  .hero .err { margin: 0; max-width: 680px; }
  .quota { font-size: var(--fs-12); line-height: var(--lh-12); color: var(--text-3); }
  .quota b { font-weight: 500; color: var(--text-2); font-variant-numeric: tabular-nums; }
  .quota:empty { display: none; }
  /* on Home the AUDITS THIS MONTH tile already says it, with its bar */
  .page[data-view="home"] .quota { display: none; }
  .page[data-view="home"] .hero-basis { display: none; }

  /* With a result on screen the result comes first; the ask stays below it
     (spec section 5). Scoped to the audit view: on Home this would push
     #hero under the job cards. .pinned is last on both views. */
  .page[data-view="audit"]:has(> #result:not([hidden])) > #hero { order: 1; }
  /* ...and under a result it is a tool bar, not a second Audit view: no
     header and no basis. */
  .page[data-view="audit"]:has(> #result:not([hidden])) > #hero > :is(.hero-ph, .hero-basis) { display: none; }
  .pinned {
    order: 2;
    max-width: 72ch;
    font-size: var(--fs-12);
    line-height: var(--lh-12);
    color: var(--text-3);
  }
  .pinned b { font-weight: 500; color: var(--text-2); }

  /* ================================================ the intents ===== */
  .intents { display: grid; gap: var(--s-3); min-width: 0; }
  .intents-all { justify-self: start; margin-left: calc(-1 * var(--s-2)); }

  /* Home is a launcher (IA spec 4): the job cards carry one action per area,
     so the library link shows on the Audit view only. */
  .page[data-view="home"] #intents { display: none; }
  /* The launcher sits inside #hero (the view rules match direct children
     only), so it is hidden here on every other view. 16px grid gap + 8 = the
     24px section gap under the ask. */
  .page:not([data-view="home"]) #hubCard { display: none; }
  #hero > #hubCard { margin-top: var(--s-2); }

  /* ============================================ #overview (Home) ===== */
  .ov { display: grid; gap: var(--s-4); min-width: 0; }

  /* "Your sites": the table bleeds to the card's edges so its hairlines do;
     cells keep the card's 20px inset. Each row is ONE link (li > a.tbl-r) to
     the host's Website overview; every li stays in the DOM, five show. */
  .ov-tbl { --cols: minmax(0, 1fr) 88px 88px 96px 144px 56px; margin: 0 calc(-1 * var(--s-5)); }
  .ov-tbl .tbl-h, .ov-tbl .tbl-r { padding: 0 var(--s-5); }
  .ov-tbl .tbl-h .tc-n { color: inherit; }
  .ov-proj > li:nth-child(n+6) { display: none; }
  .ov-proj > li:is(:last-child, :nth-child(5)) > .tbl-r { border-bottom: 0; }
  .ov-tbl .tbl-r .tc-n { color: var(--text-2); }
  /* Sprint 180 item 1: with the site score (the mean) the worst page is a
     second, smaller cell beside it */
  .ov-tbl.ov-mean { --cols: minmax(0, 1fr) 104px 96px 80px 88px 144px 56px; }
  .ov-w { font-size: var(--fs-12); line-height: var(--lh-12); color: var(--text-3); white-space: nowrap; }
  .ov-w > b { font-weight: 600; color: var(--text-2); font-variant-numeric: tabular-nums; }
  /* "Score 22 (older scoring)" is wider than its 104px column: with nowrap it
     ran under the Worst page cell ("(older scoringworst 22", round 3). It
     wraps inside its own cell instead. */
  .ov-w.ov-old { white-space: normal; min-width: 0; }
  /* "5 of 6 shown" beside "All 6 sites" */
  .ov-shown { margin-left: auto; font-size: var(--fs-12); line-height: var(--lh-12); color: var(--text-3); white-space: nowrap; }
  /* the row's own "View": the whole row is the link, this names where it goes */
  .ov-view { justify-self: end; font-weight: 500; color: var(--accent-text); }
  .ov-tbl a.tbl-r:hover .ov-view { text-decoration: underline; }

  /* zero state: one line, then the numbered path (shared with the tour) */
  .ov-first { max-width: 72ch; font-size: var(--fs-13); line-height: var(--lh-13); color: var(--text-2); }
  .ov-path, .tour-steps {
    display: grid;
    grid-template-columns: repeat(3, minmax(0, 1fr));
    gap: var(--s-4);
    counter-reset: qd-step;
  }
  .ov-path > li, .tour-steps > li {
    position: relative;
    padding-top: 32px;
    counter-increment: qd-step;
    font-size: var(--fs-13);
    line-height: var(--lh-13);
    color: var(--text-2);
  }
  .ov-path > li::before, .tour-steps > li::before {
    content: counter(qd-step);
    position: absolute;
    top: 0;
    left: 0;
    display: grid;
    place-items: center;
    width: 24px;
    height: 24px;
    border-radius: var(--r-full);
    background: var(--surface-2);
    color: var(--text);
    font-size: var(--fs-12);
    line-height: var(--lh-12);
    font-weight: 600;
    font-variant-numeric: tabular-nums;
  }
  .ov-path b, .tour-steps b { font-weight: 600; color: var(--text); }

  .ov-start { gap: var(--s-4); }

  /* could not load: sized like the strip + cards it stands in for */
  .ov-fail { min-height: 200px; justify-content: center; }

  /* loading: the strip, then one "Your sites" card */
  .ov-sk { gap: var(--s-2); }
  .ov-sk-card { gap: var(--s-3); overflow: hidden; }

  /* ====================================== #hubCard, the launcher ===== */
  /* Three job groups, two area cards each (IA spec 4). A card is a surface
     with a hairline, never a shadow, and never moves (rule 6). */
  #hubCard { display: grid; gap: var(--s-4); min-width: 0; }
  #hcBan:empty { display: none; }
  .hc-grid { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: var(--s-4); align-items: start; }
  .hc-g { display: grid; gap: var(--s-3); min-width: 0; }
  .hc-gt { margin: 0; font-size: var(--fs-14); line-height: var(--lh-14); font-weight: 600; color: var(--text); letter-spacing: 0; }
  .hc {
    display: flex;
    flex-direction: column;
    gap: var(--s-3);
    min-width: 0;
    min-height: 168px;
    padding: var(--s-4) var(--s-5);
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: var(--r-lg);
  }
  .hc-h { display: flex; align-items: flex-start; gap: var(--s-3); min-width: 0; }
  .hc-i {
    flex: none;
    width: 20px;
    height: 20px;
    fill: none;
    stroke: currentColor;
    stroke-width: 1.75;
    stroke-linecap: round;
    stroke-linejoin: round;
    color: var(--text-2);
  }
  .hc-hm { flex: 1; min-width: 0; }
  .hc-t { margin: 0; font-size: var(--fs-14); line-height: var(--lh-14); font-weight: 600; color: var(--text); letter-spacing: 0; }
  .hc-s { margin-top: 2px; font-size: var(--fs-13); line-height: var(--lh-13); color: var(--text-2); }

  /* your latest item: ONE line of data. The link takes the ellipsis; the
     score, chip and date keep their width. */
  .hc-item {
    display: flex;
    align-items: center;
    gap: var(--s-2);
    min-width: 0;
    min-height: 24px;
    font-size: var(--fs-13);
    line-height: var(--lh-13);
    color: var(--text-2);
  }
  .hc-item > * { flex: none; }
  .hc-item > :is(.hc-link, .hc-none) { flex: 0 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  /* round 4: an address is read whole ("quinndatum.com/sample-audi..." cut
     at 193px on desktop); it wraps at any character instead */
  .hc-item > .hc-link { white-space: normal; overflow-wrap: anywhere; text-overflow: clip; }
  .hc-link { font-weight: 500; color: var(--text); }
  .hc-link:hover { color: var(--accent-text); }
  .hc-when { color: var(--text-3); font-variant-numeric: tabular-nums; white-space: nowrap; }
  .hc-none { color: var(--text-3); }
  .hc-item > .hc-sk { flex: 0 1 70%; height: 12px; }
  /* Sprint 180 item 14 (s180_f1): the SEO card's item is two lines, the site
     score and then the latest report, each laid out as the one line above */
  .hc-item > .hc-rows { flex: 1 1 auto; display: grid; gap: var(--s-1); min-width: 0; }
  .hc-row { display: flex; align-items: center; gap: var(--s-2); min-width: 0; }
  .hc-row > * { flex: none; }
  .hc-row > :is(.hc-link, .hc-none) { flex: 0 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  .hc-row > .hc-sk { flex: 0 1 70%; height: 12px; }
  .hc-k { color: var(--text-3); }
  /* Sprint 180 live repair. A short label keeps its width and the sentence
     after it takes the ellipsis ("Site sc…" on a phone); the AEO chips sit on
     their own line under the site name ("qui…" beside them). */
  .hc-row > .hc-lbl { flex: none; }
  .hc-row > .hc-when { flex: 0 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; }
  /* a figure's denominator and a report's age are never cut: the row wraps */
  .hc-row.is-wrap { flex-wrap: wrap; row-gap: 2px; }
  .hc-row.is-wrap > .hc-when { overflow: visible; white-space: normal; }
  .hc-row.is-wrap > .hc-link { white-space: normal; overflow-wrap: anywhere; }
  .hc-item:has(> .hc-chips) { flex-wrap: wrap; row-gap: var(--s-1); }
  .hc-item > .hc-chips { flex: 1 1 100%; min-width: 0; }

  /* one action (the tool's short label), then "Open {Area}" */
  .hc-f { display: flex; flex-wrap: wrap; align-items: center; gap: var(--s-2) var(--s-3); margin-top: auto; }
  .hc-act { flex: none; }
  .hc-go { margin-left: auto; }

  /* ========================================= #tourCard (new accounts) ===== */
  .tour { display: grid; gap: var(--s-4); }
  .tour-h { display: flex; align-items: center; gap: var(--s-3); }
  .tour-t { flex: 1; min-width: 0; font-size: var(--fs-14); line-height: var(--lh-14); font-weight: 600; letter-spacing: 0; }
  .tour-back { font-size: var(--fs-12); line-height: var(--lh-12); color: var(--text-3); }

  /* ====================================================== tablet ===== */
  @media (max-width: 1099px) {
    .hc-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  }
}

@layer phone {
  @media (max-width: 767px) {
    .ask input { min-height: 44px; }
    .ov-tbl { margin: 0 calc(-1 * var(--s-5)); }
    .ov-tbl .tbl-r { padding: var(--s-2) var(--s-5); }
    .ov-path, .tour-steps { grid-template-columns: minmax(0, 1fr); }
    .hc-grid { grid-template-columns: minmax(0, 1fr); }
    .hc { min-height: 0; }
    /* the whole row is the link; a wrapped "View" would be a line of its own */
    .ov-view { display: none; }
    .hc-f > :is(.hc-act, .hc-go) { min-height: 44px; }
    /* the latest item is a link too: a 44px target, still one ellipsised line */
    .hc-item > .hc-link, .hc-row > .hc-link { display: block; min-height: 44px; line-height: 44px; }
    /* a row that wraps keeps its 44px target without 44px lines */
    .hc-row.is-wrap > .hc-link { display: flex; align-items: center; line-height: var(--lh-13); }
  }
}

/* ---- css/42-area.css ---- */
/* 42-area: the six area overviews (view "area", #areaCard, route #area=<key>).
   IA spec 3a, chunk A2. Everything else they show is a shared component
   (20, 25): .ph, .kpis, .cc, .tbl, .chip, .es, .legend, details.basis.
   Layout: blocks stack at the view's 16px gap; the Site health tiles are 4
   across at >=1100, 2 at 768-1099 and 1 on phones. Tokens only. */
@layer views {

  /* the header sits 24px above the strip: 8 + the view's 16px gap */
  #areaCard > .ph { margin-bottom: var(--s-2); }

  /* a one-cell strip (Content) is a cell, not a full-width band */
  .ar-k1 { max-width: 360px; }
  .ar-sk-v { width: 72px; height: 28px; }
  .ar-sk-s { width: 60%; height: 12px; margin-top: var(--s-1); }
  /* the loading card: one 200px skeleton, the height of the chart it becomes */
  .ar-sk > .sk { height: 200px; }
  .ar-state { min-height: 200px; justify-content: center; }

  /* ---- Site health tiles: each a link to its section ---- */
  .ar-health { display: grid; gap: var(--s-3); min-width: 0; }
  .ar-h { margin: 0; font-size: var(--fs-14); line-height: var(--lh-14); font-weight: 600; color: var(--text); }
  .al-tiles { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: var(--s-4); min-width: 0; }
  .al-tile {
    display: flex;
    flex-direction: column;
    gap: var(--s-1);
    min-width: 0;
    min-height: 96px;
    padding: var(--s-4);
    border: 1px solid var(--border);
    border-radius: var(--r-lg);
    background: var(--surface);
    color: var(--text);
    text-decoration: none;
  }
  .al-tile:hover { background: var(--surface-2); text-decoration: none; }
  .al-tile:hover .kpi-l { color: var(--text-2); }
  .al-wide { grid-column: span 2; }
  .al-v { font-size: var(--fs-20); line-height: var(--lh-20); font-weight: 600; letter-spacing: -.01em; color: var(--text); font-variant-numeric: tabular-nums; }
  .al-s { font-size: var(--fs-12); line-height: var(--lh-12); color: var(--text-3); }
  .al-wide .al-s { font-size: var(--fs-13); line-height: var(--lh-13); color: var(--text-2); }

  /* ---- Worst page over time: a line of per-period worst pages ----
     Points and numbers are HTML over a grid that matches the slots; the
     line is an SVG stretched to the same slots with a non-scaling stroke,
     so nothing re-renders on resize. Marks sit only on --surface. */
  .ar-per { display: flex; flex-wrap: wrap; gap: var(--s-2); }
  .ar-trend > .ar-per { margin-top: calc(-1 * var(--s-1)); }   /* the chips belong to the title above */
  .cc-plot:has(> .at) { overflow-x: auto; overflow-y: hidden; }
  .at {
    display: grid;
    grid-template-rows: minmax(0, 1fr) auto;
    height: 100%;
    min-width: calc(var(--n) * 16px + 28px);   /* narrower than this, the plot scrolls sideways */
  }
  .at-plot { position: relative; min-height: 0; margin: 22px 0 8px 28px; }
  .at-grid > i { position: absolute; left: 0; right: 0; height: 0; border-top: 1px solid var(--border); }
  .at-grid > i > span {
    position: absolute;
    right: 100%;
    bottom: -7px;
    padding-right: 6px;
    font-style: normal;
    font-size: var(--fs-12);
    line-height: var(--lh-12);
    color: var(--text-3);
    font-variant-numeric: tabular-nums;
  }
  .at-svg { position: absolute; inset: 0; width: 100%; height: 100%; overflow: visible; }
  .at-l { fill: none; stroke: var(--text-2); stroke-width: 1.5; vector-effect: non-scaling-stroke; stroke-linejoin: round; }
  .at-pts { position: absolute; inset: 0; display: grid; grid-template-columns: repeat(var(--n), minmax(0, 1fr)); }
  .at-s { position: relative; min-width: 0; }
  .at-s:hover { z-index: 1; }
  .at-d {
    position: absolute;
    left: 50%;
    width: 8px;
    height: 8px;
    margin: 0 0 -5px -5px;
    border: 1px solid var(--surface);
    border-radius: 50%;
  }
  .at-hi { background: var(--good); }
  .at-mid { background: var(--warn-mark); }
  .at-lo { background: var(--bad); }
  /* the value sits above its point: colour is never the only cue (rule 2) */
  .at-v {
    position: absolute;
    left: 50%;
    margin-bottom: 7px;
    transform: translateX(-50%);
    font-size: var(--fs-12);
    line-height: var(--lh-12);
    font-weight: 600;
    color: var(--text);
    font-variant-numeric: tabular-nums;
    white-space: nowrap;
  }
  /* not read: a dashed band over the whole period - no value and no mark on
     the 0 line, which read as a score of zero (final repair). Never an
     interpolated point; the x label and the legend say "Not read". */
  .at-nr {
    position: absolute;
    inset: 0 22%;
    border: 1px dashed var(--border-control);
    border-radius: var(--r-sm);
  }
  /* our scoring changed before this period: the solid "≠" rule, as the
     columns chart draws it (a dashed line means "not measured") */
  .at-s.is-break::before {
    content: "";
    position: absolute;
    left: -1px;
    top: 0;
    bottom: 0;
    border-left: 1.5px solid var(--border-control);
  }
  .at-b {
    position: absolute;
    top: -20px;
    left: 3px;
    font-size: var(--fs-12);
    line-height: var(--lh-12);
    color: var(--text-3);
  }
  .at-tip {
    position: absolute;
    left: 50%;
    z-index: 2;
    display: none;
    flex-direction: column;
    align-items: flex-start;
    gap: 2px;
    padding: 6px 10px;
    transform: translateX(-50%);
    background: var(--surface);
    border: 1px solid var(--border-strong);
    border-radius: var(--r-md);
    box-shadow: var(--e1);
    white-space: nowrap;
  }
  .at-s:hover > .at-tip { display: flex; }
  .at-s:first-child > .at-tip { left: 0; transform: none; }
  .at-s:last-child > .at-tip { left: auto; right: 0; transform: none; }
  .at-tp { font-size: var(--fs-12); line-height: var(--lh-12); color: var(--text-2); }
  .at-tw { font-size: var(--fs-12); line-height: var(--lh-12); color: var(--text-3); }
  .at-x {
    display: grid;
    grid-template-columns: repeat(var(--n), minmax(0, 1fr));
    margin-left: 28px;
    padding-top: 6px;
    border-top: 1px solid var(--border-strong);
  }
  .at-x > span {
    min-width: 0;
    overflow: hidden;
    font-size: var(--fs-12);
    line-height: var(--lh-12);
    font-weight: 500;
    color: var(--text-2);
    text-align: center;
    white-space: nowrap;
  }
  .at-x > .is-nr { color: var(--text-3); font-weight: 400; }
  /* Site score over time (Sprint 180 item 1, s180_f1): the indexable pages
     behind each point, under its date; a point on an older scoring version is
     drawn with the not-comparable hatch, and its value carries "≠" */
  .at-n { display: block; font-weight: 400; color: var(--text-3); }
  .at-d.is-nc { background: var(--hatch); border-color: var(--neutral-mark); }
  .ar-td { margin-top: var(--s-2); }
  .ar-td > .cc-table { margin-top: var(--s-2); }
  .at-x > .at-sk { visibility: hidden; }
  /* a narrow card labels every other period (the last one always): each
     label still reads in the tip and the screen-reader list */
  @container (max-width: 560px) {
    .at:not(.is-dense) .at-x > span:nth-last-child(even) { visibility: hidden; }
  }

  /* ---- Suggested and Recent runs tables ---- */
  /* fixed widths for the right-hand columns: each row is its own grid, so an
     `auto` column sized to its own content misaligned every row */
  .ar-sug-t { --cols: minmax(0, 1fr) minmax(0, 2.2fr) 112px 64px; margin: 0 calc(-1 * var(--s-5)); }
  .ar-runs { --cols: minmax(0, 1fr) minmax(0, 2fr) minmax(0, 1fr) 96px; margin: 0 calc(-1 * var(--s-5)); }
  .ar-sug-t > .tbl-r > .tc-p { color: var(--accent-text); }
  .ar-what { display: flex; flex-wrap: wrap; align-items: center; gap: 2px var(--s-2); min-width: 0; }
  .ar-u { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  .ar-foot { display: flex; justify-content: flex-start; margin: 0 calc(-1 * var(--s-2)); }
  .ar-runs > .tbl-h > .tc-n { color: inherit; }   /* a header label, not a value */
  /* an empty state that IS the card body: .es's min-height:100% of an
     auto-height card pushed the card's footer out below it */
  .ar-es { min-height: 200px; }

  /* ---- What this area does not do ---- */
  .ar-basis > p { margin: var(--s-2) 0 0; }
  .ar-basis b { font-weight: 600; color: var(--text); }

  @media (max-width: 1099px) {
    .al-tiles { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  }
}

@layer phone {
  @media (max-width: 767px) {
    .al-tiles { grid-template-columns: minmax(0, 1fr); }
    .al-wide { grid-column: auto; }
    .ar-k1 { max-width: none; }
    .ar-sug-t, .ar-runs { margin: 0 calc(-1 * var(--s-4)); }
    /* rule 10 for the Open link: a button-styled <a> in a two-line row */
    .ar-sug-t .btn-2 { min-width: 64px; }
    /* the Site score over time table's worst-page links */
    .ar-td .tbl-r a { display: inline-flex; align-items: center; min-height: 44px; }
  }
}

/* ---- css/44-tool.css ---- */
/* 44-tool: the tool page (view "tool", #toolCard, route #tool=<key>).
   IA spec 3b; chunk T1. Built from shared parts (20, 25): .ph, .banner, .cc,
   .tbl, .chip, .pb-chip, .es, .sk. Layout: header, gate banner, then Run
   (7fr) beside What it does (5fr) at >=1100 and one column below, then the
   output box, then "Your runs".

   FLEX AND INLINE TAGS (CLAUDE.md 5.2): .tp-act and .tp-chips are flex
   containers; each text run in them is its own element (.tp-hint is a <p>). */
@layer views {

  /* the header sits 24px above the grid: 8 + the view's 16px gap */
  #toolCard > .ph { margin-bottom: var(--s-2); }
  .tp-price {
    font-size: var(--fs-13);
    line-height: var(--lh-13);
    font-weight: 500;
    color: var(--text-2);
    font-variant-numeric: tabular-nums;
    white-space: nowrap;
  }

  .tp-grid { display: grid; grid-template-columns: minmax(0, 1fr); gap: var(--s-4); align-items: start; min-width: 0; }
  .tp-col { display: grid; gap: var(--s-4); align-content: start; min-width: 0; }
  @media (min-width: 1100px) {
    .tp-grid { grid-template-columns: minmax(0, 7fr) minmax(0, 5fr); }
  }

  /* ---------------------------------------------------------- the form -- */
  .tp-run > .tp-form { display: grid; grid-template-columns: minmax(0, 1fr); gap: var(--s-4); margin-top: var(--s-1); }   /* S184 FJ8 */
  .tp-f { display: grid; grid-template-columns: minmax(0, 1fr); gap: var(--s-1); max-width: 560px; min-width: 0; }   /* S184 FJ8 */
  .tp-f > label { font-size: var(--fs-13); line-height: var(--lh-13); font-weight: 500; color: var(--text); }
  .tp-f > input { width: 100%; min-height: 40px; }
  .tp-f > textarea { width: 100%; min-height: 96px; resize: vertical; }
  /* a fixed choice (Sprint 180: pages to read, URLs to check) */
  .tp-f > select { justify-self: start; min-width: 160px; min-height: 40px; }
  .tp-help, .tp-hint, .tp-why { font-size: var(--fs-12); line-height: var(--lh-12); color: var(--text-3); }
  .tp-act { display: flex; flex-wrap: wrap; align-items: center; gap: var(--s-2) var(--s-3); }
  .tp-act > .tp-hint { flex: 1 1 200px; }

  /* ------------------------------------------------- what it does, etc -- */
  /* .cc is a flex column with a 12px gap: its children carry no top margin */
  .tp-p { max-width: 72ch; font-size: var(--fs-13); line-height: var(--lh-13); color: var(--text-2); }
  .tp-what > .tp-facts { display: grid; gap: var(--s-3); }
  .tp-facts dt { font-size: var(--fs-12); line-height: var(--lh-12); font-weight: 500; color: var(--text-3); }
  .tp-facts dd { margin: 2px 0 0; font-size: var(--fs-13); line-height: var(--lh-13); color: var(--text); }
  .tp-facts dd > .chip { margin-right: var(--s-1); }
  ul.tp-touch { list-style: disc; padding-left: var(--s-4); }
  .tp-touch li + li { margin-top: 2px; }

  /* ------------------------------------------------------ "Your runs" -- */
  .tp-chips { display: flex; flex-wrap: wrap; gap: 6px; }
  .tp-note { font-size: var(--fs-13); line-height: var(--lh-13); color: var(--text-2); }
  /* the table runs edge to edge inside the card, as on Plan and Account */
  .tp-hist > .tbl { margin: 0 calc(var(--s-5) * -1) calc(var(--s-5) * -1); }
  .tp-tbl[data-src="audits"] { --cols: minmax(0, 1fr) 96px 128px 88px; }
  .tp-tbl[data-src="batches"] { --cols: minmax(0, 1fr) 112px 96px 88px; }
  .tp-tbl[data-src="fixes"] { --cols: minmax(0, 1fr) 88px 88px; }
  .tp-tbl[data-src="ledger"] { --cols: minmax(0, 1fr) 96px 136px; }
  .tp-tbl[data-src="jobs"] { --cols: minmax(0, 1fr) 112px 88px 88px; }
  /* fixed widths only: each row is its own grid, so an `auto` column would
     size per row and the header would not line up with the rows */
  .tp-tbl[data-src="pipeline"] { --cols: minmax(0, 1fr) 152px 88px 72px 208px; }
  .tp-tbl[data-src="gaps"] { --cols: minmax(0, 1fr) 80px 136px 72px 80px; }
  /* site · status · progress · charged · started (Sprint 180 site jobs) */
  .tp-tbl[data-src="site_jobs"] { --cols: minmax(0, 1fr) 104px 136px 96px 88px; }
  .tp-dl { display: flex; justify-content: flex-end; gap: var(--s-2); }
  .tp-tbl .chip { white-space: nowrap; }
  /* a row that holds downloads cannot itself be the link: its first cell is */
  .tp-tbl a.tc-p { color: var(--text); }
  .tp-open { text-align: left; color: var(--text); }
  :is(.tp-open, .tp-tbl a.tc-p):hover { text-decoration: underline; text-underline-offset: 2px; }

  /* ------------------------------------------------------- output box -- */
  /* Mirrors the #result rules in 50-report (lines 16-17, 160-161, 331-347,
     358, 427-436) for the same renderers drawing into #toolOut. Every run
     renderer draws one card (runCard: .rp > .cc, head .cc-h), so the box drops
     its own chrome around it; a bare error from toolRun keeps the card. */
  .tp-out { display: grid; gap: var(--s-3); align-content: start; }
  .tp-out:has(> .rp) { padding: 0; background: transparent; border: 0; border-radius: 0; }
  /* the card head names a URL: a long one wraps instead of widening the page */
  .tp-out .cc-t { overflow-wrap: anywhere; }
  .tp-out .src-note { font-size: var(--fs-12); line-height: var(--lh-12); color: var(--text-3); overflow-wrap: anywhere; }
  .tp-out .src-note b { font-weight: 600; color: var(--text-2); }
  .tp-out h3.sec { margin-top: var(--s-3); font-size: var(--fs-14); line-height: var(--lh-14); font-weight: 600; color: var(--text); }
  .tp-out .cov-note { font-size: var(--fs-12); line-height: var(--lh-12); color: var(--text-3); overflow-wrap: anywhere; }
  .tp-out .err {
    padding: 10px 14px;
    border: 1px solid var(--bad);
    border-radius: var(--r-md);
    background: var(--bad-wash);
    color: var(--bad);
    font-size: var(--fs-13);
    line-height: var(--lh-13);
  }
  .tp-out .empty {
    padding: var(--s-5) var(--s-4);
    border-radius: var(--r-md);
    background: var(--surface-2);
    color: var(--text-2);
    font-size: var(--fs-13);
    line-height: var(--lh-13);
    text-align: center;
  }
  .tp-out .lk { display: grid; min-width: 0; border: 1px solid var(--border); border-radius: var(--r-md); overflow: hidden; }
  .tp-out .pb-chips { display: flex; flex-wrap: wrap; gap: 6px; padding: var(--s-1) 0 var(--s-3); }
  .tp-out .pb-chips > .pb-chip { min-height: 24px; padding: 0 var(--s-2); font-size: var(--fs-12); line-height: var(--lh-12); white-space: normal; }
  .tp-out .score-row { display: flex; align-items: baseline; }
  .tp-out .score-row > .score {
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    gap: 4px var(--s-2);
    font-size: var(--fs-28);
    line-height: var(--lh-28);
    font-weight: 600;
    letter-spacing: -.02em;
    color: var(--text);
    font-variant-numeric: tabular-nums;
  }
  .tp-out .score-row > .score > span { font-size: var(--fs-14); line-height: var(--lh-14); font-weight: 400; letter-spacing: 0; color: var(--text-3); }
  .tp-out .score-row .cov { font-style: normal; font-size: var(--fs-12); line-height: var(--lh-12); font-weight: 400; letter-spacing: 0; color: var(--text-3); }
  .tp-out .lowconf {
    padding: 10px 14px;
    border: 1px solid var(--border-strong);
    border-radius: var(--r-md);
    background: var(--warn-wash);
    color: var(--text);
    font-size: var(--fs-13);
    line-height: var(--lh-13);
  }
  .tp-out .lowconf.partial { background: var(--surface-2); }

  /* ------------------------------------------ Sprint 180: site jobs -- */
  /* A queued or running job (renderSiteJobProgress): the line, a
     determinate bar (a quantity: neutral fill, never a status colour), the
     page being read, the rows so far. */
  .sj { gap: var(--s-2); }
  .sj-line { font-size: var(--fs-14); line-height: var(--lh-14); font-weight: 500; color: var(--text); font-variant-numeric: tabular-nums; }
  .sj-bar { height: 8px; max-width: 560px; border-radius: var(--r-sm); background: var(--surface-3); overflow: hidden; }
  .sj-bar > i { display: block; height: 100%; background: var(--text-2); }
  .sj-rows { --cols: minmax(0, 1fr) 176px; }
  .sj-rows > .tbl-r > :last-child { justify-self: end; }

  /* The site audit's result: fix first (decide-first pages, then ranked)
     and how the pages were chosen (renderSiteAuditResult). */
  .sa-df { --cols: minmax(0, 1fr) 88px 96px; }
  .sa-rk { --cols: 32px minmax(0, 1fr) 144px 136px 96px; }
  .sa-rk .chip { justify-self: end; white-space: nowrap; }
  .sa-sel { --cols: minmax(0, 1fr) 96px 96px 80px; }
  :is(.sa-df, .sa-rk) a.tc-p { color: var(--text); }
  :is(.sa-df, .sa-rk) a.tc-p:hover { color: var(--accent-text); }

  /* The index check (renderSweepResult): section table, state filter, rows. */
  .sw-sec { --cols: minmax(0, 1fr) 88px 88px 184px 128px; }
  /* round 3: "8 blocked by robots.txt, not fetched" ran past the card's
     right edge at 375px (tc-n never wraps); this cell does */
  .sw-sec > .tbl-r > .tc-n:last-child { white-space: normal; overflow-wrap: anywhere; min-width: 0; }
  .sw-f { display: flex; flex-wrap: wrap; gap: 6px; }
  .sw-tbl { --cols: minmax(0, 1.4fr) 176px 64px minmax(0, 1fr) 112px; }
  .sw-tbl > .tbl-r[hidden] { display: none; }
  /* a stacked row names each value's column on a phone (S180 live repair) */
  .sw-k { display: none; }

  /* The fixes queue (renderFixesQueue): one disclosure per page. */
  .fq-p { border-top: 1px solid var(--border); }
  .fq-p > summary {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 2px var(--s-3);
    min-height: 40px;
    padding: var(--s-1) 0;
    list-style: none;
    cursor: pointer;
  }
  .fq-p > summary::-webkit-details-marker { display: none; }
  .fq-p > summary > .tc-p { flex: 1 1 200px; }
  /* the code location wraps under the path rather than into a sliver beside it */
  .fq-p > summary > .patch-where { flex: 0 1 auto; }
  /* a disclosure says it opens: a chevron that turns (as details.basis) */
  .fq-p > summary::before {
    content: "";
    flex: none;
    width: 6px;
    height: 6px;
    border-right: 1.5px solid var(--text-3);
    border-bottom: 1.5px solid var(--text-3);
    transform: rotate(-45deg);
  }
  .fq-p[open] > summary::before { transform: rotate(45deg); }
  .fq-p > .patch { margin-bottom: var(--s-3); }
  .fq-df { --cols: minmax(0, 1fr) 176px minmax(0, 1fr); }
  /* the fixes result's summary leads the page (round 3) */
  .fq-sum { max-width: 80ch; color: var(--text-2); }
  /* needs a person: each page with its own figure ("207 words") */
  .fq-need {
    display: grid;
    gap: 2px;
    margin: 0;
    padding: var(--s-2) var(--s-3) var(--s-2) var(--s-6);
    border-top: 1px solid var(--border);
    font-size: var(--fs-12);
    line-height: var(--lh-12);
    color: var(--text-2);
    overflow-wrap: anywhere;
  }
}

@layer phone {
  @media (max-width: 767px) {
    .tp-dl { justify-content: flex-start; }
    /* static chips in a result are not controls (as #result in 50-report) */
    .tp-out .pb-chips > .pb-chip { min-height: 24px; }
    .tp-open { display: flex; align-items: center; min-height: 44px; }
    /* the fixes queue's "Open its report" link is a control too (rule 10) */
    .fq-p .patch-note > a { display: inline-flex; align-items: center; min-height: 44px; }
    .sw-k { display: inline; color: var(--text-3); }
    /* S184 FJ8: the Run label carries its price ("Run · 1 credit per URL that
       answers, at most 450"); nowrap made it 298px wide in a 246px form at 320px. */
    .tp-act > .btn-p { white-space: normal; text-align: center; }
  }
}

/* ---- css/46-connect.css ---- */
/* 46-connect: the not-available page (view "connect", #connectCard, route
   #connect=<slug>) and the same body under a not-runnable tool's header (Tn).
   IA spec 3c. Everything else it shows is a shared component (20, 25):
   .ph, .chip, .cc, .tbl, .es.
   Layout (a deliberate change from the spec's "3 equal columns", which cannot
   hold a 4-5 column table head at a third of the width - measured, not guessed):
     >=1100: "What it will show" on the left (7fr) beside "What it needs" over
             "Use today instead" (5fr) - the tool page's own 7fr/5fr split;
     768-1099: the table full width, the other two side by side;
     <=767: one column. */
@layer views {

  /* the header sits 24px above the cards: 8 + the view's 16px gap */
  #connectCard > .ph { margin-bottom: var(--s-2); }

  .cn-grid {
    display: grid;
    grid-template-columns: minmax(0, 7fr) minmax(0, 5fr);
    grid-template-areas: "show need" "show instead";
    align-items: start;
    gap: var(--s-4);
    min-width: 0;
  }
  .cn-show { grid-area: show; }
  .cn-need { grid-area: need; }
  .cn-instead { grid-area: instead; }

  /* the lead sentence and the optional bullets of "What it will show" */
  .cn-p { margin: 0; max-width: 72ch; font-size: var(--fs-13); line-height: var(--lh-13); color: var(--text-2); }
  .cn-pts {
    display: grid;
    gap: var(--s-1);
    margin: 0;
    padding-left: var(--s-5);
    font-size: var(--fs-13);
    line-height: var(--lh-13);
    color: var(--text-2);
  }

  /* the empty table, headers kept: what it WILL hold, and one honest row */
  .cn-tbl { border: 1px solid var(--border); border-radius: var(--r-md); overflow: hidden; }
  .cn-tbl > .tbl-h { background: var(--surface-2); }
  .cn-tbl > .tbl-h > span { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  .cn-e > .es { min-height: 0; }

  /* what it needs: label over value, so a long sentence never squeezes a column */
  .cn-dl { display: grid; gap: var(--s-3); margin: 0; }
  .cn-dl > div { display: grid; gap: 2px; min-width: 0; }
  .cn-dl dt { font-size: var(--fs-12); line-height: var(--lh-12); font-weight: 500; color: var(--text-3); }
  .cn-dl dd { margin: 0; max-width: 72ch; font-size: var(--fs-13); line-height: var(--lh-13); color: var(--text); }

  /* use today instead: rows bleed to the card's edges so the hover fills it */
  .cn-list { --cols: minmax(0, 1fr); margin: 0 calc(-1 * var(--s-5)); border-top: 1px solid var(--border); }
  .cn-list > .tbl-r {
    row-gap: 2px;
    align-content: center;
    padding: var(--s-2) var(--s-5);
  }
  .cn-list > .tbl-r > .tc-s { font-size: var(--fs-12); line-height: var(--lh-12); color: var(--text-3); }
  .cn-instead:has(> .cn-list) { padding-bottom: 0; overflow: hidden; }
  /* a site-bound route with no site yet: not a link, and it says what it needs */
  .cn-off > .tc-p { color: var(--text-3); }

  .cn-f { margin: 0; }

  @media (max-width: 1099px) {
    .cn-grid {
      grid-template-columns: repeat(2, minmax(0, 1fr));
      grid-template-areas: "show show" "need instead";
    }
  }

}

/* phones: in the phone layer, because the shared phone rules (20-components)
   live there and a views-layer override would lose to them */
@layer phone {
  @media (max-width: 767px) {
    .cn-grid { grid-template-columns: minmax(0, 1fr); grid-template-areas: "show" "need" "instead"; }
    /* the shared phone rule hides every .tbl-h; this one IS the content, so it
       stays, wrapped instead of squeezed */
    .cn-tbl > .tbl-h {
      display: flex;
      flex-wrap: wrap;
      gap: var(--s-1) var(--s-3);
      padding: var(--s-2) var(--s-4);
    }
    /* keep the rows' text on the card title's 20px line */
    .cn-list > .tbl-r { padding: var(--s-2) var(--s-5); }
    /* rule 10 for the one inline link */
    .cn-off a { display: inline-flex; align-items: center; min-height: 44px; }
  }
}

/* ---- css/47-aivis.css ---- */
/* 47-aivis: the AI-visibility tools (Sprint 185 lane D) on the tool page (44-tool):
   AI citations, AI answer share, Citation gap, Zero-click exposure, Reviews and
   tone. Built from shared parts (20): .tbl, .tbl-h, .tbl-r, .tc-p, .chip, .err,
   .tp-note, .src-note, .cov-note. Only the tables' columns, a multi-line text
   cell, a summary list and a sub-heading are new here. No flex container holds
   inline tags (CLAUDE.md 5.2): every cell is one span of escaped text. */
@layer views {

  /* Question · Competitors cited · AI searches · Recorded  /  Stars · Review · Tone · Date
     Site or name · Answers · Share · AI searches */
  .aiv-c4 { --cols: minmax(0, 1fr) minmax(0, 1.3fr) 128px 104px; }
  /* Phrase · AI Overview · Featured snippet · People Also Ask · Read */
  .aiv-c5 { --cols: minmax(0, 1fr) 104px 128px 128px 112px; }
  /* AI platform · Question · Your pages cited · Name written · AI searches · Recorded */
  .aiv-c6 { --cols: 136px minmax(0, 1fr) minmax(0, 1.2fr) 96px 120px 104px; }
  .aiv-c4 .tbl-r, .aiv-c5 .tbl-r, .aiv-c6 .tbl-r { padding-block: var(--s-2); }
  .aiv-ml { white-space: pre-line; overflow-wrap: anywhere; }
  .aiv-sum { margin: 0 0 var(--s-3); padding-left: var(--s-5); color: var(--text-2); }
  .aiv-h { margin: var(--s-4) 0 var(--s-2); font-size: var(--fs-13); font-weight: 600; color: var(--text); }
}

/* ---- css/48-paid.css ---- */
/* 48-paid: Keyword volume and Rank tracking (Sprint 181), Ranking keywords and
   Backlinks (Sprint 182), Keyword suggestions, Keyword gap and Rank tracking's
   AI Overview column (Sprint 183), on the tool page (44-tool). Built from
   shared parts (20): .tbl, .tbl-g, .chip, .kpis, .banner, .btn-2, .btn-t,
   .tp-act, .tp-help, .tp-hint. Only the tables' columns, their stacked phone
   labels, the weekly switch's row and a few multi-line cells are new here.

   FLEX AND INLINE TAGS (CLAUDE.md 5.2): .rk-weekly, .bl-flags, .bl-sp,
   .bl-from, .rkw-au, .rkw-pg, .rkw-join, .rkw-ch, .ks-you and .kg-kw are flex
   containers; each thing in them (a chip, a span, a button) is its own
   element. */
@layer views {

  /* Phrase · Monthly searches · CPC (USD) · Difficulty · Intent */
  .kv-tbl { --cols: minmax(0, 1fr) 128px 88px 88px 132px; }
  .kv-tbl .chip { white-space: nowrap; }
  /* the scale of a difficulty figure, quieter than the figure */
  .kv-of, .rk-of { color: var(--text-3); }
  /* a stacked row names each value's column on a phone (as .sw-k) */
  .kv-k, .rk-k, .bl-k, .rkw-k, .ks-k, .kg-k { display: none; }

  /* Phrase · Page · Position · Change · AI Overview · Checked */
  /* the position column holds "Not in the 83 results Google showed": two lines at most;
     the AI Overview column "Shown, not citing you: 0 of 10 sources" */
  .rk-tbl { --cols: minmax(0, 1fr) minmax(0, 1fr) 200px 144px 176px 88px; }
  .rk-tbl .tc-s { overflow-wrap: anywhere; }
  /* six columns leave the phrase less room: it wraps whole rather than ending in "..." */
  :is(.rk-tbl, .ks-tbl) .tc-p { white-space: normal; overflow-wrap: anywhere; }
  .rk-ai { min-width: 0; }
  .rk-pos { font-variant-numeric: tabular-nums; color: var(--text); }
  .rk-tbl .chip { white-space: normal; }

  /* the weekly re-check: its state and its switch, the price on the button */
  .rk-weekly { display: flex; flex-wrap: wrap; align-items: center; gap: var(--s-2) var(--s-3); }

  /* "Your runs" of Keyword volume: phrases · with data · charged · run */
  .tp-tbl[data-src="kv_runs"] { --cols: minmax(0, 1fr) 104px 96px 88px; }

  /* ---- Sprint 182: Backlinks -------------------------------------------- */
  /* Linking page · Anchor · Spam score · Flag · First seen */
  .bl-tbl { --cols: minmax(0, 1fr) minmax(0, 1.2fr) 136px 184px 96px; }
  .bl-tbl .tbl-r { padding-block: var(--s-2); }
  /* the linking domain over its path, both text (a vendor URL is never a link) */
  .bl-from { display: flex; flex-direction: column; gap: 2px; overflow-wrap: anywhere; }
  /* a page path or a linking domain wraps whole rather than ending in "..." */
  :is(.bl-from, .rkw-pg) > .tc-p { white-space: normal; overflow-wrap: anywhere; }
  .bl-anc { overflow-wrap: anywhere; }
  /* a vendor figure and DataForSEO's own band word for it */
  .bl-sp { display: inline-flex; flex-wrap: wrap; align-items: center; gap: var(--s-2); font-variant-numeric: tabular-nums; color: var(--text); }
  .bl-flags { display: flex; flex-wrap: wrap; gap: var(--s-1); }
  /* the flag rules, as the server states them, above the table they flag */
  .bl-rules { margin: 0 0 var(--s-3); padding-left: var(--s-5); font-size: var(--fs-12); line-height: var(--lh-12); color: var(--text-2); }
  .bl-rules li + li { margin-top: var(--s-1); }
  .bl-rules b { font-weight: 600; color: var(--text); }
  /* Domain · DataForSEO rank · Links · Spam score · First seen */
  .rd-tbl { --cols: minmax(0, 1fr) 136px 72px 136px 96px; }

  /* ---- Sprint 182: Ranking keywords ------------------------------------- */
  /* Page and its best keyword · Your latest audit of the page */
  .rkw-pages { --cols: minmax(0, 1fr) minmax(0, 1.3fr); }
  .rkw-pages .tbl-r { padding-block: var(--s-2); align-items: start; }
  .rkw-pg { display: flex; flex-direction: column; gap: 2px; overflow-wrap: anywhere; }
  .rkw-join { display: flex; flex-direction: column; align-items: flex-start; gap: var(--s-1); overflow-wrap: anywhere; }
  /* a page's score beside what the audit found */
  .rkw-au { display: flex; flex-wrap: wrap; align-items: center; gap: var(--s-2); }
  /* Keyword · Position · Page · Searches · Visits · Snapshot · Change and your audit */
  .rkw-tbl { --cols: minmax(0, 1fr) 80px minmax(0, 1fr) 88px 80px 104px minmax(0, 1.2fr); }
  .rkw-tbl .tc-s { overflow-wrap: anywhere; }
  .rkw-ch { display: flex; flex-wrap: wrap; align-items: center; gap: var(--s-1) var(--s-2); }
  .rkw-ch .chip { white-space: normal; }

  /* "Your runs" of Backlinks and Ranking keywords: site · figures · charged · run */
  .tp-tbl[data-src="bl_runs"], .tp-tbl[data-src="rkw_runs"] { --cols: minmax(0, 1fr) 176px 96px 88px; }

  /* ---- Sprint 183: Keyword suggestions ------------------------------------ */
  /* Suggestion · Monthly searches · CPC (USD) · Difficulty · Intent [· Your rank] */
  .ks-tbl { --cols: minmax(0, 1fr) 128px 88px 88px 132px; }
  .ks-tbl.ks-join { --cols: minmax(0, 1fr) 128px 88px 88px 132px minmax(0, 1fr); }
  .ks-tbl .chip { white-space: nowrap; }
  .ks-yr { overflow-wrap: anywhere; }
  /* "You rank #14" beside the date of DataForSEO's snapshot */
  .ks-you { display: flex; flex-wrap: wrap; align-items: center; gap: var(--s-1) var(--s-2); }
  /* the two fill buttons and their hint, under the seed phrases */
  .ks-fill { margin-top: var(--s-2); }

  /* ---- Sprint 183: Keyword gap -------------------------------------------- */
  /* Keyword · Their position · Their page · Searches · Difficulty · Snapshot */
  .kg-tbl { --cols: minmax(0, 1fr) 112px minmax(0, 1fr) 104px 88px 104px; }
  .kg-tbl .tc-s { overflow-wrap: anywhere; }
  /* the keyword over "Your run of ...: #54" when your own run lists you */
  .kg-kw { display: flex; flex-direction: column; align-items: flex-start; gap: var(--s-1); }
  .kg-kw > .tc-p { white-space: normal; overflow-wrap: anywhere; }
  .kg-kw .chip { white-space: normal; }

  /* "Your runs" of Keyword suggestions and Keyword gap: what · figures · charged · run */
  .tp-tbl[data-src="ks_runs"], .tp-tbl[data-src="kg_runs"] { --cols: minmax(0, 1fr) 176px 96px 88px; }
}

@layer phone {
  @media (max-width: 767px) {
    .kv-k, .rk-k, .bl-k, .rkw-k, .ks-k, .kg-k { display: inline; color: var(--text-3); }
  }
}

/* ---- css/49-gsc.css ---- */
/* 49-gsc: Search Console on the tool page (Sprint 185 lane E). Built from shared
   parts (20, 25, 44): .tbl, .kpis, .cc, .hb, .banner, .tp-f, .tp-act, .err,
   .src-note, .cov-note, .cc-f. Only the two tables' columns and their stacked
   phone labels are new here. No flex container holds inline text runs. */
@layer views {

  /* Page or search · Clicks · Impressions · Click rate · Position */
  .gsc-tbl { --cols: minmax(0, 1fr) 80px 104px 88px 80px; }
  /* Page or search · Impressions · Clicks · Click rate · Band median · Position */
  .gsc-low { --cols: minmax(0, 1fr) 104px 72px 88px 136px 80px; }
  :is(.gsc-tbl, .gsc-low) .tc-p { white-space: normal; overflow-wrap: anywhere; }
  /* a site or property select sizes to its longest option: keep it inside the column */
  .tp-f > .gsc-sel { max-width: 100%; }
  /* a stacked row names each value's column on a phone (as .bl-k) */
  .gsc-k { display: none; }
}

@layer phone {
  @media (max-width: 767px) {
    .gsc-k { display: inline; color: var(--text-3); }
  }
}

/* ---- css/50-report.css ---- */
/* 50-report: the audit result (#audit=N), the delta banner, Quinn's fixes,
   "What to do next", the site-audit result, and the other playbook results
   that render into #result. Spec section 5 "Audit result"; chunk C3.

   #result stays a .card (spec 4) so the plain playbook results keep a
   surface. A report built from components (.rp: .ph, .kpis, .cc) sits on the
   page ground instead - cards inside a card read as a box in a box. */
@layer views {

  /* ====================================== order on the audit view ===== */
  /* The result first; the ask and every intent stay visible below it
     (spec 0 and 5). Scoped to the audit view: on Home #hero leads. */
  .page[data-view="audit"]:has(> #result:not([hidden])) > #hero { order: 1; }

  /* ======================================================= report root ===== */
  #result { display: grid; gap: var(--s-3); align-content: start; }
  #result:has(> .rp) { padding: 0; background: transparent; border: 0; border-radius: 0; }
  .rp { display: grid; gap: var(--s-4); min-width: 0; }
  .rp > .ph { margin: 0; }
  .rp-two { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--s-4); align-items: start; }
  .rp-lead { font-size: var(--fs-13); line-height: var(--lh-13); color: var(--text-2); }
  @media (max-width: 1099px) {
    .rp-two { grid-template-columns: minmax(0, 1fr); }
  }

  /* skeletons: the shape of the answer; .sk itself is C0's */
  .rp-sk-l { width: 45%; height: 12px; }
  .rp-sk-v { width: 60%; height: 28px; margin: 2px 0; }
  .rp-sk-s { width: 80%; height: 12px; }
  .sk-line { width: 100%; height: 14px; }
  .sk-line + .sk-line { margin-top: var(--s-3); }
  .sk.short { width: 60%; }

  /* ===================================================== Start here ===== */
  .firstfix {
    display: grid;
    gap: var(--s-2);
    padding: var(--s-4) var(--s-5);
    background: var(--surface);
    border: 1px solid var(--border);
    border-left: 3px solid var(--accent);
    border-radius: var(--r-lg);
    min-width: 0;
  }
  .ff-top { display: flex; flex-wrap: wrap; align-items: center; gap: var(--s-2); }
  /* one line; the full sentence stays in textContent and in the finding below */
  .ff-what {
    font-size: var(--fs-14);
    line-height: var(--lh-14);
    font-weight: 500;
    color: var(--text);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
  }
  .ff-why { font-size: var(--fs-13); line-height: var(--lh-13); color: var(--text-2); }
  .firstfix .ff-go { justify-self: start; margin-left: calc(-1 * var(--s-2)); }

  /* ======================================================= findings ===== */
  .fnd-list { display: grid; min-width: 0; }
  .finding, .dfind { min-width: 0; padding: var(--s-3) 0; border-top: 1px solid var(--border); }
  .fnd-list > :first-child { border-top: 0; padding-top: 0; }
  .fnd-list > :last-child { padding-bottom: 0; }
  .finding { display: grid; gap: 6px; }
  .finding:focus-visible { outline-offset: 2px; }
  /* [88px severity][problem][dimension] - no tints, no coloured borders */
  .fnd-head {
    display: grid;
    grid-template-columns: 88px minmax(0, 1fr) auto;
    column-gap: var(--s-3);
    align-items: start;
  }
  .fnd-head > .chip { margin-top: 1px; }
  .fnd-p { font-size: var(--fs-14); line-height: var(--lh-14); font-weight: 500; color: var(--text); }
  .fnd-head ~ .evidence, .fnd-head ~ .fix, .fnd-head ~ .fnd-nd { margin-left: calc(88px + var(--s-3)); }
  /* Sprint 180 items 8a/8e: a listed code the score skips, said on its row */
  .fnd-nd { display: flex; }
  .evidence {
    display: grid;
    gap: 2px;
    padding: var(--s-2) 10px;
    background: var(--surface-2);
    border-radius: var(--r-sm);
    min-width: 0;
  }
  .fnd-ml { font-size: var(--fs-12); line-height: var(--lh-12); color: var(--text-3); }
  .fnd-mv, .evidence {
    font-family: var(--mono);
    font-size: var(--fs-12);
    line-height: var(--lh-mono);
    color: var(--text);
    overflow-wrap: anywhere;
    white-space: pre-wrap;
  }
  .fnd-ml { font-family: var(--sans); }
  .fix { font-size: var(--fs-13); line-height: var(--lh-13); color: var(--text-2); }

  /* site-level findings: the chip, then problem / evidence / fix */
  .dfind { display: grid; grid-template-columns: 88px minmax(0, 1fr); column-gap: var(--s-3); row-gap: 4px; }
  .dfind > .chip { grid-row: span 3; justify-self: start; align-self: start; margin-top: 1px; }
  .dfind > b { font-size: var(--fs-14); line-height: var(--lh-14); font-weight: 500; color: var(--text); }
  .dfind .ev {
    justify-self: start;
    max-width: 100%;
    padding: 2px var(--s-2);
    background: var(--surface-2);
    border-radius: var(--r-sm);
    font-family: var(--mono);
    font-size: var(--fs-12);
    line-height: var(--lh-mono);
    color: var(--text);
    overflow-wrap: anywhere;
  }
  .dfind .fx { font-size: var(--fs-13); line-height: var(--lh-13); color: var(--text-2); }

  /* A severity outside a chip (the comparison columns): the same look. */
  .sev:not(.chip) {
    display: inline-block;
    justify-self: start;
    min-height: 20px;
    padding: 0 var(--s-2);
    border-radius: var(--r-sm);
    background: var(--surface-2);
    color: var(--text-2);
    font-size: var(--fs-12);
    line-height: 20px;
    font-weight: 500;
    font-variant-numeric: tabular-nums;
  }
  .sev.critical:not(.chip), .sev.high:not(.chip) { background: var(--bad-wash); color: var(--bad); }
  .sev.medium:not(.chip) { background: var(--warn-wash); color: var(--warn); }
  .sev.low:not(.chip) { background: var(--surface-2); color: var(--text-2); }

  /* ================================================ what passed (.passed) ===== */
  .passed { border: 1px solid var(--border); border-radius: var(--r-md); padding: 0 var(--s-3); }
  :is(.passed, .cat-pass, details.checks, .struck) > summary {
    display: flex;
    align-items: center;
    gap: var(--s-2);
    min-height: 40px;
    list-style: none;
    cursor: pointer;
    font-size: var(--fs-13);
    line-height: var(--lh-13);
    color: var(--text);
  }
  :is(.passed, .cat-pass, details.checks, .struck) > summary::-webkit-details-marker { display: none; }
  :is(.passed, .cat-pass, details.checks, .struck) > summary::before {
    content: "";
    flex: none;
    width: 6px;
    height: 6px;
    margin: 0 2px;
    border-right: 1.5px solid var(--text-2);
    border-bottom: 1.5px solid var(--text-2);
    transform: rotate(-45deg);
    transition: transform var(--dur-1) var(--ease);
  }
  :is(.passed, .cat-pass, details.checks, .struck)[open] > summary::before { transform: rotate(45deg); }
  .passed > summary b { font-weight: 500; }
  .passed > .cov-note { padding-bottom: var(--s-3); }
  #result .pb-chips { display: flex; flex-wrap: wrap; gap: 6px; padding: var(--s-1) 0 var(--s-3); }
  #result .pb-chips > .pb-chip { min-height: 24px; padding: 0 var(--s-2); font-size: var(--fs-12); line-height: var(--lh-12); white-space: normal; }

  /* ======================================================== By area ===== */
  .rp-area .cc-s { max-width: 110ch; }
  .dim em { font-style: normal; }

  /* ================================================= Not scored card ===== */
  .notscored { display: grid; min-width: 0; }
  .notscored > b { display: block; margin-bottom: var(--s-2); font-size: var(--fs-14); line-height: var(--lh-14); font-weight: 600; color: var(--text); }
  .notscored > div {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 4px var(--s-2);
    padding: 10px 0;
    border-top: 1px solid var(--border);
  }
  .notscored > div:first-child, .notscored > b + div { border-top: 0; padding-top: 0; }
  .notscored > div > span:first-child { font-size: var(--fs-14); line-height: var(--lh-14); font-weight: 500; color: var(--text); }
  .notscored em { flex: 1 0 100%; font-style: normal; font-size: var(--fs-13); line-height: var(--lh-13); color: var(--text-2); }

  /* ================================================== What we read ===== */
  .inputs { display: grid; gap: var(--s-3); min-width: 0; }
  .in-rows { display: grid; }
  .in-row {
    display: grid;
    grid-template-columns: 116px minmax(0, 1fr);
    column-gap: var(--s-3);
    row-gap: 2px;
    align-items: start;
    padding: var(--s-2) 0;
    border-top: 1px solid var(--border);
  }
  .in-row:first-child { border-top: 0; padding-top: 0; }
  .in-row > .in-s { grid-row: span 2; justify-self: start; }
  .in-n { font-size: var(--fs-13); line-height: var(--lh-13); font-weight: 500; color: var(--text); }
  .in-f { grid-column: 2; font-style: normal; font-size: var(--fs-12); line-height: var(--lh-12); color: var(--text-3); }
  .in-stmt { font-size: var(--fs-12); line-height: var(--lh-12); color: var(--text-3); }

  /* the receipt: "no longer reported", never "fixed" */
  .receipt { display: grid; gap: var(--s-2); min-width: 0; }
  .inputs + .receipt { margin-top: var(--s-2); padding-top: var(--s-4); border-top: 1px solid var(--border); }
  .receipt > b { font-size: var(--fs-13); line-height: var(--lh-13); font-weight: 600; color: var(--text); }
  .rc { display: grid; gap: 2px; }
  .rc > span {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    font-size: var(--fs-13);
    line-height: var(--lh-13);
    font-weight: 500;
    color: var(--text);
  }
  .rc > span::before { content: ""; flex: none; width: 8px; height: 8px; border-radius: 2px; background: var(--neutral-mark); }
  .rc-ok > span::before { background: var(--good); }
  .rc-back > span::before { background: var(--bad); }
  /* our checks moved across the same pair: the not-comparable signature */
  .rc-caveat > span::before { background: var(--hatch); box-shadow: inset 0 0 0 1px var(--neutral-mark); }
  .rc > em { padding-left: 14px; font-style: normal; font-size: var(--fs-12); line-height: var(--lh-12); color: var(--text-2); overflow-wrap: anywhere; }
  .rc-w { color: var(--text-3); }
  .rc-w-ours { color: var(--warn); }
  .receipt > p { font-size: var(--fs-12); line-height: var(--lh-12); color: var(--text-3); }

  /* ==================================================== basis, checks ===== */
  .rp-basis { padding: 0 var(--s-1); }
  .rp-basis > p + p { margin-top: var(--s-2); }
  details.checks { gap: 0; padding: var(--s-1) var(--s-5); }
  details.checks > summary { min-height: 44px; font-size: var(--fs-14); line-height: var(--lh-14); font-weight: 600; }
  details.checks[open] { padding-bottom: var(--s-4); }
  .ck-list { columns: 2; column-gap: var(--s-7); margin-top: var(--s-2); }
  .ck-list > li {
    display: grid;
    grid-template-columns: 16px minmax(0, 1fr);
    column-gap: var(--s-2);
    break-inside: avoid;
    padding: 6px 0;
    font-size: var(--fs-13);
    line-height: var(--lh-13);
    color: var(--text);
  }
  /* the glyph differs as well as the colour (rule 2) */
  .ck-list > li::before { content: "\2713"; grid-row: span 2; font-weight: 600; color: var(--good); }
  .ck-list > li.ck-no::before { content: "\2715"; color: var(--bad); }
  /* S184 SAE-05: a check whose input we could not read - neither a pass nor a fail */
  .ck-list > li.ck-nm::before { content: "\2013"; color: var(--text-3); }
  .ck-c { grid-column: 2; font-family: var(--mono); font-size: var(--fs-12); line-height: var(--lh-mono); color: var(--text-3); overflow-wrap: anywhere; }
  details.checks > .cov-note { margin-top: var(--s-2); }

  /* ============================================== delta banner (#deltaBox) ===== */
  .delta { align-items: flex-start; }
  .d-x { display: grid; gap: var(--s-1); }
  .d-top { display: flex; flex-wrap: wrap; align-items: baseline; gap: 4px 10px; }
  .d-num { font-size: var(--fs-20); line-height: var(--lh-20); font-weight: 600; color: var(--text); font-variant-numeric: tabular-nums; }
  .d-v { font-size: var(--fs-14); line-height: var(--lh-14); font-weight: 600; color: var(--text); }
  .d-was { font-size: var(--fs-13); line-height: var(--lh-13); color: var(--text-2); font-variant-numeric: tabular-nums; }
  .d-tags { display: flex; flex-wrap: wrap; gap: 6px; margin-top: var(--s-1); }
  .d-moved { display: grid; gap: var(--s-1); margin-top: var(--s-2); }
  .d-moved > li {
    display: grid;
    grid-template-columns: minmax(120px, 200px) minmax(0, 1fr);
    column-gap: var(--s-3);
    font-size: var(--fs-12);
    line-height: var(--lh-12);
  }
  .d-moved > li.ev-note { display: block; color: var(--text-2); }
  .mv-l { color: var(--text-2); }
  .mv-v { font-family: var(--mono); line-height: var(--lh-mono); color: var(--text); overflow-wrap: anywhere; }

  /* ================================================== Quinn's fixes ===== */
  #fixes { display: grid; gap: var(--s-3); }
  .fx-go { display: flex; }
  .fx-charge { font-size: var(--fs-13); line-height: var(--lh-13); font-weight: 500; color: var(--text); }
  .fx-policy { font-size: var(--fs-13); line-height: var(--lh-13); color: var(--text-2); }
  .patch { border: 1px solid var(--border); border-radius: var(--r-md); overflow: hidden; min-width: 0; background: var(--surface); }
  .patch-head {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 4px var(--s-3);
    min-height: 44px;
    padding: 6px var(--s-3);
    border-bottom: 1px solid var(--border);
  }
  .patch-head > b { font-size: var(--fs-13); line-height: var(--lh-13); font-weight: 600; color: var(--text); }
  .patch-where { flex: 1; min-width: 0; font-family: var(--mono); font-size: var(--fs-12); line-height: var(--lh-mono); color: var(--text-3); overflow-wrap: anywhere; }
  .patch-copy { margin-left: auto; }
  .patch-body {
    margin: 0;
    max-height: 320px;
    overflow: auto;
    padding: var(--s-3);
    background: var(--bg);
    color: var(--text);
    font-family: var(--mono);
    font-size: var(--fs-12);
    line-height: var(--lh-mono);
    white-space: pre;
  }
  .patch-note { padding: var(--s-2) var(--s-3); font-size: var(--fs-12); line-height: var(--lh-12); color: var(--text-2); }
  .patch-body + .patch-note { border-top: 1px solid var(--border); }
  .patch-note b { font-weight: 600; color: var(--text); }
  .patch-note em { font-style: normal; color: var(--text-3); }
  .fx-person .patch-note + .patch-note { border-top: 1px solid var(--border); }

  /* ================================================ What to do next ===== */
  #fuCard .fu { display: grid; gap: var(--s-2); }
  #fuCard .fu > b { font-size: var(--fs-14); line-height: var(--lh-14); font-weight: 600; color: var(--text); }
  .fu-list { --cols: minmax(0, 1fr) minmax(0, 1.3fr) 80px 128px; }
  .fu-list > .tbl-r { padding: var(--s-2) 0; }
  .fu-list > .tbl-r > .tc-p { white-space: normal; }
  .fu-list > .tbl-r > :last-child { justify-self: end; }
  .fu-why { font-size: var(--fs-13); line-height: var(--lh-13); }

  /* ================================================ site-audit result ===== */
  .seg .seg-s { font-variant-numeric: tabular-nums; }
  .rp-pages .pages { --cols: 32px minmax(0, 1fr) minmax(0, 1.2fr) 88px 88px; }
  :is(.rp-pages, .pl-card) .tbl { margin-inline: calc(-1 * var(--s-5)); }
  :is(.rp-pages, .pl-card) .tbl > :is(.tbl-h, .tbl-r) { padding-inline: var(--s-5); }
  .rp-pages .tbl > .tbl-r:last-child { border-bottom: 0; }
  .pages > .tbl-r { padding-block: var(--s-2); }
  .pg-rank { color: var(--text-3); }
  .pg-why { font-size: var(--fs-13); line-height: var(--lh-13); }
  .pg-imp { color: var(--text-3); }
  .pg-crit { color: var(--bad); white-space: nowrap; }
  .dom { display: grid; grid-template-columns: minmax(120px, max-content) minmax(0, 1fr); column-gap: var(--s-4); }
  .dom dt, .dom dd { margin: 0; padding: var(--s-2) 0; border-top: 1px solid var(--border); font-size: var(--fs-13); line-height: var(--lh-13); }
  .dom dt { color: var(--text-2); }
  .dom dd { color: var(--text); overflow-wrap: anywhere; }
  .dom dt:first-of-type, .dom dt:first-of-type + dd { border-top: 0; padding-top: 0; }
  .cat-pass > summary { color: var(--text-2); font-weight: 500; }

  /* ======================= other playbook results inside the #result card ===== */
  #result > h2 { font-size: var(--fs-20); line-height: var(--lh-20); font-weight: 600; letter-spacing: -.01em; overflow-wrap: anywhere; }
  #result > .sub { font-size: var(--fs-13); line-height: var(--lh-13); color: var(--text-3); }
  #result .src-note { font-size: var(--fs-12); line-height: var(--lh-12); color: var(--text-3); overflow-wrap: anywhere; }
  #result .src-note b { font-weight: 600; color: var(--text-2); }
  #result h3.sec { margin-top: var(--s-3); font-size: var(--fs-14); line-height: var(--lh-14); font-weight: 600; color: var(--text); }
  :is(#result, #fixes) .cov-note { font-size: var(--fs-12); line-height: var(--lh-12); color: var(--text-3); overflow-wrap: anywhere; }
  :is(#result, #fixes) .err {
    padding: 10px 14px;
    border: 1px solid var(--bad);
    border-radius: var(--r-md);
    background: var(--bad-wash);
    color: var(--bad);
    font-size: var(--fs-13);
    line-height: var(--lh-13);
  }
  /* a measured "nothing" (no findings, no gaps): a result, so no dashed outline */
  :is(#result, #fixes) .empty {
    padding: var(--s-5) var(--s-4);
    border-radius: var(--r-md);
    background: var(--surface-2);
    color: var(--text-2);
    font-size: var(--fs-13);
    line-height: var(--lh-13);
    text-align: center;
  }

  /* count rows with a denominator (.lk): accessibility, conversion, links, ... */
  #result .lk { display: grid; min-width: 0; border: 1px solid var(--border); border-radius: var(--r-md); overflow: hidden; }
  .lk > li {
    display: grid;
    grid-template-columns: minmax(0, 1fr) auto auto auto;
    align-items: center;
    column-gap: var(--s-3);
    row-gap: 4px;
    min-height: 44px;
    padding: var(--s-2) 14px;
    border-top: 1px solid var(--border);
    font-size: var(--fs-13);
    line-height: var(--lh-13);
  }
  .lk > li:first-child { border-top: 0; }
  .lk-u { min-width: 0; color: var(--text); overflow-wrap: anywhere; }
  .lk-u i { font-style: normal; font-size: var(--fs-12); line-height: var(--lh-12); color: var(--text-3); }
  .lk-u code { font-size: var(--fs-12); color: var(--text-2); overflow-wrap: anywhere; }
  .lk-s { color: var(--text-2); text-align: right; font-variant-numeric: tabular-nums; }
  .lk-tag {
    display: inline-block;
    justify-self: end;
    padding: 0 var(--s-2);
    border: 1px solid var(--border-strong);
    border-radius: var(--r-sm);
    font-size: var(--fs-12);
    line-height: 18px;
    font-weight: 500;
    color: var(--text-2);
    white-space: nowrap;
  }
  /* the row's state as a swatch beside the words that already say it */
  :is(.lk-bad, .lk-unk, .lk-red) > .lk-u::before {
    content: "";
    display: inline-block;
    width: 8px;
    height: 8px;
    margin-right: var(--s-2);
    border-radius: 2px;
    vertical-align: 1px;
  }
  .lk-bad > .lk-u::before { background: var(--bad); }
  .lk-red > .lk-u::before { background: var(--changed); }
  .lk-unk > .lk-u::before { border: 1px dashed var(--border-control); }

  /* the older numeral blocks (local, demand gap, cadence, comparison) */
  #result .score-row { display: flex; align-items: baseline; }
  #result .score-row > .score {
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    gap: 4px var(--s-2);
    font-size: var(--fs-28);
    line-height: var(--lh-28);
    font-weight: 600;
    letter-spacing: -.02em;
    color: var(--text);
    font-variant-numeric: tabular-nums;
  }
  #result .score-row > .score > span { font-size: var(--fs-14); line-height: var(--lh-14); font-weight: 400; letter-spacing: 0; color: var(--text-3); }
  #result .score-row .cov { font-style: normal; font-size: var(--fs-12); line-height: var(--lh-12); font-weight: 400; letter-spacing: 0; color: var(--text-3); }
  .sev-counts { display: flex; flex-wrap: wrap; gap: var(--s-2) var(--s-4); }
  .sev-counts > div { display: flex; align-items: baseline; gap: 6px; }
  .sev-counts em { font-style: normal; font-size: var(--fs-12); line-height: var(--lh-12); color: var(--text-3); }
  .cmp { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--s-4); }
  .cmp-col { display: grid; gap: var(--s-2); align-content: start; min-width: 0; padding: var(--s-4); border: 1px solid var(--border); border-radius: var(--r-md); }
  .cmp-col > b { font-size: var(--fs-14); line-height: var(--lh-14); font-weight: 600; color: var(--text); }
  .cmp-col > i { font-style: normal; font-size: var(--fs-12); line-height: var(--lh-12); color: var(--text-3); overflow-wrap: anywhere; }
  .cmp-vs { font-style: normal; font-weight: 400; color: var(--text-3); }
  .cmp-dimhead { margin-top: var(--s-2); font-size: var(--fs-13); line-height: var(--lh-13); color: var(--text); }
  #result .lowconf {
    padding: 10px 14px;
    border: 1px solid var(--border-strong);
    border-radius: var(--r-md);
    background: var(--warn-wash);
    color: var(--text);
    font-size: var(--fs-13);
    line-height: var(--lh-13);
  }
  #result .lowconf.partial { background: var(--surface-2); }
  .gap { display: flex; flex-wrap: wrap; gap: 6px; }
  .gap > li > b {
    display: inline-block;
    padding: 2px 10px;
    border: 1px solid var(--border-strong);
    border-radius: var(--r-sm);
    font-size: var(--fs-13);
    line-height: var(--lh-13);
    font-weight: 500;
    color: var(--text);
  }
  .struck > summary { color: var(--text-2); font-weight: 500; }
  .struck li { padding: 4px 0; font-size: var(--fs-13); line-height: var(--lh-13); color: var(--text); }
  .struck em { margin-left: 6px; font-style: normal; color: var(--text-3); }
  .takeaway { display: flex; flex-wrap: wrap; align-items: center; gap: var(--s-2) var(--s-3); }
  .takeaway .dl {
    display: inline-flex;
    align-items: center;
    min-height: 32px;
    padding: 0 var(--s-3);
    border: 1px solid var(--border-strong);
    border-radius: var(--r-md);
    background: var(--surface);
    color: var(--text);
    font-size: var(--fs-13);
    line-height: var(--lh-13);
    font-weight: 500;
  }
  .takeaway .dl:hover { background: var(--surface-2); text-decoration: none; }
  .dl-note { font-size: var(--fs-12); line-height: var(--lh-12); color: var(--text-3); }
  .cad { display: grid; gap: 2px; }
  .cad > li {
    display: grid;
    grid-template-columns: 88px minmax(0, 1fr) 48px;
    align-items: center;
    column-gap: var(--s-3);
    min-height: 24px;
    font-size: var(--fs-13);
    line-height: var(--lh-13);
  }
  .cad > li > b { font-weight: 500; color: var(--text-2); font-variant-numeric: tabular-nums; }
  .cad > li > span { display: block; height: 8px; min-width: 1px; border-radius: 2px; background: var(--neutral-mark); }
  .cad > li > em { font-style: normal; text-align: right; color: var(--text); font-variant-numeric: tabular-nums; }
  .lc { display: grid; }
  .lc > li { display: grid; gap: 2px; padding: var(--s-2) 0; border-top: 1px solid var(--border); }
  .lc > li:first-child { border-top: 0; }
  .lc > li > b { font-size: var(--fs-13); line-height: var(--lh-13); font-weight: 500; color: var(--text); }
  .lc > li > b::before { display: inline-block; width: 16px; font-weight: 600; }
  .lc-ok > b::before { content: "\2713"; color: var(--good); }
  .lc-no > b::before { content: "\2715"; color: var(--bad); }
  .lc > li > em { padding-left: 16px; font-style: normal; font-size: var(--fs-12); line-height: var(--lh-12); color: var(--text-2); }
}

@layer phone {
  @media (max-width: 767px) {
    /* one line is a handful of words at 375: two, still clamped */
    .ff-what { white-space: normal; display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2; }
    .fnd-head { display: flex; flex-wrap: wrap; gap: 6px var(--s-2); }
    .fnd-head > .fnd-p { flex: 1 0 100%; order: 3; }
    .fnd-head ~ .evidence, .fnd-head ~ .fix, .fnd-head ~ .fnd-nd { margin-left: 0; }
    .dfind { grid-template-columns: minmax(0, 1fr); }
    .dfind > .chip { grid-row: auto; }
    .ck-list { columns: 1; }
    .cmp { grid-template-columns: minmax(0, 1fr); }
    .d-moved > li { grid-template-columns: minmax(0, 1fr); }
    .in-row { grid-template-columns: minmax(0, 1fr); }
    .in-row > .in-s { grid-row: auto; }
    .in-f { grid-column: auto; }
    .lk > li { grid-template-columns: minmax(0, 1fr) auto; }
    .lk > li > .lk-u { grid-column: 1 / -1; }
    .lk-s { text-align: left; }
    .lk-tag { justify-self: start; }
    /* static chips are not controls: C0's 44px phone floor is for targets */
    #result .pb-chips > .pb-chip { min-height: 24px; }
    /* the rank rides beside the page link, not on a line of its own */
    .pages > .tbl-r > .pg-rank { flex: none; }
    .pages > .tbl-r > .pg-url { flex: 1 0 calc(100% - 44px); display: flex; align-items: center; min-height: 44px; }
    .fu-list > .tbl-r > :last-child { justify-self: auto; margin-left: auto; }
    :is(.rp-pages, .pl-card) .tbl { margin-inline: calc(-1 * var(--s-5)); }
    .dom { grid-template-columns: minmax(96px, max-content) minmax(0, 1fr); }
  }
}

/* ---- css/51-scale.css ---- */
/* 51-scale: Sprint 186 lane F - the watch cadence choice and the alert feed
   (Pages view, 60-pages owns .wt-tbl), the Page Explorer's text columns
   (82-section owns the table) and the local rank grid's heat map on the tool
   page (44-tool). Built from shared parts (20): .tbl, .tbl-h, .tbl-r, .tc-s,
   .tc-p, .chip, .tp-note. No flex container holds inline tags (CLAUDE.md 5.2):
   the heat map is a grid of one-text cells, the legend a plain paragraph. */
@layer views {

  /* Weekly / Daily on an active watch's row */
  .wt-cad { justify-self: start; min-height: 32px; font-size: var(--fs-13); }

  /* Changes on watched pages: When · Page · What changed · Reading */
  .wa-tbl { --cols: 136px minmax(0, .8fr) minmax(0, 1.6fr) 88px; }
  .wa-tbl .tbl-r { padding-block: var(--s-2); }
  .wa-new { background: var(--surface-2); }
  .wa-msg { overflow-wrap: anywhere; color: var(--text); }
  .wa-bar { display: flex; align-items: center; justify-content: space-between; gap: var(--s-3);
    min-height: 32px; margin-bottom: var(--s-2); color: var(--text-2); font-size: var(--fs-13); }

  /* Page Explorer: a recorded text, cut to its cell, with its length after it */
  .pe-tx { display: block; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  .pe-n { font-style: normal; color: var(--text-3); font-size: var(--fs-12); }

  /* The local grid's heat map: --n cells a side, north at the top */
  .lg-grid { display: grid; grid-template-columns: repeat(var(--n), minmax(0, 48px)); gap: var(--s-1);
    margin: var(--s-3) 0; }
  .lg-c { display: inline-grid; place-items: center; min-width: 36px; aspect-ratio: 1; border-radius: var(--r-sm);
    border: 1px solid var(--border); font-size: var(--fs-13); font-weight: 600; color: var(--text); }
  .lg-leg .lg-c { min-width: 40px; aspect-ratio: auto; padding: 0 var(--s-1); margin-inline: var(--s-1); }
  .lg-leg { color: var(--text-2); font-size: var(--fs-12); line-height: 28px; }
  .lg-pack { background: var(--good-wash); color: var(--good); border-color: var(--good); }
  .lg-near { background: var(--warn-wash); color: var(--warn); }
  .lg-far { background: var(--bad-wash); color: var(--text-2); }
  .lg-none { background: var(--bad-wash); color: var(--bad); }
  .lg-nr { background: transparent; border-style: dashed; color: var(--text-3); }
  .lg-mid { outline: 2px solid var(--text); outline-offset: 1px; }
}

/* ---- css/52-smo-cms.css ---- */
/* 52-smo-cms: Sprint 186 lane D. Quinn's per-platform steps (.fx-how, inside a
   .patch and under a fixes-queue group) and the share preview's sketch cards.
   Built from shared parts: details.basis (20), .patch and .lk (50), .cov-note.
   No flex container holds inline tags (CLAUDE.md 5.2): the card caption is a grid
   whose children are each one element, and .fx-check is a plain paragraph. */
@layer views {

  /* ------------------------------------------- Quinn: apply it on <platform> */
  .fx-how { padding: var(--s-2) var(--s-3); border-top: 1px solid var(--border); }
  .fx-steps {
    display: grid;
    gap: var(--s-1);
    margin: var(--s-1) 0 0;
    padding-left: var(--s-5);
    font-size: var(--fs-13);
    line-height: var(--lh-13);
    color: var(--text);
    overflow-wrap: anywhere;
  }
  .fx-how .cov-note {
    margin-top: var(--s-1);
    font-size: var(--fs-12);
    line-height: var(--lh-12);
    color: var(--text-3);
    overflow-wrap: anywhere;
  }
  .fx-check > b { font-weight: 600; color: var(--text-2); }

  /* --------------------------------------------------- share preview cards */
  .sp-cards { display: grid; grid-template-columns: minmax(0, 1fr); gap: var(--s-4); }
  @media (min-width: 900px) {
    .sp-cards { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  }
  .sp-col { display: grid; gap: var(--s-2); align-content: start; min-width: 0; }
  .sp-card {
    margin: 0;
    max-width: 520px;
    border: 1px solid var(--border);
    border-radius: var(--r-md);
    overflow: hidden;
    background: var(--surface);
  }
  .sp-img { display: grid; place-items: center; aspect-ratio: 1.91 / 1; overflow: hidden; background: var(--surface-2); }
  .sp-sq .sp-img { aspect-ratio: 1 / 1; max-width: 200px; }
  .sp-img > img { display: block; width: 100%; height: 100%; object-fit: cover; }
  .sp-none { font-size: var(--fs-12); line-height: var(--lh-12); color: var(--text-3); }
  .sp-cap { display: grid; gap: 2px; padding: var(--s-2) var(--s-3); min-width: 0; }
  .sp-host { font-size: var(--fs-12); line-height: var(--lh-12); color: var(--text-3); overflow-wrap: anywhere; }
  .sp-title { font-size: var(--fs-14); line-height: var(--lh-14); font-weight: 600; color: var(--text); overflow-wrap: anywhere; }
  .sp-desc {
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
    font-size: var(--fs-13);
    line-height: var(--lh-13);
    color: var(--text-2);
    overflow-wrap: anywhere;
  }

  /* --------------------------------------------- post drafts: wrap the text */
  .sd-body { white-space: pre-wrap; overflow-wrap: anywhere; }
}

/* ---- css/53-free-first.css ---- */
/* 53-free-first: the one line every paid card and paid tool page carries before the
   paid tool (Sprint 187 lane C): the FREE first-party source for your own site, and
   a link to its connection page. Inside a playbook row (.pb-body, a flex column) the
   line is ONE span, so its text and link stay in one inline run (CLAUDE.md 5.2). */
@layer views {

  .ff-line { margin: 0 0 var(--s-3); font-size: var(--fs-13); line-height: var(--lh-13); color: var(--text-2); }
  .pb-body .ff-line { margin: 0; font-size: var(--fs-12); line-height: var(--lh-12); }
}

@layer phone {
  @media (max-width: 767px) {
    .ff-line a { display: inline-flex; align-items: center; min-height: 44px; }
  }
}

/* ---- css/54-google-reviews.css ---- */
/* 54-google-reviews: Google reviews from free Google sources (Sprint 187 lane B) - the
   Places lookup and the Business Profile page. Google's Places policies set the
   attribution: the text "Google Maps" in Roboto 400 at 12-16 px, in #5E5E5E, #1F1F1F
   or white (--gmaps-text), never translated (translate="no" in the markup). A review
   row is a flex line of ONE avatar and ONE span, so the name, link and date stay in
   one inline run (CLAUDE.md 5.2). */
@layer views {

  .gmaps-attr { margin: var(--s-2) 0 0; font-family: Roboto, Arial, sans-serif; font-weight: 400; font-style: normal;
    font-size: var(--fs-13); line-height: var(--lh-13); color: var(--gmaps-text); }
  .gr-list { list-style: none; margin: 0; padding: 0; }
  .gr-item { padding: var(--s-3) 0; border-top: 1px solid var(--border); }
  .gr-who { display: flex; align-items: center; gap: var(--s-2); }
  .gr-av { width: 32px; height: 32px; border-radius: 50%; flex: none; }
  .gr-meta { font-size: var(--fs-12); line-height: var(--lh-12); color: var(--text-2); }
  .gr-txt { margin: var(--s-2) 0 0; white-space: pre-line; overflow-wrap: anywhere; }
}

@layer phone {
  @media (max-width: 767px) {
    .gr-item a { display: inline-flex; align-items: center; min-height: 44px; }
  }
}

/* ---- css/55-pipeline.css ---- */
/* 55-pipeline: the pipeline panel and a model run's output, both rendered
   into #result. Spec section 5 "Pipeline panel"; chunk C3.
   A model wrote everything below the caveat banner: it is drawn as text in a
   plain box, never as a chart or a score. */
@layer views {

  /* ======================== progress: one segment per specialist ===== */
  .pl-prog {
    display: grid;
    grid-auto-flow: column;
    grid-auto-columns: minmax(0, 1fr);
    gap: 2px;
    height: 8px;
  }
  .pl-prog > i { display: block; min-width: 0; border-radius: 2px; background: var(--surface-3); }
  .pl-prog > .plp-done { background: var(--good); }
  .pl-prog > .plp-failed { background: var(--bad); }
  .pl-prog > .plp-running { background: var(--changed); animation: q-pulse 1.2s ease-in-out infinite alternate; }
  .pl-prog > .plp-queued { background: var(--surface-3); }
  /* not run: the not-measured signature, an empty dashed segment */
  .pl-prog > .plp-skipped { background: transparent; border: 1px dashed var(--border-control); }

  /* ================================================ specialist rows ===== */
  .pl { --cols: minmax(0, 1fr) 104px 72px; }
  .pl > .pl-r { row-gap: 2px; padding-block: 6px; }
  /* round 3: a specialist's name wraps; at 375px nine were cut with "..."
     ("The work order - what each specialist is aske...") */
  .pl > .pl-r > .tc-p { white-space: normal; overflow-wrap: anywhere; }
  .pl-c { color: var(--text-2); }
  .pl-e {
    grid-column: 1 / -1;
    font-size: var(--fs-12);
    line-height: var(--lh-12);
    color: var(--text-3);
    overflow-wrap: anywhere;
  }

  /* ================================================== deliverables ===== */
  .pl-out { border-top: 1px solid var(--border); }
  .pl-card > .cc-h + .pl-out { border-top: 0; }
  .pl-out > summary {
    display: flex;
    align-items: center;
    gap: var(--s-2);
    min-height: 44px;
    list-style: none;
    cursor: pointer;
    font-size: var(--fs-14);
    line-height: var(--lh-14);
    font-weight: 500;
    color: var(--text);
  }
  .pl-out > summary::-webkit-details-marker { display: none; }
  .pl-out > summary::before {
    content: "";
    flex: none;
    width: 6px;
    height: 6px;
    margin: 0 2px;
    border-right: 1.5px solid var(--text-2);
    border-bottom: 1.5px solid var(--text-2);
    transform: rotate(-45deg);
    transition: transform var(--dur-1) var(--ease);
  }
  .pl-out[open] > summary::before { transform: rotate(45deg); }
  /* an open deliverable keeps its title (and the way to close it) in view */
  .pl-out[open] > summary { position: sticky; top: 0; z-index: 2; background: var(--surface); }
  .pl-ol { flex: 1; min-width: 0; overflow-wrap: anywhere; }   /* a phone wraps a long title (S180 live repair: 9 cut at 375px) */
  .pl-out > summary > i {
    font-style: normal;
    font-size: var(--fs-12);
    line-height: var(--lh-12);
    font-weight: 400;
    color: var(--text-3);
    font-variant-numeric: tabular-nums;
  }
  .pl-body { display: grid; gap: var(--s-2); padding-bottom: var(--s-4); min-width: 0; }
  .pl-nr { display: grid; gap: 6px; padding-bottom: var(--s-4); }
  .pl-nr > li { font-size: var(--fs-13); line-height: var(--lh-13); color: var(--text-2); }
  .pl-nr > li > b { font-weight: 500; color: var(--text); }

  /* ======================================= model output (drafts) ===== */
  /* A deliverable drawn as a document, never a JSON dump (S180 live repair) */
  /* No inner scroller (S180 live repair round 2): a 556px box around a
     document 15-33 boxes long was a scroll trap on a phone. The deliverable's
     own summary stays at the top while it is read, and closes it. */
  .agent-out {
    display: grid;
    gap: var(--s-2);
    margin: 0;
    padding: var(--s-3) var(--s-4);
    background: var(--bg);
    border: 1px solid var(--border);
    border-radius: var(--r-md);
    color: var(--text);
    font-size: var(--fs-13);
    line-height: var(--lh-13);
    /* round 4: "anywhere", not "break-word" - only "anywhere" lowers the
       min-content width, so a long address or a code token in a list item
       no longer widened the item past the card and the phone's viewport
       (Measurement, job 105: "IP rege...", "google-site-..." cut off) */
    overflow-wrap: anywhere;
    min-width: 0;
  }
  .agent-out :is(ul, ol) > li, .agent-out .ao-md > *, .agent-out .ao-it > * { min-width: 0; }
  .agent-out p { margin: 0; }
  .agent-out :is(h3, h4) { margin: 0; font-size: var(--fs-13); line-height: var(--lh-13); letter-spacing: 0; }
  .agent-out :is(ul, ol) { margin: 0; padding-left: var(--s-5); display: grid; gap: var(--s-1); }
  .agent-out code {
    font-family: var(--mono);
    font-size: var(--fs-12);
    padding: 0 var(--s-1);
    border-radius: var(--r-sm);
    background: var(--surface-2);
  }
  .agent-out a { color: var(--accent-text); }
  /* counted by us before the model was called: a measurement, shown apart */
  .agent-measured { background: var(--surface-2); }
  .ao-md { display: grid; gap: var(--s-2); min-width: 0; }
  .ao-mh { font-weight: 600; color: var(--text); padding-top: var(--s-1); }
  .ao-h {
    font-size: var(--fs-12);
    line-height: var(--lh-12);
    font-weight: 600;
    color: var(--text-2);
    padding-top: var(--s-2);
  }
  .ao-kv { color: var(--text); }
  .ao-k { font-weight: 500; color: var(--text-2); }
  .ao-k::after { content: ":"; }
  .ao-it {
    display: grid;
    gap: var(--s-1);
    padding: var(--s-2) 0 var(--s-2) var(--s-3);
    border-left: 2px solid var(--border);
    min-width: 0;
  }
  .ao-t { font-weight: 600; color: var(--text); }
  /* the model's markdown quote ("> For self-directed investors..."), round 3 */
  .ao-q { margin: 0; padding-left: var(--s-3); border-left: 2px solid var(--border-strong); color: var(--text); }
  .ao-none { color: var(--text-3); }
  .ao-code {
    margin: 0;
    padding: var(--s-2) var(--s-3);
    max-height: 320px;
    overflow: auto;
    background: var(--surface-2);
    border-radius: var(--r-sm);
    font-family: var(--mono);
    font-size: var(--fs-12);
    line-height: var(--lh-mono);
    white-space: pre-wrap;
    overflow-wrap: anywhere;
  }
  /* A table scrolls sideways inside its own box; a cell never breaks a word
     (a phone read "Pilla r", "Cros s- Bord er" in 41-57px columns). */
  .ao-tbl {
    overflow-x: auto;
    min-width: 0;
    /* round 4: a table cut at the right edge gave no cue that it scrolls.
       Two covers that move with the content hide two shadows that do not,
       so a shadow shows only on a side with more to see. */
    background:
      linear-gradient(to right, var(--bg) 40%, transparent) left / 24px 100% no-repeat local,
      linear-gradient(to left, var(--bg) 40%, transparent) right / 24px 100% no-repeat local,
      radial-gradient(farthest-side at 0 50%, color-mix(in srgb, var(--text) 22%, transparent), transparent) left / 10px 100% no-repeat scroll,
      radial-gradient(farthest-side at 100% 50%, color-mix(in srgb, var(--text) 22%, transparent), transparent) right / 10px 100% no-repeat scroll;
  }
  .agent-measured .ao-tbl {
    background:
      linear-gradient(to right, var(--surface-2) 40%, transparent) left / 24px 100% no-repeat local,
      linear-gradient(to left, var(--surface-2) 40%, transparent) right / 24px 100% no-repeat local,
      radial-gradient(farthest-side at 0 50%, color-mix(in srgb, var(--text) 22%, transparent), transparent) left / 10px 100% no-repeat scroll,
      radial-gradient(farthest-side at 100% 50%, color-mix(in srgb, var(--text) 22%, transparent), transparent) right / 10px 100% no-repeat scroll;
  }
  .ao-tbl table { border-collapse: collapse; min-width: 100%; font-size: var(--fs-12); line-height: var(--lh-12); }
  .ao-tbl :is(th, td) { min-width: 9ch; padding: var(--s-1) var(--s-2); border-bottom: 1px solid var(--border); text-align: left; vertical-align: top; overflow-wrap: normal; word-break: normal; }
  .ao-tbl th { font-weight: 600; color: var(--text-2); }
  .ao-tbl :is(th, td):last-child { min-width: 22ch; }

  /* ============ Sprint 180 item 17: "Is this your business?" (.pc) ===== */
  /* the page's own words, each labelled with where it was read */
  .pc-q { display: grid; gap: var(--s-2); margin: 0; min-width: 0; }
  .pc-q > div { display: grid; grid-template-columns: 72px minmax(0, 1fr); column-gap: var(--s-3); min-width: 0; }
  .pc-q dt { font-size: var(--fs-12); line-height: var(--lh-13); font-weight: 500; color: var(--text-3); }
  .pc-q dd { margin: 0; font-size: var(--fs-13); line-height: var(--lh-13); color: var(--text); overflow-wrap: anywhere; }
  .pc-f { display: grid; gap: var(--s-2); min-width: 0; margin: 0; padding: 0; border: 0; }
  .pc-l { padding: 0; margin-bottom: var(--s-1); font-size: var(--fs-13); line-height: var(--lh-13); font-weight: 500; color: var(--text); }
  .pc-mks {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(min(100%, 240px), 1fr));
    gap: var(--s-2);
    min-width: 0;
  }
  /* one market: a checkbox and its count; the quote that proves it beneath */
  .pc-mk {
    display: grid;
    grid-template-columns: auto minmax(0, 1fr);
    /* round 4: "center" set each card's title by its own height, so paired
       titles sat 4px apart (Canada 657 vs United States 661) */
    align-items: baseline;
    align-content: start;
    column-gap: var(--s-2);
    max-width: 100%;
    min-height: 40px;
    padding: 6px var(--s-3);
    border: 1px solid var(--border-strong);
    border-radius: var(--r-md);
    background: var(--surface);
    cursor: pointer;
  }
  .pc-mk:has(> input:checked) { border-color: var(--accent-text); background: var(--accent-wash); }
  .pc-mk > input { width: 16px; height: 16px; margin: 0; accent-color: var(--accent); align-self: start; margin-top: 2px; }
  .pc-mt { font-size: var(--fs-13); line-height: var(--lh-13); font-weight: 500; color: var(--text); font-variant-numeric: tabular-nums; }
  .pc-mq {
    grid-column: 2;
    max-width: 48ch;
    font-style: normal;
    font-size: var(--fs-12);
    line-height: var(--lh-12);
    color: var(--text-2);
    overflow-wrap: anywhere;
  }
  .pc-mk > .pc-h { grid-column: 2; max-width: 48ch; }
  .pc-add { display: flex; flex-wrap: wrap; align-items: center; gap: var(--s-2) var(--s-3); }
  .pc-add > select { min-width: 200px; min-height: 40px; }
  .pc-h { font-size: var(--fs-12); line-height: var(--lh-12); color: var(--text-3); }
  .pc-none { flex: 1 0 100%; }

  /* ============ the reviewer's grounding check, measured by us ========= */
  /* a measurement among model drafts: the stronger border sets it apart */
  .pl-gr { border-color: var(--border-strong); }
  .pl-gl { display: flex; flex-wrap: wrap; align-items: center; gap: 4px var(--s-2); font-size: var(--fs-13); line-height: var(--lh-13); color: var(--text); }
  .pl-gf { display: grid; }
  .pl-gf > li { display: grid; gap: 6px; padding: var(--s-3) 0; border-top: 1px solid var(--border); min-width: 0; }
  .pl-gf > li:first-child { border-top: 0; padding-top: 0; }
  .pl-gf > li > b { font-size: var(--fs-14); line-height: var(--lh-14); font-weight: 500; color: var(--text); }
  .pl-gf > li > em { font-style: normal; font-size: var(--fs-13); line-height: var(--lh-13); color: var(--text-2); }
  .pl-gc { display: flex; flex-wrap: wrap; gap: 6px; }
  .pl-gn { font-size: var(--fs-13); line-height: var(--lh-13); color: var(--text-2); }

  @media (prefers-reduced-motion: reduce) {
    .pl-prog > .plp-running { animation: none; }
  }
}

@layer phone {
  @media (max-width: 767px) {
    .pl > .pl-r > .pl-s { margin-left: 0; }
    .pl > .pl-r > .pl-c { margin-left: auto; }
    /* a market row is the tap target (rule 10): 44px, full width */
    .pc-mk { min-height: 44px; }
    .pc-q > div { grid-template-columns: minmax(0, 1fr); }
    .pc-add > select { flex: 1 1 160px; min-width: 0; }
    /* below the rail, which is a 56px sticky row on a phone */
    .pl-out[open] > summary { top: 56px; }
  }
}

/* ---- css/56-bing.css ---- */
/* 56-bing: Bing Webmaster Tools on the tool page (Sprint 187 lane A). Built from
   shared parts (20, 25, 44, 49): .tbl, .kpis, .cc, .hb, .tp-f, .tp-act, .err,
   .src-note, .cov-note, .cc-f, and Search Console's .gsc-tbl / .gsc-k / .gsc-sel
   for the searches and pages tables. Only the connect steps list and four tables'
   columns are new here. No flex container holds inline text runs. */
@layer views {

  /* the steps to connect with Bing's read-only sign-in */
  ol.bng-steps { list-style: decimal; padding-left: var(--s-4); }
  .bng-steps li + li { margin-top: 2px; }

  /* Your page · Links Bing counts */
  .bng-tgt { --cols: minmax(0, 1fr) 136px; }
  /* Linking page · Anchor text · To your page */
  .bng-lnk { --cols: minmax(0, 1fr) minmax(0, 1fr) minmax(0, 1fr); }
  /* Page · HTTP · What Bing found · Links in */
  .bng-iss { --cols: minmax(0, 1fr) 64px minmax(0, 1fr) 80px; }
  /* Grounding query or page · Citations */
  .bng-ai { --cols: minmax(0, 1fr) 96px; }
  /* Day · Citations · Cited pages */
  .bng-ai3 { --cols: minmax(0, 1fr) 96px 112px; }
  :is(.bng-tgt, .bng-lnk, .bng-iss, .bng-ai, .bng-ai3) .tc-p { white-space: normal; overflow-wrap: anywhere; }
}

/* ---- css/57-backlink-intel.css ---- */
/* 57-backlink-intel: Sprint 189 lane A - backlink intelligence below the Backlinks
   run on its tool page (44-tool). Built from shared parts: .tp-out, .rp, .cc and the
   notes (44, 50, 25), .tbl and its Show all (20), hbars and the legend (25), the .at
   line frame of 42-area, and Sprint 182's .bl-k, .bl-from and .bl-flags (48). New
   here: four tables' columns, the two lines' colours and the disavow pick rows.

   FLEX AND INLINE TAGS (CLAUDE.md 5.2): .bli-pick is a flex container; each thing in
   it (the box, the domain-over-path stack, the flag chips, a label's words) is its own
   element. */
@layer views {

  /* Anchor · Type · Backlinks · Domains · First seen */
  .bli-anc { --cols: minmax(0, 1fr) 128px 88px 80px 96px; }
  .bli-anc .tc-p { white-space: normal; overflow-wrap: anywhere; }
  /* Attribute · Count */
  .bli-att { --cols: minmax(0, 1fr) minmax(0, 1.4fr); }
  /* Month · New · Lost · New domains · Lost domains */
  .bli-vel { --cols: minmax(0, 1fr) 72px 72px 104px 104px; }
  /* Subnet · Domains · Backlinks · IPs · First seen · Mark */
  .bli-net { --cols: minmax(0, 1fr) 80px 88px 56px 96px 152px; }

  /* New and lost links: two lines on 42-area's frame; the dots carry the same tones */
  .at-l.bli-new { stroke: var(--good); }
  .at-l.bli-lost { stroke: var(--bad); }

  /* the disavow picks: one 44px row each - the box, the linking domain over its path,
     its flags - and the two "write each pick as" choices */
  .bli-dv { --cols: minmax(0, 1fr); }
  .bli-pick { display: flex; align-items: center; gap: var(--s-2) var(--s-3); min-width: 0; min-height: 44px; cursor: pointer; }
  .bli-pick > input { flex: none; width: 16px; height: 16px; margin: 0; accent-color: var(--accent); }
  .bli-pick > .bl-from { flex: 1 1 auto; min-width: 0; }
}

@layer phone {
  @media (max-width: 767px) {
    /* the flags go under the domain, lined up with it: beside it they squeezed the
       domain to a third of the row and broke it mid-word (measured at 390px) */
    .bli-pick { flex-wrap: wrap; }
    .bli-pick > .bl-flags { flex-basis: 100%; padding-left: calc(16px + var(--s-3)); }
  }
}

/* ---- css/58-link-prospects.css ---- */
/* 58-link-prospects: link prospects on the tool page (Sprint 189 lane B). Built from
   shared parts (20, 44, 47, 50): .tbl, .cc, .chip, .tp-f, .tp-act, .tp-note, .src-note,
   .cov-note, .err, .aiv-sum, .patch. Only the prospect block, its proof records, the
   checklist rows and two tables' columns are new here. No flex container holds a bare
   inline text run (CLAUDE.md 5.2): .lp-h and each .lp-ck row hold chips and ONE span. */
@layer views {

  .lp-page { display: grid; gap: var(--s-4); min-width: 0; }

  /* one prospect: its head (kind, state, address), what was checked, its records, its draft */
  .lp-p { display: grid; gap: var(--s-2); min-width: 0; padding-top: var(--s-4); border-top: 1px solid var(--border); }
  .lp-h { display: flex; flex-wrap: wrap; align-items: center; gap: var(--s-2); min-width: 0; }
  .lp-u { min-width: 0; overflow-wrap: anywhere; font-weight: 500; }

  /* one CASL proof record and its checklist */
  .lp-c { display: grid; gap: var(--s-2); min-width: 0; padding-left: var(--s-3); border-left: 2px solid var(--border); }
  ul.lp-ck { display: grid; gap: var(--s-1); margin: 0; padding: 0; list-style: none; }
  .lp-ck > li { display: flex; align-items: flex-start; gap: var(--s-2); min-width: 0; }
  .lp-ck > li > span:last-child { min-width: 0; overflow-wrap: anywhere; }

  .lp-form { display: grid; gap: var(--s-2); max-width: 560px; min-width: 0; }

  /* Search · State · Price or why · Open */
  .lp-parts { --cols: minmax(0, 1fr) 140px minmax(0, 2fr) 72px; }
  /* Page · Verdict · Why */
  .lp-chk { --cols: minmax(0, 2fr) 120px minmax(0, 2fr); }
  :is(.lp-parts, .lp-chk) .tc-p { white-space: normal; overflow-wrap: anywhere; }
}

/* ---- css/60-pages.css ---- */
/* 60-pages: the Pages view (`sites`: #trendCard, #watchCard, #evCard) and the
   History view (#histCard). Sprint 178 chunk C4, spec section 5.
   Components (.tbl, .kpis, .sc, .chip, .es, .ph) come from 20-components and
   25-charts; this file only lays them out. Tokens only - the build refuses a
   colour or font-size literal here. */
@layer views {

  /* ------------------------------------------------------ shared panels ---- */
  /* A view root is transparent (.view); these carry the surfaces. overflow:clip,
     not hidden: hidden would make the panel a scroll container and break the
     sticky History day heads. */
  .pg-panel {
    min-width: 0;
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: var(--r-lg);
    overflow: clip;
  }
  /* #watchCard and #evCard stay .card; their tables run edge to edge */
  .card.pg-card { padding: 0; overflow: clip; }
  .pg-h { display: grid; gap: 2px; padding: var(--s-4) var(--s-5) var(--s-3); border-bottom: 1px solid var(--border); }
  .pg-h > details.basis { margin-top: var(--s-1); }
  /* "What changed": the selected site or all sites (Sprint 180 item 13) */
  .ev-scope { display: flex; flex-wrap: wrap; gap: 6px; margin-top: var(--s-1); }
  :is(#trendCard, #histCard) > .ph { margin-bottom: 0; }
  #trendCard > .ph details.basis { margin-top: var(--s-1); }
  .tr-roll { min-width: 0; }
  /* a numeric header keeps the label colour (.tc-n alone would ink it) */
  :is(.tr-tbl, .h-tbl, .wt-tbl) .tbl-h > .tc-n { color: var(--text-3); }
  .pg-foot { font-size: var(--fs-12); line-height: var(--lh-12); color: var(--text-3); }

  /* could-not-load and nothing-yet, sized like the list they stand in for */
  :is(.pg-panel, .pg-card) > :is(.unknown, .empty).es { min-height: 200px; }

  /* ------------------------------------------------------------ Pages ---- */
  /* page · readings over time · now · change · findings (spec 5, Pages) */
  /* the change column fits "≠ Scoring changed" on one line (160) */
  .tr-tbl { --cols: minmax(0, 1fr) 128px 88px 160px 80px; }
  .tr-site .ts-h { min-width: 0; overflow-wrap: anywhere; }
  .tr-site .ts-m { display: inline-flex; align-items: center; gap: 6px; }
  .t-u { display: flex; flex-direction: column; align-items: flex-start; gap: 2px; min-width: 0; padding-block: var(--s-2); }
  .t-url { display: block; max-width: 100%; }
  a.t-url:hover { color: var(--accent-text); }
  .t-root::before { content: "/"; }
  /* a url shown alone: its host lower-cased on screen (live rows carry
     https://Quinndatum.com); textContent stays the raw url (watch_state) */
  .t-host { text-transform: lowercase; }
  .t-wo { margin-left: calc(-1 * var(--s-2)); }
  /* a KPI sub that names a page: one line, the end elided, never broken
     mid-word ("www.gnu.org/philosop / hy/free-sw.html" at 375) */
  .kpi-1l { display: block; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  .t-spark { display: flex; align-items: center; min-height: 28px; }
  .t-c { min-width: 0; }
  .t-chg { font-size: var(--fs-13); line-height: var(--lh-13); color: var(--text-2); font-variant-numeric: tabular-nums; }
  .t-chg.is-up { color: var(--good); }
  .t-chg.is-down { color: var(--bad); }

  /* ---------------------------------------------------- watches card ---- */
  .wt-tbl { --cols: minmax(0, 1fr) 120px minmax(0, 220px) 112px; }
  .wt-tbl .tbl-r > .btn-2 { justify-self: end; }
  .wt-u { display: flex; flex-direction: column; gap: 2px; min-width: 0; padding-block: var(--s-2); }
  .wt-u > .tc-p { max-width: 100%; }
  .wt-why { font-size: var(--fs-12); line-height: var(--lh-12); color: var(--text-3); }

  /* ------------------------------------------------------ what changed ---- */
  .ev-tbl { --cols: 136px 160px minmax(0, 1fr); }
  .ev-g .ev-p { min-width: 0; color: var(--text); overflow-wrap: anywhere; }
  .ev-g .ev-p:hover { color: var(--accent-text); }
  .ev-r { align-items: start; padding-block: var(--s-3); }
  .ev-when { font-size: var(--fs-13); line-height: var(--lh-13); color: var(--text-2); font-variant-numeric: tabular-nums; }
  a.ev-when:hover { color: var(--accent-text); }
  .ev-num { min-width: 0; }
  .ev-list { display: grid; gap: var(--s-1); min-width: 0; font-size: var(--fs-13); line-height: var(--lh-13); color: var(--text-2); }
  .ev-i { min-width: 0; overflow-wrap: anywhere; }
  .ev-k { font-weight: 500; color: var(--text); }
  .ev-v { color: var(--text-2); }
  .ev-note { color: var(--text-3); }
  /* a finding in words now ("The heading levels skip a step"), not its code */
  .ev-code { color: var(--text); }

  /* ---------------------------------------------------------- History ---- */
  /* fixed columns: the score sits at ONE x position whether or not a row
     carries a change chip - each cell is pinned to its column. */
  .h-tbl { --cols: minmax(0, 1fr) 72px 88px 72px; }
  .h-head > .tbl-h { border-bottom: 1px solid var(--border); }
  .pg-panel:has(> #hist:empty) > .h-head { display: none; }
  .h-r > * { grid-row: 1; }
  .h-r > .h-u { grid-column: 1; }
  .h-r > .h-d { grid-column: 2; justify-self: start; }
  /* a comparable 0: kept for the engine check, drawn as nothing */
  .h-r > .h-d.h-z:not(.t-nc) { visibility: hidden; }
  .h-r > .n { grid-column: 3; }
  .h-r > .when { grid-column: 4; color: var(--text-3); }
  .h-u { display: flex; flex-direction: column; gap: 2px; min-width: 0; padding-block: var(--s-2); }
  .h-url {
    min-width: 0;
    font-size: var(--fs-14);
    line-height: var(--lh-14);
    font-weight: 500;
    color: var(--text);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
  }
  .h-err { font-size: var(--fs-12); line-height: var(--lh-12); color: var(--text-3); overflow-wrap: anywhere; }
  .h-day {
    position: sticky;
    top: 56px;              /* under the sticky 56px top bar */
    z-index: 1;
    display: flex;
    align-items: center;
    min-height: 32px;
    padding: 0 var(--s-4);
    background: var(--surface-2);
    border-bottom: 1px solid var(--border);
    font-size: var(--fs-12);
    line-height: var(--lh-12);
    font-weight: 500;
    color: var(--text-3);
  }

  /* the first-visit empty state: a dashed "—" where the score will go */
  .h-empty { display: grid; gap: var(--s-5); padding: var(--s-6) var(--s-5); }
  .first-score { display: flex; align-items: center; gap: var(--s-4); }
  .fs-dash {
    flex: none;
    display: grid;
    place-items: center;
    width: 56px;
    height: 56px;
    border: 1px dashed var(--border-control);
    border-radius: var(--r-lg);
    font-size: var(--fs-28);
    line-height: var(--lh-28);
    font-weight: 600;
    color: var(--text-3);
  }
  .fs-cap { font-size: var(--fs-14); line-height: var(--lh-14); font-weight: 600; color: var(--text); }
  .fs-note { margin-top: 2px; font-size: var(--fs-13); line-height: var(--lh-13); color: var(--text-2); }
  .steps { display: grid; gap: var(--s-3); counter-reset: step; max-width: 72ch; }
  .steps > li {
    position: relative;
    padding-left: var(--s-7);
    counter-increment: step;
    font-size: var(--fs-13);
    line-height: var(--lh-13);
    color: var(--text-2);
  }
  .steps > li::before {
    content: counter(step);
    position: absolute;
    left: 0;
    top: 0;
    display: grid;
    place-items: center;
    width: 20px;
    height: 20px;
    border-radius: var(--r-full);
    background: var(--surface-2);
    font-size: var(--fs-12);
    line-height: var(--lh-12);
    font-weight: 600;
    color: var(--text-2);
  }
  .steps b { color: var(--text); font-weight: 600; }
  .unlock { display: grid; grid-template-columns: repeat(auto-fill, minmax(200px, 1fr)); gap: var(--s-2); }
  .unlock:empty { display: none; }
  .unlock-card { display: grid; gap: 2px; padding: var(--s-3); border-radius: var(--r-md); background: var(--surface-2); }
  .unlock-card b { font-size: var(--fs-13); line-height: var(--lh-13); color: var(--text); }
  .unlock-card span { font-size: var(--fs-12); line-height: var(--lh-12); color: var(--text-2); font-variant-numeric: tabular-nums; }
  .unlock-card em { font-style: normal; font-size: var(--fs-12); line-height: var(--lh-12); color: var(--text-3); }

  /* ---------------------------------- Sprint 178 IA, chunk L (lists) ---- */
  /* A monitoring card never shows its empty line under a could-not-look
     block: an outage is not "nothing yet" (first_run asserts the unknown). */
  .pg-card:has(> .unknown.es:not([hidden])) > .empty.es { display: none; }

  /* The This site | All sites scope toggle (AI crawler access): two links on
     a track, the current one raised - the #themeSeg shape, with words. */
  .scope-tg {
    display: inline-flex;
    align-items: center;
    gap: 2px;
    height: 32px;
    padding: 1px;
    background: var(--surface-2);
    border: 1px solid var(--border);
    border-radius: var(--r-md);
  }
  .scope-tg > a {
    display: inline-flex;
    align-items: center;
    height: 28px;
    padding: 0 var(--s-3);
    border-radius: var(--r-sm);
    font-size: var(--fs-13);
    line-height: var(--lh-13);
    font-weight: 500;
    color: var(--text-2);
    white-space: nowrap;
    transition: background-color var(--dur-1) var(--ease), color var(--dur-1) var(--ease);
  }
  .scope-tg > a:hover { color: var(--text); }
  .scope-tg > a[aria-current="page"] {
    background: var(--surface);
    color: var(--text);
    box-shadow: 0 0 0 1px var(--border-strong);
  }
}

@layer phone {
  @media (max-width: 767px) {
    .pg-h { padding: var(--s-3) var(--s-4); }
    /* rule 10 for LINK controls (the base phone rule covers buttons) */
    a.ev-when, .ev-g .ev-p { display: flex; align-items: center; min-height: 44px; }
    .t-u, .wt-u, .h-u { padding-block: 0; }
    .t-url { line-height: 44px; }
    /* date and chip on one line, what moved under them */
    .ev-r > :first-child { flex: 0 1 auto; }
    .ev-list { flex: 1 0 100%; }
    .h-r > .when, .tr .tc-n { margin-left: auto; }
    /* the top bar's phone height is not 56px; a sticky head would slide under it */
    .h-day { position: static; }
    .first-score { align-items: flex-start; }
    /* rule 10 for the toggle's links */
    .scope-tg { height: auto; }
    .scope-tg > a { height: auto; min-height: 44px; }
  }
}

/* ---- css/61-placements.css ---- */
/* 61-placements: sponsored placements on the tool page (Sprint 189 lane D). Built from
   shared parts (20, 44): .tbl, .cc, .tp-grid, .tp-f, .tp-act, .tp-facts, .chip, .basis,
   .src-note, .cov-note. New here: two tables' columns, the actions cell, the <a> tag
   exactly as served, and the weekly checkbox. No flex container holds a bare text run:
   the actions cell holds buttons only, and the checkbox label wraps its words in one
   span (CLAUDE.md 5.2). Tokens only. */
@layer views {

  /* Publisher page · Your page · Status · Last check · actions; the status column fits
     "Waiting for the page" on one line */
  .plc-tbl { --cols: minmax(0, 1fr) minmax(0, 1fr) 160px 128px auto; }
  .plc-acts { display: flex; flex-wrap: wrap; justify-content: flex-end; gap: var(--s-2); }

  /* When · Result · What it found */
  .plc-hist { --cols: 128px 160px minmax(0, 1fr); }
  .plc-hist .tc-s { white-space: normal; overflow-wrap: anywhere; }

  /* the <a> tag exactly as served: wrapped, never cut */
  .plc-tag {
    display: block;
    padding: var(--s-2);
    font-family: var(--mono);
    font-size: var(--fs-12);
    line-height: var(--lh-12);
    color: var(--text);
    white-space: pre-wrap;
    overflow-wrap: anywhere;
    background: var(--surface-2);
    border: 1px solid var(--border);
    border-radius: var(--r-sm);
  }

  .plc-wk { display: inline-flex; align-items: center; gap: var(--s-2); }
}

@layer phone {
  @media (max-width: 767px) {
    .plc-acts { justify-content: flex-start; }
    .plc-wk { min-height: 44px; }
  }
}

/* ---- css/65-lists.css ---- */
/* 65-lists: Keywords, Model runs, AI answers and Reports (Sprint 178, chunk
   C5; build spec section 5). Tables, chips, score cells, menus and empty
   states come from 20-components / 25-charts; this file only lays them out.
   Tokens only: the build refuses a colour or font-size literal here. */
@layer views {

  /* ============================================== the four view roots ===== */
  /* the header sits 24px above the first panel: 8 here + the view's 16 gap */
  :is(#kwCard, #jobsCard, #aeoCard, #repCard) > .ph { margin-bottom: var(--s-2); }
  :is(#kwCard, #jobsCard) .ph-m > details.basis { margin-top: var(--s-1); }

  /* empty and could-not-load states are panels of their own, the height of
     the table they stand in for (spec 3.8: sized to what they replace) */
  :is(#kwCard, #jobsCard, #aeoCard, #repCard) > :is(.empty, .unknown) {
    min-height: 200px;
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: var(--r-lg);
  }

  /* a list panel is a table edge to edge inside its card */
  :is(.kw-cc, .jobs-cc, .rep-cc) { padding: var(--s-2) 0; gap: 0; }
  .aeo-cc, .rep-pipe { padding-bottom: var(--s-2); }
  :is(.aeo-cc, .rep-pipe) > .tbl { margin: 0 calc(-1 * var(--s-5)); }

  /* ======================================================== Keywords ===== */
  /* every column fixed or fr: each row is its own grid, so an `auto` column
     would size per row and the header would drift off its cells */
  .kws { --cols: minmax(0, 1fr) 96px minmax(0, 1.1fr) 176px 148px; }
  .kw { align-items: center; row-gap: 0; padding-block: var(--s-3) 0; }
  .kw-id { display: flex; flex-direction: column; min-width: 0; }
  .kw-w {
    font-size: var(--fs-12);
    line-height: var(--lh-12);
    color: var(--text-3);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
  }
  .kw-n { justify-self: end; font-size: var(--fs-13); line-height: var(--lh-13); color: var(--text-3); white-space: nowrap; }
  .kw-n b {
    font-size: var(--fs-20);
    line-height: var(--lh-20);
    font-weight: 600;
    color: var(--text);
    font-variant-numeric: tabular-nums;
  }
  .kw-m { display: flex; flex-wrap: wrap; align-items: center; gap: var(--s-1) var(--s-2); min-width: 0; font-variant-numeric: tabular-nums; }
  .kw-q, .kw-lc { flex-basis: 100%; font-size: var(--fs-12); line-height: var(--lh-12); color: var(--text-3); }
  .kw-s { color: var(--text-2); font-variant-numeric: tabular-nums; }
  .kw-err { grid-column: span 2; display: flex; flex-wrap: wrap; align-items: center; gap: var(--s-1) var(--s-2); min-width: 0; }
  .kw-why { color: var(--text-2); overflow-wrap: anywhere; }
  .kw > .dl { justify-self: end; }
  /* a numeric column's HEADER keeps the label colour: .tc-n (C0) inks the
     value, and on a .tbl-h cell it made "GAPS" the only ink label in the row */
  :is(.kws, .jobs-l, .aeos) > .tbl-h > .tc-n { color: inherit; }
  /* a run with no topic map (it errored) still ends its row with a gap */
  .kw:not(:has(> .tm)) { padding-bottom: var(--s-3); }

  /* ---- the topic map: a disclosure under its run ---- */
  .kw > .tm { grid-column: 1 / -1; min-width: 0; }
  /* 44px at every width: topic_map.mjs measures it at 1512 with a fine pointer */
  .tm > summary {
    display: inline-flex;
    align-items: center;
    gap: var(--s-2);
    min-height: 44px;
    list-style: none;
    font-size: var(--fs-13);
    line-height: var(--lh-13);
    font-weight: 500;
    color: var(--accent-text);
    cursor: pointer;
  }
  .tm > summary::-webkit-details-marker { display: none; }
  .tm > summary::before {
    content: "";
    width: 6px;
    height: 6px;
    margin: 0 2px;
    border-right: 1.5px solid currentColor;
    border-bottom: 1.5px solid currentColor;
    transform: rotate(-45deg);
    transition: transform var(--dur-1) var(--ease);
  }
  .tm[open] > summary::before { transform: rotate(45deg); }
  .tm-body {
    display: grid;
    gap: var(--s-3);
    margin-bottom: var(--s-4);
    padding: var(--s-4);
    background: var(--surface-2);
    border-radius: var(--r-md);
    font-size: var(--fs-13);
    line-height: var(--lh-13);
    color: var(--text-2);
  }
  .tm-h { font-size: var(--fs-12); line-height: var(--lh-12); font-weight: 500; color: var(--text-3); font-variant-numeric: tabular-nums; }
  .tm-l { display: grid; grid-template-columns: repeat(auto-fill, minmax(280px, 1fr)); gap: var(--s-3); }
  .tm-t {
    display: flex;
    flex-direction: column;
    gap: var(--s-2);
    min-width: 0;
    padding: var(--s-3) var(--s-4);
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: var(--r-md);
  }
  .tm-t > b { font-size: var(--fs-14); line-height: var(--lh-14); color: var(--text); }
  .tm-d { font-size: var(--fs-12); line-height: var(--lh-12); color: var(--text-3); font-variant-numeric: tabular-nums; }
  /* a phrase: covered ones carry a check, open gaps an empty ring - a glyph as
     well as a colour (rule 2), and the glyph is CSS so textContent is unchanged */
  .tm-p { display: flex; flex-wrap: wrap; gap: var(--s-1); }
  .tm-p > li {
    display: inline-flex;
    align-items: center;
    gap: var(--s-1);
    min-height: 20px;
    padding: 0 var(--s-2);
    border: 1px solid var(--border-strong);
    border-radius: var(--r-sm);
    font-size: var(--fs-12);
    line-height: 18px;
    color: var(--text-2);
  }
  .tm-p > .tm-has { background: var(--good-wash); border-color: transparent; color: var(--good); }
  .tm-p > .tm-has::before { content: "\2713"; }
  .tm-p > .tm-gap::before { content: "\25CB"; color: var(--text-3); }
  .tm-q { font-size: var(--fs-12); line-height: var(--lh-12); color: var(--text-2); }
  .tm-q > ul { margin: var(--s-1) 0 0; padding-left: var(--s-5); }
  .tm-q li + li { margin-top: 2px; }
  .tm-u { font-size: var(--fs-12); line-height: var(--lh-12); color: var(--text-2); overflow-wrap: anywhere; }
  .tm-none { color: var(--text-3); }
  :is(.tm-ug, .tm-q-sum, .tm-m) { font-size: var(--fs-12); line-height: var(--lh-12); color: var(--text-3); max-width: 96ch; }
  .tm-un { color: var(--text-2); }

  /* ====================================================== Model runs ===== */
  .jobs-cav { font-weight: 500; color: var(--text-2); }
  /* status fits "Finished with gaps" on one line */
  .jobs-l { --cols: minmax(0, 1fr) 156px 88px 88px 140px; }
  .jobs-l .tbl-r { padding-block: var(--s-2); row-gap: var(--s-1); }
  .jobs-l > li:last-child > .tbl-r { border-bottom: 0; }
  .job-id { display: flex; flex-direction: column; min-width: 0; }
  .job-u {
    font-size: var(--fs-12);
    line-height: var(--lh-12);
    color: var(--text-3);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
  }
  /* a raw model error can run to 500 characters: two lines, the Failed chip
     already carries the state (full text stays in textContent and the title) */
  .job-err {
    grid-column: 1 / -1;
    display: -webkit-box;
    -webkit-box-orient: vertical;
    -webkit-line-clamp: 2;
    overflow: hidden;
    font-size: var(--fs-12);
    line-height: var(--lh-12);
    color: var(--text-2);
    overflow-wrap: anywhere;
  }

  /* ====================================================== AI answers ===== */
  .aeo-dn { max-width: 440px; padding: var(--s-1) 0 var(--s-2); }
  .aeos { --cols: minmax(0, 1fr) 80px 232px minmax(0, 1.6fr); }
  .aeo { padding-block: var(--s-2); }
  .aeo-d { min-width: 0; color: var(--text-2); }
  .aeo-not { font-size: var(--fs-12); line-height: var(--lh-12); color: var(--text-2); }

  /* ========================================================= Reports ===== */
  .rep-cc, .rep-cc .tbl { --cols: minmax(0, 1fr) 88px 96px 120px 28px; }
  .reps-g { border-top: 1px solid var(--border); }
  .rep-cc > .tbl-h { border-bottom: 0; }
  .rep { position: relative; }
  .rep:hover { background: var(--surface-2); }
  .rep-p { display: flex; align-items: baseline; gap: var(--s-2); min-width: 0; }
  .rep-u {
    min-width: 0;
    font-size: var(--fs-14);
    line-height: var(--lh-14);
    font-weight: 500;
    color: var(--text);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
  }
  /* the whole row opens the report: the link stretches over it, and the menu
     trigger sits above the stretch (a button inside an <a> is invalid HTML) */
  .rep-u::after { content: ""; position: absolute; inset: 0; }
  .rep-u:hover { text-decoration: none; }
  .rep-u:focus-visible { outline: none; }
  .rep:has(.rep-u:focus-visible) { outline: 2px solid var(--accent-text); outline-offset: -2px; }
  .rep .sx-btn { position: relative; z-index: 1; justify-self: end; }
  .rep-k { flex: none; font-size: var(--fs-12); line-height: var(--lh-12); color: var(--text-3); }
  .rep-old .rep-u { padding-left: var(--s-4); font-weight: 400; color: var(--text-2); }
  .rep-host { min-width: 0; overflow-wrap: anywhere; }
  /* sites whose readings are all older than the list: named, never absent */
  .rep-older { padding: var(--s-3) var(--s-5) 0; font-size: var(--fs-12); line-height: var(--lh-12); color: var(--text-3); }
  .rep-pipe .tbl { --cols: minmax(0, 1fr) 96px minmax(0, 1fr) auto; }
  .rep-dl { display: flex; gap: var(--s-2); justify-self: end; }
}

@layer phone {
  @media (max-width: 767px) {
    /* rows take two lines (C0); a table panel keeps its card's padding */
    :is(.aeo-cc, .rep-pipe) > .tbl { margin: 0 calc(-1 * var(--s-4)); }
    .kw { padding-block: var(--s-2) 0; }
    /* rule 10: the older sites' links are 44px targets */
    .rep-older { padding-inline: var(--s-4); }
    .rep-older a { display: inline-flex; align-items: center; justify-content: center; min-width: 44px; min-height: 44px; }
    .kw-n { justify-self: start; }
    .kw-err { flex-basis: 100%; }
    .kw > .dl, .rep-dl { margin-left: auto; }
    .tm-l { grid-template-columns: minmax(0, 1fr); }
    .tm-body { padding: var(--s-3); }
    /* rule 10: the covering-page links are controls too */
    .tm-u a { display: inline-flex; align-items: center; min-height: 44px; }
    .job-err { flex-basis: 100%; }
    .aeo-d { flex-basis: 100%; }
    .aeo-dn .dn { flex-wrap: wrap; }
    /* rule 10: the row's link is a 44px target of its own */
    .rep-u { display: inline-flex; align-items: center; min-height: 44px; }
    .rep-p { flex-wrap: wrap; align-items: center; }
    .rep .sx-btn { margin-left: auto; }
    /* C0's phone `.tbl-r { display: flex }` sits in this later layer and
       un-hid the capped rows: re-hide them at a higher specificity */
    .reps-g:not(.is-all) > .is-more { display: none; }
  }
}

/* ---- css/70-plan-account.css ---- */
/* 70-plan-account: the Plan and Account views (build spec section 5, chunk C6).
   Markup: #planCard and #acctCard; rows are .tbl-r beside the hooks the tests
   read (.le, .ses, .tier, .key-revoke). Tokens only. */
@layer views {

  /* Tables in these cards run edge to edge, like Search Atlas's lists; the
     card's own 20px padding stays on the title and the footnote. */
  :is(#planCard, #acctCard) .cc > :is(.tbl, .tbl-more) { margin-inline: calc(var(--s-5) * -1); }
  :is(#planCard, #acctCard) .cc > .tbl-more { padding: 0 var(--s-4); }
  :is(#planCard, #acctCard) .cc > .tbl { border-top: 1px solid var(--border); }
  :is(#planCard, #acctCard) .cc > .tbl:last-child { margin-bottom: calc(var(--s-5) * -1); }
  .plan-kpis:empty { display: none; }

  /* ============================================== headroom (#headroom) ===== */
  /* action · price · you can run · limited by, and what it buys under them */
  .hr-tbl { --cols: minmax(0, 1fr) 56px 88px 80px; --hr-rows: 10; }
  .hr-r { row-gap: 2px; padding-block: 10px; align-items: start; }
  .hr-l { min-width: 0; font-size: var(--fs-14); line-height: var(--lh-14); font-weight: 500; color: var(--text); }
  .hr-r > .tc-n { line-height: var(--lh-14); }
  .hr-basis {
    grid-column: 1 / -1;
    max-width: 72ch;
    font-size: var(--fs-12);
    line-height: var(--lh-12);
    color: var(--text-3);
  }
  .hr-h2 { display: none; }
  @media (min-width: 1100px) {
    /* two columns, filled top to bottom; --hr-rows is set by renderCredits */
    .hr-tbl {
      display: grid;
      grid-template-columns: repeat(2, minmax(0, 1fr));
      grid-template-rows: repeat(var(--hr-rows), auto);
      grid-auto-flow: column;
    }
    .hr-tbl > .hr-h2 { display: grid; }
    .hr-tbl > .hr-h2, .hr-tbl > .hr-h2 ~ li { border-left: 1px solid var(--border); }
  }

  /* ================================================== ledger (#ledger) ===== */
  .led-w { display: flex; flex-wrap: wrap; gap: var(--s-2); }
  .ledger { --cols: 132px minmax(0, 1fr) 72px 96px; }
  .le-when { color: var(--text-2); font-variant-numeric: tabular-nums; white-space: nowrap; }
  .le-what { display: flex; flex-direction: column; min-width: 0; padding-block: 6px; }
  .le-what > b, .le-what > small { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  .le-what > b { font-size: var(--fs-14); line-height: var(--lh-14); font-weight: 500; color: var(--text); }
  .le-what > small { font-size: var(--fs-12); line-height: var(--lh-12); color: var(--text-3); }
  .le-amt { font-weight: 500; }
  /* the unit a phone row needs because its column header is hidden there */
  .m-u { display: none; }

  /* ============================================================ tiers ===== */
  .tiers {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(208px, 1fr));
    gap: var(--s-3);
  }
  @media (min-width: 1100px) { .tiers { grid-template-columns: repeat(5, minmax(0, 1fr)); } }
  .tiers-x { grid-column: 1 / -1; }
  .tier {
    display: flex;
    flex-direction: column;
    gap: var(--s-2);
    min-width: 0;
    padding: var(--s-4);
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: var(--r-lg);
  }
  /* the current tier: an accent border (2px, drawn inside so nothing shifts) */
  .tier.is-current { border-color: var(--accent); box-shadow: inset 0 0 0 1px var(--accent); }
  .t-h { display: flex; align-items: center; justify-content: space-between; gap: var(--s-2); min-height: 20px; }
  .t-name { font-size: var(--fs-14); line-height: var(--lh-14); font-weight: 600; color: var(--text); }
  .t-price { display: flex; align-items: baseline; gap: 2px; }
  .t-price b {
    font-size: var(--fs-28);
    line-height: var(--lh-28);
    font-weight: 600;
    letter-spacing: -.02em;
    color: var(--text);
    font-variant-numeric: tabular-nums;
  }
  .t-price span { font-size: var(--fs-13); line-height: var(--lh-13); color: var(--text-3); }
  .t-blurb { min-height: calc(var(--lh-13) * 2); font-size: var(--fs-13); line-height: var(--lh-13); color: var(--text-2); }
  .t-facts {
    padding: var(--s-2) 0;
    border-block: 1px solid var(--border);
    font-size: var(--fs-13);
    line-height: var(--lh-13);
    color: var(--text);
    font-variant-numeric: tabular-nums;
  }
  .t-caps { font-size: var(--fs-12); line-height: var(--lh-12); color: var(--text-3); }
  .t-list { display: grid; gap: 6px; }
  .t-list > li { display: flex; align-items: flex-start; gap: var(--s-2); font-size: var(--fs-13); line-height: var(--lh-13); color: var(--text); }
  .t-list > li.c-no { color: var(--text-3); }
  .t-list > li > span { min-width: 0; }
  .t-mk { width: 16px; height: 16px; flex: none; margin-top: 2px; fill: none; stroke: var(--good); stroke-width: 1.75; stroke-linecap: round; stroke-linejoin: round; }
  /* not startable here: the "not measured / not wired" signature, empty dashed */
  .c-nm { flex: none; width: 10px; height: 10px; margin: 5px 3px 0; border: 1px dashed var(--border-control); border-radius: 50%; }
  .t-pend-d { margin-top: var(--s-2); }
  .t-pend-d > summary > .c-nm { display: inline-block; margin: 0 6px 0 3px; vertical-align: -1px; }
  .t-pend-d > .t-pend { max-width: none; }
  .t-pend { --cols: minmax(0, 220px) minmax(0, 1fr); }
  .t-pend > .tbl-r { padding-block: 10px; align-items: start; }

  /* ========================================================= sign-ins ===== */
  .ses-tbl { --cols: minmax(0, 1fr) 160px 140px; }
  .ses-dev { display: flex; align-items: center; gap: var(--s-2); min-width: 0; color: var(--text); font-weight: 500; }
  .ses-dev > span:first-child { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  .ses-tbl .mono { color: var(--text); }

  /* ============================================================= keys ===== */
  .key-tbl { --cols: minmax(0, 1fr) 144px 96px; }
  .key-st > .chip { white-space: nowrap; }
  .key-id { display: flex; align-items: baseline; gap: var(--s-2); min-width: 0; }
  .key-id > code { flex: none; color: var(--text); }
  .key-id > span { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; color: var(--text-2); }
  .key-off .key-id > code { color: var(--text-3); }
  .key-tbl .key-revoke, .key-tbl .key-st { justify-self: end; }
  .key-none { display: block; padding-block: 14px; }
  .key-new { display: flex; flex-wrap: wrap; align-items: center; gap: var(--s-2); }
  .key-new > input { flex: 0 1 320px; min-width: 0; }
  .key-show p { color: var(--text); }
  .key-v {
    margin-top: var(--s-2);
    padding: var(--s-2) var(--s-3);
    background: var(--surface);
    border: 1px solid var(--border-strong);
    border-radius: var(--r-sm);
    color: var(--text);
    white-space: pre-wrap;
    word-break: break-all;
    user-select: all;
  }

  /* Account at 1100px and up: sign-ins and keys full width, then password and
     your data side by side (both are short forms). */
  @media (min-width: 1100px) {
    #acctCard { grid-template-columns: repeat(2, minmax(0, 1fr)); align-items: start; }
    #acctCard > :not(.pw, .acct-data) { grid-column: 1 / -1; }
  }
  /* natural heights: a stretched card beside the password form was half empty */
  .acct-data { align-self: start; }
  /* the destructive action on its own row, under a hairline, away from Download */
  .danger-row { display: flex; flex-wrap: wrap; align-items: center; gap: var(--s-2); margin-top: var(--s-4); padding-top: var(--s-4); border-top: 1px solid var(--border); }


  /* ========================================================= password ===== */
  .pw-f { display: grid; gap: var(--s-1); max-width: 360px; }
  .pw-f > label, .del-zone label { font-size: var(--fs-13); line-height: var(--lh-13); font-weight: 500; color: var(--text-2); }
  .pw { align-self: start; }
  .pw input { min-height: 40px; }
  .pw-row { display: flex; flex-wrap: wrap; align-items: center; gap: var(--s-2); }
  .pw-msg { font-size: var(--fs-13); line-height: var(--lh-13); color: var(--text-2); }
  .pw-msg.good { color: var(--good); }
  .pw-msg.bad { color: var(--bad); }

  /* ======================================================== your data ===== */
  .del-zone {
    display: grid;
    gap: var(--s-2);
    max-width: 560px;
    padding-top: var(--s-4);
    border-top: 1px solid var(--border);
  }
  .del-zone p { font-size: var(--fs-13); line-height: var(--lh-13); color: var(--text-2); }
  .del-zone p b { color: var(--text); font-weight: 600; }
  .del-zone code { color: var(--text); }
  .del-zone input { max-width: 360px; }
}

@layer phone {
  @media (max-width: 767px) {
    /* a ledger row: what it was first, then when, amount and balance */
    /* C0's phone .tbl-r {display:flex} sits in a later layer than its
       .tbl:not(.is-all) > .is-more {display:none}, so capped rows reappeared
       on phones (measured: 50 of 50 ledger rows at 375). Re-hidden here for
       these two lists; the general fix belongs in 20-components. */
    :is(.ledger, .ses-tbl):not(.is-all) > .is-more { display: none; }
    .le > .le-what { order: -1; flex: 1 0 100%; }
    .le > .le-when { flex: 0 1 auto; }
    .hr-basis { flex: 1 0 100%; }
    .m-u { display: inline; color: var(--text-3); font-weight: 400; }
    /* three KPI cells in C0's 2x2 phone grid: the third takes the full row */
    .plan-kpis .kpi:nth-child(3):last-child { grid-column: 1 / -1; }
    .t-pend > .tbl-r > .tc-s { flex: 1 0 100%; }
    .key-new > input { flex: 1 0 100%; }
    .key-tbl .key-revoke { margin-left: auto; }
    .pw-f { max-width: none; }
  }
}

/* ---- css/75-playbooks.css ---- */
/* 75-playbooks: the Playbooks view (#pbCard). Spec section 5 "Playbooks";
   Sprint 178 part 2 (IA_SPEC 5, chunk P): the library rows link to the tool
   page, "For your site" (#pbRec) sits above the library, and the header links
   to "Your model runs". The pre-run dialog (#pbModal) is retired by chunk T2,
   so its .pm-* rules left this file with it.

   Contracts the tests read (smoke 1440-1600):
   #pbQ 13px / radius 8px / 1px border (from 10-base; only the width is set
   here), .pb-head b at 600, .pb-list > li, one <b> per .pb (the short label),
   .pb-none, .pb-go only on runnable rows, #pbRec rows carry no .pb/.pb-go.

   FLEX AND INLINE TAGS (CLAUDE.md 5.2): .pb-body, .pb-t, .pb-meta, .pb-rec-b
   and .pb-head are flex containers; every text run in them is its own element. */
@layer views {

  /* ------------------------------------------------------------ header -- */
  #pbCard > .ph { margin-bottom: var(--s-2); }   /* + the view's 16px gap = 24 */
  #pbQ { width: 320px; max-width: 100%; }

  /* ----------------------------------------------------------- filters -- */
  /* One row when it fits. At 1440 the two groups need about 1,200px of a
     1,184px column, so the modes wrap as a group: a gap, not a border divider,
     separates them, so a wrapped row never starts with a stray rule. */
  .pb-filters {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--s-2) var(--s-5);
  }
  #pbCard .pb-chips { display: flex; flex-wrap: wrap; align-items: center; gap: var(--s-2); }

  /* ------------------------------------------------- list and #pbRec -- */
  /* One card each; two columns of rows at 1100px and up, split by whitespace
     so each column's hairlines read as its own list. Section heads span both. */
  .pb-list, #pbRec {
    display: grid;
    grid-template-columns: minmax(0, 1fr);
    column-gap: var(--s-8);
    padding: 0 var(--s-5) var(--s-2);
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: var(--r-lg);
  }
  .pb-list:empty { display: none; }

  .pb-head {
    grid-column: 1 / -1;
    display: flex;
    align-items: baseline;
    gap: var(--s-2);
    padding: var(--s-6) 0 var(--s-2);
    border-bottom: 1px solid var(--border);
  }
  .pb-head:first-child { padding-top: var(--s-4); }
  .pb-head b { font-size: var(--fs-14); line-height: var(--lh-14); font-weight: 600; color: var(--text); }
  .pb-head i {
    font-style: normal;
    font-size: var(--fs-12);
    line-height: var(--lh-12);
    color: var(--text-3);
    font-variant-numeric: tabular-nums;
  }
  /* "From your last audit of quinndatum.com/…": right-aligned, one line */
  .pb-head em {
    margin-left: auto;
    min-width: 0;
    font-style: normal;
    font-size: var(--fs-12);
    line-height: var(--lh-12);
    color: var(--text-3);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
  }

  /* a row: [short label + name / when / area + mode][state][price][Run] */
  .pb.tbl-r {
    /* state is 168, not the spec's 128: "Needs a model key here" (a keyless
       deployment) wrapped to two lines (38px) at 144, measured in the P rig */
    --cols: minmax(0, 1fr) 168px 64px minmax(52px, auto);
    min-height: 64px;
    padding: var(--s-3) 0;
  }
  /* a runnable row has no state chip (its section says it runs): the name
     and its "when" line take the freed width, and wrap to two lines rather
     than stopping at "care abo..." */
  .pb.tbl-r.is-run { --cols: minmax(0, 1fr) auto minmax(52px, auto); }
  .pb.is-run > .pb-state { display: none; }
  .pb.is-run .pb-body em { white-space: normal; display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2; }
  .pb-body { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
  /* the short label and the full name: ONE link to the tool page */
  .pb-t {
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    column-gap: var(--s-2);
    min-width: 0;
    color: var(--text);
  }
  .pb-t:hover { text-decoration: none; }
  .pb-t:hover b { text-decoration: underline; text-underline-offset: 2px; }
  .pb-body b { font-size: var(--fs-14); line-height: var(--lh-14); font-weight: 600; color: var(--text); }
  .pb-full {
    min-width: 0;
    max-width: 100%;
    font-size: var(--fs-13);
    line-height: var(--lh-13);
    color: var(--text-2);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
  }
  .pb-body em {
    font-style: normal;
    font-size: var(--fs-13);
    line-height: var(--lh-13);
    color: var(--text-2);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
  }
  .pb-meta {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--s-1) var(--s-2);
    margin-top: 2px;
  }
  .pb-area, .pb-why { font-size: var(--fs-12); line-height: var(--lh-12); color: var(--text-3); }
  .pb-area { font-weight: 500; }
  .pb-cost {
    justify-self: end;
    text-align: right;
    font-size: var(--fs-13);
    line-height: var(--lh-13);
    color: var(--text-2);
    font-variant-numeric: tabular-nums;
  }
  .pb .pb-go { justify-self: end; }

  /* "For your site": [short label / because][price][Run or Open] */
  .pb-rec.tbl-r {
    --cols: minmax(0, 1fr) auto minmax(52px, auto);
    min-height: 56px;
    padding: var(--s-3) 0;
  }
  .pb-rec-b { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
  .pb-rec-t {
    align-self: flex-start;
    max-width: 100%;
    font-size: var(--fs-14);
    line-height: var(--lh-14);
    font-weight: 600;
    color: var(--text);
  }
  .pb-rec-why { font-size: var(--fs-13); line-height: var(--lh-13); color: var(--text-2); }
  .pb-rec .pb-rec-go { justify-self: end; }

  .pb-none {
    grid-column: 1 / -1;
    padding: var(--s-7) var(--s-4);
    text-align: center;
    font-size: var(--fs-13);
    line-height: var(--lh-13);
    color: var(--text-2);
  }
  #pbCard .pb-foot { font-size: var(--fs-12); line-height: var(--lh-12); color: var(--text-3); }

  @media (min-width: 1100px) {
    .pb-list, #pbRec { grid-template-columns: repeat(2, minmax(0, 1fr)); }
    /* #pbRec's head is always child 1, so an even child that is second-last
       is the left cell of a full last row: no hairline under it either */
    #pbRec > .pb-rec:nth-last-child(2):nth-child(even) { border-bottom: 0; }
  }
}

@layer phone {
  @media (max-width: 767px) {
    #pbQ { width: 100%; }
    #pbCard .ph-a { justify-content: stretch; }
    /* each filter axis is one row that scrolls sideways, edge to edge: wrapped,
       the 11 chips took five 44px rows above the list at 375 */
    .pb-filters { display: grid; gap: var(--s-2); }
    #pbCard .pb-chips { flex-wrap: nowrap; overflow-x: auto; margin: 0 calc(-1 * var(--s-4)); padding: 0 var(--s-4); scrollbar-width: none; }
    #pbCard .pb-chips > .pb-chip { flex: none; }
    .pb-list, #pbRec { padding: 0 var(--s-4) var(--s-2); }
    /* 20-components' phone .tbl-r padding is 8/16; these lists pad themselves */
    .pb.tbl-r, .pb-rec.tbl-r { padding: var(--s-3) 0; }
    .pb .pb-go, .pb-rec .pb-rec-go { margin-left: auto; }
    .pb-body em { white-space: normal; display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2; }
    /* rule 10: the row's link is a 44px target */
    .pb-t { min-height: 44px; align-content: center; }
    .pb-rec-t { display: flex; align-items: center; min-height: 44px; min-width: 44px; }
    .pb-head em { flex: 1 0 100%; margin-left: 0; }
    .pb-head { flex-wrap: wrap; }
  }
}

/* ---- css/80-website.css ---- */
/* 80-website: the Website overview (view "website", #webCard, route #site=<host>).
   Spec section 6. Everything else it shows is a shared component (20, 25):
   .ph, .banner, .kpis, .cc, columns/donut/hbars, .tbl, .chip, .es.
   Layout: a 12-column grid, gap 16. Desktop 12 / 6+6 / 4+4+4 / 6+3+3 / 12;
   tablet pairs the third-width cards; phone is one column. */
@layer views {

  /* the header sits 24px above the strip: 8 + the view's 16px gap */
  #webCard > .ph { margin-bottom: var(--s-2); }

  /* align-items:start - a card stretched to its row's tallest was half empty
     (AI crawlers: one chip and one sentence in a ~225px card) */
  .wo-grid {
    display: grid;
    grid-template-columns: repeat(12, minmax(0, 1fr));
    align-items: start;
    gap: var(--s-4);
    min-width: 0;
  }
  /* the two half-width change charts: equal header heights, so their plots
     and baselines line up whether or not a subtitle wraps */
  .wo-grid > .cc-half .cc-s { min-height: calc(var(--lh-12) * 2); }
  /* the half-width charts mark a scoring break with "≠" alone: the readings
     chart above names it in full, and its legend says what "≠" is */
  .wo-grid > .cc-half .col-brk-w { display: none; }
  .wo-grid > * { min-width: 0; }
  .wo-s12 { grid-column: span 12; }
  .wo-s6 { grid-column: span 6; }
  .wo-s4 { grid-column: span 4; }
  .wo-s3 { grid-column: span 3; }

  /* KPI skeleton bars keep the cell's height while loading */
  .wo-sk-v { width: 72px; height: 28px; }
  .wo-sk-s { width: 60%; height: 12px; margin-top: var(--s-1); }
  /* the "Older scoring" chip rides on the caption's line */
  .wo-kpis .kpi-s .chip { margin-left: 2px; }
  /* Sprint 180 item 1 (s180_f1): the Site score caption is up to three lines -
     the mean and its denominator, the worst page (a link that filters Page
     explorer), and what is counted apart. Each is its own block. */
  .wo1-l { display: block; }
  .wo1-l + .wo1-l { margin-top: 2px; }
  .wo-kpis .wo1-l > .chip:first-child { margin-left: 0; }
  /* round 4: a not-comparable chip stays one line ("2 on older scoring"
     wrapped to a 2-line box on a phone), and a tile's age never sits alone */
  .wo1-l .chip.t-nc { white-space: nowrap; }
  .nw { white-space: nowrap; }
  /* the headline's basis sentence, under the strip */
  .wo1-basis { padding: 0 var(--s-1); }
  /* Coverage by section: 8 rows at most; a bar across 1,400px reads as nothing */
  .wo1-cov .hb { max-width: 760px; }
  .wo1-cov .hb.is-of { grid-template-columns: minmax(0, 40%) minmax(0, 1fr) minmax(112px, max-content); }

  /* the whole-view states (never_read, could_not_load) */
  .wo-state { min-height: 240px; justify-content: center; }

  /* read once: the history card is one state, sized like the chart it replaces */
  .wo-once .cc-plot { height: 200px; }

  /* ---- AI crawlers ---- */
  .wo-chips { display: flex; flex-wrap: wrap; gap: 6px; }
  .wo-p { font-size: var(--fs-13); line-height: var(--lh-13); color: var(--text-2); }
  .wo-ai .cc-f { margin-top: auto; }

  /* ---- Speed and weight: two measured blocks, then the not-measured one ---- */
  .wo-m { display: grid; gap: 2px; padding-bottom: var(--s-3); border-bottom: 1px solid var(--border); }
  .wo-m-h { display: flex; flex-wrap: wrap; align-items: baseline; justify-content: space-between; gap: 2px var(--s-2); margin-bottom: 2px; }
  .wo-m-h b { font-size: var(--fs-13); line-height: var(--lh-13); font-weight: 600; color: var(--text); }
  .wo-m-h span { font-size: var(--fs-12); line-height: var(--lh-12); color: var(--text-3); font-variant-numeric: tabular-nums; }
  .wo-m-r { display: flex; align-items: baseline; justify-content: space-between; gap: var(--s-2); min-width: 0; }
  .wo-m-r > span {
    min-width: 0;
    font-size: var(--fs-12);
    line-height: var(--lh-12);
    color: var(--text-3);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
  }
  .wo-m-r > b { flex: none; font-size: var(--fs-13); line-height: var(--lh-13); font-weight: 600; color: var(--text); font-variant-numeric: tabular-nums; }
  .wo-nm {
    display: grid;
    gap: 6px;
    justify-items: start;
    margin-top: auto;
    padding: var(--s-3);
    border: 1px dashed var(--border-control);
    border-radius: var(--r-md);
  }
  .wo-nm p { font-size: var(--fs-12); line-height: var(--lh-12); color: var(--text-2); }
  .wo-nm b { font-weight: 600; color: var(--text); }

  /* ---- Pages, worst first: the score-chip column fits "≠ Older scoring" ---- */
  .wo-tbl { --cols: minmax(0, 1fr) 88px 136px 72px 72px 176px; margin: 0 calc(-1 * var(--s-5)); }
  /* why a row is outside the site score: its indexability, older scoring */
  .wo-out { display: inline-flex; flex-wrap: wrap; align-items: center; gap: var(--s-1); min-width: 0; }
  .wo-tbl > .tbl-h, .wo-tbl > .tbl-r { padding: 0 var(--s-5); }
  .wo-tbl > .tbl-h { border-top: 1px solid var(--border); }
  .wo-tbl > .tbl-more { padding: var(--s-2) var(--s-3) 0; }
  .wo-pages { padding-bottom: var(--s-3); }

  /* the in-links column's own word, shown only once the header row is gone */
  .wo-il { display: none; }

  /* the share button's chevron */
  #webCard .sx-btn > svg { margin-right: -4px; }

  .wo-foot { padding: 0 var(--s-1); }
  /* a critical/high finding about the set of pages, under Indexability (round 3) */
  .wo-across { display: flex; flex-wrap: wrap; align-items: baseline; gap: 4px var(--s-2); overflow-wrap: anywhere; }

  /* ---- tablet: the third-width cards pair up ---- */
  @media (max-width: 1099px) {
    .wo-s4, .wo-s3 { grid-column: span 6; }
    /* the two change charts need ~72px a column: side by side they scroll */
    .wo-s6 { grid-column: span 12; }
    .wo-t12 { grid-column: span 12; }
  }
  /* below ~900px the six table columns no longer fit: two lines per row */
  @media (max-width: 899px) {
    .wo-tbl > .tbl-h { display: none; }
    .wo-tbl > .tbl-r {
      display: flex;
      flex-wrap: wrap;
      align-items: center;
      column-gap: var(--s-3);
      row-gap: 2px;
      padding: var(--s-2) var(--s-5);
    }
    .wo-tbl > .tbl-r > :first-child { flex: 1 0 100%; }
    .wo-il { display: inline; }
  }
}

@layer phone {
  @media (max-width: 767px) {
    .wo-s12, .wo-s6, .wo-s4, .wo-s3, .wo-t12 { grid-column: 1 / -1; }
    .wo-tbl { margin: 0 calc(-1 * var(--s-5)); }
    .wo-tbl > .tbl-r { padding: var(--s-2) var(--s-5); }
    .wo-tbl .tc-n { text-align: left; }
    /* rule 10: links in captions and blocks are 44px targets on a phone */
    .wo-m a, .wo-ai .cc-f a { display: inline-flex; align-items: center; min-height: 44px; }
    .wo-across > a { display: inline-flex; align-items: center; justify-content: center; min-height: 44px; min-width: 44px; }
    .wo1-a { display: inline-flex; align-items: center; min-height: 44px; }
    .wo1-cov .hb.is-of { grid-template-columns: minmax(0, 1fr) max-content; }
  }
}

/* ---- css/82-section.css ---- */
/* 82-section: the site section pages (view "section", #secCard, route
   #site=<host>/<section>). IA spec 3d. Each section is a KPI strip plus one
   filterable, sortable per-page (per-URL, per-issue) table card; before the
   server sends per-page rows, the section's summary card from the Website
   overview (80-website's .wo-* cards) and a not-recorded table slot.
   Everything else is a shared component (20, 25): .ph, .kpis, .cc, .tbl,
   .chip, .pb-chip, .es, .dom (50). Tokens only. */
@layer views {

  /* the header sits 24px above the strip: 8 + the view's 16px gap */
  #secCard > .ph { margin-bottom: var(--s-2); }

  /* Core Web Vitals' "Not measured" chip leads its KPI caption */
  .sec-kpis .kpi-s .chip { margin-right: var(--s-1); }

  /* summary cards (before per-page rows) and the domain page's two cards */
  .sec-pre { display: grid; gap: var(--s-4); min-width: 0; }
  .sec-two {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    align-items: start;
    gap: var(--s-4);
    min-width: 0;
  }
  .sec-act { display: flex; justify-content: center; }
  /* the index-check card's empty state is not the whole card body: at
     .es's min-height:100% it pushed the card's own Run link out under the
     next card, where nothing could press it (s180_t, tabs_click run4) */
  .pe-sw-es { min-height: 0; }
  /* a summary card at full width keeps its content at reading width; its
     Core Web Vitals note is already the strip's own cell on this page */
  .sec-pre :is(.dn, .hb, .wo-m) { max-width: 640px; }
  .sec-pre .wo-nm { display: none; }

  /* ---- the table card ---- */
  .sec-tc { padding-bottom: var(--s-3); }
  .sec-f { display: flex; flex-wrap: wrap; align-items: center; gap: var(--s-2) var(--s-5); }
  .sec-fg { display: flex; flex-wrap: wrap; align-items: center; gap: var(--s-2); }
  /* the row's name before its chips (Sprint 180 live repair) */
  .sec-fl { flex: none; font-size: var(--fs-12); line-height: var(--lh-12); font-weight: 500; color: var(--text-3); }
  /* two groups each start with "All": a rule between them says which is which */
  .sec-fg + .sec-fg { padding-left: var(--s-5); border-left: 1px solid var(--border); }
  /* the table runs edge to edge inside its card, like the overview's */
  .sec-tbl { margin: 0 calc(-1 * var(--s-5)); }
  .sec-tbl > .tbl-h, .sec-tbl > .tbl-r { padding: 0 var(--s-5); }
  .sec-tbl > .tbl-h { border-top: 1px solid var(--border); }
  .sec-tbl > .tbl-more { padding: var(--s-2) var(--s-3) 0; }
  .sec-none { padding: var(--s-4) 0 var(--s-2); font-size: var(--fs-13); line-height: var(--lh-13); color: var(--text-2); }

  /* one column set per section: path first, the rest fixed so every row's
     score, state and number sit at one x position */
  .sec-t-pages .sec-tbl { --cols: minmax(0, 1fr) 88px 136px 96px 72px 104px; }
  .sec-t-byp .sec-tbl { --cols: minmax(0, 1fr) 104px 72px 88px; }
  .sec-t-issues .sec-tbl { --cols: minmax(0, 1fr) 96px 160px 128px; }
  .sec-t-idx .sec-tbl { --cols: minmax(0, 1fr) 176px minmax(0, .6fr); }
  .sec-t-out .sec-tbl { --cols: minmax(0, 1fr) 152px 72px 112px; }
  .sec-t-sch .sec-tbl { --cols: minmax(0, 1fr) minmax(0, 1.2fr) 136px; }
  .sec-t-spd .sec-tbl { --cols: minmax(0, 1fr) 112px 104px 144px; }
  .sec-t-ai .sec-tbl { --cols: minmax(0, 1fr) 232px 104px; }

  /* A sort control is the column's own label: header type, no box until hover. */
  .sec-sort {
    display: inline-flex;
    align-items: center;
    gap: var(--s-1);
    min-height: 32px;
    margin: 0 calc(-1 * var(--s-2));
    padding: 0 var(--s-2);
    border: 0;
    border-radius: var(--r-sm);
    background: none;
    font: inherit;
    letter-spacing: inherit;
    text-transform: inherit;
    color: inherit;
    cursor: pointer;
  }
  .sec-sort:hover { background: var(--surface-2); color: var(--text-2); }
  .sec-sort[aria-pressed="true"] { color: var(--text); }
  .sec-ar { width: 12px; height: 12px; flex: none; }

  /* schema types: chips that wrap inside their cell */
  .sec-types { display: flex; flex-wrap: wrap; gap: var(--s-1); min-width: 0; }

  /* the domain's own findings: a chip, then the evidence as one text run */
  .sec-fnd { display: grid; margin: 0; padding: 0; list-style: none; }
  .sec-fnd > li {
    display: flex;
    align-items: baseline;
    gap: var(--s-2);
    padding: var(--s-2) 0;
    border-top: 1px solid var(--border);
    font-size: var(--fs-13);
    line-height: var(--lh-13);
    color: var(--text);
  }
  .sec-fnd > li > span { min-width: 0; overflow-wrap: anywhere; }
  /* the severity chip keeps its word: as a flex item it shrank to one or two
     letters a line ("Hi / g / h") beside a long finding (S180 live repair) */
  .sec-fnd > li > .chip { flex: none; white-space: nowrap; }

  /* This site / All sites: an in-page segmented control (links, not a 4th level) */
  .sec-seg {
    display: inline-flex;
    justify-self: start;
    gap: 2px;
    padding: 2px;
    border: 1px solid var(--border);
    border-radius: var(--r-md);
    background: var(--surface-2);
  }
  .sec-seg > a {
    display: inline-flex;
    align-items: center;
    min-height: 28px;
    padding: 0 var(--s-3);
    border-radius: var(--r-sm);
    font-size: var(--fs-13);
    line-height: var(--lh-13);
    font-weight: 500;
    color: var(--text-2);
    text-decoration: none;
  }
  .sec-seg > a:hover { color: var(--text); }
  .sec-seg > a[aria-current="page"] { background: var(--surface); color: var(--text); box-shadow: 0 0 0 1px var(--border-strong); }

  /* ---- Sprint 180 (s180_f2) ---- */
  /* Issues with points (item 4): Points carries "+N" and, when some of the
     issue's pages are on an older scoring, a "≠ k older" chip beside it */
  .sec-t-iss2 .sec-tbl { --cols: minmax(0, 1fr) 96px 144px 112px 136px; }
  /* round 3: on desktop 17 issue rows cut their problem sentence with an
     ellipsis ("...asking search engines not to index them, so ..."), so the
     issue could only be read in the drawer. The sentence wraps in its cell. */
  .sec-t-iss2 .sec-tbl > .tbl-r > .tc-p { white-space: normal; overflow-wrap: anywhere; }
  .iss-pt { display: inline-flex; flex-wrap: wrap; justify-content: flex-end; align-items: center; gap: var(--s-1); }

  /* Page explorer (item 15): the column set is the table's own inline
     --cols; --pe-min is the width it needs, and past the card's width the
     table scrolls inside the card, never the page */
  .sec-t-pe .sec-tbl { --pe-min: 0px; }
  .pe-bar { display: grid; gap: var(--s-3); min-width: 0; }
  .pe-tools { display: flex; flex-wrap: wrap; align-items: center; gap: var(--s-2); }
  .pe-ffp { display: block; margin-top: var(--s-1); overflow-wrap: anywhere; }
  .pe-c { min-width: 0; }
  .pe-k { display: none; }
  .pe-u { display: block; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  /* the Page column's path wraps (at most two lines) instead of cutting
     "/blog/2026-06-15-daily-market-wrap.html" to "/blog/2026-0…" while the
     Title column had room (Sprint 180 live repair) */
  .sec-t-pe .sec-tbl > .tbl-r > .tc-p {
    white-space: normal;
    overflow-wrap: anywhere;
    display: -webkit-box;
    -webkit-box-orient: vertical;
    -webkit-line-clamp: 2;
  }
  .pe-h4 { margin: var(--s-4) 0 var(--s-2); font-size: var(--fs-12); line-height: var(--lh-12); font-weight: 500; color: var(--text-3); }

  /* the Indexability page's sitemap index check (item 7) */
  .pe-sw-k { margin-top: var(--s-3); }
  .pe-sw-l { display: grid; gap: var(--s-1); margin: 0; padding: 0; list-style: none; font-size: var(--fs-13); line-height: var(--lh-13); color: var(--text-2); }
  .pe-sw-l b { font-weight: 600; color: var(--text); }

  /* The issue drawer (item 5): the C0 dialog as a right-side sheet */
  .dlg-scrim.idw { place-items: stretch end; padding: 0; }
  .dlg.dlg-side {
    width: min(480px, 100vw);
    height: 100dvh;
    max-height: 100dvh;
    border-width: 0 0 0 1px;
    border-radius: 0;
  }
  .dlg-side .dlg-t { overflow-wrap: anywhere; }
  .idw-sv { flex: none; }
  .idw-sk { height: 48px; margin-bottom: var(--s-2); }
  /* one text run per line (a flex line would split "2" from its words); a
     chip in it sits inline after the text */
  .idw-m { margin: 0 0 var(--s-2); }
  .idw-m .chip { margin-left: var(--s-1); vertical-align: middle; }
  .idw-h { margin: var(--s-4) 0 var(--s-2); font-size: var(--fs-13); line-height: var(--lh-13); font-weight: 600; color: var(--text); }
  .idw-fix { margin: 0 0 var(--s-2); color: var(--text); }
  .idw-tbl { --cols: minmax(0, 1fr) 88px auto; margin: 0 calc(-1 * var(--s-6)); }
  .idw-tbl > .tbl-h, .idw-tbl > .tbl-r { padding-left: var(--s-6); padding-right: var(--s-6); }
  .idw-tbl > .tbl-r { padding-top: var(--s-2); padding-bottom: var(--s-2); }
  .idw-p { display: grid; gap: 2px; min-width: 0; }
  .idw-p .tc-p { white-space: normal; overflow-wrap: anywhere; }
  .idw-e { font-size: var(--fs-13); line-height: var(--lh-13); color: var(--text); overflow-wrap: break-word; }
  .idw-q { font-size: var(--fs-12); line-height: var(--lh-12); color: var(--text-3); }
  .idw-open { white-space: nowrap; }

  @media (min-width: 900px) {
    .sec-t-pe .sec-tbl { overflow-x: auto; }
    .sec-t-pe .sec-tbl > .tbl-h, .sec-t-pe .sec-tbl > .tbl-r { min-width: var(--pe-min); }
  }

  /* below ~900px the columns no longer fit: two lines per row, and the
     header row keeps only its sort controls */
  @media (max-width: 899px) {
    .sec-tbl > .tbl-h {
      display: flex;
      flex-wrap: wrap;
      align-items: center;
      gap: 0 var(--s-4);
      padding: var(--s-1) var(--s-5);
    }
    .sec-tbl > .tbl-h > span:not(:has(> .sec-sort)) { display: none; }
    .sec-tbl > .tbl-r {
      display: flex;
      flex-wrap: wrap;
      align-items: center;
      column-gap: var(--s-3);
      row-gap: 2px;
      padding: var(--s-2) var(--s-5);
    }
    .sec-tbl > .tbl-r > :first-child { flex: 1 0 100%; }
    .sec-tbl .tc-n { text-align: left; }
    .sec-two { grid-template-columns: minmax(0, 1fr); }
    /* groups wrap onto their own lines here: the rule would float mid-row */
    .sec-fg + .sec-fg { padding-left: 0; border-left: 0; }
    /* a stacked explorer row names each value's column */
    .pe-k { display: inline; color: var(--text-3); }
    /* an issue's problem is the row: up to three lines, not one cut line */
    .sec-t-iss2 .sec-tbl > .tbl-r > .tc-p { white-space: normal; overflow: hidden; display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 3; line-clamp: 3; }
  }
}

@layer phone {
  @media (max-width: 767px) {
    /* the components' phone rule hides every .tbl-h; this one carries the sorts */
    .sec-tbl > .tbl-h { display: flex; }
    .sec-tbl > .tbl-r { padding: var(--s-2) var(--s-5); }
    /* rule 10: 44px targets on a phone */
    .sec-sort, .sec-seg > a { min-height: 44px; min-width: 44px; justify-content: center; }
    /* the issue drawer: a full-height sheet; its links are 44px targets */
    .dlg-scrim.idw { place-items: stretch; }
    .dlg.dlg-side { width: 100%; height: 100dvh; max-height: 100dvh; border-width: 0; border-radius: 0; }
    .idw-tbl > .tbl-r { padding: var(--s-2) var(--s-6); }
    .idw-open, .idw-m a, .pe-ffp a { display: inline-flex; align-items: center; min-height: 44px; }
  }
}

