/* reports.css — styles for the Reports section (#sec-reports).
   Token-only: every color/space/radius references a theme.css custom property
   (no hardcoded hex), so the two report pages + Settings stay on-brand by
   construction. Loaded after app.css in index.html. Scoped under #sec-reports
   where practical; a few standalone pieces (the tracked-URL modal lives outside
   the section) reuse the shared invite-card/board-modal classes verbatim. */

/* ── Report grids (reuse .cov-table look; add report-specific affordances) ─ */
#sec-reports .rep-grid {
  border-collapse: collapse;
  font-size: var(--text-sm);
  width: 100%;
}
#sec-reports .rep-grid th,
#sec-reports .rep-grid td {
  padding: var(--space-2) var(--space-3);
  border-bottom: 1px solid var(--border);
  text-align: center;
  white-space: nowrap;
}
/* Left-aligned identity columns (city/state, URL, keyword). */
#sec-reports .rep-grid th.rep-ident,
#sec-reports .rep-grid td.rep-ident {
  text-align: left;
}
/* Sticky header band + sticky first column so the city/URL stays visible while
   scrolling weeks horizontally. */
#sec-reports .rep-grid thead th {
  background: var(--surface-sunken);
  font-weight: var(--fw-semibold);
  color: var(--text-muted);
  position: sticky;
  top: 0;
  z-index: 2;
}
#sec-reports .rep-grid thead th.rep-week-group {
  border-left: 1px solid var(--border);
  text-transform: none;
}
#sec-reports .rep-grid thead th.rep-week-current {
  color: var(--accent);
}
#sec-reports .rep-grid .rep-week-tag {
  display: block;
  font-size: var(--text-xs);
  font-weight: var(--fw-regular);
  color: var(--text-faint);
  letter-spacing: 0.02em;
}
#sec-reports .rep-grid tbody tr:hover { background: var(--accent-tint); }
#sec-reports .rep-grid td.rep-week-cell {
  border-left: 1px solid var(--border);
  font-variant-numeric: tabular-nums;
}
/* The two sub-metrics inside a week cell ([Avg | #1 days] etc.). */
#sec-reports .rep-grid .rep-metric-sep { color: var(--text-faint); margin: 0 var(--space-1); }
#sec-reports .rep-grid .rep-zero { color: var(--text-faint); }

/* Pinned AVERAGE row sits above the body, tinted so it reads as a summary. */
#sec-reports .rep-grid tr.rep-avg-row td {
  background: var(--surface-sunken);
  font-weight: var(--fw-semibold);
  position: sticky;
  top: 38px;            /* below the sticky header band */
  z-index: 1;
}

/* ── Frozen identity columns (horizontal) ─────────────────────────────────
   The header band and AVERAGE row are already sticky vertically (above); these
   add a horizontal freeze so the row-label columns stay visible while the week
   columns scroll right: City + State on Homepage Ranking, URL on Off-Site.
   Identity cells get an opaque background so scrolled week cells slide cleanly
   under them; z-index is layered (body 1, avg-row 2, header 3) so the pinned
   top-left corners stay on top where the two sticky axes intersect. */
#sec-reports .rep-grid td.rep-ident { background: var(--surface); }
#sec-reports .rep-grid thead th.rep-ident,
#sec-reports .rep-grid tr.rep-avg-row td.rep-ident { background: var(--surface-sunken); }
#sec-reports .rep-grid tbody tr:hover td.rep-ident { background: var(--accent-tint); }
#sec-reports .rep-grid tbody tr.rep-row-clickable:hover td.rep-ident { background: var(--surface-hover); }
/* The AVERAGE row is a pinned summary, not an interactive row: it must NOT pick
   up the hover tint. --accent-tint is semi-transparent, and on a sticky cell that
   lets scrolled week cells bleed through underneath (text overlap). Keep every
   AVERAGE cell on its opaque --surface-sunken fill on hover too. */
#sec-reports .rep-grid tbody tr.rep-avg-row:hover td,
#sec-reports .rep-grid tbody tr.rep-avg-row:hover td.rep-ident { background: var(--surface-sunken); }

/* Homepage Ranking: freeze City (col 1) + State (col 2). */
#rep-hp-grid .rep-grid .rep-ident:nth-child(1) { position: sticky; left: 0; z-index: 1; min-width: 150px; }
#rep-hp-grid .rep-grid .rep-ident:nth-child(2) {
  position: sticky; left: 150px; z-index: 1; min-width: 56px; box-shadow: 1px 0 0 var(--border);
}
/* Corners where the two sticky axes intersect must outrank the body:
   header band (3) > AVERAGE row (2) > body (1). Explicit per-column so the
   nth-child specificity matches the rules above and these win. */
