/*
 * fuelwatch.css — the chart's colour system and chrome.
 *
 * Every colour the chart draws with is declared here as a role, in two
 * selected sets: one for the dark surface (the site default) and one for light.
 * The light values are not a flip of the dark ones — they are the same three
 * hues stepped for a light surface and validated against it separately.
 *
 * The five series hues are a validated categorical set, in fixed order:
 *
 *   slot 1  Saskatoon · Regular       slot 2  Saskatoon · Diesel
 *   slot 3  Ann Arbor · Regular       slot 4  Ann Arbor · Diesel (GasBuddy)
 *   slot 5  Ann Arbor · Diesel (Open Roads)
 *
 * The slot is assigned by the server over every series that could be plotted,
 * not over the ones currently selected (see fuelwatch_entities in lib.php), so
 * deselecting a city cannot repaint the survivors — a filter that changes the
 * series count must not change what the remaining lines look like.
 *
 * Validated with the palette validator on the adjacent pairlist (lines): the
 * lightness band, chroma floor and normal-vision separation pass in both modes.
 * Three slots sit under 3:1 on the light surface, which raises a contrast WARN;
 * that is why the table view and the direct end-labels are not optional extras
 * but the relief the warning obligates. Dark mode is a selected set of steps
 * for the dark surface, not an automatic flip of the light ones.
 *
 * Selected controls (segments, chips) are marked by inverting to the text
 * colour rather than by filling with a series hue. It reads at a glance, and
 * it keeps "blue" meaning one thing only: the first series.
 */

.fw {
  color-scheme: light;
  --plane:          #f9f9f7;
  --surface-1:      #fcfcfb;
  --text-primary:   #0b0b0b;
  --text-secondary: #52514e;
  --text-muted:     #898781;
  --grid:           #e1e0d9;
  --axis:           #c3c2b7;
  --hairline:       rgba(11, 11, 11, 0.10);
  --series-1:       #2a78d6;
  --series-2:       #eb6834;
  --series-3:       #1baf7a;
  --series-4:       #eda100;
  --series-5:       #e87ba4;
  --bad:            #d03b3b;

  margin: 0;
  padding: 0 1rem 3rem;
  background: var(--plane);
  color: var(--text-primary);
  font: 15px/1.5 system-ui, -apple-system, "Segoe UI", sans-serif;
}

@media (prefers-color-scheme: dark) {
  :root:where(:not([data-theme="light"])) .fw {
    color-scheme: dark;
    --plane:          #0d0d0d;
    --surface-1:      #1a1a19;
    --text-primary:   #ffffff;
    --text-secondary: #c3c2b7;
    --text-muted:     #898781;
    --grid:           #2c2c2a;
    --axis:           #383835;
    --hairline:       rgba(255, 255, 255, 0.10);
    --series-1:       #3987e5;
    --series-2:       #d95926;
    --series-3:       #199e70;
    --series-4:       #c98500;
    --series-5:       #d55181;
  }
}

:root[data-theme="dark"] .fw {
  color-scheme: dark;
  --plane:          #0d0d0d;
  --surface-1:      #1a1a19;
  --text-primary:   #ffffff;
  --text-secondary: #c3c2b7;
  --text-muted:     #898781;
  --grid:           #2c2c2a;
  --axis:           #383835;
  --hairline:       rgba(255, 255, 255, 0.10);
  --series-1:       #3987e5;
  --series-2:       #d95926;
  --series-3:       #199e70;
  --series-4:       #c98500;
  --series-5:       #d55181;
}

.fw a { color: var(--series-1); }

/* ---------- head ---------- */

.fw-head {
  max-width: 1100px;
  margin: 0 auto;
  padding: 2rem 0 0.5rem;
}

.fw-head h1 {
  display: none;
  margin: 0;
  font-size: 1.5rem;
  font-weight: 600;
  letter-spacing: -0.01em;
}

.fw-sub {
  margin: 0.25rem 0 0;
  color: var(--text-secondary);
  font-size: 0.9rem;
}

/* ---------- controls ---------- */

/*
 * Two rows. The first holds the three single-choice groups (range, plot,
 * radius); the second holds the multi-select facets (cities, fuels, sources)
 * and the table toggle. They are separate rows because they behave
 * differently — a segmented control always has exactly one answer, a chip
 * group can have several — and putting them in one run of controls would
 * invite the reader to assume they all work the same way.
 */
