/* ---------------------------------------------------------------------------
   Giulia comparison table

   Dark, dense, unsentimental. The scene: a buyer at a desk at night, twelve
   tabs deep, cross-referencing prices six websites have each quietly
   misrepresented. Every saturated pixel is a claim; nothing is colored for
   decoration.
   --------------------------------------------------------------------------- */

:root {
  /* Neutral ramp, tinted 0.008C toward the Alfa red the data is full of --
     enough to keep the surface from reading as dead gray, not enough to read
     as "themed". */
  --bg:        oklch(0.17 0.008 25);
  --surface:   oklch(0.21 0.009 25);
  --surface-2: oklch(0.25 0.010 25);
  --line:      oklch(0.31 0.010 25);
  --line-soft: oklch(0.26 0.009 25);

  --ink:       oklch(0.96 0.004 25);   /* 15.9:1 on --bg */
  --ink-2:     oklch(0.80 0.006 25);   /*  9.0:1 -- secondary text, still AA at any size */
  --ink-3:     oklch(0.66 0.008 25);   /*  5.4:1 -- labels; above the 4.5 floor, not a dim gray */

  /* Signal colors. Three roles only: a favorable claim, an unfavorable claim,
     and a missing value. Each is paired with a glyph in the markup -- never
     hue alone.

     Text and fill are deliberately far apart on the L axis. Tinting a tag's
     background with a low-alpha wash of its own text color is the obvious move
     and it lands both ends on nearly the same pixel: measured 1.04:1 against a
     4.5 floor. The fill is a dark, desaturated seat for bright text instead. */
  --good:      oklch(0.86 0.17 155);   /*  9.9:1 on --good-bg */
  --good-bg:   oklch(0.31 0.05 155);
  --bad:       oklch(0.78 0.16 25);    /*  6.9:1 on --bad-bg  */
  --bad-bg:    oklch(0.32 0.06 25);
  --warn:      oklch(0.87 0.14 80);    /* 10.0:1 on --warn-bg */
  --warn-bg:   oklch(0.32 0.05 80);
  --accent:    oklch(0.72 0.13 250);   /* interaction only: focus, sort, hover */
  --accent-bg: oklch(0.72 0.13 250 / 0.14);

  --w: 1500px;
  --radius: 6px;
  --ease: cubic-bezier(0.22, 1, 0.36, 1);
  --z-sticky: 10;
  --z-popover: 20;
}

*, *::before, *::after { box-sizing: border-box; }

html { color-scheme: dark; }

body {
  margin: 0;
  background: var(--bg);
  color: var(--ink);
  font: 400 14px/1.45 ui-sans-serif, -apple-system, "Segoe UI", system-ui, sans-serif;
  -webkit-font-smoothing: antialiased;
  font-variant-numeric: tabular-nums;
}

/* Every number in this interface is meant to be compared against the number
   above it. Tabular figures are not a nicety here, they are the point. */
.num { font-variant-numeric: tabular-nums; }

:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
  border-radius: 3px;
}

/* Visible to screen readers, never to the eye. Used for link affordance text
   ("opens in a new tab") that would be noise if printed. */
.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

.skip {
  position: absolute;
  left: -9999px;
}
.skip:focus {
  left: 12px;
  top: 12px;
  z-index: var(--z-popover);
  padding: 8px 14px;
  background: var(--accent);
  color: oklch(0.15 0 0);
  border-radius: var(--radius);
  font-weight: 600;
}

/* ---------- Header ---------- */

header {
  padding: 22px 24px 0;
  max-width: var(--w);
  margin: 0 auto;
}

.title-row {
  display: flex;
  align-items: baseline;
  gap: 14px;
  flex-wrap: wrap;
}

h1 {
  margin: 0;
  font-size: 19px;
  font-weight: 620;
  letter-spacing: -0.01em;
}

.subtitle {
  color: var(--ink-3);
  font-size: 13px;
}

/* The four numbers worth knowing before you read a single row. Not a
   hero-metric shrine -- a one-line readout, sized like the rest of the UI. */
.readout {
  display: flex;
  flex-wrap: wrap;
  gap: 0 28px;
  margin: 14px 0 0;
  padding: 0 0 16px;
  list-style: none;
  border-bottom: 1px solid var(--line);
  font-size: 13px;
  color: var(--ink-2);
}