#rep-hp-grid .rep-grid thead th.rep-ident:nth-child(1),
#rep-hp-grid .rep-grid thead th.rep-ident:nth-child(2) { z-index: 3; }
#rep-hp-grid .rep-grid tr.rep-avg-row .rep-ident:nth-child(1),
#rep-hp-grid .rep-grid tr.rep-avg-row .rep-ident:nth-child(2) { z-index: 2; }

/* Off-Site Content: freeze the URL column (col 1); Type + Keyword scroll. */
#rep-os-grid .rep-grid .rep-ident:nth-child(1) {
  position: sticky; left: 0; z-index: 1; min-width: 230px; box-shadow: 1px 0 0 var(--border);
}
#rep-os-grid .rep-grid thead th.rep-ident:nth-child(1) { z-index: 3; }

/* Perfect week: the homepage was #1 every day scraped. Calm green tint so the
   wins stand out and imperfect weeks stay plain (less exhausting than flagging
   every wobble). */
#sec-reports .rep-grid td.rep-perfect {
  color: var(--success);
  background: var(--success-tint);
}

/* Delta chips inside stat cards / trend latest (reuse up/down semantics).
   A restrained sans annotation — sized independently of the (serif) headline so
   it never inherits a 20px glyph; the caret is a small accent, not a competing mark. */
#sec-reports .rep-delta {
  font-family: var(--font-sans);
  font-size: var(--text-sm);          /* 12px, regardless of the headline size */
  font-weight: 600;
  letter-spacing: .2px;
  font-variant-numeric: tabular-nums;
  display: inline-flex;
  align-items: center;
  gap: 2px;
}
#sec-reports .rep-delta-caret { font-size: 8px; line-height: 1; position: relative; top: -0.5px; }
#sec-reports .rep-delta.is-up { color: var(--success); }
#sec-reports .rep-delta.is-down { color: var(--danger); }
#sec-reports .rep-delta.is-flat { color: var(--text-faint); }

/* Top stat cards (Off-Site): a coloured signed headline with a small caret. The
   caret rides at ~0.45em so the magnitude stays the hero in the serif value. */
#sec-reports .rep-stat-val { display: inline-flex; align-items: baseline; gap: 3px; }
#sec-reports .rep-stat-caret { font-size: 0.42em; line-height: 1; position: relative; top: -0.42em; }
#sec-reports .rep-up { color: var(--success); }
#sec-reports .rep-down { color: var(--danger); }
#sec-reports .rep-flat { color: var(--text-faint); }
#sec-reports .rep-mom-sep { color: var(--text-faint); }
#sec-reports .rep-stat-foot { color: var(--text-faint); }

/* ── Settings page ────────────────────────────────────────────────────── */
#sec-reports .rep-settings-section {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-sm);
  padding: var(--space-5);
}
#sec-reports .rep-settings-header-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-3);
  margin-bottom: var(--space-4);
}
#sec-reports .rep-settings-header-row h2 {
  font-family: var(--font-serif);
  font-size: var(--text-2xl);
  font-weight: var(--fw-regular);
  margin: 0;
}
/* Title + live count of tracked URLs, baseline-aligned beside the serif title. */
#sec-reports .rep-settings-title {
  display: flex; align-items: baseline; gap: var(--space-2); min-width: 0;
}
/* A quiet neutral count pill (echoes the Owned/Paid pill shape, but un-colored so
   it reads as metadata, not a status). Hidden until the first load sets it. */
#sec-reports .rep-track-count {
  font-size: var(--text-sm); font-weight: var(--fw-medium);
  color: var(--text-muted); font-variant-numeric: tabular-nums;
  background: var(--surface-sunken);
  padding: 1px var(--space-2); border-radius: var(--radius-full);
}
#sec-reports .rep-track-count:empty { display: none; }
#sec-reports .rep-audit-sub {
  font-size: var(--text-sm);
  color: var(--text-muted);
}
#sec-reports .rep-table-wrap { overflow-x: auto; }
#sec-reports .rep-settings-table {
  border-collapse: collapse;
  width: 100%;
  font-size: var(--text-sm);
}
#sec-reports .rep-settings-table th,
#sec-reports .rep-settings-table td {
  padding: var(--space-2) var(--space-3);
  border-bottom: 1px solid var(--border);
  text-align: left;
  white-space: nowrap;
}
#sec-reports .rep-settings-table thead th {
  background: var(--surface-sunken);
  font-weight: var(--fw-semibold);
  color: var(--text-muted);
  text-transform: uppercase;
  letter-spacing: 0.04em;
  font-size: var(--text-xs);
}
#sec-reports .rep-settings-table tbody tr:hover { background: var(--surface-hover); }

/* Owned/Paid + exact/prefix type pills (reuse badge-ish look via tokens). */
#sec-reports .rep-type-pill {
  display: inline-block;
  padding: 2px var(--space-2);
  border-radius: var(--radius-full);
  font-size: var(--text-xs);
  font-weight: var(--fw-medium);
  letter-spacing: 0.02em;
}
#sec-reports .rep-type-owned { background: var(--success-tint); color: var(--success); }
#sec-reports .rep-type-paid  { background: var(--info-tint);    color: var(--info); }