.fw-controls {
  max-width: 1100px;
  margin: 1.25rem auto 0;
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  gap: 0.85rem 1.5rem;
}

.fw-controls-series { margin-top: 0.85rem; align-items: center; }

.fw-ctl {
  display: flex;
  flex-direction: column;
  gap: 0.35rem;
  min-width: 0;
}

.fw-controls-series .fw-ctl { flex-direction: row; align-items: center; gap: 0.6rem; }

.fw-ctl-label {
  color: var(--text-muted);
  font-size: 0.78rem;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  flex: none;
}

.fw-seg {
  display: inline-flex;
  border: 1px solid var(--hairline);
  border-radius: 8px;
  overflow: hidden;
}

.fw-seg button {
  appearance: none;
  border: 0;
  background: transparent;
  color: var(--text-secondary);
  font: inherit;
  font-size: 0.85rem;
  padding: 0.4rem 0.8rem;
  cursor: pointer;
  /* Removes the 300ms tap delay and the grey flash on iOS without disabling
     pinch-zoom on the page. */
  touch-action: manipulation;
}

.fw-seg button + button { border-left: 1px solid var(--hairline); }
.fw-seg button:hover { background: var(--plane); }

/* Selected = inverted, in both control types. Never a series hue: blue means
   "Saskatoon · Regular" here, and a control that is also blue would read as a
   statement about the data. */
.fw-seg button[aria-checked="true"] {
  background: var(--text-primary);
  color: var(--plane);
}

.fw-chips {
  display: flex;
  flex-wrap: wrap;
  gap: 0.4rem;
}

.fw-chip {
  appearance: none;
  border: 1px solid var(--hairline);
  border-radius: 999px;
  background: transparent;
  color: var(--text-secondary);
  font: inherit;
  font-size: 0.82rem;
  padding: 0.32rem 0.75rem;
  cursor: pointer;
  touch-action: manipulation;
}

.fw-chip:hover { background: var(--plane); }

.fw-chip[aria-pressed="true"] {
  background: var(--text-primary);
  color: var(--plane);
  border-color: transparent;
}

.fw-opts-btn, .fw-quick { display: none; }

.fw-toggle {
  margin-left: auto;
  appearance: none;
  border: 1px solid var(--hairline);
  border-radius: 8px;
  background: transparent;
  color: var(--text-secondary);
  font: inherit;
  font-size: 0.85rem;
  padding: 0.4rem 0.8rem;
  cursor: pointer;
  touch-action: manipulation;
}

.fw-toggle:hover { background: var(--plane); }
.fw-toggle[aria-pressed="true"] {
  background: var(--text-primary);
  color: var(--plane);
  border-color: transparent;
}

/* The series picker on the cheapest-stations card. */
.fw-pick {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
}

.fw-pick select {
  appearance: none;
  border: 1px solid var(--hairline);
  border-radius: 8px;
  background: var(--plane);
  color: var(--text-primary);
  font: inherit;
  font-size: 0.85rem;
  padding: 0.35rem 0.7rem;
  max-width: 22rem;
  cursor: pointer;
  touch-action: manipulation;
}

/* ---------- panels ---------- */

.fw-panels {
  max-width: 1100px;
  margin: 0 auto;
  display: grid;
  gap: 1.25rem;
}

.fw-card {
  background: var(--surface-1);
  border: 1px solid var(--hairline);
  border-radius: 12px;
  padding: 1rem 1rem 0.5rem;
}

.fw-card-head {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 0.5rem 0.9rem;
  margin-bottom: 0.25rem;
}

.fw-card-title {
  margin: 0;
  font-size: 1rem;
  font-weight: 600;
}

.fw-card-unit {
  color: var(--text-muted);
  font-size: 0.8rem;
}

/* A legend is always present for two or more series, so identity never rests
   on colour alone. It sits in the card head rather than under the plot. */
.fw-legend {
  display: flex;
  flex-wrap: wrap;
  gap: 0.75rem;
  margin-left: auto;
}

.fw-legend-item {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  color: var(--text-secondary);
  font-size: 0.8rem;
  cursor: default;
}

.fw-swatch {
  width: 10px;
  height: 10px;
  border-radius: 3px;
  flex: none;
}

.fw-plot { position: relative; }

