/* ============================================================================
   Report, opportunity & analysis surfaces
   ----------------------------------------------------------------------------
   App-specific composites. Every class name here is already emitted by the
   views/helpers; the rules are ported onto design tokens so they re-theme with
   the rest of the system.
   ============================================================================ */

@layer components {
  /* --- Run & schedule panels (generation + schedule forms) ---------------- */
  /* Both forms share the .report-config shell: the bare fieldset becomes a
     card-grade settings panel so it sits comfortably beside the metric and
     table cards around it. */
  .report-config { margin-bottom: var(--space-5); }
  /* The run and schedule panels share the top of the reports page: side by
     side where they fit so the data cards below start higher, stacking on a
     phone. `align-items: start` keeps each panel its natural height — the
     compact run panel shouldn't stretch to match the schedule's. */
  .report-config-row {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(min(340px, 100%), 1fr));
    align-items: start;
    gap: var(--space-4);
    margin-bottom: var(--space-5);
  }
  .report-config-row .report-config { margin-bottom: 0; min-width: 0; }
  .report-config fieldset {
    background: var(--bg-primary);
    border: 0.5px solid var(--border);
    border-radius: var(--radius-lg);
    box-shadow: var(--shadow-sm);
    margin: 0;
    padding: var(--space-5);
  }
  /* Float pulls the legend off the fieldset border into normal flow — the one
     reliable cross-browser way to restyle it as the panel's title row. Every
     row clears it, so the first in-flow row always lands below. */
  .report-config legend {
    float: left;
    width: 100%;
    padding: 0;
    margin-bottom: var(--space-4);
    font-size: 13.5px;
    letter-spacing: -0.01em;
    color: var(--text-primary);
  }
  .report-config fieldset > * { clear: both; }
  .report-config fieldset > * + * { margin-top: var(--space-4); }

  /* A labelled row of fields; the two schedule selects share one line where
     they fit and stack on a phone. */
  .report-config-fields {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-3) var(--space-6);
  }
  .report-config .report-config-field {
    display: inline-flex;
    flex-direction: column;
    align-items: flex-start;
    gap: var(--space-1);
    margin: 0;
  }
  /* Small quiet caption shared by field names and group headings, so the
     panel's labels read one step below the legend. */
  .report-config-field-name,
  .report-config-label {
    font-size: 12.5px;
    font-weight: 500;
    color: var(--text-secondary);
  }
  .report-config-label { display: block; margin-bottom: var(--space-2); }

  /* Provider checkboxes as pill chips: the border says "control", the accent
     wash says "selected". Browsers without :has() still show the checkbox
     state inside the chip. */
  .provider-options {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-2);
  }
  .report-config .provider-options label {
    display: inline-flex;
    align-items: center;
    gap: var(--space-2);
    margin: 0;
    padding: var(--space-1) var(--space-3) var(--space-1) var(--space-2);
    font-size: 12.5px;
    font-weight: 400;
    background: var(--bg-primary);
    border: 0.5px solid var(--border-strong);
    border-radius: var(--radius-full);
    cursor: pointer;
    transition: background var(--speed-fast) var(--ease-out),
                border-color var(--speed-fast) var(--ease-out);
  }
  .report-config .provider-options label:hover { background: var(--bg-secondary); }
  .report-config .provider-options label:has(input:checked) {
    background: var(--accent-soft);
    border-color: color-mix(in srgb, var(--accent) 50%, transparent);
  }
  .report-config .provider-options input[type="checkbox"] { margin: 0; }

  /* Stacked email toggles; the checkbox tops-aligns so a label that wraps on
     a phone hangs cleanly off it. */
  .report-config-toggles {
    display: flex;
    flex-direction: column;
    gap: var(--space-2);
  }
  .report-config .report-config-toggles label {
    display: flex;
    align-items: flex-start;
    gap: var(--space-2);
    margin: 0;
    font-weight: 400;
  }
  .report-config .report-config-toggles input[type="checkbox"] { margin: 3px 0 0; }

  /* The sampling/coverage explainer sits collapsed like the methodology note. */
  .report-config-note > summary {
    font-size: 12.5px;
    font-weight: 500;
    color: var(--text-secondary);
    transition: color var(--speed-fast) var(--ease-out);
  }
  .report-config-note > summary:hover { color: var(--text-primary); }
  .report-config-note > p { margin: var(--space-2) 0 0; max-width: 68ch; }

  /* Action row: the submit button with the credit-cost / current-schedule note
     beside it, wrapping under on narrow screens. */
  .report-config-footer {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--space-3) var(--space-4);
    padding-top: var(--space-4);
    border-top: 0.5px solid var(--border);
  }
  .report-config-footer .muted { margin: 0; flex: 1 1 260px; }
  .report-credit-context { flex: 1 1 260px; }
  .report-credit-context p { margin: 0; }
  .report-credit-summary { width: fit-content; font-weight: 500; }

  /* --- Methodology note (collapsed under the metrics heading) ------------- */
  .report-methodology { margin-bottom: var(--space-3); }
  .report-methodology > summary { transition: color var(--speed-fast) var(--ease-out); }
  .report-methodology > summary:hover { color: var(--text-primary); }
  .report-methodology > p { margin: var(--space-2) 0 0; }

  /* --- Run status pill ----------------------------------------------------- */
  /* The generation status reads as a quiet chip under the page header: neutral
     while the run is live, success-tinted once it settles, danger on failure.
     Turbo swaps the whole element, so the tint tracks the run in place. */
  .report-status {
    display: inline-flex;
    align-items: center;
    gap: var(--space-2);
    margin: 0 0 var(--space-4);
    padding: var(--space-1) var(--space-3);
    font-size: 12.5px;
    font-weight: 500;
    background: var(--bg-secondary);
    border: 0.5px solid var(--border);
    border-radius: var(--radius-full);
    color: var(--text-secondary);
  }
  .report-status svg { flex-shrink: 0; }
  .report-status-completed {
    background: var(--success-bg);
    border-color: var(--success-border);
    color: var(--success-text);
  }
  .report-status-failed {
    background: var(--danger-bg);
    border-color: var(--danger-border);
    color: var(--danger-text);
  }
  /* History-table badges only (the run pill above stays neutral while live):
     an in-flight run reads as active among the settled rows. */
  .badge.report-status-pending,
  .badge.report-status-processing {
    background: var(--info-bg);
    border-color: var(--info-border);
    color: var(--info-text);
  }

  /* --- Answers card (the prompt-group accordion's shell) ------------------- */
  /* The prompt list joins the metrics/trends cards instead of floating bare on
     the page; the prompts' own hairlines become the card's internal dividers,
     with the first doubling as the rule under the heading. */
  .report-answers {
    background: var(--bg-primary);
    border: 0.5px solid var(--border);
    border-radius: var(--radius-lg);
    box-shadow: var(--shadow-sm);
    padding: var(--space-4) var(--space-5);
    margin: var(--space-4) 0;
  }
  /* Heading row with the expand/collapse-all control at the trailing edge. */
  .report-answers-header {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: space-between;
    gap: var(--space-2) var(--space-3);
    margin-bottom: var(--space-3);
  }
  .report-answers-header h2 {
    margin: 0;
    font-size: 13.5px;
  }
  .report-answers .report-prompt:last-child { padding-bottom: 0; }

  /* --- Prompt groups (collapsed prompt → answers accordion) --------------- */
  .report-prompt {
    padding: var(--space-4) 0;
    border-top: 0.5px solid var(--border);
  }
  .report-prompt > summary {
    font-size: 13.5px;
    font-weight: 500;
  }
  /* The prompt text warms to the accent on hover — the open/close affordance
     for the whole row, without underlining it like a navigation link. */
  .report-prompt-title { transition: color var(--speed-fast) var(--ease-out); }
  .report-prompt > summary:hover .report-prompt-title { color: var(--accent); }
  /* The tally chips trailing the prompt text on the summary line. Inline-flex
     (not flex on the summary itself) so the disclosure marker keeps rendering. */
  .report-prompt-summary {
    display: inline-flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--space-2);
    margin-left: var(--space-2);
    vertical-align: middle;
    font-weight: 400;
  }

  /* --- One answer (provider/sample) within a prompt group ----------------- */
  .report-result {
    padding-top: var(--space-4);
    margin-top: var(--space-4);
    border-top: 0.5px dashed var(--border);
  }
  .report-result > h3 { margin-top: 0; font-size: 12.5px; color: var(--text-secondary); }

  /* --- Rendered Markdown (report answers & the opportunities summary) ------ */
  /* Every surface that renders model-authored Markdown through
     ApplicationHelper#render_markdown carries .report-markdown, so the output
     is styled once. The content is model-generated, so long unbroken runs
     (URLs, slugs, domain lists) must wrap rather than push the page sideways
     on a phone. */
  .report-markdown { overflow-wrap: break-word; }
  .report-markdown > :first-child { margin-top: 0; }
  .report-markdown > :last-child { margin-bottom: 0; }
  .report-markdown h1, .report-markdown h2, .report-markdown h3,
  .report-markdown h4, .report-markdown h5, .report-markdown h6 {
    margin: var(--space-5) 0 var(--space-2);
    line-height: 1.25;
  }
  .report-markdown h1 { font-size: 22px; }
  .report-markdown h2 { font-size: 14px; }
  .report-markdown h3 { font-size: 13.5px; }
  .report-markdown p, .report-markdown ul, .report-markdown ol,
  .report-markdown blockquote, .report-markdown pre, .report-markdown table {
    margin: 0 0 var(--space-3);
  }
  .report-markdown ul, .report-markdown ol { padding-left: var(--space-6); }
  .report-markdown blockquote {
    margin-left: 0;
    padding-left: var(--space-3);
    border-left: 3px solid var(--border-strong);
    color: var(--text-secondary);
  }
  .report-markdown pre {
    background: var(--bg-tertiary);
    border: 0.5px solid var(--border);
    padding: var(--space-3) var(--space-4);
    border-radius: var(--radius-md);
    overflow-x: auto;
    scrollbar-width: thin;
  }
  .report-markdown pre code { background: none; border: none; padding: 0; }
  .report-markdown img { max-width: 100%; height: auto; }
  /* Model-emitted comparison tables can be arbitrarily wide and sit outside
     any card, so they scroll within their own box like `pre` does instead of
     stretching the page. */
  .report-markdown table {
    display: block;
    width: max-content;
    max-width: 100%;
    overflow-x: auto;
    scrollbar-width: thin;
  }

  /* --- Web-search sources listed after a result -------------------------- */
  .report-sources { margin-top: var(--space-4); font-size: 12.5px; }
  .report-sources h4 { margin: var(--space-3) 0 var(--space-1); font-size: 12.5px; }
  .report-sources ol { margin: 0; padding-left: var(--space-5); }
  .report-sources li { word-break: break-word; }

  /* --- Per-answer analysis verdict --------------------------------------- */
  .analysis { margin-top: var(--space-4); }
  .analysis-badges {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-2);
    margin-bottom: var(--space-2);
  }

  /* --- Public share link (report page) ------------------------------------ */
  /* A dashed quiet panel — visually "an aside about this report", not another
     data card, so it doesn't compete with the metrics card below it. */
  .report-share {
    margin: var(--space-4) 0;
    padding: var(--space-3) var(--space-4);
    background: var(--bg-secondary);
    border: 0.5px dashed var(--border-strong);
    border-radius: var(--radius-md);
  }
  .report-share p { margin: 0 0 var(--space-2); max-width: 68ch; }
  .report-share code { word-break: break-all; }
  /* The link + copy button row; the copy button keeps a stable footing while
     the long URL wraps beside it. */
  .report-share-link {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--space-2);
    margin-bottom: var(--space-2);
  }
  .report-share-form {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--space-2);
  }

  /* --- Metrics, trends, cited-source & history cards ---------------------- */
  .report-metrics,
  .report-trends,
  .cited-sources,
  .report-history {
    background: var(--bg-primary);
    border: 0.5px solid var(--border);
    border-radius: var(--radius-lg);
    box-shadow: var(--shadow-sm);
    padding: var(--space-4) var(--space-5);
    margin: var(--space-4) 0;
  }
  .report-metrics > h2,
  .report-trends > h2,
  .cited-sources > h2,
  .report-history > .section-header { margin: 0 0 var(--space-3); }
  .report-history > .section-header h2 { font-size: 13.5px; }
  .report-metrics h3,
  .report-trends h3,
  .cited-sources h3 { margin: var(--space-4) 0 var(--space-1); font-size: 13.5px; }

  .metrics-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(160px, 1fr));
    gap: var(--space-3);
    margin: 0;
  }
  /* Each metric reads as a .tile (see cards.css) — shared by the metrics and
     trends cards so the two summary surfaces speak one visual language. Label
     and figure styling (size aside) come from the shared stat-tile rules in
     cards.css. */
  .metrics-grid dd { font-size: 25px; }
  /* The raw "(3/5)" tally beside a headline rate — smaller and quieter so the
     percentage stays the figure that reads. */
  .metrics-grid dd .metric-sub {
    font-size: 13px;
    font-weight: 400;
    letter-spacing: 0;
    color: var(--text-tertiary);
  }

  /* Hairline dividers section the card: after the headline tiles, each
     drill-down (changes, donuts, providers, prompts, standings) opens its
     own labelled zone instead of running into the previous one. */
  .metrics-providers, .metrics-missing, .metrics-changes, .metrics-standings,
  .metrics-prompt-changes, .metrics-coverage, .metrics-share {
    margin-top: var(--space-5);
    padding-top: var(--space-4);
    border-top: 0.5px solid var(--border);
  }
  /* Each section's heading opens it flush against the divider. */
  .report-metrics > div > h3:first-child { margin-top: 0; }
  .metrics-changes ul, .metrics-prompt-changes ul {
    margin: 0;
    padding-left: var(--space-5);
  }
  .metrics-changes li { font-weight: 500; }

  /* Low-visibility entries read as stacked rows — the prompt, then its
     tally-and-competitors line under it — split by hairlines instead of
     running the two apart on one bulleted line. */
  .metrics-missing ul { list-style: none; margin: 0; padding: 0; }
  .metrics-missing li { margin: 0; padding: var(--space-2) 0; }
  .metrics-missing li:last-child { padding-bottom: 0; }
  .metrics-missing li + li { border-top: 0.5px solid var(--border); }
  .missing-prompt { font-weight: 500; }
  /* Scoped to the low-visibility list: the prompt-changes list reuses
     .missing-prompt inline ahead of its "— summary" run-on. */
  .metrics-missing .missing-prompt,
  .missing-detail { display: block; }
  .missing-detail { max-width: 72ch; }

  /* The card's sampling/failure notes and section intros stay a readable
     measure; its tables are figure-dense, so tabular digits keep the percent
     columns from wobbling between rows (mirrors the trends card). */
  .report-metrics p { max-width: 68ch; }
  .report-metrics td { font-variant-numeric: tabular-nums; }
  /* Headings and captions carrying a title tooltip advertise it. */
  .report-metrics h3[title], .report-metrics h4[title],
  .report-metrics dt[title], .share-chart figcaption[title] { cursor: help; }

  /* --- Visibility trends card --------------------------------------------- */
  /* The stat tiles (.tile, see cards.css) gain a sparkline here, pinned to
     the tile's bottom edge so the mini-charts land on one line across a row
     even when a delta wraps or a sparkline is missing. */
  .report-trends .metrics-grid {
    grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
  }
  .report-trends .metrics-grid > div,
  .visibility-pulse-grid > div {
    display: flex;
    flex-direction: column;
  }
  .report-trends .metrics-grid dd,
  .visibility-pulse-grid dd {
    display: flex;
    flex: 1;
    flex-direction: column;
    gap: var(--space-2);
  }
  .report-trends .sparkline,
  .visibility-pulse-grid .sparkline { margin-top: auto; }
  /* The rate, its raw "(3/5)" tally and its delta chip share one baseline; a
     long "vs previous" label wraps under the number instead of stretching the
     tile sideways. Every stat tile emits this span (see
     projects/_metric_tile), so it is not scoped to the trends card. */
  .trend-figure {
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    gap: var(--space-1) var(--space-2);
  }
  /* History rows are almost all figures; tabular digits keep the percent
     columns from wobbling between rows. */
  .report-trends td { font-variant-numeric: tabular-nums; }
  /* The intro line and the uneven-scoring caveat stay a readable measure. */
  .report-trends > p { max-width: 68ch; }
  /* The uneven-scoring caveat sits below the tiles; paragraphs only carry
     bottom margin, so it needs its own breathing room from the grid. */
  .report-trends .metrics-grid + p { margin-top: var(--space-3); }

  /* --- Sparkline (helper-rendered SVG) ----------------------------------- */
  /* The helper emits a fixed 140px width; the viewBox lets it scale down
     inside a metrics-grid column that lands narrower than that. The polygon
     is the soft fill under the line; the circle marks the latest value. */
  .sparkline { display: block; margin-top: var(--space-1); max-width: 100%; height: auto; }
  .sparkline polyline {
    fill: none;
    stroke: var(--chart-1);
    stroke-width: 2;
    stroke-linecap: round;
    stroke-linejoin: round;
  }
  .sparkline polygon { fill: color-mix(in srgb, var(--chart-1) 10%, transparent); }
  .sparkline circle { fill: var(--chart-1); }

  /* --- Project visibility pulse ----------------------------------------- */
  /* A compact read of the latest project metrics. It stays unframed so the
     three stat tiles are the only card surfaces and can sit cleanly above the
     project's longer detail sections. */
  .visibility-pulse { margin: var(--space-5) 0 var(--space-6); }
  .visibility-pulse-header {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: space-between;
    gap: var(--space-2) var(--space-4);
    margin-bottom: var(--space-3);
  }
  .visibility-pulse-header h2 { margin: 0; }
  .visibility-pulse-grid {
    grid-template-columns: repeat(3, minmax(0, 1fr));
  }
  .visibility-pulse-grid > div { min-width: 0; }
  .visibility-pulse-grid dt[title] { cursor: help; }
  .visibility-pulse-latest {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--space-1);
    margin: var(--space-3) 0 0;
    font-size: 12.5px;
  }

  @media (max-width: 640px) {
    .visibility-pulse-grid { grid-template-columns: 1fr; }
  }

  /* --- Share-of-voice donuts (helper-rendered SVG) ------------------------ */
  /* One indirection carries the palette: a slice's circle strokes with the
     entry's color while its legend swatch fills with the same one, so the
     ring and the legend can't disagree. The rollup "Others" slice reads as
     quiet gray rather than spending a palette color on a grab-bag. */
  .chart-color-1 { --chart-color: var(--chart-1); }
  .chart-color-2 { --chart-color: var(--chart-2); }
  .chart-color-3 { --chart-color: var(--chart-3); }
  .chart-color-4 { --chart-color: var(--chart-4); }
  .chart-color-5 { --chart-color: var(--chart-5); }
  .chart-color-other { --chart-color: var(--text-tertiary); }

  .metrics-share .share-charts {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-3);
    margin-top: var(--space-3);
  }
  /* Each donut sits in a .tile (see cards.css) like the trend cards: caption,
     then the ring and its legend side by side, wrapping on a phone. */
  .share-chart {
    flex: 1 1 280px;
    max-width: 480px;
    margin: 0;
  }
  .share-chart figcaption {
    font-size: 12.5px;
    font-weight: 500;
    color: var(--text-secondary);
    margin-bottom: var(--space-3);
  }
  .share-chart-body {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--space-3) var(--space-5);
  }
  .donut-wrap { position: relative; flex-shrink: 0; }
  .donut-chart { display: block; }
  .donut-chart circle { fill: none; stroke: var(--chart-color); }
  /* The brand's cut of the share sits in the ring's hole — the number the
     caption asks about, readable without the legend. The label truncates to
     the hole's width; the legend still carries the full name. */
  .donut-center {
    position: absolute;
    inset: 0;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    text-align: center;
    pointer-events: none;
  }
  .donut-center-value {
    font-size: 19px;
    font-weight: 500;
    letter-spacing: -0.02em;
    font-variant-numeric: tabular-nums;
  }
  .donut-center-label {
    font-size: 10.5px;
    color: var(--text-tertiary);
    max-width: 68px;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
  }

  /* Swatch / name / share columns share one grid so the values line up into
     a right-aligned figure column at the tile's edge. */
  .chart-legend {
    list-style: none;
    margin: 0;
    padding: 0;
    flex: 1 1 150px;
    display: grid;
    grid-template-columns: auto minmax(0, 1fr) auto;
    align-items: center;
    gap: var(--space-1) var(--space-2);
    font-size: 13px;
  }
  .chart-legend li { display: contents; }
  .chart-legend li .muted {
    justify-self: end;
    font-size: 12.5px;
    font-variant-numeric: tabular-nums;
    white-space: nowrap;
  }
  .chart-swatch {
    width: 10px;
    height: 10px;
    border-radius: 3px;
    flex-shrink: 0;
    background: var(--chart-color);
  }
  .chart-brand { font-weight: 500; }

  /* --- Per-provider share bars (provider breakdown) ----------------------- */
  /* Label / bar / value columns share one grid so the bars align into a
     comparable chart no matter how long the provider names run. */
  .provider-bars {
    display: grid;
    grid-template-columns: auto minmax(120px, 1fr) auto;
    gap: var(--space-2) var(--space-3);
    align-items: center;
    max-width: 480px;
    margin-bottom: var(--space-4);
  }
  .provider-bars h4 {
    grid-column: 1 / -1;
    margin: 0;
    font-size: 12.5px;
    font-weight: 500;
    color: var(--text-secondary);
  }
  .provider-bar-row { display: contents; }
  .provider-bar-label { font-size: 13.5px; }
  .provider-bar-value {
    justify-self: end;
    font-size: 13px;
    font-variant-numeric: tabular-nums;
  }
  /* Every column after the provider name is a figure; right alignment stacks
     the digits under their headers so the rates compare down a column. */
  .metrics-providers th:not(:first-child),
  .metrics-providers td:not(:first-child) { text-align: right; }
  .metrics-providers td:first-child { white-space: nowrap; }
  .fraction-bar {
    height: 8px;
    border-radius: var(--radius-full);
    background: var(--chart-grid);
    overflow: hidden;
  }
  .fraction-bar-fill {
    height: 100%;
    border-radius: inherit;
    background: var(--chart-1);
  }

  /* --- Visibility by prompt (bar per prompt) ------------------------------ */
  /* Each prompt is a stacked entry — the full question on its own line, the
     bar and tally under it — split by hairlines like the low-visibility list
     that follows. The bar tracks share one cap so lengths stay comparable
     instead of stretching with the page. */
  .coverage-rows { margin-top: var(--space-3); }
  .coverage-row {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--space-1) var(--space-2);
    padding: var(--space-2) 0;
  }
  .coverage-row:first-child { padding-top: 0; }
  .coverage-row:last-child { padding-bottom: 0; }
  .coverage-row + .coverage-row { border-top: 0.5px solid var(--border); }
  .coverage-prompt {
    flex: 1 1 100%;
    font-size: 13.5px;
    max-width: 72ch;
  }
  /* Many stacked bars at the default 8px read as a wall of ink; slimmer
     tracks keep the color crisp while the prompts stay the foreground. */
  .coverage-row .fraction-bar {
    flex: 1 1 120px;
    max-width: 360px;
    height: 5px;
  }
  .coverage-value {
    font-size: 13px;
    font-variant-numeric: tabular-nums;
    white-space: nowrap;
  }

  /* Bars inside the standings and cited-domain tables sit under their counts
     as a glance layer; the floor keeps them chart-grade when a column lands
     narrow. */
  .metrics-standings .fraction-bar,
  .cited-domains .fraction-bar {
    min-width: 90px;
    margin-top: var(--space-1);
  }
  /* The mentioned/recommended columns get equal, generous tracks so their
     bars compare across rows instead of hugging the 90px floor while the
     name column soaks up the width. */
  .metrics-standings th:nth-child(2),
  .metrics-standings th:nth-child(3) { width: 28%; min-width: 150px; }

  /* The report list is a run of timestamps; count the "3 of 5" tallies and
     row dates in tabular digits like the other figure-dense tables. */
  .report-history td { font-variant-numeric: tabular-nums; }
  .report-history td:first-child a { font-weight: 500; }
  .history-pager {
    display: flex;
    align-items: baseline;
    gap: var(--space-3);
    margin-top: var(--space-3);
    font-size: 13px;
  }

  .cited-sources ol { margin: 0; padding-left: var(--space-5); }
  .cited-sources li { word-break: break-word; }

  /* The full domain table sits collapsed behind this disclosure; its summary
     line stands in for the section's h3, with the methodology note's hover
     warmth as the open affordance. */
  .cited-domains { margin-top: var(--space-4); }
  .cited-domains > summary {
    font-size: 13.5px;
    font-weight: 500;
    letter-spacing: -0.01em;
    color: var(--text-secondary);
    transition: color var(--speed-fast) var(--ease-out);
  }
  .cited-domains > summary:hover { color: var(--text-primary); }
  .cited-domains > p { margin-top: var(--space-1); }

  /* --- Opportunities ----------------------------------------------------- */
  /* The ranked action list. The cards number themselves via a CSS counter so
     the "biggest expected impact first" ordering stays visible without <ol>
     markers fighting the card layout. */
  .opportunities {
    counter-reset: opportunity;
    list-style: none;
    margin: 0 0 var(--space-5);
    padding: 0;
    display: flex;
    flex-direction: column;
    gap: var(--space-3);
  }
  .opportunity {
    /* Reset the base <li> margin so the list's `gap` is the only spacing. */
    margin: 0;
    counter-increment: opportunity;
    background: var(--bg-primary);
    border: 0.5px solid var(--border);
    border-radius: var(--radius-lg);
    box-shadow: var(--shadow-sm);
    padding: var(--space-4) var(--space-5);
    word-break: break-word;
  }

  /* Title row: rank chip, then the title with its kind chip, with the status
     control pushed to the trailing edge (it drops onto its own right-aligned
     line when the row runs out of room). */
  .opportunity-header {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--space-2) var(--space-3);
  }
  .opportunity-header::before {
    content: counter(opportunity);
    flex: none;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 22px;
    height: 22px;
    border: 0.5px solid var(--border);
    border-radius: var(--radius-full);
    background: var(--bg-secondary);
    font-size: 11px;
    font-weight: 500;
    font-variant-numeric: tabular-nums;
    color: var(--text-secondary);
  }
  .opportunity-heading {
    display: inline-flex;
    flex: 1 1 240px;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--space-1) var(--space-2);
    min-width: 0;
  }

  /* Kind chips borrow the semantic families: coverage to earn reads as info,
     weak visibility as a warning, negative framing as danger. */
  .opportunity-kind-coverage { background: var(--info-bg); border-color: var(--info-border); color: var(--info-text); }
  .opportunity-kind-visibility { background: var(--warning-bg); border-color: var(--warning-border); color: var(--warning-text); }
  .opportunity-kind-framing { background: var(--danger-bg); border-color: var(--danger-border); color: var(--danger-text); }

  /* Tier chips: only the high tier carries color — one signal per row. */
  .opportunity-tier-high { background: var(--danger-bg); border-color: var(--danger-border); color: var(--danger-text); }

  /* The analysis' explanation reads as body copy; the evidence sentence under
     it stays a readable measure. */
  .opportunity-explanation { margin: var(--space-2) 0 0; max-width: 72ch; }
  .opportunity-evidence { margin: var(--space-2) 0 0; max-width: 72ch; }

  /* --- Opportunities summary (AI overview across the whole list) ---------- */
  /* The disclosure card shell the summary renders in. The surface itself is
     .tile (see cards.css), applied alongside these classes in the markup; the
     summary body is ordinary .report-markdown, sized down a little here. */
  .opportunity-summary-card > summary {
    font-weight: 500;
    font-size: 12.5px;
    color: var(--text-secondary);
    transition: color var(--speed-fast) var(--ease-out);
  }
  .opportunity-summary-card > summary:hover { color: var(--text-primary); }
  .opportunity-summary-body { margin-top: var(--space-3); font-size: 14px; }
  /* "Summarized by …" footer under the rendered summary. */
  .opportunity-summary-card > p { margin: var(--space-3) 0 0; }
  .opportunity-summary { margin: 0 0 var(--space-5); }

  /* --- Generated prompts list -------------------------------------------- */
  .generated-prompts { margin: var(--space-3) 0; }
}