/* Row actions — ghost text buttons, zoned apart from the attribute columns.
   Edit wakes to the clay accent on hover; Delete mirrors the app's shipped
   destructive idiom (.row-delete-btn): danger-tint bg + red text on hover/focus.
   The "Edit"/"Delete" text labels carry the grayscale-safe distinction; color
   reinforces. focus-visible rings added (were missing). */
#sec-reports .rep-row-actions { text-align: right; padding-left: var(--space-4); }
/* Row-action kebab + its dropdown. The dropdown is the global .menu, but
   position:fixed (coords set in JS on open) so it isn't clipped by the table-wrap
   overflow — same approach as the crunchbase row kebab. */
#sec-reports .rep-kebab {
  background: none; border: 1px solid transparent; border-radius: var(--radius-sm);
  color: var(--text-muted); cursor: pointer;
  padding: 2px 8px; font-size: var(--text-lg); line-height: 1;
  transition: background var(--dur-fast) var(--ease), color var(--dur-fast) var(--ease),
              border-color var(--dur-fast) var(--ease);
}
#sec-reports .rep-kebab:hover,
#sec-reports .rep-kebab[aria-expanded="true"] {
  background: var(--surface-hover); color: var(--accent); border-color: var(--border);
}
#sec-reports .rep-kebab:focus-visible { outline: none; box-shadow: 0 0 0 3px var(--accent-ring); }
#sec-reports .rep-row-menu { position: fixed; z-index: 1000; min-width: 132px; }
#sec-reports .rep-row-menu.hidden { display: none; }
#sec-reports .rep-row-btn {
  background: none;
  border: none;
  color: var(--text-muted);
  cursor: pointer;
  border-radius: var(--radius-sm);
  padding: 3px var(--space-2);
  font-size: var(--text-xs);
  font-weight: var(--fw-medium);
  vertical-align: middle;
  transition: background var(--dur-fast) var(--ease), color var(--dur-fast) var(--ease);
}
#sec-reports .rep-row-btn:hover { background: var(--surface-hover); color: var(--accent); }
#sec-reports .rep-row-btn:focus-visible { outline: 2px solid var(--accent-ring); outline-offset: 1px; }
/* Edit is disabled while a row backfills (a later refresh re-enables it). */
#sec-reports .rep-row-btn.is-busy,
#sec-reports .rep-row-btn:disabled {
  color: var(--text-faint); cursor: not-allowed;
}
#sec-reports .rep-row-btn.is-busy:hover,
#sec-reports .rep-row-btn:disabled:hover { background: none; color: var(--text-faint); }
#sec-reports .rep-row-btn.is-danger:hover { background: var(--danger-tint); color: var(--danger); }
#sec-reports .rep-row-btn.is-danger:focus-visible { outline: 2px solid var(--danger); outline-offset: 1px; color: var(--danger); }

#sec-reports .rep-empty {
  font-size: var(--text-sm);
  color: var(--text-muted);
  padding: var(--space-5);
  text-align: center;
}

/* In-progress (current partial week) marker in the grid header. */
#sec-reports .rep-inprogress {
  display: inline-block;
  font-size: var(--text-xs);
  color: var(--accent);
  font-weight: var(--fw-medium);
}

/* Trend legend (multi-line offsite chart) — mirrors cov-trend-legend feel. */
#sec-reports .rep-trend-legend {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-3);
  margin-top: var(--space-3);
  font-size: var(--text-xs);
  color: var(--text-muted);
}
#sec-reports .rep-trend-legend-item {
  display: inline-flex;
  align-items: center;
  gap: var(--space-1);
}

@media (max-width: 768px) {
  #sec-reports .rep-grid { font-size: var(--text-xs); }
  #sec-reports .rep-settings-header-row { flex-wrap: wrap; }
  #sec-reports .rep-drawer-panel { width: 100vw; }
}

/* ── Clickable grid rows → per-row drawer ──────────────────────────────── */
#sec-reports .rep-grid tbody tr.rep-row-clickable { cursor: pointer; }
#sec-reports .rep-grid tbody tr.rep-row-clickable:hover td { background: var(--surface-hover); }
/* Dimmed (no-data) rows hover with the SAME neutral surface-hover as the data
   rows — not the generic clay accent-tint the table otherwise falls back to — so
   hover reads consistently across every row, including the sticky identity cells. */
#sec-reports .rep-grid tbody tr.rep-row-empty:hover td,
#sec-reports .rep-grid tbody tr.rep-row-empty:hover td.rep-ident { background: var(--surface-hover); }
#sec-reports .rep-grid tbody tr.rep-row-clickable:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: -2px;
}