/*
 * The SVG is drawn at the container's measured width in real pixels, so it
 * must NOT be scaled by CSS — that is what shrank the labels to ~5px on a
 * phone. max-width is a safety net for the one frame between a container
 * resize and the redraw, not the sizing mechanism.
 */
.fw-plot svg { display: block; max-width: 100%; height: auto; }

.fw-empty {
  color: var(--text-muted);
  font-size: 0.85rem;
  padding: 2rem 0;
  text-align: center;
}

/* The brand rides alongside the station name in a muted span rather than its
   own column — it is a qualifier on the name, not a second fact. */
.fw-station-brand {
  color: var(--text-muted);
  font-size: 0.78rem;
}

/* The address exists twice in the markup: as its own column, and folded under
   the station name. Only one of the two is ever visible — the wide layout
   shows the column, the narrow one folds it, so the table never has to push
   the price off the right edge to make room for an address. */
.fw-station-sub { display: none; }

/* The stations card ends in a table, not a plot, so it does not want the
   tightened bottom padding the chart cards use. */
#fw-stations-card { padding-bottom: 0.9rem; }

/* Crosshair tooltip. Pointer-events:none so it never eats the hover it
   depends on; the hit layer under it is full-plot. */
.fw-tip {
  position: absolute;
  pointer-events: none;
  z-index: 2;
  min-width: 9rem;
  padding: 0.5rem 0.6rem;
  border-radius: 8px;
  border: 1px solid var(--hairline);
  background: var(--plane);
  color: var(--text-primary);
  font-size: 0.8rem;
  line-height: 1.35;
  box-shadow: 0 6px 20px rgba(0, 0, 0, 0.28);
  opacity: 0;
  transition: opacity 0.1s ease;
}

.fw-tip[data-show="1"] { opacity: 1; }

.fw-tip-date {
  color: var(--text-muted);
  margin-bottom: 0.25rem;
}

.fw-tip-row {
  display: flex;
  align-items: center;
  gap: 0.4rem;
  white-space: nowrap;
}

.fw-tip-name { color: var(--text-secondary); }
.fw-tip-val { margin-left: auto; font-variant-numeric: tabular-nums; }
.fw-tip-n { color: var(--text-muted); font-size: 0.75rem; }

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

.fw-error {
  max-width: 1100px;
  margin: 0 auto 1rem;
  padding: 0.75rem 1rem;
  border-radius: 10px;
  border: 1px solid var(--hairline);
  border-left: 3px solid var(--bad);
  background: var(--surface-1);
  color: var(--text-secondary);
  font-size: 0.9rem;
}

/* ---------- tables ---------- */

.fw-tables {
  max-width: 1100px;
  margin: 1.5rem auto 0;
}

.fw-table-block { margin-bottom: 1.75rem; }

.fw-table-block h3 {
  margin: 0 0 0.5rem;
  font-size: 0.95rem;
  font-weight: 600;
}

.fw-table-block h3 span {
  color: var(--text-muted);
  font-weight: 400;
  font-size: 0.85rem;
}

.fw-table-wrap { overflow-x: auto; }

.fw table {
  border-collapse: collapse;
  width: 100%;
  font-size: 0.85rem;
}

.fw th, .fw td {
  text-align: left;
  padding: 0.4rem 0.6rem;
  border-bottom: 1px solid var(--hairline);
  white-space: nowrap;
}

.fw th {
  color: var(--text-muted);
  font-weight: 500;
  font-size: 0.78rem;
  text-transform: uppercase;
  letter-spacing: 0.04em;
}

.fw td.num { text-align: right; font-variant-numeric: tabular-nums; }
.fw tbody tr:hover { background: var(--plane); }

/* ---------- foot ---------- */

.fw-foot {
  max-width: 1100px;
  margin: 2rem auto 0;
  color: var(--text-muted);
  font-size: 0.8rem;
  line-height: 1.6;
}

.fw-foot strong { color: var(--text-secondary); font-weight: 600; }

/* ============================================================
   Responsive
   ============================================================ */

/*
 * Two breakpoints, both about touch and width rather than device class:
 * 720px is where the filter row and legend stop fitting on one line, and
 * 480px is where the chart itself drops its end-labels and tightens margins
 * (the matching logic is in fuelwatch.js — the two must agree on 560px of
 * *plot* width, which is roughly 640px of viewport once the page padding and
 * card padding are subtracted).
 */