.readout b {
  color: var(--ink);
  font-weight: 600;
}

.readout .flag { color: var(--warn); }

/* ---------- Controls ---------- */

.controls {
  position: sticky;
  top: 0;
  z-index: var(--z-sticky);
  background: color-mix(in oklab, var(--bg) 92%, transparent);
  backdrop-filter: blur(8px);
  border-bottom: 1px solid var(--line);
}

.controls-inner {
  max-width: var(--w);
  margin: 0 auto;
  padding: 10px 24px;
  display: flex;
  align-items: center;
  gap: 10px;
  flex-wrap: wrap;
}

.group {
  display: flex;
  align-items: center;
  gap: 6px;
}

.group-label {
  color: var(--ink-3);
  font-size: 12px;
  margin-right: 2px;
}

.chip {
  appearance: none;
  border: 1px solid var(--line);
  background: var(--surface);
  color: var(--ink-2);
  padding: 5px 11px;
  border-radius: var(--radius);
  font: inherit;
  font-size: 13px;
  cursor: pointer;
  transition: background 140ms var(--ease), color 140ms var(--ease), border-color 140ms var(--ease);
}

.chip:hover { background: var(--surface-2); color: var(--ink); }

.chip[aria-pressed='true'] {
  background: var(--accent-bg);
  border-color: color-mix(in oklab, var(--accent) 55%, transparent);
  color: var(--ink);
}

.chip .count {
  color: var(--ink-3);
  font-size: 12px;
  margin-left: 4px;
}
.chip[aria-pressed='true'] .count { color: var(--ink-2); }

.spacer { flex: 1; }

.status {
  color: var(--ink-3);
  font-size: 13px;
}
.status b { color: var(--ink); font-weight: 600; }

/* ---------- Table ---------- */

/* 1340px, not 1680: at full width the eight columns stretch and strand a dead
   gap before the last one, which puts the seller and the listing link a long
   saccade away from the price they belong to. Comparison wants the columns
   close. */
.scroll {
  max-width: var(--w);
  margin: 0 auto;
  padding: 0 24px 64px;
  overflow-x: auto;
}

table {
  width: 100%;
  border-collapse: collapse;
  font-size: 13px;
  table-layout: auto;
}

/* Keep the numeric columns from being squeezed by the prose ones, and let the
   last column shrink-wrap its button rather than stretching it. */
th:nth-child(2), td:nth-child(2) { width: 1%; white-space: nowrap; }  /* landed  */
th:nth-child(3), td:nth-child(3) { width: 1%; }                       /* mileage */
th:nth-child(6), td:nth-child(6) { width: 1%; white-space: nowrap; }  /* distance */
th:last-child,   td:last-child   { width: 1%; white-space: nowrap; }  /* listing */

caption {
  text-align: left;
  padding: 14px 0 10px;
  color: var(--ink-3);
  font-size: 12.5px;
}

thead th {
  position: sticky;
  top: 45px;                      /* clears the sticky control bar */
  z-index: calc(var(--z-sticky) - 1);
  background: var(--bg);
  text-align: left;
  font-weight: 500;
  font-size: 12px;
  color: var(--ink-3);
  padding: 0;
  border-bottom: 1px solid var(--line);
  white-space: nowrap;
}

thead th.n { text-align: right; }

/* Sort buttons fill the header cell so the whole header is the target. */
.sort {
  appearance: none;
  width: 100%;
  background: none;
  border: 0;
  color: inherit;
  font: inherit;
  padding: 9px 10px;
  cursor: pointer;
  text-align: inherit;
  display: flex;
  align-items: center;
  gap: 5px;
  transition: color 140ms var(--ease);
}

th.n .sort { justify-content: flex-end; }
.sort:hover { color: var(--ink); }

th[aria-sort] .sort { color: var(--accent); font-weight: 600; }

.arrow { opacity: 0; font-size: 10px; transition: opacity 140ms var(--ease); }
.sort:hover .arrow { opacity: 0.45; }
th[aria-sort] .arrow { opacity: 1; }

tbody td {
  padding: 11px 10px;
  border-bottom: 1px solid var(--line-soft);
  vertical-align: top;
}

tbody tr {
  transition: background 120ms var(--ease);
}
tbody tr:hover { background: var(--surface); }

