/* Stylesheet for the written pages, which are not the app.
 *
 * Deliberately its own file. The app's styles.css locks the page to the
 * viewport height and hides overflow, because the app is a map that must never
 * scroll - link it here and a long article becomes unscrollable and unreadable
 * below the fold. So these pages take the colours and nothing else.
 *
 * Same palette as the app, restated rather than imported, so the two look like
 * one site without the article inheriting the instrument panel's geometry.
 * Light is the complete set; dark redefines only the tokens, twice, so an
 * explicit choice wins in both directions and the default un-stamped state
 * still resolves.
 */

:root {
  --bg: #f3f6f5;
  --bg-panel: #ffffff;
  --bg-panel-fade: rgba(255, 255, 255, 0);
  --bg-raised: #e9efed;
  --text: #0d1c19;
  --text-dim: #334743;
  --text-faint: #5d716c;
  --line: #d2dbd8;
  --line-strong: #b3c1bd;
  --accent: #087b77;
  --amber: #8a4a15;
  --shadow: 0 1px 2px rgba(13, 28, 25, .05), 0 8px 24px -14px rgba(13, 28, 25, .18);
  /* The same two stacks the app uses, by the same names. They were written
     out literally seven times here and were NOT the app's stack - articles
     fell back to ui-monospace on a Mac and Consolas on Windows while the app
     got SF Mono and Cascadia Mono, so the same table rendered in two
     different faces depending which half of the site you were on. */
  --mono: "JetBrains Mono", "Cascadia Mono", Consolas, "SF Mono", monospace;
  --sans: "Inter", "Segoe UI", system-ui, -apple-system, sans-serif;
}
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    --bg: #07131a;
    --bg-panel: #0f1f26;
    --bg-panel-fade: rgba(15, 31, 38, 0);
    --bg-raised: #162b31;
    --text: #e8f4f2;
    --text-dim: #c2d5d3;
    --text-faint: #8ba7ab;
    --line: #1e3038;
    --line-strong: #2c454d;
    --accent: #35d6cf;
    --amber: #f5c58a;
    --shadow: 0 1px 2px rgba(0, 0, 0, .4), 0 8px 24px -14px rgba(0, 0, 0, .6);
  }
}
:root[data-theme="dark"] {
  --bg: #07131a;
  --bg-panel: #0f1f26;
  --bg-panel-fade: rgba(15, 31, 38, 0);
  --bg-raised: #162b31;
  --text: #e8f4f2;
  --text-dim: #c2d5d3;
  --text-faint: #8ba7ab;
  --line: #1e3038;
  --line-strong: #2c454d;
  --accent: #35d6cf;
  --amber: #f5c58a;
  --shadow: 0 1px 2px rgba(0, 0, 0, .4), 0 8px 24px -14px rgba(0, 0, 0, .6);
}

* { box-sizing: border-box; }

body {
  margin: 0;
  padding: 0 20px 80px;
  background: var(--bg);
  color: var(--text);
  font: 16.5px/1.62 var(--sans);
  -webkit-font-smoothing: antialiased;
}

.wrap { max-width: 860px; margin: 0 auto; }
.col { max-width: 68ch; }

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

/* ------------------------------------------------------------- masthead */
.top {
  display: flex; align-items: baseline; gap: 14px; flex-wrap: wrap;
  padding: 26px 0 0; border-bottom: 1px solid var(--line); padding-bottom: 16px;
}
.top a.home { font-weight: 600; color: var(--text); text-decoration: none; letter-spacing: -.01em; }
.top a.map-back { font-size: 13px; text-decoration: none; }
.top .crumb { font-size: 13px; color: var(--text-faint); }
.top .crumb a { color: var(--text-faint); }