@media (max-width: 720px) {
  .fw { padding: 0 0.75rem 2.5rem; }

  .fw-head { padding-top: 1.25rem; }
  .fw-head h1 { font-size: 1.3rem; }

  .fw-controls { margin-top: 1rem; gap: 0.7rem 1rem; }
  .fw-controls-series { margin-top: 0.7rem; }

  /* Each group takes the full width and stacks its label above its options.
     Left to wrap naturally the chips ragged-edge across the row, which reads
     as one undifferentiated block rather than three separate questions. */
  .fw-ctl { width: 100%; }
  .fw-controls-series .fw-ctl { flex-direction: column; align-items: flex-start; gap: 0.35rem; }

  /* The table toggle stops being pushed to the far edge where it would sit
     under the thumb, and takes its own full-width row. */
  .fw-toggle { margin-left: 0; width: 100%; }

  .fw-legend {
    margin-left: 0;
    width: 100%;
    gap: 0.5rem 0.9rem;
  }

  .fw-card { padding: 0.85rem 0.75rem 0.35rem; border-radius: 10px; }
  .fw-card-title { font-size: 0.95rem; }
  .fw-panels { gap: 1rem; }
  #fw-stations-card { padding-bottom: 0.8rem; }

  .fw-pick { width: 100%; }
  .fw-pick select { max-width: none; flex: 1 1 auto; }

  /* Fold the address under the station name, and the distance and date under
     the price, so nothing the reader needs ends up off the right edge. */
  .fw-col-address, .fw-col-meta { display: none; }
  /* white-space is inherited from the nowrap on td, so the sub-line has to
     opt out of it explicitly or a long address is clipped mid-word instead of
     wrapping. */
  .fw-station-sub {
    display: block;
    color: var(--text-muted);
    font-size: 0.75rem;
    white-space: normal;
  }
  .fw-station-cell { white-space: normal; min-width: 7rem; }
}

@media (max-width: 480px) {
  .fw { padding: 0 0.6rem 2rem; }

  .fw-head h1 { font-size: 1.2rem; }
  .fw-sub { font-size: 0.82rem; }

  /* The segmented control stops being one strip and becomes a grid of separate
     cells. The radius group has six options; on a 320px screen a single row
     would leave each under 50px, too narrow for "100 km" and well under a
     comfortable touch target — so it wraps.
     It is a grid of outlined cells rather than a wrapped strip because a strip
     that wraps leaves the unused cells of its last row empty, and the only
     thing there to fill them is the container's own background — which is the
     divider colour. A row of dead grey blocks reads as a broken control. */
  .fw-seg {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(4.5rem, 1fr));
    gap: 0.35rem;
    width: 100%;
    border: 0;
    border-radius: 0;
    overflow: visible;
    background: none;
  }
  .fw-seg button {
    border: 1px solid var(--hairline);
    border-radius: 8px;
    background: var(--plane);
    padding: 0.55rem 0.3rem;
    text-align: center;
  }
  /* :not() keeps this off the selected button, which must stay inverted —
     a plain :hover here would outrank the aria-checked rule above it. */
  .fw-seg button:not([aria-checked="true"]):hover { background: var(--surface-1); }

  /* The Plot group is the one that has nothing to gain from the width the other
     groups need. Its four options are single short words, and at the shared
     4.5rem cell they wrap onto a second row on the narrowest phones — which
     doubles the height of the control block above the chart without making a
     word of it easier to read. Given a smaller cell, a smaller label and less
     side padding they stay on one line everywhere, which is the whole of the
     compaction: the four options are still four separate tap targets at the
     full 40px height the coarse-pointer rule sets. */
  #fw-agg { grid-template-columns: repeat(auto-fit, minmax(3.9rem, 1fr)); }
  #fw-agg button { padding: 0.45rem 0.2rem; font-size: 0.78rem; }

  .fw-toggle { width: 100%; padding: 0.5rem 0.8rem; }

  .fw-tip { min-width: 7.5rem; font-size: 0.78rem; }

  /* Tables scroll horizontally rather than squashing columns into unreadable
     slivers; the wrapper already sets overflow-x. */
  .fw table { font-size: 0.8rem; }
  .fw th, .fw td { padding: 0.35rem 0.45rem; }
  .fw-table-block h3 { font-size: 0.88rem; }

  .fw-foot { font-size: 0.76rem; }
}

/* Coarse pointers get taller hit targets regardless of width — a tablet is
   wide but still driven by a finger. */
