/* ============================================================================
   ALTO - stylesheet
   ============================================================================
   Organised in the order the page is built:
     1. tokens      every colour and size, named, in one place
     2. layout      the overall page frame
     3. controls    the panel on the left
     4. results     the cost figures
     5. chart       the gate occupancy Gantt
     6. responsive  what changes on a narrow screen
   ========================================================================= */

/* ---- 1. TOKENS ---------------------------------------------------------- */
/* Change a colour here and it changes everywhere it is used. Nothing below
   this block contains a raw colour value. */

:root {
  /* Sky, cloud and desert. The subject is aviation, so the ground is cloud-
     cream, the accent is sky, and the alert is the terracotta of a runway at
     dusk. Started from a palette Evan chose; the two DATA colours below were
     then stepped darker until they passed a colour-vision validator against
     this exact background — the originals read as grey to a deuteranope and
     failed contrast on cream. Same hues, usable weight. */

  --paper:      #E6E1D1;   /* cloud cream — the page ground */
  --card:       #F4F1E8;   /* panels float lighter than the ground */
  --raised:     #FBFAF6;   /* inputs and buttons, lighter still */

  --ink:        #22303A;   /* deep slate-blue, never pure black */
  --ink-2:      #4A5C68;
  --muted:      #7A8892;
  --rule:       #CFC7B4;
  --rule-2:     #DDD7C7;

  --accent:     #0E7FA3;   /* sky */
  --accent-soft:#D6E6EC;

  /* THE TWO DATA COLOURS. Validated on this surface: lightness band, chroma
     floor, colour-vision separation, and 3:1 contrast all pass. Neither is
     ever the only signal — moved aircraft also carry a legend entry. */
  --moved:      #0E7FA3;   /* this aircraft changed gate */
  --delayed:    #AB4E33;   /* this aircraft is running late */

  --block:      #93A3AD;   /* an ordinary, unchanged aircraft — recessive on purpose */
  --block-tow:  #D5C2A3;   /* off-gate at a hardstand — sand, from the same palette */

  --good:       #2F7358;
  --shadow:     0 1px 2px rgba(34,48,58,.06), 0 8px 24px -16px rgba(34,48,58,.30);

  --radius:     4px;
  --gap:        16px;
}

@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    /* Night sky rather than an inverted cream. The data colours are stepped
       independently for this surface and re-validated on it — a lightened
       version of the light-mode pair fails the dark lightness band. */
    --paper:      #131C24;
    --card:       #1B2530;
    --raised:     #22303A;
    --ink:        #E8E3D6;   /* the cream returns as text */
    --ink-2:      #B6BFC6;
    --muted:      #7E8C96;
    --rule:       #2E3C48;
    --rule-2:     #222E38;
    --accent:     #35A0C7;
    --accent-soft:#14313E;
    --moved:      #35A0C7;
    --delayed:    #C4653F;
    --block:      #52646F;
    --block-tow:  #6E6249;
    --good:       #5FAE86;
    --shadow:     0 1px 2px rgba(0,0,0,.45), 0 8px 24px -16px rgba(0,0,0,.85);
  }
}

:root[data-theme="dark"] {
  --paper:#131C24; --card:#1B2530; --raised:#22303A;
  --ink:#E8E3D6; --ink-2:#B6BFC6; --muted:#7E8C96;
  --rule:#2E3C48; --rule-2:#222E38;
  --accent:#35A0C7; --accent-soft:#14313E;
  --moved:#35A0C7; --delayed:#C4653F;
  --block:#52646F; --block-tow:#6E6249;
  --good:#5FAE86;
  --shadow:0 1px 2px rgba(0,0,0,.45), 0 8px 24px -16px rgba(0,0,0,.85);
}

/* ---- 2. LAYOUT ---------------------------------------------------------- */

* { box-sizing: border-box; }

body {
  margin: 0;
  background: var(--paper);
  color: var(--ink);
  font-family: "IBM Plex Sans", system-ui, -apple-system, sans-serif;
  font-size: 15px;
  line-height: 1.55;
  -webkit-font-smoothing: antialiased;
}