header.page { padding: 44px 0 0; }
h1 {
  font-size: clamp(28px, 4.4vw, 40px); line-height: 1.1; font-weight: 600;
  letter-spacing: -.02em; margin: 0 0 10px; text-wrap: balance;
}
.iata {
  font-family: var(--mono);
  color: var(--accent); font-weight: 500;
}
.where { color: var(--text-faint); font-size: 16px; margin: 0 0 4px; }

/* The window every number on the page is measured over. It sits directly
   under the title because it qualifies everything below it. */
.window {
  font-family: var(--mono);
  font-size: 12px; letter-spacing: .04em; color: var(--text-faint);
  margin: 18px 0 0; padding: 10px 14px;
  background: var(--bg-panel); border: 1px solid var(--line); border-radius: 8px;
}

/* The directories are a separate, dated shelf. Put the choice between
   airports and airlines above the long table; the live map remains in the
   masthead so these links cannot be mistaken for today's timetable. */
.collection-switch { display: flex; flex-wrap: wrap; gap: 8px; margin: 22px 0 16px; }
.collection-switch a {
  padding: 9px 14px; border: 1px solid var(--line); border-radius: 9px;
  background: var(--bg-panel); color: var(--text-dim); text-decoration: none;
  font-size: 14px; font-weight: 600;
}
.collection-switch a[aria-current="page"] { border-color: var(--accent); color: var(--accent); background: var(--bg-raised); }
.collection-switch a:hover, .collection-switch a:focus-visible { border-color: var(--accent); color: var(--accent); }
.featured-records { margin: 20px 0 26px; }
.featured-records h2 { margin: 0 0 12px; font-size: 19px; }
.featured-records > div { display: grid; grid-template-columns: repeat(auto-fit, minmax(145px, 1fr)); gap: 8px; }
.featured-records a {
  display: flex; align-items: center; min-height: 52px; padding: 9px 12px;
  border: 1px solid var(--line); border-radius: 9px; background: var(--bg-panel);
  color: var(--accent); text-decoration: none; font-weight: 600; font-size: 14px;
}
.featured-records a:hover, .featured-records a:focus-visible { border-color: var(--accent); background: var(--bg-raised); }

p { margin: 0 0 1em; }
.lede { font-size: 17.5px; color: var(--text-dim); }

h2 {
  font-size: 21px; font-weight: 600; letter-spacing: -.01em;
  margin: 44px 0 6px; text-wrap: balance;
}
.sub { color: var(--text-faint); font-size: 14.5px; margin: 0 0 16px; }

/* ---------------------------------------------------------------- stats */
/* A photograph, and the credit its licence requires.
 *
 * The same markup as the app's .photo, written by photo_figure() in
 * tools/build_pages.py, but styled here rather than shared: this sheet
 * restates the palette instead of importing it, on purpose, because an
 * article is opaque paper where the app is glass over a moving map. The
 * class names match so the two stay recognisably the same object; the
 * values match .figures below, which is the component it sits above.
 *
 * The caption is a condition of use, not decoration. These come from
 * Wikimedia and almost all are CC BY-SA, under which the photographer must be
 * named wherever the picture appears. Small and quiet is fine. Absent is not.
 *
 * Radius and border are literals rather than tokens because this sheet
 * declares no --radius, and referencing a token that is not declared here is
 * the one thing the house rules single out about these two files. */
.photo {
  margin: 26px 0 0;
  border: 1px solid var(--line);
  border-radius: 10px;
  overflow: hidden;
  background: var(--bg-panel);
  box-shadow: var(--shadow);
}
.photo img {
  display: block; width: 100%;
  aspect-ratio: 16 / 10; object-fit: cover;
}
/* Wide, because on a written page this sits directly under the heading and a
 * tall picture would push the figures that answer the reader's question below
 * the fold. */
.photo-wide img { aspect-ratio: 21 / 9; }
.photo figcaption {
  padding: 7px 12px;
  border-top: 1px solid var(--line);
  font-size: 11px; color: var(--text-faint);
}
.photo figcaption a { color: inherit; }
.photo figcaption a:hover { color: var(--accent); }
/* Answer pages keep the answer above the image. The shared photo component
 * retains the credit on route pictures; a shallow crop prevents decoration
 * from pushing the next useful action too far down on a phone. */
