
:root {
  color-scheme: light dark;
  --bg: #ffffff;
  --fg: #1a1a1a;
  --muted: #6b6b6b;
  --line: #e2e2e2;
  --row: #fafafa;
  --ok: #1a7f37;
  --warn: #9a6700;
  --bad: #b42318;
  --accent: #0b5cad;

  /*
   * Status tints for card backgrounds. Deliberately far weaker than the --ok/--warn/--bad
   * text colours: the card still has to carry body text and a table at readable contrast,
   * and a saturated fill would make a page of eight sources unreadable rather than
   * scannable. The state is spelled out in a badge as well, so these carry no information
   * on their own.
   */
  --ok-bg: #eaf7ee;
  --warn-bg: #fdf5e3;
  --bad-bg: #fdeceb;
  --muted-bg: #f3f4f6;
  --card: #ffffff;
}

@media (prefers-color-scheme: dark) {
  :root {
    --bg: #16181d;
    --fg: #e6e6e6;
    --muted: #9aa0a6;
    --line: #2c3038;
    --row: #1c1f25;
    --ok: #4ac26b;
    --warn: #d4a72c;
    --bad: #ff6b5e;
    --accent: #6cb6ff;

    --ok-bg: #16291d;
    --warn-bg: #2b2515;
    --bad-bg: #2e1a19;
    --muted-bg: #1f2229;
    --card: #1c1f25;
  }
}

* { box-sizing: border-box; }

body {
  margin: 0;
  background: var(--bg);
  color: var(--fg);
  font: 14px/1.5 ui-sans-serif, system-ui, -apple-system, "Segoe UI", sans-serif;
}

header.bar {
  display: flex;
  align-items: center;
  gap: 1.5rem;
  padding: 0.75rem 1.25rem;
  border-bottom: 1px solid var(--line);
}

header.bar h1 { font-size: 1rem; margin: 0; font-weight: 600; }
header.bar nav { display: flex; gap: 1rem; }
header.bar form { margin-left: auto; }

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

main { padding: 1.25rem; max-width: 1400px; }

table { border-collapse: collapse; width: 100%; margin-bottom: 2rem; }
caption { text-align: left; font-weight: 600; padding: 0.5rem 0; }
th, td { text-align: left; padding: 0.4rem 0.7rem; border-bottom: 1px solid var(--line); }
th { color: var(--muted); font-weight: 500; white-space: nowrap; }
tbody tr:nth-child(odd) { background: var(--row); }
td.num { text-align: right; font-variant-numeric: tabular-nums; }

.badge {
  display: inline-block;
  padding: 0 0.45rem;
  border-radius: 999px;
  font-size: 0.75rem;
  border: 1px solid currentColor;
}
.badge.ok { color: var(--ok); }
.badge.stale { color: var(--bad); }
.badge.imported { color: var(--muted); }
.published { font-weight: 600; }

/*
 * Three explicit levels, so the same colour means the same thing on every page: a bare
 * .banner is neutral/informational (the overview strip, the history header), .warn is
 * "something needs attention but the page is still telling the truth", .bad is a failure.
 * The bare rule used to be red, which made a healthy dashboard look alarming and left
 * .banner.bad working only by accident.
 */
.banner {
  padding: 0.6rem 1rem;
  border-left: 3px solid var(--line);
  background: var(--row);
  margin-bottom: 1rem;
}
.banner.warn { border-left-color: var(--warn); }
.banner.bad { border-left-color: var(--bad); }
.empty { color: var(--muted); padding: 2rem 0; }

form.login { max-width: 20rem; margin: 4rem auto; display: grid; gap: 0.75rem; }
form.login input {
  padding: 0.5rem;
  border: 1px solid var(--line);
  border-radius: 4px;
  background: var(--bg);
  color: var(--fg);
}
button {
  padding: 0.4rem 0.9rem;
  border: 1px solid var(--line);
  border-radius: 4px;
  background: var(--row);
  color: var(--fg);
  cursor: pointer;
}

/*
 * The history legend's per-series colours. They live here rather than in a style="" on the
 * badge because the page's own CSP is style-src 'self' with no 'unsafe-inline': the
 * browser drops an inline style attribute, so every legend badge rendered in the default
 * colour and could not be matched to its line. The SVG strokes stay as presentation
 * attributes, which style-src does not cover. Keep this list in step with SERIES_COLOURS
 * in views/history.ts.
 */