/* Keyboard-selected row: a left-edge accent bar is out (side-stripe ban), so
   selection reads as a full tinted surface plus a ring. */
tbody tr:focus-within { background: var(--surface-2); }

td.n { text-align: right; }

/* ---------- Cells ---------- */

.car {
  min-width: 190px;
}

.car-name {
  display: flex;
  align-items: center;
  gap: 8px;
  font-weight: 560;
  color: var(--ink);
  font-size: 13.5px;
}

/* Paint swatch. Decorative in the strict sense -- it encodes a color name that
   is also written out beside it -- so it's aria-hidden and never load-bearing. */
.swatch {
  width: 11px;
  height: 11px;
  border-radius: 50%;
  flex: none;
  box-shadow: inset 0 0 0 1px oklch(1 0 0 / 0.22);
}

.car-sub {
  color: var(--ink-3);
  font-size: 12px;
  margin-top: 3px;
}

/* Landed cost: the honest comparison figure, and therefore the biggest text in
   any row. */
.landed {
  font-size: 15px;
  font-weight: 640;
  color: var(--ink);
  letter-spacing: -0.01em;
  white-space: nowrap;
}

.landed-sub {
  font-size: 11.5px;
  margin-top: 3px;
  color: var(--ink-3);
  white-space: nowrap;
}

/* When landed differs from sticker, show the sticker struck through. This is
   the single most important visual in the dashboard: it is the moment the user
   sees that the marketplace's number was not the number. */
.was {
  text-decoration: line-through;
  text-decoration-color: color-mix(in oklab, var(--ink-3) 70%, transparent);
  color: var(--ink-3);
}

.landed-sub .add { color: var(--warn); }
.landed-sub .allin { color: var(--good); }

/* A price we cannot trust gets a dotted underline and a floor marker. Never a
   bare number. */
.floor {
  border-bottom: 1px dotted var(--warn);
  padding-bottom: 1px;
}

/* ---------- Signals ---------- */

/* Every signal pairs a glyph with a hue. Remove all color and these still
   read: ✓ clean, ▲ reported, ✕ damage, ? unknown. */
.tag {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  padding: 2px 7px;
  border-radius: 4px;
  font-size: 12px;
  font-weight: 500;
  white-space: nowrap;
  border: 1px solid transparent;
}

.tag-glyph { font-size: 10px; line-height: 1; }

.t-good    { background: var(--good-bg); color: var(--good); border-color: color-mix(in oklab, var(--good) 30%, transparent); }
.t-bad     { background: var(--bad-bg);  color: var(--bad);  border-color: color-mix(in oklab, var(--bad) 30%, transparent); }
.t-warn    { background: var(--warn-bg); color: var(--warn); border-color: color-mix(in oklab, var(--warn) 30%, transparent); }
.t-neutral { background: var(--surface-2); color: var(--ink-3); border-color: var(--line); }

.tag-sub {
  display: block;
  color: var(--ink-3);
  font-size: 11.5px;
  margin-top: 4px;
}

/* Deal ratings are claims made by a named site, never the dashboard's verdict.
   The source is printed under every one. */
.deal-src {
  display: block;
  color: var(--ink-3);
  font-size: 11px;
  margin-top: 4px;
}

/* Rows must stay a uniform height or the eye can't scan a column cleanly --
   a single wrapped cell shoves every neighbouring row out of rhythm. The
   secondary detail lines are short enough to hold one line; hold them there. */
.hist-detail {
  display: block;                 /* stack under the tag, matching .deal-src */
  color: var(--ink-3);
  font-size: 11.5px;
  margin-top: 4px;
  white-space: nowrap;
}

td:nth-child(4) { white-space: nowrap; }   /* history  */
td:nth-child(7) { white-space: nowrap; }   /* seller   */

/* Mileage bar: mileage matters and the twelve sit in a narrow 31k-46k band,
   so absolute numbers hide the spread. The bar is scaled to the band, not to
   zero, which makes small real differences visible. Redundant with the number
   beside it, so it's aria-hidden. */
.miles-bar {
  height: 3px;
  margin-top: 5px;
  background: var(--line);
  border-radius: 2px;
  overflow: hidden;
}
.miles-fill {
  height: 100%;
  background: var(--ink-3);
  border-radius: 2px;
}