.answer-photo img { height: 210px; object-fit: cover; }
.answer-jump + .answer-photo { margin-top: 0; }
@media(max-width:600px){.answer-photo img{height:150px}}
/* Directory art stays shallow so the dated observation table remains the main
 * reason to visit, including on a narrow phone screen. */
.directory-photo img { height: 180px; object-fit: cover; }
@media(max-width:600px){.directory-photo img{height:130px}}

.figures {
  display: grid; gap: 1px; background: var(--line);
  grid-template-columns: repeat(auto-fit, minmax(132px, 1fr));
  border: 1px solid var(--line); border-radius: 10px; overflow: hidden;
  margin: 26px 0 8px; box-shadow: var(--shadow);
}
.fig { background: var(--bg-panel); padding: 15px 16px 13px; }
.fig-link { color: inherit; text-decoration: none; }
.fig-link:hover, .fig-link:focus-visible { background: var(--bg-raised); }
.fig b {
  display: block; font-family: var(--mono);
  font-size: 23px; font-weight: 500; letter-spacing: -.02em;
  font-variant-numeric: tabular-nums;
}
.fig span {
  display: block; margin-top: 4px; font-size: 11px; letter-spacing: .1em;
  text-transform: uppercase; color: var(--text-faint);
}

/* ---------------------------------------------------------------- table */
.scroll {
  overflow-x: auto; margin: 18px 0 10px; border: 1px solid var(--line);
  border-radius: 8px; background-color: var(--bg-panel); box-shadow: var(--shadow);
  /* Scrolled by keyboard as well as finger. Without this a table wider than
     the screen is reachable only by dragging it, which leaves the numbers on
     the right unreadable to anybody not using a mouse or a touchscreen. */
  scrollbar-width: thin;

  /* A shadow at whichever edge has more behind it, and at neither when there
     is nothing to scroll to.
     Four layers: two the colour of the panel that scroll WITH the content and
     so slide over the shadows when you reach an end, and two shadows fixed to
     the container. On a phone the destinations table is 511px inside 343, and
     it gave no sign of it at all - no fade, no shadow, and a 2px scrollbar -
     so a reader saw "168 destinations observed" above a table whose count
     column was off the screen edge, and nothing to suggest it was there. */
  background-image:
    linear-gradient(to right, var(--bg-panel) 30%, var(--bg-panel-fade)),
    linear-gradient(to left,  var(--bg-panel) 30%, var(--bg-panel-fade)),
    linear-gradient(to right, rgba(0, 0, 0, .17), rgba(0, 0, 0, 0)),
    linear-gradient(to left,  rgba(0, 0, 0, .17), rgba(0, 0, 0, 0));
  background-position: 0 0, 100% 0, 0 0, 100% 0;
  background-repeat: no-repeat;
  background-size: 34px 100%, 34px 100%, 13px 100%, 13px 100%;
  background-attachment: local, local, scroll, scroll;
}
.scroll:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
table { border-collapse: collapse; width: 100%; font-size: 14.5px; }
th, td { text-align: left; padding: 9px 14px; border-bottom: 1px solid var(--line); }
/* The way into the live map, from the page a visitor actually landed on. */
.live-now { margin: 10px 0 0; }
.live-now a {
  display: inline-block;
  padding: 7px 13px;
  border: 1px solid var(--accent);
  border-radius: 8px;
  color: var(--accent);
  text-decoration: none;
  font-size: 14px;
}
.live-now a:hover, .live-now a:focus-visible {
  background: var(--bg-raised);
  text-decoration: underline;
}

/* Where a carrier has no name anybody checked. Set apart from the names it
   sits among, so it reads as an admission rather than as a very short airline. */