.badge.series-0 { color: #0b5cad; }
.badge.series-1 { color: #b42318; }
.badge.series-2 { color: #1a7f37; }
.badge.series-3 { color: #9a6700; }
.badge.series-4 { color: #6b3fa0; }
.badge.series-5 { color: #0f766e; }

svg.chart { width: 100%; height: auto; }
svg.chart .axis { stroke: var(--line); }
svg.chart text { fill: var(--muted); font-size: 11px; }

/*
 * Cards. A grid rather than a fixed column count so the same markup reads on a phone and
 * on the wide screen this dashboard usually lives on; the minimum is wide enough for the
 * per-source table inside an overview card, which carries both time columns and cannot be
 * narrowed without dropping one of them.
 */
.cards {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 32rem), 1fr));
  gap: 1rem;
  margin-bottom: 2rem;
}

.card {
  border: 1px solid var(--line);
  border-radius: 8px;
  padding: 0.9rem 1rem;
  background: var(--card);
}

.card--ok { background: var(--ok-bg); }
.card--stale { background: var(--bad-bg); }
.card--never { background: var(--warn-bg); }
.card--imported { background: var(--muted-bg); }

/* The tint is the card's own; the table inside must not repeat it as zebra striping. */
.card tbody tr:nth-child(odd) { background: transparent; }
.card table { margin-bottom: 0; background: transparent; }
.card th, .card td { border-bottom-color: var(--line); }
.card caption { color: var(--muted); font-weight: 500; font-size: 0.8rem; }

.card-head { display: flex; align-items: baseline; gap: 0.6rem; margin-bottom: 0.35rem; }
.card-head h2 { font-size: 0.95rem; margin: 0; font-weight: 600; }

.card-price {
  margin: 0;
  font-size: 2rem;
  font-weight: 600;
  font-variant-numeric: tabular-nums;
  line-height: 1.15;
}
.card-note { margin: 0.15rem 0 0.75rem; color: var(--muted); font-size: 0.8rem; }
.card-links { margin: 0.75rem 0 0; font-size: 0.85rem; }

.card-facts {
  display: grid;
  grid-template-columns: max-content 1fr;
  gap: 0.15rem 0.75rem;
  margin: 0.5rem 0 0;
  font-size: 0.85rem;
}
.card-facts dt { color: var(--muted); }
.card-facts dd { margin: 0; font-variant-numeric: tabular-nums; }

h2.section { font-size: 1rem; font-weight: 600; margin: 0 0 0.75rem; }

/* The history range picker: preset buttons and an explicit from–to. */
.filters {
  display: flex;
  align-items: flex-end;
  flex-wrap: wrap;
  gap: 1rem 1.5rem;
  margin-bottom: 1rem;
}
.filters .presets { display: flex; gap: 0.5rem; flex-wrap: wrap; }
.filters .presets a, .filters .presets strong {
  padding: 0.25rem 0.7rem;
  border: 1px solid var(--line);
  border-radius: 999px;
}
.filters .presets strong { background: var(--row); border-color: var(--accent); }
.filters form { display: flex; align-items: flex-end; gap: 0.5rem; flex-wrap: wrap; }
.filters label { display: grid; gap: 0.2rem; color: var(--muted); font-size: 0.8rem; }
.filters input {
  padding: 0.35rem 0.5rem;
  border: 1px solid var(--line);
  border-radius: 4px;
  background: var(--bg);
  color: var(--fg);
}

/* Pager. Wide enough to hit on a phone, and the current page is not a link. */
.pager { display: flex; align-items: center; gap: 0.4rem; flex-wrap: wrap; margin: 0 0 2rem; }
.pager a, .pager strong, .pager span {
  padding: 0.2rem 0.6rem;
  border: 1px solid transparent;
  border-radius: 4px;
}
.pager a { border-color: var(--line); }
.pager strong { border-color: var(--accent); background: var(--row); }
.pager span { color: var(--muted); border-color: transparent; }
.pager .count { margin-right: auto; color: var(--muted); }

svg.chart .band { stroke: none; opacity: 0.18; }

/*
 * The hover readout. Its colours are here rather than on the elements because the page's
 * CSP is style-src 'self': the script sets geometry (x/y/width) as attributes, which CSP
 * does not cover, and leaves every colour to this stylesheet.
 */
svg.chart { cursor: crosshair; }
svg.chart .crosshair { stroke: var(--muted); stroke-dasharray: 3 3; }
svg.chart .readout { pointer-events: none; }
svg.chart .readout-bg { fill: var(--bg); stroke: var(--line); opacity: 0.95; }
svg.chart .readout-text { fill: var(--fg); font-size: 12px; font-variant-numeric: tabular-nums; }
svg.chart .marker { stroke: var(--bg); stroke-width: 1.5; }