.dist-approx { color: var(--ink-3); }
.dist-approx::after {
  content: '≈';
  margin-left: 2px;
  color: var(--warn);
}

/* Two links where a free Carfax report exists: the original listing (which owns
   the price and the deal rating) and the report. Stacked, primary on top. */
/* Side by side, not stacked: a stacked pair makes those two rows taller than
   the other ten and breaks the scan rhythm down the column. */
.links {
  display: flex;
  align-items: center;
  gap: 6px;
}

/* Carfax is the secondary link, but it's the one that answers the dealbreaker
   question, so it gets the accent rather than being demoted to plain text. */
.view-carfax {
  border-color: color-mix(in oklab, var(--accent) 42%, transparent);
  color: var(--ink-2);
}
.view-carfax:hover { color: var(--ink); }

/* The history cell's "Free Carfax report" link: this is the row's way of
   saying an unknown is resolvable. Underlined so it reads as a link at 11.5px
   without relying on the accent hue alone. */
.hist-link {
  color: var(--accent);
  text-decoration: underline;
  text-underline-offset: 2px;
  text-decoration-color: color-mix(in oklab, var(--accent) 45%, transparent);
  transition: text-decoration-color 140ms var(--ease);
}
.hist-link:hover { text-decoration-color: var(--accent); }

.view {
  display: inline-block;
  padding: 5px 10px;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  color: var(--ink-2);
  text-decoration: none;
  font-size: 12.5px;
  white-space: nowrap;
  transition: background 140ms var(--ease), border-color 140ms var(--ease), color 140ms var(--ease);
}
.view:hover {
  background: var(--accent-bg);
  border-color: color-mix(in oklab, var(--accent) 55%, transparent);
  color: var(--ink);
}

/* Ruling a car out. A quiet, muted control by default -- it must not compete with
   the listing link beside it -- that warms to a warning tint on hover, because the
   action removes the row. In the hidden view it flips to "Unhide" and reads as a
   restore. */
.hide-btn {
  appearance: none;
  background: none;
  border: 1px solid transparent;
  border-radius: var(--radius);
  color: var(--ink-3);
  cursor: pointer;
  padding: 5px 8px;
  font-size: 12px;
  white-space: nowrap;
  transition: background 140ms var(--ease), border-color 140ms var(--ease), color 140ms var(--ease);
}
.hide-btn:hover {
  color: var(--warn);
  border-color: color-mix(in oklab, var(--warn) 45%, transparent);
  background: color-mix(in oklab, var(--warn) 10%, transparent);
}
.hide-btn.is-unhide:hover {
  color: var(--accent);
  border-color: color-mix(in oklab, var(--accent) 45%, transparent);
  background: var(--accent-bg);
}

/* ---------- Detail row ---------- */

/* Specs the user asked to compare but that don't earn a permanent column.
   Inline expansion, not a modal -- the row stays in place, and two rows can be
   open at once for actual side-by-side reading. */
.detail td {
  padding: 0;
  border-bottom: 1px solid var(--line-soft);
  background: var(--surface);
}

/* Cap the spec grid rather than letting auto-fit spread eight items across the
   full 1500px -- at that width the eye travels the whole table to read one
   car's specs, which is the opposite of what an expanded row is for. */
.detail-inner {
  padding: 14px 10px 18px;
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(150px, 200px));
  justify-content: start;
  gap: 14px 32px;
}

.spec dt {
  color: var(--ink-3);
  font-size: 11.5px;
  margin-bottom: 3px;
}
.spec dd {
  margin: 0;
  color: var(--ink);
  font-size: 13px;
}
/* The raw source-site history sentence is the longest value in the panel and
   the one worth reading in full; give it room instead of wrapping it in a
   200px column. */
.spec.wide {
  grid-column: span 3;
  max-width: 70ch;
}

.spec dd.mono {
  font-family: ui-monospace, "Cascadia Mono", "SF Mono", Menlo, monospace;
  font-size: 12px;
  letter-spacing: -0.01em;
}

.basis-note {
  grid-column: 1 / -1;
  color: var(--ink-2);
  font-size: 12.5px;
  padding: 9px 11px;
  background: var(--bg);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  max-width: 72ch;
}
.basis-note b { color: var(--ink); font-weight: 600; }