.unnamed { color: var(--text-faint); font-style: italic; }

thead th {
  font-family: var(--mono);
  font-size: 10.5px; letter-spacing: .1em; text-transform: uppercase;
  color: var(--text-faint); font-weight: 500; background: var(--bg-raised);
  border-bottom: 1px solid var(--line-strong); white-space: nowrap;
}
tbody tr:last-child td { border-bottom: 0; }
td.n, th.n {
  text-align: right; font-family: var(--mono);
  font-variant-numeric: tabular-nums; white-space: nowrap;
}
td.code {
  font-family: var(--mono);
  font-weight: 500;
}
.carriers { color: var(--text-faint); font-size: 13px; }

/* A row resting on one sighting is evidence of almost nothing, and a table
   padded with them is the visual signature of a generated page. They are kept
   - removing them would be its own kind of dishonesty - but marked, and the
   count is stated above the table so nobody has to infer it. */
tr.once td { color: var(--text-faint); }
.once-tag {
  font-family: var(--mono);
  font-size: 10px; letter-spacing: .06em; text-transform: uppercase;
  color: var(--amber); margin-left: 8px;
}

/* ----------------------------------------------------------------- note */
.note {
  border: 1px solid var(--line); border-left: 3px solid var(--accent);
  background: var(--bg-panel); border-radius: 6px; padding: 15px 18px;
  margin: 26px 0; font-size: 15px;
}
.note p:last-child { margin-bottom: 0; }
.note strong { color: var(--text); }

footer {
  margin-top: 64px; padding-top: 22px; border-top: 1px solid var(--line);
  font-size: 13.5px; color: var(--text-faint);
}
footer a { color: var(--text-faint); }

@media (max-width: 600px) {
  body { font-size: 16px; padding: 0 15px 56px; }
  th, td { padding: 8px 9px; }
  table { font-size: 13.5px; }

  /* The second column is the place name in every table that has one - City on
     an airport page, Where on the index, Between on a carrier's routes - and
     it was taking 220 of the 343 pixels available, two thirds of the screen
     for "Los Angeles, United States". Capped, it wraps onto a second line and
     the counts the page is actually about come back into view. Tables whose
     second column is a code are already narrower than this and are untouched. */
  .scroll td:nth-child(2) { max-width: 116px; }
  .scroll td.carriers { max-width: 96px; }
}
/* Search visitors can open today's board before reading historical tables. */
.landing-actions{display:flex;flex-wrap:wrap;gap:10px;margin:20px 0 12px}
.landing-actions a{display:inline-block;padding:11px 16px;border:1px solid var(--accent);border-radius:8px;background:var(--bg-panel);color:var(--accent);text-decoration:none;font-weight:600}
.landing-actions a:hover,.landing-actions a:focus-visible{background:var(--bg-raised);outline:2px solid var(--accent);outline-offset:2px}
@media(max-width:600px){.landing-actions a{flex:1;text-align:center;min-width:120px}}
/* Flight answers sit above historical context. Search visitors asked about
   today's journey, so the request button is not buried after an archive table. */
.answer-kicker{color:var(--accent);font:600 12px var(--mono);letter-spacing:.1em;text-transform:uppercase;margin:0 0 10px}
.answer-card{border:1px solid var(--line-strong);background:var(--bg-panel);border-radius:14px;box-shadow:var(--shadow);padding:22px;margin:28px 0 12px}
.answer-card h2{margin:0 0 8px}
.answer-card p{color:var(--text-dim)}
/* This pilot puts the useful published route and the honest unchecked state
   ahead of the request. A quiet route label keeps it distinct from live data. */