#sec-reports .rep-drawer[hidden] { display: none; }
#sec-reports .rep-drawer { position: fixed; inset: 0; z-index: 1000; }
#sec-reports .rep-drawer-backdrop {
  position: absolute; inset: 0; background: var(--overlay);
  opacity: 0; transition: opacity var(--dur-fast) var(--ease);
}
#sec-reports .rep-drawer.rep-drawer-open .rep-drawer-backdrop { opacity: 1; }
#sec-reports .rep-drawer-panel {
  position: absolute; top: 0; right: 0; height: 100%;
  width: min(520px, 92vw);
  background: var(--surface-raised);
  border-left: 1px solid var(--border);
  box-shadow: var(--shadow-lg);
  display: flex; flex-direction: column;
  transform: translateX(100%);
  transition: transform var(--dur-fast) var(--ease);
}
#sec-reports .rep-drawer.rep-drawer-open .rep-drawer-panel { transform: translateX(0); }
#sec-reports .rep-drawer-head {
  display: flex; align-items: flex-start; justify-content: space-between;
  gap: var(--space-3); padding: var(--space-4) var(--space-5);
  border-bottom: 1px solid var(--border); flex: 0 0 auto;
}
#sec-reports .rep-drawer-title {
  font-family: var(--font-serif); font-size: var(--text-xl);
  color: var(--text); word-break: break-all; line-height: 1.25;
}
#sec-reports .rep-drawer-sub { margin-top: var(--space-1); display: flex; align-items: center; gap: var(--space-2); }
#sec-reports .rep-drawer-kw { font-size: var(--text-sm); color: var(--text-muted); }
#sec-reports .rep-drawer-close {
  background: none; border: none; cursor: pointer;
  font-size: 22px; line-height: 1; color: var(--text-faint); padding: 0 4px;
}
#sec-reports .rep-drawer-close:hover { color: var(--text); }
#sec-reports .rep-drawer-body { padding: var(--space-5); overflow-y: auto; }
#sec-reports .rep-drawer-stats { display: flex; gap: var(--space-4); margin-bottom: var(--space-4); }
#sec-reports .rep-drawer-stat { flex: 1; }
#sec-reports .rep-drawer-stat-v { font-family: var(--font-serif); font-size: var(--text-2xl); color: var(--text); }
#sec-reports .rep-drawer-stat-l {
  font-size: var(--text-xs); color: var(--text-faint);
  text-transform: uppercase; letter-spacing: .4px; margin-top: 2px;
}
/* "so far" tag on the in-progress (partial) week's headline value. */
#sec-reports .rep-sofar {
  font-family: var(--font-sans); font-size: var(--text-xs); color: var(--text-faint);
  font-style: italic; vertical-align: baseline; margin-left: 2px;
}
/* Stacked dual charts (rank + appearances) as small multiples. */
#sec-reports .rep-drawer-chart-section { margin-top: var(--space-4); }
#sec-reports .rep-drawer-chart-label {
  font-size: var(--text-xs); color: var(--text-faint);
  text-transform: uppercase; letter-spacing: .4px; margin-bottom: var(--space-2);
  display: flex; align-items: center; gap: 6px;
}
#sec-reports .rep-chart-dot { width: 8px; height: 8px; border-radius: 50%; display: inline-block; flex: 0 0 auto; }
#sec-reports .rep-chart-dot-rank { background: var(--accent); }
#sec-reports .rep-chart-dot-apps { background: var(--info); }

/* Custom HTML chart tooltip (data-rows). Lives on <body> (outside #sec-reports)
   so it can escape the drawer's clipping — selectors are intentionally unscoped. */
.rep-chart-tt {
  position: fixed; z-index: 2000; pointer-events: none;
  opacity: 0; transition: opacity .12s ease;
  background: var(--surface-raised);
  border: 1px solid var(--border);   /* crisp edge over a near-white plot */
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-lg);
  padding: 10px 12px 11px;
  min-width: 168px; max-width: 280px;
  font-family: var(--font-sans);
}
.rep-chart-tt .rep-tt-h {
  font-size: var(--text-xs); text-transform: uppercase; letter-spacing: .6px;
  color: var(--text-faint);
  padding-bottom: 7px; margin-bottom: 7px; border-bottom: 1px solid var(--border);
}
.rep-chart-tt .rep-tt-r {
  display: flex; align-items: center; justify-content: space-between;
  gap: 20px; margin: 4px 0;
}
.rep-chart-tt .rep-tt-lab {
  display: flex; align-items: center; gap: 7px;
  color: var(--text-muted); font-size: var(--text-sm);
}
.rep-chart-tt .rep-tt-lab i { width: 7px; height: 7px; border-radius: 50%; display: inline-block; flex: 0 0 auto; }
.rep-chart-tt .rep-tt-val {
  font-size: var(--text-sm); font-weight: 600; color: var(--text);
  font-variant-numeric: tabular-nums;
}
.rep-chart-tt .rep-tt-note { font-size: var(--text-xs); color: var(--text-faint); margin-top: 6px; }
.rep-chart-tt .rep-tt-pill {
  display: inline-block; margin-top: 8px;
  padding: 2px 8px; border-radius: var(--radius-full);
  background: var(--accent-tint); color: var(--accent-contrast-text);
  font-size: var(--text-xs); font-weight: 600; letter-spacing: .2px;
}