@media (pointer: coarse) {
  .fw-seg button, .fw-toggle, .fw-chip, .fw-pick select { min-height: 40px; }
  .fw-chip { display: inline-flex; align-items: center; }
  .fw-legend-item { padding: 0.15rem 0; }
}

/* ============================================================
   Phone layout
   ============================================================ */

/*
 * Stations first, chart second. The page is a flex column here purely so the
 * cards can be reordered without touching the markup (desktop keeps the chart
 * on top). Cities and fuel stay visible; everything else sits behind Options.
 */
@media (max-width: 720px) {
  .fw { display: flex; flex-direction: column; }
  .fw > * { width: 100%; box-sizing: border-box; }

  .fw-head          { order: 0; }
  .fw-error         { order: 1; }
  .fw-controls-series { order: 2; }
  .fw-opts-btn      { order: 3; }
  .fw-controls-main { order: 4; }
  #fw-stations-card { order: 5; }
  .fw-panels        { order: 6; margin-top: 1rem; }
  .fw-tables        { order: 7; }
  .fw-foot          { order: 8; }

  .fw-opts-btn {
    display: block;
    margin: 0.7rem 0 0;
    appearance: none;
    border: 1px solid var(--hairline);
    border-radius: 8px;
    background: transparent;
    color: var(--text-secondary);
    font: inherit;
    font-size: 0.85rem;
    padding: 0.5rem 0.8rem;
    text-align: center;
    touch-action: manipulation;
  }
  .fw-opts-btn::after { content: " \25BE"; }
  .fw-opts-btn[aria-expanded="true"]::after { content: " \25B4"; }

  /* Collapsed by default. */
  .fw-controls-main,
  #fw-sources-ctl,
  #fw-table-toggle { display: none; }
  .fw-opts-open .fw-controls-main { display: flex; }
  .fw-opts-open #fw-sources-ctl { display: flex; }
  .fw-opts-open #fw-table-toggle { display: block; }

  /* Stations: a compact list, the price is the loudest thing on each row. */
  #fw-stations-card { margin-top: 0.85rem; }
  #fw-stations-body th:first-child,
  #fw-stations-body td:first-child { display: none; }
  #fw-stations-body td.num { font-size: 1.05rem; font-weight: 600; }
  #fw-stations-body td { vertical-align: top; padding-top: 0.55rem; padding-bottom: 0.55rem; }
  #fw-stations-body .fw-station-name { font-weight: 500; }
  .fw-card-head .fw-card-unit { width: 100%; }
}

@media (max-width: 720px) {
  .fw-quick { order: 2; display: grid; grid-template-columns: 1fr 1fr; gap: 0.5rem; margin-top: 1rem; }
  .fw-quick .fw-seg { display: flex; width: 100%; border: 1px solid var(--hairline); border-radius: 8px; overflow: hidden; gap: 0; background: none; }
  .fw-quick .fw-seg button { flex: 1; border: 0; border-radius: 0; background: transparent; padding: 0.6rem 0.3rem; }
  .fw-quick .fw-seg button + button { border-left: 1px solid var(--hairline); }
  .fw-quick .fw-seg button[aria-checked="true"] { background: var(--text-primary); color: var(--plane); }

  /* The chips are superseded by the quick control; sources stay in Options. */
  #fw-cities-ctl, #fw-fuels-ctl { display: none; }
  .fw-controls-series { order: 3; margin-top: 0; }
  .fw-opts-btn { order: 4; }
  .fw-controls-main { order: 5; }
  #fw-stations-card { order: 6; }
  .fw-panels { order: 7; }
  .fw-tables { order: 8; }
  .fw-foot { order: 9; }
  /* Series picker is only needed when a selection has several series. */
}

@media (max-width: 720px) {
  .fw-head { padding: 1rem 0 0; }
  /* Order: age, quick pick, stations, chart, then options. */
  .fw-quick            { order: 2; }
  #fw-stations-card    { order: 3; }
  .fw-panels           { order: 4; }
  .fw-opts-btn         { order: 5; margin-top: 1rem; }
  .fw-controls-main    { order: 6; margin-top: 0.7rem; }
  .fw-controls-series  { order: 7; margin-top: 0.7rem; }
  .fw-tables           { order: 8; }
  .fw-foot             { order: 9; }
  .fw-pick             { display: none; }
}