.masthead {
  border-bottom: 1px solid var(--rule);
  padding: 22px 28px 18px;
  display: flex;
  align-items: baseline;
  gap: 18px;
  flex-wrap: wrap;
}
.masthead h1 {
  font-family: "Archivo", system-ui, sans-serif;
  font-weight: 700;
  font-size: 22px;
  letter-spacing: -.02em;
  margin: 0;
}
.masthead .tagline { color: var(--muted); font-size: 14px; }
.masthead nav { margin-left: auto; display: flex; gap: 18px; font-size: 13px; }
.masthead nav a { color: var(--accent); text-decoration: none; }
.masthead nav a:hover { text-decoration: underline; }

.shell {
  display: grid;
  grid-template-columns: 300px minmax(0, 1fr);
  gap: var(--gap);
  padding: var(--gap) 28px 60px;
  align-items: start;
}

/* The gate chart is far wider than the screen, on purpose - a day at SEA does
   not fit in 1400px and squashing it would make it unreadable.
   
   By default a grid or flex item refuses to shrink below its content's width,
   so the chart would stretch its whole column, push the page wider than the
   window, and take every panel with it. `minmax(0, 1fr)` above and these
   `min-width: 0` rules tell those boxes they ARE allowed to be narrower than
   what is inside them - which is what lets the chart scroll inside its own
   container instead of dragging the page sideways. */
.shell > aside,
.shell > main { min-width: 0; }
.panel { min-width: 0; }

.panel {
  background: var(--card);
  border: 1px solid var(--rule);
  border-radius: var(--radius);
  box-shadow: var(--shadow);
}
.panel > h2 {
  font-family: "IBM Plex Mono", monospace;
  font-size: 10.5px;
  letter-spacing: .14em;
  text-transform: uppercase;
  color: var(--muted);
  font-weight: 500;
  margin: 0;
  padding: 12px 16px;
  border-bottom: 1px solid var(--rule-2);
}
.panel-body { padding: 16px; }

/* ---- 3. CONTROLS -------------------------------------------------------- */

.control { margin-bottom: 20px; }
.control:last-child { margin-bottom: 0; }
.control > label {
  display: block;
  font-size: 12px;
  font-weight: 600;
  color: var(--ink-2);
  margin-bottom: 6px;
}
.control .hint { font-size: 11.5px; color: var(--muted); margin-top: 5px; line-height: 1.4; }
.control .hint a { color: var(--accent); }

/* ---- quick picks and day facts ---- */
.quick-picks { display: flex; flex-wrap: wrap; gap: 4px; margin-top: 7px; }
.quick-picks button {
  font-size: 11px; font-weight: 500;
  padding: 3px 7px; border-radius: 3px;
  border: 1px solid var(--rule); background: var(--raised); color: var(--ink-2);
}
.quick-picks button:hover { border-color: var(--accent); color: var(--accent); }

.day-facts {
  margin-top: 10px;
  border-top: 1px solid var(--rule-2);
  padding-top: 9px;
  font-size: 12px;
  line-height: 1.5;
}
.day-facts .headline { font-weight: 600; color: var(--ink); margin-bottom: 4px; }
.day-facts .row { display: flex; justify-content: space-between; gap: 10px; color: var(--muted); }
.day-facts .row b {
  font-family: "IBM Plex Mono", monospace;
  font-variant-numeric: tabular-nums;
  color: var(--ink-2); font-weight: 500;
}
.day-facts .tag-note {
  margin-top: 6px; color: var(--accent);
  font-size: 11.5px; line-height: 1.45;
}

input[type="date"], select, input[type="number"] {
  width: 100%;
  padding: 7px 9px;
  font: inherit;
  font-size: 13.5px;
  color: var(--ink);
  background: var(--raised);
  border: 1px solid var(--rule);
  border-radius: 3px;
}
input[type="range"] { width: 100%; accent-color: var(--accent); }

button {
  font: inherit;
  font-size: 13.5px;
  font-weight: 600;
  padding: 9px 14px;
  border-radius: 3px;
  border: 1px solid var(--rule);
  background: var(--raised);
  color: var(--ink);
  cursor: pointer;
}
button:hover { border-color: var(--accent); }
button.primary {
  background: var(--accent);
  border-color: var(--accent);
  color: var(--card);
  width: 100%;
}
button.primary:disabled { opacity: .55; cursor: default; }
button.tiny { padding: 3px 8px; font-size: 11.5px; font-weight: 500; }

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