/* Header-definition tooltip: column legends moved off-page into hover popovers.
   A dotted underline (not an icon) hints that the header reveals a definition. */
.rep-def-tt {
  position: fixed; z-index: 2000; pointer-events: none;
  opacity: 0; transition: opacity .12s ease;
  background: var(--surface-raised);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-lg);
  padding: 8px 11px; max-width: 260px;
  font-family: var(--font-sans); font-size: var(--text-sm);
  line-height: 1.45; color: var(--text-muted);
}
#sec-reports th[data-def] {
  cursor: help;
  text-decoration: underline dotted var(--text-faint);
  text-underline-offset: 3px;
}

#sec-reports .rep-drawer-chart-wrap { position: relative; }
/* The rank chart hides its x labels (xHeight:8) and the appearances chart shows
   the shared date axis (xHeight:36). Sizing the apps wrap 28px taller cancels
   that band difference so the two PLOT areas render the same height. */
#sec-reports .rep-drawer-chart-rank { height: 120px; }
#sec-reports .rep-drawer-chart-apps { height: 148px; }
#sec-reports .rep-drawer-chart-wrap > canvas { position: absolute; inset: 0; width: 100% !important; height: 100% !important; }

/* Homepage page-level charts (avg rank + city-days at #1), side by side. Equal
   columns that collapse to one column on narrow screens; each chart carries its
   own date axis. */
#sec-reports .rep-hp-charts-row {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--space-5);
}
#sec-reports .rep-hp-chart-wrap { position: relative; height: 190px; }
#sec-reports .rep-hp-chart-wrap > canvas { position: absolute; inset: 0; width: 100% !important; height: 100% !important; }
#sec-reports .rep-hp-chart-label {
  display: flex; align-items: center; gap: 6px;
  font-size: var(--text-xs); color: var(--text-muted);
  margin: 0 0 4px;
}
@media (max-width: 768px) {
  #sec-reports .rep-hp-charts-row { grid-template-columns: 1fr; gap: var(--space-3); }
}

/* Per-week detail table under the drawer chart. */
#sec-reports .rep-drawer-table {
  width: 100%; border-collapse: collapse; margin-top: var(--space-4);
  font-size: var(--text-sm); font-variant-numeric: tabular-nums;
}
#sec-reports .rep-drawer-table th,
#sec-reports .rep-drawer-table td {
  padding: var(--space-2) var(--space-3);
  border-bottom: 1px solid var(--border); text-align: right;
}
#sec-reports .rep-drawer-table th {
  color: var(--text-faint); font-weight: var(--fw-semibold);
  font-size: var(--text-xs); text-transform: uppercase; letter-spacing: .4px;
  position: sticky; top: 0; z-index: 1; background: var(--surface-raised);
}
#sec-reports .rep-drawer-table th:first-child,
#sec-reports .rep-drawer-table td:first-child { text-align: left; color: var(--text-muted); }
#sec-reports .rep-drawer-table td.rep-dt-zero { color: var(--text-faint); }
/* Perfect week (#1 every day scraped) -> green row, matching the page grid.
   The Δ chip keeps its own up/down/dash color via .rep-delta. */
#sec-reports .rep-drawer-table tr.rep-perfect td { background: var(--success-tint); color: var(--success); }
/* Week-over-week ± columns: sit tight against the metric they annotate, and the
   delta chip aligns to the cell's right edge. */
#sec-reports .rep-drawer-table .rep-dt-delta { padding-left: 2px; }
#sec-reports .rep-drawer-table td.rep-dt-delta .rep-delta { display: inline-flex; }

/* ── Off-site 2-row grid: separate Avg Rank / Appears columns per week ───── */
/* Week-boundary border on the week-START sub-column only, so Avg+Appears read
   as one week group (not split by a line). Scoped to .rep-grid-2row so the
   Homepage grid's per-week borders are untouched. Appended last to win on
   equal specificity. */
#sec-reports .rep-grid-2row td.rep-week-cell { border-left: none; }
#sec-reports .rep-grid-2row .rep-week-start { border-left: 1px solid var(--border); }
#sec-reports .rep-grid-2row .rep-subhead {
  font-size: var(--text-xs); font-weight: var(--fw-regular);
  color: var(--text-faint); text-transform: none; letter-spacing: .02em;
}
/* Two-row sticky header: row 1 (week dates) at top:0; row 2 (Avg Rank / Appears)
   pinned directly beneath it. Fixed row-1 height makes the offset exact. */