.answer-card-first{margin-top:20px}
.answer-card-first .answer-route{padding:14px 0;border-block:1px solid var(--line)}
.answer-route span{display:block;font:500 12px var(--mono);letter-spacing:.07em;text-transform:uppercase;color:var(--text-faint)}
.answer-route strong{display:block;margin:4px 0;color:var(--text);font-size:clamp(18px,3vw,24px);line-height:1.3}
.answer-route small{font:500 .65em var(--mono);color:var(--accent)}
.answer-route p{margin:0;font-size:13px}
.answer-card-first .answer-summary{margin:16px 0 6px;color:var(--text);font-weight:600}
.answer-card-first .answer-explainer{margin-bottom:16px}
.answer-button{appearance:none;border:1px solid var(--accent);background:var(--accent);color:var(--bg-panel);border-radius:8px;padding:12px 18px;font:600 15px var(--sans);cursor:pointer}
.answer-button:hover,.answer-button:focus-visible{outline:2px solid var(--accent);outline-offset:3px}
.answer-button:disabled{opacity:.6;cursor:wait}
.answer-result{margin-top:18px}
.answer-result:empty{display:none}
.answer-flight{border-top:1px solid var(--line);padding:16px 0 2px}
.answer-flight h3{margin:0 0 8px;font:600 18px var(--mono)}
.answer-flight p{margin:2px 0}
.answer-source,.answer-related{color:var(--text-faint);font-size:14px}
@media(max-width:600px){.answer-card{padding:18px}.answer-button{width:100%}}
/* The historical route count is useful even before a paid board request.
   Give it its own quiet panel so nobody mistakes it for today's status. */
.answer-evidence{border:1px solid var(--line);background:var(--bg-panel);border-radius:12px;padding:18px 20px;margin:18px 0}
.answer-evidence h2{font-size:18px;margin:0 0 8px}
.answer-evidence p{color:var(--text-dim);margin:0 0 8px}
.answer-evidence p:last-child{margin-bottom:0}
.answer-evidence strong{color:var(--text)}
/* The browse page was a long bullet list with tiny tap targets. Each target
   now carries both the code and the place or carrier without inventing data. */
.answer-index{list-style:none;display:grid;grid-template-columns:repeat(auto-fit,minmax(190px,1fr));gap:10px;padding:0;margin:14px 0 30px}
.answer-index li{min-width:0}
.answer-index a{display:flex;flex-direction:column;min-height:72px;padding:12px 14px;border:1px solid var(--line);border-radius:10px;background:var(--bg-panel);text-decoration:none}
.answer-index a:hover,.answer-index a:focus-visible{border-color:var(--accent);background:var(--bg-raised)}
.answer-index strong{font:600 16px var(--mono);color:var(--text)}
.answer-index span{font-size:13px;color:var(--text-dim)}
/* The directory has two kinds of answers. Keep the choice visible before the
   card grid, especially on a phone where the second group is below the fold. */
.answer-jump{display:flex;flex-wrap:wrap;gap:10px;margin:0 0 28px}
.answer-jump a{display:inline-block;padding:10px 14px;border:1px solid var(--line);border-radius:8px;background:var(--bg-panel);color:var(--accent);text-decoration:none;font-weight:600}
.answer-jump a:hover,.answer-jump a:focus-visible{border-color:var(--accent);background:var(--bg-raised)}
@media(max-width:600px){
  .answer-evidence{padding:16px}
  .answer-index{grid-template-columns:repeat(2,minmax(0,1fr));gap:8px}
  .answer-index a{padding:10px;min-height:80px}
  /* Three equal buttons produced three narrow columns of wrapped words on a
     phone. Keep the main map action full width and the other choices in pairs. */
  .answer-page .landing-actions{display:grid;grid-template-columns:repeat(2,minmax(0,1fr))}
  .answer-page .landing-actions a{min-width:0}
  .answer-page .landing-actions a:first-child{grid-column:1/-1}
}
/* The owner requested uniform 80 percent sizing at normal browser zoom. CSS zoom also scales layout and fixed controls, while a transform would leave their original space behind. */
html{zoom:.8}