.count {
  font-family: "IBM Plex Mono", monospace;
  font-size: 11px; font-weight: 500; color: var(--delayed);
}

/* ---- the gate grid ---- */
.gate-group { margin-bottom: 12px; }
.gate-group:last-child { margin-bottom: 0; }
.gate-group-head {
  display: flex; align-items: baseline; gap: 8px;
  margin-bottom: 5px;
}
.gate-group-head .name {
  font-size: 11.5px; font-weight: 600; color: var(--ink-2);
}
.gate-group-head .close-all {
  margin-left: auto;
  font-family: "IBM Plex Mono", monospace;
  font-size: 10.5px; font-weight: 500;
  background: none; border: none; padding: 0;
  color: var(--accent); cursor: pointer; text-decoration: underline;
}

.chips { display: flex; flex-wrap: wrap; gap: 4px; }
.chip.gate {
  font-size: 10.5px;
  padding: 2px 5px;
  min-width: 30px;
  text-align: center;
}

/* ---- the solving clock ---- */
.solving {
  margin-top: 12px;
  padding: 12px 14px;
  border: 1px solid var(--accent);
  border-radius: var(--radius);
  background: var(--accent-soft);
  text-align: center;
}
.solving.hidden { display: none; }
.solving-clock {
  font-family: "IBM Plex Mono", monospace;
  font-variant-numeric: tabular-nums;
  font-size: 26px; font-weight: 600;
  color: var(--accent); line-height: 1.1;
}
.solving-note {
  font-size: 11.5px; color: var(--ink-2); margin-top: 6px; line-height: 1.4;
}
.solving.done { border-color: var(--rule); background: var(--card); }
.solving.done .solving-clock { color: var(--good); font-size: 20px; }
.chip {
  font-family: "IBM Plex Mono", monospace;
  font-size: 11px;
  padding: 3px 7px;
  border-radius: 3px;
  border: 1px solid var(--rule);
  background: var(--raised);
  color: var(--ink-2);
  cursor: pointer;
  user-select: none;
}
.chip[aria-pressed="true"] {
  background: var(--delayed);
  border-color: var(--delayed);
  color: #fff;
}

.delay-row {
  display: flex;
  align-items: center;
  gap: 8px;
  font-family: "IBM Plex Mono", monospace;
  font-size: 12px;
  padding: 5px 0;
  border-bottom: 1px solid var(--rule-2);
}
.delay-row:last-child { border-bottom: none; }
.delay-row .tail { font-weight: 600; }
.delay-row .mins { color: var(--delayed); }
.delay-row button { margin-left: auto; }

/* ---- 4. RESULTS --------------------------------------------------------- */

.figures {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
  gap: 1px;
  background: var(--rule);
  border: 1px solid var(--rule);
  border-radius: var(--radius);
  overflow: hidden;
  margin-bottom: var(--gap);
}
.figure { background: var(--card); padding: 16px 18px; }
.figure .value {
  font-family: "IBM Plex Mono", monospace;
  font-variant-numeric: tabular-nums;
  font-size: 25px;
  font-weight: 600;
  letter-spacing: -.02em;
  line-height: 1.1;
}
.figure .value.recovered { color: var(--good); }
.figure .value.damage    { color: var(--delayed); }
.figure .label { font-size: 12px; color: var(--muted); margin-top: 6px; line-height: 1.35; }

/* Any wide block scrolls inside its own container, so the page body never
   scrolls sideways on a phone. */
.tbl-scroll { overflow-x: auto; }
.breakdown { width: 100%; min-width: 480px; border-collapse: collapse; font-size: 13.5px; }
.breakdown th, .breakdown td {
  text-align: right; padding: 7px 0 7px 14px;
  border-bottom: 1px solid var(--rule-2);
}
.breakdown th:first-child, .breakdown td:first-child { text-align: left; padding-left: 0; }
.breakdown th {
  font-family: "IBM Plex Mono", monospace;
  font-size: 10px; letter-spacing: .1em; text-transform: uppercase;
  color: var(--muted); font-weight: 500;
}
.breakdown td { font-variant-numeric: tabular-nums; font-family: "IBM Plex Mono", monospace; font-size: 12.5px; }
.breakdown td:first-child { font-family: inherit; font-size: 13.5px; }
.breakdown tr:last-child td { border-bottom: none; }