.expand {
  appearance: none;
  background: none;
  border: 0;
  color: var(--ink-3);
  cursor: pointer;
  padding: 3px 6px;
  border-radius: 4px;
  font: inherit;
  font-size: 11px;
  transition: color 140ms var(--ease), background 140ms var(--ease);
}
.expand:hover { color: var(--ink); background: var(--surface-2); }
.expand .chev {
  display: inline-block;
  transition: transform 180ms var(--ease);
}
.expand[aria-expanded='true'] .chev { transform: rotate(90deg); }

/* ---------- Empty / error ---------- */

.empty {
  padding: 56px 24px;
  text-align: center;
  color: var(--ink-3);
}
.empty h2 {
  color: var(--ink);
  font-size: 15px;
  font-weight: 600;
  margin: 0 0 6px;
}
.empty p { margin: 0 0 14px; }

/* Two max-widths: the outer block aligns to the same 1680px gutter as the
   table above it, the inner prose caps at a readable measure. Setting both on
   one element (as I first did) centers the footer in the viewport instead of
   left-aligning it under the table. */
footer {
  max-width: var(--w);
  margin: 0 auto;
  padding: 0 24px 48px;
}

footer p {
  max-width: 78ch;
  margin: 0 0 10px;
  color: var(--ink-3);
  font-size: 12px;
  line-height: 1.6;
  text-wrap: pretty;
}

footer b { color: var(--ink-2); font-weight: 600; }

/* ---------- Responsive ---------- */

/* The table is the design; below ~1100px it scrolls horizontally rather than
   reflowing into cards, because reflowing into cards destroys exactly the
   column alignment that makes comparison possible. The car column stays pinned
   so you never lose your place. */
@media (max-width: 1100px) {
  .scroll { padding-inline: 12px; }
  thead th:first-child,
  tbody td:first-child {
    position: sticky;
    left: 0;
    background: var(--bg);
  }
  tbody tr:hover td:first-child { background: var(--surface); }
  header, .controls-inner, footer { padding-inline: 12px; }
}

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    transition-duration: 0.01ms !important;
  }
}

/* ─── Lifecycle: new, sold, price drop ──────────────────────────────────────
   Added when the dashboard stopped being a fixed set of twelve and became a
   daily scan. A car is now something that can arrive, get cheaper, and vanish. */

.badge {
  display: inline-block;
  margin-left: 6px;
  padding: 1px 6px;
  border-radius: 999px;
  font-size: 10px;
  font-weight: 600;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  vertical-align: middle;
}
.badge-new  { background: var(--accent-bg); color: var(--accent); border: 1px solid color-mix(in oklab, var(--accent) 30%, transparent); }
.badge-sold { background: var(--surface-2); color: var(--ink-3); border: 1px solid var(--line); }
/* Ships from beyond the drive radius. Kept because landed cost fits the budget,
   flagged because it is not a car you can drive to today. */
.badge-far  { background: var(--warn-bg, var(--surface-2)); color: var(--warn, var(--ink-2)); border: 1px solid color-mix(in oklab, var(--warn, var(--ink-3)) 30%, transparent); text-transform: none; }
.dist-far   { color: var(--warn, var(--ink-3)); font-size: 11px; }

/* A sold car is kept for its evidence, not for shopping. It reads as a record,
   not an option: dimmed, struck through the name, still fully legible. */
tr.is-sold { opacity: 0.55; }
tr.is-sold .car-name { text-decoration: line-through; text-decoration-color: var(--ink-3); }
tr.is-sold:hover { opacity: 0.8; }

/* The one change a shopper acts on immediately. Green, because it is good news,
   and it is the only place in the table where green means "cheaper" rather than
   "clean history" -- the ↓ glyph carries the distinction. */
.drop { color: var(--good); font-weight: 600; }

.readout .change { color: var(--accent); }
.readout .change b { color: var(--accent); }

.chip-sold[aria-pressed='true'] { border-color: var(--line); }
.chip-hidden[aria-pressed='true'] { border-color: color-mix(in oklab, var(--warn) 45%, transparent); }

/* A source that lists a car but publishes no link to it. The row is still real;
   the link is not. Saying so beats an <a href="null"> that goes nowhere. */
.view-dead {
  color: var(--ink-3);
  cursor: help;
  text-decoration: underline dotted color-mix(in oklab, var(--ink-3) 50%, transparent);
  text-underline-offset: 3px;
}