#sec-reports .rep-grid-2row thead tr:first-child th.rep-week-group { box-sizing: border-box; height: 34px; }
#sec-reports .rep-grid-2row thead tr:nth-child(2) th { top: 34px; }

/* Rows that never ranked in any shown week: disabled look (dimmed, inert). */
#sec-reports .rep-grid tbody tr.rep-row-empty { opacity: 0.4; }
#sec-reports .rep-grid tbody tr.rep-row-empty:hover { background: none; cursor: default; }

/* ════════════════════════════════════════════════════════════════════════
   Per-week day-screenshots accordion (drawer week row -> grid of day cards).
   Ported from the approved prototype /Users/alex/hp-prototype/index.html
   (Layout=Grid, Legend=OFF, Thumb=S). Token-only.
   ════════════════════════════════════════════════════════════════════════ */

/* Week row as an accordion toggle. */
#sec-reports .rep-drawer-table tr.rep-wkrow { cursor: pointer; }
#sec-reports .rep-drawer-table tr.rep-wkrow:hover td { background: var(--surface-hover); }
#sec-reports .rep-drawer-table tr.rep-wkrow:focus-visible {
  outline: 2px solid var(--accent-ring); outline-offset: -2px;
}
/* Active (expanded) week: a quiet sunken fill that connects the row to its
   screenshots panel directly below — no accent rail. */
#sec-reports .rep-drawer-table tr.rep-wkrow-active td { background: var(--surface-sunken); }
#sec-reports .rep-drawer-table tr.rep-wkrow-active td:first-child { font-weight: var(--fw-semibold); }
/* Keep the connected fill even on a perfect (green-tinted) week. */
#sec-reports .rep-drawer-table tr.rep-wkrow-active.rep-perfect td { background: var(--surface-sunken); }
#sec-reports .rep-wk-chev {
  display: inline-block; width: 12px; margin-right: 2px;
  color: var(--text-faint); font-size: 10px;
}
#sec-reports .rep-wkrow-active .rep-wk-chev { color: var(--text-muted); }

/* Reveal shell: a sunken well spanning the table width. */
#sec-reports .rep-drawer-table tr.rep-hp-reveal > td {
  padding: 0; background: var(--surface-sunken); border-bottom: 1px solid var(--border);
}
#sec-reports .rep-hp-revwrap { padding: var(--space-3); text-align: left; }

/* GRID: ~96px columns, 3:4 cards, thumbnail cropped from the top. */
#sec-reports .rep-hp-grid {
  display: grid; grid-template-columns: repeat(auto-fill, minmax(96px, 1fr));
  gap: var(--space-3);
}
#sec-reports .rep-hp-card { cursor: pointer; }
#sec-reports .rep-hp-card:focus { outline: none; }
#sec-reports .rep-hp-card:focus-visible .rep-hp-cwrap {
  outline: 2px solid var(--accent-ring); outline-offset: 2px;
}
#sec-reports .rep-hp-cwrap {
  position: relative; border: 1px solid var(--border); border-radius: var(--radius-sm);
  overflow: hidden; background: var(--surface-hover); aspect-ratio: 3 / 4;
}
/* Gentle shimmer while the screenshot loads — animates the BACKGROUND only (not
   opacity), so the rank badge stays crisp and the tile reads as "loading", never
   as an empty hard-framed box. */
@media (prefers-reduced-motion: no-preference) {
  #sec-reports .rep-hp-cwrap:not(.rep-hp-loaded) { animation: rep-hp-bgpulse 1.2s ease-in-out infinite; }
}
#sec-reports .rep-hp-cwrap img {
  width: 100%; height: 100%; object-fit: cover; object-position: top; display: block;
  opacity: 0;   /* no fade: revealed instantly, in sync with the ring, only after the image decodes */
}
#sec-reports .rep-hp-cwrap.rep-hp-loaded img { opacity: 1; }
/* #1 "pass" treatment: a 2px success ring — applied only once the image is there
   to frame, so a still-loading tile never shows a stark ring on a void. */
#sec-reports .rep-hp-card-pass .rep-hp-cwrap.rep-hp-loaded { box-shadow: inset 0 0 0 2px var(--success); }

/* Corner badge. Rank numerals in the serif face per the spec. */
#sec-reports .rep-hp-badge {
  position: absolute; top: 6px; left: 6px;
  display: inline-flex; align-items: center; gap: 4px;
  background: rgba(255, 255, 255, 0.92); border: 1px solid var(--border);
  border-radius: 999px; padding: 2px 7px;
  font-family: var(--font-serif); font-size: var(--text-sm); color: var(--text);
  line-height: 1.2;
}
#sec-reports .rep-hp-badge-pass { color: var(--success); }
#sec-reports .rep-hp-badge-off {
  color: var(--warn); font-family: var(--font-sans);
  font-weight: var(--fw-semibold); font-size: var(--text-xs);
}
#sec-reports .rep-hp-badge-na {
  color: var(--text-faint); font-family: var(--font-sans);
  font-weight: var(--fw-regular); font-size: var(--text-xs);
}
#sec-reports .rep-hp-dot { width: 8px; height: 8px; border-radius: 50%; display: inline-block; }
#sec-reports .rep-hp-dot-fill { background: var(--success); }
#sec-reports .rep-hp-dot-ring { background: transparent; box-shadow: inset 0 0 0 1.5px var(--text-faint); }