/* ---- 5. CHART ----------------------------------------------------------- */

/* The chart scrolls here, inside its own panel, and nowhere else. */
.chart-wrap { overflow-x: auto; overscroll-behavior-x: contain; padding: 4px 16px 16px; }
svg.gantt { display: block; }
svg.gantt .grid-line { stroke: var(--rule-2); stroke-width: 1; }
/* Midnight. Marked because a day's chart routinely runs into the next one. */
svg.gantt .grid-line.day-break { stroke: var(--rule); stroke-width: 1.5; stroke-dasharray: 3 3; }
svg.gantt .day-break-label { fill: var(--muted); font-size: 9.5px; }
svg.gantt .axis-text {
  font-family: "IBM Plex Mono", monospace;
  font-size: 10px;
  fill: var(--muted);
}
svg.gantt .gate-label {
  font-family: "IBM Plex Mono", monospace;
  font-size: 10px;
  fill: var(--ink-2);
}
svg.gantt .bar { fill: var(--block); rx: 2; }
svg.gantt .bar.tow { fill: var(--block-tow); }
svg.gantt .bar.moved { fill: var(--moved); }
svg.gantt .bar.delayed { fill: var(--delayed); }
/* A 2px ring in the surface colour so touching bars never visually merge. */
svg.gantt .bar { stroke: var(--card); stroke-width: 2; paint-order: stroke; }
svg.gantt .bar:hover { stroke: var(--ink); stroke-width: 1.5; }

.legend { display: flex; flex-wrap: wrap; gap: 16px; padding: 0 16px 14px; font-size: 12px; color: var(--ink-2); }
.legend span { display: inline-flex; align-items: center; gap: 6px; }
.legend i { width: 12px; height: 12px; border-radius: 2px; display: inline-block; }

.tooltip {
  position: fixed;
  pointer-events: none;
  z-index: 20;
  background: var(--raised);
  border: 1px solid var(--rule);
  border-radius: 3px;
  box-shadow: var(--shadow);
  padding: 9px 11px;
  font-family: "IBM Plex Mono", monospace;
  font-size: 11.5px;
  line-height: 1.6;
  color: var(--ink);
  max-width: 260px;
}
.tooltip.hidden { display: none; }
.tooltip b { color: var(--accent); }

/* the year strip */
.year { padding: 12px 16px 16px; }
svg.year-strip { display: block; width: 100%; height: 96px; }
svg.year-strip path.trend { fill: none; stroke: var(--accent); stroke-width: 2; stroke-linejoin: round; }
/* The daily bars sit back so the seven-day average reads clearly on top of
   them. They are context; the trend is the point. */
svg.year-strip rect.day { cursor: pointer; fill: var(--block); opacity: .45; }
svg.year-strip rect.day:hover { opacity: .9; }
svg.year-strip rect.day.selected { opacity: 1; fill: var(--accent); }
svg.year-strip rect.day:hover { stroke: var(--ink); stroke-width: 1; }
svg.year-strip rect.day.selected { stroke: var(--accent); stroke-width: 2; }
svg.year-strip text { font-family: "IBM Plex Mono", monospace; font-size: 9.5px; fill: var(--muted); }

.status {
  font-family: "IBM Plex Mono", monospace;
  font-size: 11.5px;
  color: var(--muted);
  padding: 0 16px 14px;
}
.status.error { color: var(--delayed); }

/* Anything that exists only for screen readers. */
.sr-only {
  position: absolute; width: 1px; height: 1px;
  padding: 0; margin: -1px; overflow: hidden;
  clip: rect(0,0,0,0); white-space: nowrap; border: 0;
}

/* ---- 6. RESPONSIVE ------------------------------------------------------ */

@media (max-width: 900px) {
  .shell { grid-template-columns: 1fr; padding: var(--gap) 16px 60px; }
  .masthead { padding: 18px 16px 14px; }
  .figures { grid-template-columns: repeat(2, 1fr); }
  .figure .value { font-size: 21px; }
  .masthead nav { margin-left: 0; width: 100%; }
}