/* Caption: weekday+month+day bold, M/DD/YYYY faint. */
#sec-reports .rep-hp-cap {
  display: flex; flex-direction: column; line-height: 1.15; margin-top: 5px;
}
#sec-reports .rep-hp-cap b { font-size: var(--text-sm); font-weight: var(--fw-semibold); color: var(--text); }
#sec-reports .rep-hp-cap span { font-size: var(--text-xs); color: var(--text-faint); }

/* Skeleton cards (sized to days_scraped so the grid doesn't reflow). */
#sec-reports .rep-hp-card-skel { cursor: default; }
#sec-reports .rep-hp-card-skel .rep-hp-cwrap { background: var(--surface-hover); }
#sec-reports .rep-hp-card-skel .rep-hp-cap b,
#sec-reports .rep-hp-card-skel .rep-hp-cap span {
  color: transparent; background: var(--surface-hover); border-radius: 3px; margin-top: 2px;
}
@media (prefers-reduced-motion: no-preference) {
  #sec-reports .rep-hp-card-skel .rep-hp-cwrap { animation: rep-hp-pulse 1.2s ease-in-out infinite; }
}
@keyframes rep-hp-pulse { 0%, 100% { opacity: 1; } 50% { opacity: 0.55; } }
@keyframes rep-hp-bgpulse { 0%, 100% { background-color: var(--surface-hover); } 50% { background-color: var(--surface-sunken); } }

/* Empty / error / retry line. */
#sec-reports .rep-hp-msg {
  padding: var(--space-4) var(--space-2); color: var(--text-muted);
  font-size: var(--text-sm); text-align: center;
}
#sec-reports .rep-hp-empty { color: var(--text-muted); }
#sec-reports .rep-hp-retry {
  appearance: none; border: 1px solid var(--border); background: var(--surface-raised);
  color: var(--accent); font: inherit; font-size: var(--text-sm);
  padding: 2px 10px; border-radius: var(--radius-sm); cursor: pointer; margin-left: 4px;
}
#sec-reports .rep-hp-retry:hover { background: var(--surface-hover); }

/* ════════════════════════════════════════════════════════════════════════
   BACKFILL PROGRESS — Direction 1: a slim clay bar on a cream track in the
   tracked-URLs Status column, with a tabular "X / N" count beside it. The bar
   is animated in place by the poll loop (paintBackfill); the browser is an
   OBSERVER, never the driver. Tokens only; motion gated below.
   ════════════════════════════════════════════════════════════════════════ */
#sec-reports .rep-bf-cell { min-width: 168px; }
#sec-reports .rep-bf {
  display: inline-flex; align-items: center; gap: var(--space-2);
  font-size: var(--text-xs); color: var(--text-muted);
}
/* The cream track + clay fill. */
#sec-reports .rep-bf-track {
  position: relative; flex: 0 0 auto;
  width: 96px; height: 6px;
  background: var(--surface-sunken);
  border: 1px solid var(--border);
  border-radius: var(--radius-full);
  overflow: hidden;
}
#sec-reports .rep-bf-fill {
  position: absolute; inset: 0 auto 0 0;
  width: 0;
  /* clay-600 (not clay-500) clears WCAG 1.4.11 non-text contrast (~3.6:1) vs the
     cream track. */
  background: var(--accent-hover);
  border-radius: var(--radius-full);
}
/* An active fill never shows empty — floor it so 1/312 still reads as "started". */
#sec-reports .rep-bf-active .rep-bf-fill { min-width: 3px; }
/* The tabular count never jitters as digits change width. */
#sec-reports .rep-bf-count {
  font-variant-numeric: tabular-nums;
  color: var(--text-muted);
  white-space: nowrap;
}
/* Done: olive check + label (shown briefly before the row refreshes to blank). */
#sec-reports .rep-bf-done { color: var(--success); }
#sec-reports .rep-bf-done .rep-bf-check { font-weight: var(--fw-semibold); }
#sec-reports .rep-bf-done .rep-bf-label {
  font-size: var(--text-xs); font-weight: var(--fw-medium); color: var(--success);
}
/* Settled (already-backfilled) row: a quiet "Done" so the Status column never reads
   as an empty cell. Muted text + a small olive check — calmer than the completion
   flash above so a whole column of them doesn't shout. */
#sec-reports .rep-bf-settled { color: var(--text-muted); }
#sec-reports .rep-bf-settled .rep-bf-check { color: var(--success); font-weight: var(--fw-semibold); }
/* Error / paused: amber label + the bordered-clay Resume button (reuses .rep-hp-retry).
   amber-700 (#74521b) clears 4.5:1 on surface + hover; --warn fails. */
#sec-reports .rep-bf-error { color: var(--c-amber-700); }
#sec-reports .rep-bf-error .rep-bf-label {
  font-weight: var(--fw-semibold); color: var(--c-amber-700);
}
#sec-reports .rep-bf-error .rep-bf-count { color: var(--text-muted); }
#sec-reports .rep-bf-error .rep-bf-sep { color: var(--text-muted); }
/* Resume: clay-700 label clears ~5.55:1; the larger padding + min-height lifts the
   hit target past the 24x24 floor. */
#sec-reports .rep-bf-resume {
  margin-left: var(--space-1);
  color: var(--accent-contrast-text);
  padding: 4px 12px;
  min-height: 28px;
}

/* Freshly-inserted row gets a brief clay-tint highlight so the eye lands on it. */
#sec-reports tr.rep-row-fresh { background: var(--accent-tint); }

/* The width/highlight transitions + the active-bar shimmer animate only when the
   user hasn't asked for reduced motion. With reduced motion, the bar still grows
   (width is set inline) — it just snaps instead of easing. */
@media (prefers-reduced-motion: no-preference) {
  #sec-reports .rep-bf-fill {
    transition: width var(--dur-fast) var(--ease);
  }
  #sec-reports tr.rep-row-fresh {
    animation: rep-bf-freshfade 1.4s var(--ease) forwards;
  }
  /* A soft sheen sweeping the active fill signals "working" without re-rendering. */
  #sec-reports .rep-bf-active .rep-bf-fill::after {
    content: ''; position: absolute; inset: 0;
    background: linear-gradient(90deg, transparent, var(--accent-tint), transparent);
    animation: rep-bf-sheen 1.6s ease-in-out infinite;
  }
}
@keyframes rep-bf-freshfade {
  0% { background-color: var(--accent-tint); }
  100% { background-color: transparent; }
}
@keyframes rep-bf-sheen {
  0% { transform: translateX(-100%); }
  100% { transform: translateX(100%); }
}

/* ════════════════════════════════════════════════════════════════════════
   URL TYPEAHEAD AUTOCOMPLETE — the dropdown lives INSIDE the tracked-URL modal
   (#rep-track-backdrop), which is a TOP-LEVEL element OUTSIDE #sec-reports. So
   these selectors are intentionally NOT scoped under #sec-reports — scoping them
   there would hide the dropdown entirely.
   ════════════════════════════════════════════════════════════════════════ */
.rep-ac-field { position: relative; }
.rep-ac-list {
  position: absolute; left: 0; right: 0; top: 100%; z-index: 30;
  margin: var(--space-1) 0 0; padding: var(--space-1);
  list-style: none;
  /* Capped; it floats as an overlay over the Type field / buttons below the input. */
  max-height: 220px; overflow-y: auto;
  background: var(--surface-raised);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  /* Neutral warm elevation — --accent-ring is reserved for :focus rings, not depth. */
  box-shadow: var(--shadow-md);
}
.rep-ac-list.hidden { display: none; }
.rep-ac-item {
  display: flex; align-items: baseline; justify-content: space-between;
  gap: var(--space-3);
  padding: var(--space-2) var(--space-3);
  border-radius: var(--radius-sm);
  cursor: pointer;
}
.rep-ac-item:hover,
.rep-ac-item.is-active { background: var(--accent-tint); }
/* The keyboard-active row gets a marker beyond the shared hover tint so it's
   distinguishable from a mouse hover. */
.rep-ac-item.is-active { box-shadow: inset 2px 0 0 var(--accent); }
/* No-match hint: non-selectable, faint, keeps the list open. */
.rep-ac-empty {
  padding: var(--space-2) var(--space-3);
  font-size: var(--text-xs); color: var(--text-faint);
  cursor: default;
}
.rep-ac-url {
  font-size: var(--text-sm); color: var(--text);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.rep-ac-meta {
  flex: 0 0 auto;
  font-size: var(--text-xs); color: var(--text-muted);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

/* The suggestion list is an absolute overlay (z-index above the modal controls),
   so it floats over the Type field / buttons below the input and needs NO reserved
   space in the card. (Earlier a large padding-bottom here left a big empty gap
   below Save whenever the dropdown was closed.) */

/* The URL combobox relies on the modal's input:focus border; add an explicit ring
   so the focus state reads clearly without weakening the existing border styling. */
#rep-track-url:focus-visible {
  outline: none;
  box-shadow: 0 0 0 3px var(--accent-ring);
}

/* Visually-hidden but screen-reader-available. Lives here because app.css/base.css
   carry no sr-only utility; the backfill live region (#rep-bf-live) consumes it. */
.sr-only {
  position: absolute !important;
  width: 1px; height: 1px;
  padding: 0; margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}
