/* ===== Tokens ===== */
:root {
  --bg: #10141a;
  --panel: #171d26;
  --panel-raised: #1c2330;
  --border: #2a323f;
  --text: #e7ecf2;
  /* One step above --text, for the state that should read as lit rather than
     merely legible. Only hover uses it, so it stays a highlight. */
  --text-bright: #ffffff;
  --text-dim: #8993a4;
  --text-faint: #5b6472;
  --amber: #e8a33d;
  --amber-dim: #b9822f;
  --amber-glow: rgba(232, 163, 61, 0.35);
  --green: #4fae7c;
  --red: #e2574c;

  --font-display: 'IBM Plex Sans Condensed', sans-serif;
  --font-body: 'Inter', sans-serif;
  --font-mono: 'IBM Plex Mono', monospace;
}

* { box-sizing: border-box; }

html, body {
  margin: 0;
  padding: 0;
  background: var(--bg);
  color: var(--text);
  font-family: var(--font-body);
  -webkit-font-smoothing: antialiased;
}

::selection { background: var(--amber-glow); }

/* ===== Top bar ===== */
.topbar {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 18px 28px;
  border-bottom: 1px solid var(--border);
  background: linear-gradient(180deg, #131822 0%, var(--bg) 100%);
  flex-wrap: wrap;
  gap: 12px;
}

.topbar__brand { display: flex; align-items: center; gap: 14px; }

.topbar__mark {
  font-family: var(--font-mono);
  font-weight: 600;
  font-size: 22px;
  color: var(--amber);
  border: 1px solid var(--amber-dim);
  width: 40px;
  height: 40px;
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: 4px;
  flex-shrink: 0;
}

.topbar__titles h1 {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 19px;
  letter-spacing: 0.02em;
  margin: 0;
  text-transform: uppercase;
}

.topbar__titles p {
  margin: 2px 0 0;
  font-size: 12.5px;
  color: var(--text-dim);
}

/* Wrapping at every width, not only at a breakpoint: the nav grows with the
   role (a regional officer carries eleven links, 981px of them), so the width
   at which it stops fitting depends on who is signed in, not on a number
   chosen here. A 1085px laptop was scrolling sideways. */
.topbar__status { display: flex; align-items: center; gap: 18px; flex-wrap: wrap; }

.clock { display: flex; align-items: baseline; gap: 6px; font-family: var(--font-mono); }
.clock__label { font-size: 11px; color: var(--text-faint); letter-spacing: 0.1em; }
.clock__time { font-size: 16px; color: var(--amber); font-variant-numeric: tabular-nums; }

.badge {
  font-family: var(--font-display);
  font-size: 12px;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  padding: 6px 12px;
  border-radius: 3px;
  border: 1px solid var(--border);
  color: var(--text-dim);
}
.badge[data-state="valid"] { color: var(--green); border-color: var(--green); }
.badge[data-state="invalid"] { color: var(--red); border-color: var(--red); }
.badge[data-state="pending"] { color: var(--text-dim); }

/* ===== Layout ===== */
.layout {
  display: grid;
  grid-template-columns: minmax(0, 1.15fr) minmax(340px, 0.85fr);
  gap: 20px;
  padding: 24px 28px 60px;
  align-items: start;
  max-width: 1400px;
  margin: 0 auto;
}

@media (max-width: 980px) {
  .layout { grid-template-columns: 1fr; }
}

.panel {
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: 6px;
}

.form-panel { padding: 22px 24px; display: flex; flex-direction: column; gap: 22px; }

.preview-panel {
  position: sticky;
  top: 20px;
  padding: 20px;
  display: flex;
  flex-direction: column;
  gap: 16px;
  max-height: calc(100vh - 40px);
  overflow-y: auto;
}

/* ===== Cards / sections ===== */
.card { display: flex; flex-direction: column; gap: 14px; }

.card h2 {
  font-family: var(--font-display);
  font-size: 14px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  margin: 0;
  padding-bottom: 10px;
  /* currentColor, not a literal, so the rule under a section title always
     matches the title above it. Same 1px weight as before. */
  border-bottom: 1px solid currentColor;
  color: var(--text);
  display: flex;
  align-items: center;
  gap: 10px;
}

.eyebrow {
  font-family: var(--font-mono);
  color: var(--amber);
  font-size: 12px;
}

/* ===== Form fields ===== */
.grid { display: grid; gap: 14px; }
.grid--1 { grid-template-columns: 1fr; }
.grid--2 { grid-template-columns: 1fr 1fr; }
.grid--3 { grid-template-columns: 1fr 1fr 1fr; }
.grid--4 { grid-template-columns: 1fr 1fr 1fr 1fr; }
@media (max-width: 620px) {
  .grid--2, .grid--3, .grid--4 { grid-template-columns: 1fr 1fr; }
}

/* Item 01 identification. A series is one character and a year is two, so an
   equal quarter each starves the two fields that carry real text: the message
   type, whose longest option is "Replace (NOTAMR)", and the number, which in
   the regional console shows the auto-assignment preview
   ("C0143/26 — Auto-assigned if left blank"). Series and year get exactly
   what they need and the width goes where it is read. */
/* 180px is what the longest option ("Replace (NOTAMR)") needs including its
   dropdown arrow; the number field then takes everything left over, because it
   is the one carrying a sentence. */
.identification-row { grid-template-columns: 180px 66px minmax(0, 1fr) 66px; }
@media (max-width: 820px) {
  /* Two rows rather than a truncated one: type + series, then number + year. */
  .identification-row { grid-template-columns: minmax(0, 1fr) 66px; }
}

.field { display: flex; flex-direction: column; gap: 6px; font-size: 13px; }
.field span { color: var(--text-dim); font-size: 12px; }
.field--sm { min-width: 0; }

/* A field whose value failed a hard validation rule (build_notam error). */
.field--invalid > span,
.field--invalid > label { color: var(--red); }
.field--invalid input[type="text"],
.field--invalid input[type="datetime-local"],
.field--invalid select,
.field--invalid textarea { border-color: var(--red); }
.field--invalid.checkgroup,
#schedule-mode-toggle.field--invalid,
#schedule-blocks.field--invalid,
#schedule-monthly-blocks.field--invalid {
  outline: 1px solid var(--red);
  outline-offset: 3px;
  border-radius: 4px;
}

input[type="text"], input[type="datetime-local"], input[type="email"],
input[type="password"], input[type="search"], select, textarea {
  background: var(--panel-raised);
  border: 1px solid var(--border);
  color: var(--text);
  padding: 9px 10px;
  border-radius: 4px;
  font-family: var(--font-mono);
  font-size: 13.5px;
  width: 100%;
}

/* The browser draws the calendar button of a datetime-local input as a dark
   glyph, which on this panel is all but invisible. Invert it so it reads at
   the same weight as the date and time beside it. */
input[type="datetime-local"]::-webkit-calendar-picker-indicator {
  filter: invert(1);
  opacity: 0.85;
  cursor: pointer;
}
input[type="datetime-local"]::-webkit-calendar-picker-indicator:hover { opacity: 1; }

textarea { resize: vertical; line-height: 1.5; }

input:focus, select:focus, textarea:focus, button:focus-visible {
  outline: 2px solid var(--amber);
  outline-offset: 1px;
  border-color: var(--amber);
}

select optgroup { font-family: var(--font-body); color: var(--text-dim); }
select option { font-family: var(--font-mono); color: var(--text); background: var(--panel-raised); }

.checkline { display: flex; align-items: center; gap: 8px; font-size: 13px; color: var(--text-dim); }
.checkline input { accent-color: var(--amber); }

.checkgroup { display: flex; gap: 4px; }
.checkgroup__item {
  display: flex; align-items: center; gap: 4px;
  font-family: var(--font-mono); font-size: 12.5px;
  background: var(--panel-raised); border: 1px solid var(--border);
  padding: 7px 9px; border-radius: 4px; cursor: pointer;
}
.checkgroup__item input { accent-color: var(--amber); }

/* ===== Quick picks ===== */
#quickpick-category { margin: 6px 0 8px; max-width: 100%; }
.quickpicks { display: flex; flex-wrap: wrap; gap: 6px; }
.quickpicks--scroll {
  max-height: 160px;
  overflow-y: auto;
  padding: 8px;
  border: 1px solid var(--border);
  border-radius: 4px;
  background: var(--panel-raised);
}
.quickpicks__group { display: flex; flex-wrap: wrap; gap: 6px; }
.quickpicks__group[hidden] { display: none; }
.chip {
  background: var(--panel-raised);
  border: 1px solid var(--border);
  color: var(--text-dim);
  font-family: var(--font-body);
  font-size: 12px;
  padding: 6px 10px;
  border-radius: 999px;
  cursor: pointer;
  transition: border-color .15s, color .15s;
}
.chip:hover { border-color: var(--amber-dim); color: var(--text); }
.chip.active { border-color: var(--amber); color: var(--amber); }

/* ===== Tabs ===== */
.tabs { display: flex; gap: 4px; border-bottom: 1px solid var(--border); }
.tab {
  background: none; border: none; color: var(--text-dim);
  font-family: var(--font-display); font-size: 13px; text-transform: uppercase;
  letter-spacing: 0.04em; padding: 8px 4px; cursor: pointer;
  border-bottom: 2px solid transparent;
}
.tab.active { color: var(--amber); border-bottom-color: var(--amber); }

/* ===== Teleprinter tape (signature element) ===== */
.tape {
  background: #0c0f14;
  border: 1px solid var(--border);
  border-radius: 4px;
  position: relative;
  overflow: hidden;
  flex-shrink: 0;
}
.tape::before, .tape::after {
  content: "";
  display: block;
  height: 8px;
  background-image: radial-gradient(circle, var(--bg) 2px, transparent 2.2px);
  background-size: 14px 8px;
  background-position: 4px center;
}
/* Item E) templates: chips that carry text, and the surrounding controls. */
.chip--template { border-style: dashed; }
.chip--template.active { border-style: solid; }
.quickpicks__mode {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 12px;
  margin: 6px 0 4px;
  font-size: 12px;
  color: var(--text-dim);
}
.quickpicks__mode label { display: inline-flex; align-items: center; gap: 4px; cursor: pointer; }
.quickpicks__mode-label { font-weight: 600; }
.quickpicks__hint {
  margin: 6px 0 0;
  padding: 6px 8px;
  border-left: 2px solid var(--amber-dim);
  font-size: 12px;
  line-height: 1.45;
  color: var(--text-dim);
}
.quickpicks__empty { margin: 4px; font-size: 12px; color: var(--text-dim); }
/* A heading inside the unit's own models, which are one flat list otherwise.
   Full width so the chips under it start a new row — the group is a wrapping
   flex row, and a heading that shares a line with chips groups nothing. */
.quickpicks__category {
  flex: 0 0 100%;
  margin: 8px 0 2px;
  font-family: var(--font-display);
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--text-dim);
}
.quickpicks__category:first-child { margin-top: 0; }
.item-e-actions {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px;
  margin: -4px 0 12px;
}
.item-e-actions__note { font-size: 12px; color: var(--text-dim); }
#item_e_text { font-family: var(--font-mono); text-transform: uppercase; }
.template-row {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 12px;
  padding: 10px 12px;
  border-bottom: 1px solid var(--border);
}
.template-row__text {
  margin: 4px 0 2px;
  white-space: pre-wrap;
  font-size: 12px;
  color: var(--text-dim);
}
.template-row__by { font-size: 11px; color: var(--text-dim); }
.template-row__actions { display: flex; gap: 6px; flex-shrink: 0; }
.modal__error { margin: 8px 12px 0; color: var(--red); font-size: 12.5px; }

/* Day + optional month, side by side in one schedule-block cell. */
.block-date-pair { display: flex; gap: 4px; }
.block-date-pair input { flex: 1 1 auto; min-width: 0; }
.block-date-pair select { flex: 0 0 5.2em; padding: 9px 4px; font-size: 12px; }

/* Estimated-NOTAM expiry urgency: 72 h = yellow, 24 h = red. */
.tape--yellow { border-color: var(--amber-dim); }
.tape--red { border-color: var(--red); }
/* Published but not yet in force (future item B) start). */
.tape--pending { border-style: dashed; opacity: 0.85; }
/* Recorded as issued outside this app — never produced or validated here, so
   it must not read like the published tapes above it. */
.tape--external { border-style: dotted; }
.tape--external .tape__header { color: var(--text-dim); }
.tape__tag {
  display: inline-block;
  padding: 1px 6px;
  border-radius: 3px;
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 0.04em;
  background: var(--amber-dim);
  color: #fff;
  vertical-align: middle;
}
[data-urgency="yellow"] { color: var(--amber); }
[data-urgency="red"] { color: var(--red); }
#estimated-notams-btn[data-urgency="yellow"] { color: var(--amber); font-weight: 600; }
#estimated-notams-btn[data-urgency="red"] { color: var(--red); font-weight: 600; }
#perm-notams-btn[data-urgency="yellow"] { color: var(--amber); font-weight: 600; }
/* Which AIS units have confirmed the current AIRAC PERM check, for the
   regional view — one line each, colour carried by [data-urgency] above. */
.plain-list { list-style: none; margin: 6px 0 0; padding: 0; font-size: 13px; }
.plain-list li { padding: 3px 0; border-bottom: 1px solid var(--border); }
.plain-list li:last-child { border-bottom: 0; }
.est-alert {
  padding: 8px 12px;
  border-radius: 4px;
  font-size: 13px;
  font-weight: 600;
  border: 1px solid var(--border);
}
.est-alert[data-urgency="yellow"] { color: var(--amber); border-color: var(--amber-dim); background: rgba(232, 163, 61, 0.08); }
.est-alert[data-urgency="red"] { color: var(--red); border-color: var(--red); background: rgba(226, 87, 76, 0.08); }
.tape__header {
  display: flex;
  justify-content: space-between;
  padding: 6px 16px;
  font-family: var(--font-mono);
  font-size: 11px;
  color: var(--text-faint);
  letter-spacing: 0.1em;
  border-bottom: 1px dashed var(--border);
}
.tape__body {
  margin: 0;
  padding: 16px;
  font-family: var(--font-mono);
  font-size: 13px;
  line-height: 1.7;
  color: var(--amber);
  text-shadow: 0 0 10px var(--amber-glow);
  white-space: pre-wrap;
  word-break: break-word;
  min-height: 140px;
}

.plain-output {
  font-size: 14px;
  line-height: 1.65;
  color: var(--text);
  background: var(--panel-raised);
  border: 1px solid var(--border);
  border-radius: 4px;
  padding: 16px;
  min-height: 140px;
}

/* ===== Actions / issues ===== */
/* Wraps for the same reason the nav does: four buttons in a row need 327px,
   and Download .txt was hanging off the edge of a 320px screen. */
.actions { display: flex; gap: 10px; flex-wrap: wrap; }
.btn {
  flex: 1;
  background: var(--panel-raised);
  border: 1px solid var(--border);
  color: var(--text);
  font-family: var(--font-display);
  font-size: 13px;
  text-transform: uppercase;
  letter-spacing: 0.03em;
  padding: 10px 12px;
  border-radius: 4px;
  cursor: pointer;
  transition: border-color .15s;
}
.btn:hover { border-color: var(--amber-dim); }
.btn--primary { background: var(--amber); color: #1a1300; border-color: var(--amber); font-weight: 600; }
.btn--primary:hover { background: var(--amber-dim); }

.issues { display: flex; flex-direction: column; gap: 6px; }
.issue {
  font-size: 12.5px;
  padding: 8px 10px;
  border-radius: 4px;
  border-left: 3px solid var(--border);
  background: var(--panel-raised);
  color: var(--text-dim);
}
.issue--error { border-left-color: var(--red); color: #f2b3ae; }
.issue--ok { border-left-color: var(--green); color: #a9dcc0; }
.issue--warning { border-left-color: var(--amber); color: #f0d3a4; }
.issue strong { color: var(--text); font-family: var(--font-mono); text-transform: uppercase; font-size: 11px; }

.disclaimer {
  font-size: 11.5px;
  color: var(--text-faint);
  line-height: 1.5;
  border-top: 1px solid var(--border);
  padding-top: 12px;
  margin: 0;
}

.app-footer {
  text-align: center;
  font-size: 11px;
  color: var(--text-faint);
  padding: 16px 12px 24px;
  margin: 0;
}
/* The standards the checks are written against, above the attribution: it is a
   claim about the software rather than about its author, so it reads as its
   own line. */
.app-footer__compliance {
  display: block;
  color: var(--text-dim);
  margin-bottom: 4px;
}

/* ===== Auth pages ===== */
.auth-body {
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: 100vh;
  padding: 24px;
}
.auth-card {
  width: 100%;
  max-width: 400px;
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: 6px;
  padding: 28px 26px;
  display: flex;
  flex-direction: column;
  gap: 18px;
}
/* The registration form asks for more than a username and password, so it gets
   a little more room than the sign-in card. */
.auth-card--wide { max-width: 520px; }
.auth-brand { margin-bottom: 4px; }
.auth-form { display: flex; flex-direction: column; gap: 14px; }
.auth-submit { width: 100%; margin-top: 4px; }
.auth-switch { font-size: 13px; color: var(--text-dim); text-align: center; margin: 0; }
.auth-switch a { color: var(--amber); text-decoration: none; }
.auth-switch a:hover { text-decoration: underline; }
.auth-error { margin: 0; }

/* ===== Officer menu ===== */
.officer-menu {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 10px;
  font-size: 13px;
  color: var(--text-dim);
}
.officer-menu strong { color: var(--text); }
.officer-menu a {
  color: var(--text);
  text-decoration: none;
  border: 1px solid var(--border);
  padding: 6px 10px;
  border-radius: 4px;
  font-family: var(--font-display);
  font-size: 12px;
  text-transform: uppercase;
  letter-spacing: 0.03em;
}
.officer-menu a:hover { border-color: var(--amber-dim); color: var(--text-bright); }

/* A tab holding work that is waiting on this officer. Red and outlined so the
   count is visible across the nav without opening anything; the title
   attribute carries the "N actions needed" tooltip. */
.officer-menu a[data-actions="true"] {
  color: var(--red);
  border-color: var(--red);
  font-weight: 600;
}
.officer-menu a[data-actions="true"]:hover {
  color: var(--red);
  border-color: var(--red);
  background: rgba(226, 87, 76, 0.12);
}
/* Estimated NOTAM checks additionally distinguishes 72 h from 24 h, so its own
   urgency shade wins over the flat red above. */
.officer-menu a#estimated-notams-btn[data-urgency="yellow"],
.officer-menu a#perm-notams-btn[data-urgency="yellow"] {
  color: var(--amber);
  border-color: var(--amber-dim);
}

/* ===== Drafts modal ===== */
.modal-overlay {
  position: fixed;
  inset: 0;
  background: rgba(6, 8, 12, 0.72);
  display: flex;
  align-items: flex-start;
  justify-content: center;
  /* Modest padding so the dialog can use nearly the whole viewport; the
     overlay scrolls as a last resort on very short screens. */
  padding: 24px 16px;
  overflow-y: auto;
  z-index: 50;
}
.modal-overlay[hidden] { display: none; }
.modal {
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: 6px;
  width: 100%;
  max-width: 680px;
  /* The dialog itself is the scroll container. It used to be a fixed-height
     flex column with overflow:hidden and no minimum on its sections, so a
     dialog carrying several of them (a list, a second list, a form) squeezed
     each one toward nothing and clipped the rest out of reach entirely. */
  max-height: calc(100vh - 48px);
  display: flex;
  flex-direction: column;
  overflow-y: auto;
  overscroll-behavior: contain;
}
.modal--wide { max-width: 900px; }
/* The heading and its close button stay put while the body scrolls under them. */
.modal__header {
  position: sticky;
  top: 0;
  z-index: 3;
  background: var(--panel);
}

/* ===== Archived NOTAMs ===== */
/* Wider and taller than the other modals: it carries filters, statistics,
   charts and a two-pane browser rather than a single list. */
.modal--tall { max-width: 1280px; }
.archive__filters {
  display: grid;
  grid-template-columns: 2fr 1fr 1fr 1fr;
  gap: 8px;
  padding: 0 12px 8px;
  align-items: end;
}
.archive__quick { grid-column: 1 / -1; display: flex; gap: 6px; flex-wrap: wrap; }
.archive__quick .btn.is-active,
.archive__period-row .btn.is-active { border-color: var(--amber-dim); color: var(--amber); }

.archive__stats {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  padding: 0 12px 10px;
}
.archive__stat {
  flex: 1 1 108px;
  border: 1px solid var(--border);
  border-radius: 4px;
  padding: 6px 10px;
  background: var(--panel-raised);
}
.archive__stat b { display: block; font-size: 20px; font-family: var(--font-display); }
.archive__stat span { font-size: 11px; color: var(--text-dim); text-transform: uppercase; letter-spacing: .04em; }

.archive__charts {
  display: grid;
  grid-template-columns: 1.6fr 1fr;
  gap: 12px;
  padding: 0 12px 10px;
}
.archive__chart {
  border: 1px solid var(--border);
  border-radius: 4px;
  padding: 8px 10px;
  background: var(--panel-raised);
  min-width: 0;
}
.archive__chart h4 { margin: 0 0 6px; font-size: 12px; color: var(--text-dim); font-weight: 600; }
.archive__period-row { display: flex; gap: 4px; flex-wrap: wrap; margin-bottom: 6px; }
.archive__chart svg { display: block; width: 100%; height: auto; }
.archive__chart .chart-empty { font-size: 12px; color: var(--text-faint); }

/* Horizontal bars for the categorical breakdowns. */
.chart-bars { display: flex; flex-direction: column; gap: 4px; }
.chart-bar { display: grid; grid-template-columns: 92px 1fr 28px; gap: 6px; align-items: center; font-size: 12px; }
.chart-bar__label { color: var(--text-dim); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.chart-bar__track { background: var(--bg); border-radius: 2px; height: 12px; overflow: hidden; }
.chart-bar__fill { background: var(--amber-dim); height: 100%; }
.chart-bar__value { text-align: right; font-family: var(--font-mono); font-size: 11px; }

.archive__panes {
  display: grid;
  grid-template-columns: 340px 1fr;
  gap: 12px;
  padding: 0 12px 12px;
  /* Not a flex child competing for leftover height — the dialog scrolls, so
     these panes keep a usable size instead of collapsing under the filters,
     statistics and charts stacked above them. */
  flex: 0 0 auto;
}
.archive__list, .archive__detail {
  border: 1px solid var(--border);
  border-radius: 4px;
  overflow-y: auto;
  background: var(--panel-raised);
  /* Side by side, each pane scrolls on its own: the record on the right must
     stay readable however long the list on the left grows. */
  min-height: 300px;
  max-height: 52vh;
}
.archive__item {
  padding: 7px 10px;
  border-bottom: 1px solid var(--border);
  cursor: pointer;
  font-size: 12px;
}
.archive__item:hover { background: var(--panel); }
.archive__item.is-selected { background: var(--panel); border-left: 2px solid var(--amber); }
.archive__item b { font-family: var(--font-mono); font-size: 12px; }
.archive__item span { display: block; color: var(--text-dim); font-size: 11px; margin-top: 2px; }
.archive__detail { padding: 10px 12px; }
.archive__detail dl { display: grid; grid-template-columns: auto 1fr; gap: 3px 10px; margin: 0 0 10px; font-size: 12px; }
.archive__detail dt { color: var(--text-dim); }
.archive__detail dd { margin: 0; }
.archive__detail pre {
  font-family: var(--font-mono);
  font-size: 12px;
  white-space: pre-wrap;
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: 3px;
  padding: 8px;
  margin: 0;
}
/* Purging destroys published records, so it sits apart from everything else in
   the tab and is styled to look like what it is. */
.archive__purge {
  margin: 0 12px 12px;
  border: 1px solid var(--red);
  border-radius: 4px;
  padding: 8px 10px;
  background: rgba(226, 87, 76, 0.06);
}
.archive__purge h4 { margin: 0 0 4px; font-size: 12px; color: var(--red); font-weight: 600; }
.archive__purge-row { display: flex; gap: 8px; align-items: end; flex-wrap: wrap; }
.archive__purge-row .field { flex: 0 1 170px; }
.archive__purge-msg { font-size: 12px; margin: 8px 0 0; }
.archive__purge-msg[data-state="blocked"] { color: var(--red); }
.archive__purge-msg[data-state="ready"] { color: var(--amber); }
.archive__purge-msg[data-state="done"] { color: var(--green); }
#purge-confirm-row { display: flex; gap: 8px; align-items: end; margin-top: 8px; }
#purge-confirm-row .field { flex: 0 1 200px; }

/* --- Posteriori checks -------------------------------------------------- */
.posteriori__toolbar {
  display: flex;
  gap: 12px;
  align-items: center;
  justify-content: space-between;
  flex-wrap: wrap;
  padding: 0 12px 8px;
}
.posteriori__stats { display: flex; gap: 8px; flex-wrap: wrap; }
.posteriori__stat {
  border: 1px solid var(--border);
  border-radius: 4px;
  padding: 4px 10px;
  background: var(--panel-raised);
  min-width: 74px;
}
.posteriori__stat b { display: block; font-size: 18px; font-family: var(--font-display); }
.posteriori__stat span { font-size: 10px; color: var(--text-dim); text-transform: uppercase; letter-spacing: .04em; }
.posteriori__stat[data-tone="nc"] b { color: var(--red); }
.posteriori__stat[data-tone="c"] b { color: var(--green); }
.posteriori__stat[data-tone="warn"] b { color: var(--amber); }
.posteriori__filters { display: flex; gap: 8px; }
.posteriori__filters input { min-width: 240px; }

.posteriori__panes {
  display: grid;
  grid-template-columns: 320px 1fr;
  gap: 12px;
  padding: 0 12px 12px;
  /* Same reasoning as .archive__panes: the dialog is the scroll container, so
     these must not shrink to nothing under the toolbar above them. */
  flex: 0 0 auto;
}
.posteriori__list, .posteriori__detail {
  border: 1px solid var(--border);
  border-radius: 4px;
  overflow-y: auto;
  background: var(--panel-raised);
  min-height: 320px;
  max-height: 62vh;
}
.posteriori__detail { padding: 10px 12px; }
.posteriori__item {
  padding: 7px 10px;
  border-bottom: 1px solid var(--border);
  cursor: pointer;
  font-size: 12px;
}
.posteriori__item:hover { background: var(--panel); }
.posteriori__item.is-selected { background: var(--panel); border-left: 2px solid var(--amber); }
.posteriori__item b { font-family: var(--font-mono); font-size: 12px; }
.posteriori__item span { display: block; color: var(--text-dim); font-size: 11px; margin-top: 2px; }

/* The verdict pill: the one thing a reader scanning the list is looking for. */
.pmark {
  display: inline-block;
  font-family: var(--font-mono);
  font-size: 10px;
  font-weight: 700;
  border-radius: 3px;
  padding: 1px 5px;
  border: 1px solid;
}
.pmark[data-verdict="C"] { color: var(--green); border-color: var(--green); }
.pmark[data-verdict="NC"] { color: var(--red); border-color: var(--red); background: rgba(226, 87, 76, 0.08); }
.pmark[data-verdict="ASSIGNED"] { color: var(--amber); border-color: var(--amber-dim); }
.pmark[data-verdict="NONE"] { color: var(--text-faint); border-color: var(--border); }

/* Side-by-side tapes. Each scrolls horizontally on its own rather than
   letting a long item E) widen the whole dialog. */
.posteriori__versions { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; margin-bottom: 12px; }
.posteriori__version h4 {
  margin: 0 0 4px;
  font-size: 11px;
  color: var(--text-dim);
  text-transform: uppercase;
  letter-spacing: .04em;
  font-weight: 600;
}
.posteriori__version pre {
  font-family: var(--font-mono);
  font-size: 11.5px;
  white-space: pre-wrap;
  overflow-x: auto;
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: 3px;
  padding: 8px;
  margin: 0;
}
.posteriori__version--published pre { border-color: var(--amber-dim); }

.posteriori__table { width: 100%; border-collapse: collapse; font-size: 11.5px; }
.posteriori__table th {
  text-align: left;
  font-size: 10px;
  text-transform: uppercase;
  letter-spacing: .04em;
  color: var(--text-dim);
  border-bottom: 1px solid var(--border);
  padding: 4px 6px;
}
.posteriori__table td { padding: 4px 6px; border-bottom: 1px solid var(--border); vertical-align: top; }
.posteriori__table td.is-value { font-family: var(--font-mono); word-break: break-word; }
.posteriori__table tr.is-nc td.is-value.is-changed { color: var(--red); }
.posteriori__table td.is-mark { text-align: center; white-space: nowrap; }
.posteriori__reason td {
  font-size: 11px;
  color: var(--text-dim);
  background: var(--bg);
  border-bottom: 1px solid var(--border);
}
.posteriori__key { font-size: 11px; color: var(--text-dim); margin: 8px 0 0; line-height: 1.5; }
.posteriori__signoff {
  margin-top: 12px;
  border: 1px solid var(--border);
  border-radius: 4px;
  padding: 8px 10px;
  background: var(--bg);
}
.posteriori__signoff h4 { margin: 0 0 6px; font-size: 12px; font-weight: 600; }
.posteriori__signoff textarea { width: 100%; min-height: 54px; }
.posteriori__signoff-row { display: flex; gap: 8px; margin-top: 8px; flex-wrap: wrap; }
.posteriori__msg { font-size: 12px; margin: 8px 0 0; }
.posteriori__msg[data-state="error"] { color: var(--red); }
.posteriori__msg[data-state="done"] { color: var(--green); }

@media (max-width: 1100px) {
  .posteriori__panes { grid-template-columns: 1fr; }
  .posteriori__versions { grid-template-columns: 1fr; }
}

@media (max-width: 900px) {
  .archive__filters { grid-template-columns: 1fr 1fr; }
  .archive__charts, .archive__panes { grid-template-columns: 1fr; }
  /* Stacked rather than side by side, so the list gives the record room. */
  .archive__list { min-height: 200px; max-height: 34vh; }
  .archive__detail { min-height: 220px; max-height: none; }
}
.modal__body { overflow-y: auto; padding: 16px 20px; display: flex; flex-direction: column; gap: 10px; }
.modal__body .modal__save-row { padding: 0; border-bottom: none; margin-top: 6px; }
/* Publication numbering: series and year are 1-2 characters, so give the
   width to the number field, which carries the auto-assignment preview. */
/* Selectors are scoped to the row so they outrank `.modal__save-row input`,
   which otherwise flexes all three fields to equal width. */
.publish-number-row { align-items: center; }
.publish-number-row input.publish-number-row__series,
.publish-number-row input.publish-number-row__year {
  flex: 0 0 4em;
  text-align: center;
}
.publish-number-row input.publish-number-row__number { flex: 1 1 auto; min-width: 0; }
/* The preview sits in the placeholder; keep it legible rather than ghosted.
   The console's own number field carries the identical preview when a regional
   officer has loaded a request into it, so it reads the same there. */
.publish-number-row input.publish-number-row__number::placeholder,
input.number--auto-preview::placeholder {
  color: var(--amber);
  opacity: 1;
}

.org-section__title {
  font-family: var(--font-display);
  font-size: 13px;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--text-dim);
  margin: 14px 0 4px;
}
.org-list { display: flex; flex-direction: column; gap: 6px; margin-top: 8px; }
.modal__header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 16px 20px;
  border-bottom: 1px solid var(--border);
}
.modal__header h2 {
  font-family: var(--font-display);
  font-size: 15px;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  margin: 0;
}
.modal__close {
  background: none; border: none; color: var(--text-dim);
  font-size: 20px; line-height: 1; cursor: pointer;
}
.modal__close:hover { color: var(--text); }
.modal__save-row {
  display: flex;
  gap: 10px;
  padding: 16px 20px;
  border-bottom: 1px solid var(--border);
}
.modal__save-row[hidden] { display: none; }
.modal__save-row input { flex: 1; }
.modal__save-row select { flex: 0 0 auto; width: auto; }
.modal__save-row button { flex-shrink: 0; width: auto; padding: 9px 16px; }
.modal__list {
  padding: 8px 12px;
  display: flex;
  flex-direction: column;
  gap: 6px;
  /* Never squeezed below one readable entry, and never shrunk by a sibling
     section: the dialog scrolls instead. Two lists in one dialog (Valid NOTAMs
     and the externally-issued register, or PERM NOTAMs and PERM supplements)
     used to fight each other for a fixed height and both lost. */
  flex: 0 0 auto;
  min-height: 132px;
}
.draft-item {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 10px;
  padding: 10px 12px;
  border: 1px solid var(--border);
  border-radius: 4px;
  background: var(--panel-raised);
}
.draft-item__info { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.draft-item__label {
  font-family: var(--font-mono);
  font-size: 13px;
  color: var(--text);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.draft-item__meta { font-size: 11px; color: var(--text-faint); }
.draft-item__actions { display: flex; gap: 6px; flex-shrink: 0; }
.draft-item__actions button {
  background: none;
  border: 1px solid var(--border);
  color: var(--text-dim);
  font-family: var(--font-display);
  font-size: 11px;
  text-transform: uppercase;
  padding: 6px 9px;
  border-radius: 4px;
  cursor: pointer;
}
.draft-item__actions button:hover { border-color: var(--amber-dim); color: var(--text); }
.draft-item__actions button.danger:hover { border-color: var(--red); color: var(--red); }
.draft-item__actions .btn-link {
  background: none;
  border: 1px solid var(--border);
  color: var(--text-dim);
  font-family: var(--font-display);
  font-size: 11px;
  text-transform: uppercase;
  padding: 6px 9px;
  border-radius: 4px;
  cursor: pointer;
  text-decoration: none;
  display: inline-flex;
  align-items: center;
}
.draft-item__actions .btn-link:hover { border-color: var(--amber-dim); color: var(--text); }
.btn.danger:hover { border-color: var(--red); color: var(--red); }
.btn--danger:hover { border-color: var(--red); color: var(--red); }
.btn--small { font-size: 11px; padding: 4px 8px; }
.draft-item--inactive { opacity: 0.55; }
/* Aerodrome-data list rows (AIP data panel) reuse the draft-item look. */
.list-row {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 10px;
  padding: 10px 12px;
  border: 1px solid var(--border);
  border-radius: 4px;
  background: var(--panel-raised);
  font-size: 12px;
}
.list-row + .list-row { margin-top: 6px; }
.list-row small { color: var(--text-faint); }
.modal__empty { padding: 24px 20px; color: var(--text-faint); font-size: 13px; text-align: center; }

.draft-status { font-size: 12px; margin-top: -4px; }
.reference-number-display {
  font-family: var(--font-mono);
  font-size: 14px;
  font-weight: 600;
  margin: 4px 0 0;
  color: var(--text-dim);
}
.reference-number-display[data-assigned="true"] { color: var(--text); }
.draft-status[data-status="submitted"] { color: var(--amber); }
.draft-status[data-status="forwarded"] { color: var(--amber); }
.draft-status[data-status="unit_approved"] { color: var(--green); }
.draft-status[data-status="published"] { color: var(--green); }
.draft-status[data-status="unit_rejected"] { color: var(--red); }
.draft-status[data-status="regional_rejected"] { color: var(--red); }
/* Unsaved edits win over the status colour: until the draft is saved again,
   what is on screen is not what would be submitted. */
.draft-status[data-dirty="true"] {
  color: var(--amber);
  font-weight: 600;
}
.draft-item__actions button.approve:hover { border-color: var(--green); color: var(--green); }

/* ===== Schedule builder (item D) ===== */
.mode-toggle { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 6px; }
.mode-btn {
  background: var(--panel-raised);
  border: 1px solid var(--border);
  color: var(--text-dim);
  font-family: var(--font-display);
  font-size: 12px;
  text-transform: uppercase;
  letter-spacing: 0.03em;
  padding: 7px 12px;
  border-radius: 4px;
  cursor: pointer;
}
.mode-btn:hover { border-color: var(--amber-dim); color: var(--text); }
.mode-btn.active { border-color: var(--amber); color: var(--amber); background: rgba(232, 163, 61, 0.08); }

.hint {
  font-size: 12px;
  color: var(--text-faint);
  margin: 6px 0 0;
}
/* A hint sitting under its own field, inside the .field flex column. Written
   as `.field span.hint--field` because `.field span` styles the caption above
   it and would otherwise win on specificity, making the two read alike. */
.field span.hint--field {
  font-size: 11px;
  color: var(--text-faint);
  margin: 0;
}
.hint--field code { font-family: var(--font-mono); color: var(--text-dim); }

.wie-note {
  font-size: 12px;
  color: var(--text-dim);
  margin: 2px 0 0;
  padding: 8px 10px;
  border: 1px dashed var(--amber-dim);
  border-radius: 4px;
  background: var(--panel-raised);
}
.wie-note strong { color: var(--amber); }

.schedule-block {
  border: 1px solid var(--border);
  border-radius: 4px;
  padding: 12px;
  margin-top: 10px;
  display: flex;
  flex-direction: column;
  gap: 10px;
  background: var(--panel-raised);
}
.daychips { display: flex; flex-wrap: wrap; gap: 5px; }
.daychip {
  background: var(--panel);
  border: 1px solid var(--border);
  color: var(--text-dim);
  font-family: var(--font-mono);
  font-size: 11.5px;
  padding: 5px 8px;
  border-radius: 3px;
  cursor: pointer;
}
.daychip:hover { border-color: var(--amber-dim); }
.daychip.active { background: var(--amber); border-color: var(--amber); color: #1a1300; font-weight: 600; }

.daypresets { display: flex; gap: 6px; }
.chip--sm { font-size: 11px; padding: 4px 9px; }

.schedule-block__times { align-items: end; }
.remove-block {
  width: 100%;
  background: none;
  border: 1px solid var(--border);
  color: var(--text-faint);
  font-family: var(--font-display);
  font-size: 11px;
  text-transform: uppercase;
  padding: 9px 8px;
  border-radius: 4px;
  cursor: pointer;
}
.remove-block:hover { border-color: var(--red); color: var(--red); }

.schedule-builder__text { margin-top: 4px; }

/* ===== Quality check tab ===== */
.quality-panel { display: flex; flex-direction: column; gap: 14px; }
.quality-summary {
  font-family: var(--font-display);
  font-size: 13px;
  text-transform: uppercase;
  letter-spacing: 0.03em;
  padding: 10px 12px;
  border-radius: 4px;
  border: 1px solid var(--border);
  margin: 0;
}
.quality-summary.ok { color: var(--green); border-color: var(--green); }
.quality-summary.blocked { color: var(--red); border-color: var(--red); }

.quality-results { display: flex; flex-direction: column; gap: 16px; }
.quality-category h3 {
  font-family: var(--font-display);
  font-size: 12.5px;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--text-dim);
  margin: 0 0 8px;
  padding-bottom: 6px;
  border-bottom: 1px solid var(--border);
}
.quality-check {
  display: flex;
  gap: 8px;
  align-items: flex-start;
  font-size: 12.5px;
  padding: 6px 0;
  color: var(--text-dim);
}
.quality-check__icon { flex-shrink: 0; width: 16px; text-align: center; font-family: var(--font-mono); }
.quality-check--pass .quality-check__icon { color: var(--green); }
.quality-check--critical .quality-check__icon { color: var(--red); }
.quality-check--critical { color: #f2b3ae; }
.quality-check--advisory .quality-check__icon { color: var(--amber); }
.quality-check--advisory { color: #f0d3a4; }

/* ===== Service-owner dashboard ===== */
/* One column: the owner has no drafting console beside it. */
.layout--single { grid-template-columns: 1fr; }

.owner__stats { display: flex; flex-wrap: wrap; gap: 8px; }
.owner__stat {
  border: 1px solid var(--border);
  border-radius: 4px;
  padding: 8px 14px;
  background: var(--panel-raised);
  min-width: 110px;
}
.owner__stat b { display: block; font-size: 22px; font-family: var(--font-display); }
.owner__stat span {
  font-size: 10px; color: var(--text-dim);
  text-transform: uppercase; letter-spacing: .04em;
}
.owner__stat[data-tone="warn"] b { color: var(--amber); }
.owner__stat[data-tone="ok"] b { color: var(--green); }
.owner__stat[data-tone="bad"] b { color: var(--red); }

.owner__toolbar { display: flex; gap: 8px; flex-wrap: wrap; }
.owner__toolbar select { flex: 0 0 220px; }
.owner__toolbar input { flex: 1 1 260px; }

.owner__list { display: flex; flex-direction: column; gap: 10px; }
.owner__org {
  border: 1px solid var(--border);
  border-left: 3px solid var(--border);
  border-radius: 4px;
  padding: 12px 14px;
  background: var(--panel-raised);
  display: flex;
  flex-direction: column;
  gap: 10px;
}
/* An application waiting on a decision is the thing the owner came here for. */
.owner__org[data-orgstatus="pending"] { border-left-color: var(--amber); }
.owner__org[data-orgstatus="active"] { border-left-color: var(--green); }
.owner__org[data-orgstatus="suspended"] { border-left-color: var(--red); }
.owner__org[data-orgstatus="rejected"] { border-left-color: var(--text-faint); opacity: .75; }

.owner__org-head { display: flex; justify-content: space-between; align-items: center; }
.owner__org-head b { font-size: 15px; margin-right: 10px; }
.owner__org-meta {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
  gap: 4px 16px;
  font-size: 12px;
}
.owner__k { color: var(--text-dim); margin-right: 6px; }
.owner__v { color: var(--text); }

.owner__counts { display: flex; gap: 8px; flex-wrap: wrap; }
.owner__count {
  border: 1px solid var(--border);
  border-radius: 3px;
  padding: 4px 10px;
  background: var(--bg);
  min-width: 68px;
}
.owner__count b { display: block; font-family: var(--font-mono); font-size: 14px; }
.owner__count span { font-size: 10px; color: var(--text-dim); text-transform: uppercase; }

.owner__notes { font-size: 12px; color: var(--text-dim); margin: 0; }
.owner__org-actions { display: flex; gap: 8px; flex-wrap: wrap; }

.pmark[data-orgstatus="pending"] { color: var(--amber); border-color: var(--amber-dim); }
.pmark[data-orgstatus="active"] { color: var(--green); border-color: var(--green); }
.pmark[data-orgstatus="suspended"] { color: var(--red); border-color: var(--red); }
.pmark[data-orgstatus="rejected"] { color: var(--text-faint); border-color: var(--border); }

.owner__activity { max-height: 320px; overflow-y: auto; }
.owner__activity .plain-list b { font-size: 12px; }
.owner__activity .plain-list span { font-size: 11px; color: var(--text-dim); font-family: var(--font-mono); }


/* The one-time code: six digits, read back character by character, so it gets
   monospace and enough tracking to check against the mail. */
.otp-input {
  font-family: var(--font-mono);
  font-size: 24px;
  letter-spacing: 0.4em;
  text-align: center;
}


/* ---- Mail routes and two-step sign-in ---- */
/* One row per route, so "which of these can actually send right now" is
   readable at a glance rather than buried in a dropdown. */
.owner__route {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 8px 10px;
  border: 1px solid var(--border);
  border-radius: 6px;
  margin-bottom: 6px;
  cursor: pointer;
}
.owner__route:has(input:checked) { border-color: var(--accent); background: rgba(56, 189, 248, 0.06); }
.owner__route > div { display: flex; align-items: baseline; gap: 10px; flex: 1; min-width: 0; }
.owner__route b { min-width: 84px; font-family: var(--font-mono); }
/* The reason a route cannot send is the useful part, so it is not dimmed
   into invisibility next to the name. */
.owner__route-detail { font-size: 12px; color: var(--text-dim); }
.owner__route[data-ready="yes"] .owner__route-detail { color: var(--ok, #34d399); }
.owner__mail { display: flex; gap: 8px; align-items: center; flex-wrap: wrap; margin-top: 10px; }
.owner__mail input { flex: 1; min-width: 200px; }

.twofa-panel { margin: 12px 0 18px; padding: 12px; border: 1px solid var(--border); border-radius: 6px; }
.twofa-state { font-weight: 600; margin: 0 0 8px; }
.twofa-state[data-on="yes"] { color: var(--ok, #34d399); }
.twofa-state[data-on="no"] { color: var(--text-dim); }
/* Named plainly, because each one is a thing the org_admin has to go and fix. */
.twofa-blocker {
  font-size: 12px;
  color: var(--warn, #fbbf24);
  margin: 0 0 6px;
  padding-left: 14px;
  text-indent: -14px;
}
.twofa-blocker::before { content: "— "; }

.account-email { display: block; font-size: 11px; color: var(--text-dim); }
.account-email--missing { color: var(--warn, #fbbf24); }
.account-email-input { width: 190px; font-size: 12px; }


/* ---- Plans, seats and invoices ---- */
.owner__routes { display: flex; flex-direction: column; }

.owner__plan {
  display: flex;
  align-items: center;
  gap: 10px;
  flex-wrap: wrap;
  padding: 8px 10px;
  border: 1px solid var(--border);
  border-radius: 6px;
  margin-bottom: 6px;
}
/* A retired tier stays visible — organisations may still be on it — but reads
   as no longer on offer. */
.owner__plan[data-inactive="yes"] { opacity: 0.55; }
.owner__plan-name { display: flex; flex-direction: column; min-width: 140px; }
.owner__plan-code { font-family: var(--font-mono); font-size: 11px; color: var(--text-dim); }
.owner__plan-seats, .owner__plan-price { width: 110px; }
.owner__plan-meta { flex: 1; min-width: 180px; font-size: 12px; color: var(--text-dim); }

.owner__billing { display: flex; gap: 18px; flex-wrap: wrap; margin-bottom: 12px; }
.owner__billing .owner__stat b { font-size: 20px; }

.owner__invoices { margin-top: 12px; }
.owner__invoice {
  display: flex;
  align-items: center;
  gap: 12px;
  flex-wrap: wrap;
  padding: 7px 10px;
  border-bottom: 1px solid var(--border);
  font-size: 12px;
}
.owner__invoice b { font-family: var(--font-mono); }
.owner__invoice-amount { margin-left: auto; font-family: var(--font-mono); }
.owner__invoice-status { text-transform: uppercase; font-size: 11px; font-weight: 700; }
.owner__invoice[data-status="paid"] .owner__invoice-status { color: var(--ok, #34d399); }
.owner__invoice[data-status="issued"] .owner__invoice-status { color: var(--warn, #fbbf24); }
.owner__invoice[data-status="void"] { opacity: 0.5; }

/* The organisation's own view of its allowance. */
.seats-line { font-size: 12px; color: var(--text-dim); margin: 0 0 10px; }
.seats-line[data-full="yes"] { color: var(--warn, #fbbf24); font-weight: 600; }


/* ---- Audit log filter ---- */
.audit-filter { align-items: flex-end; flex-wrap: wrap; gap: 10px; }
/* Label above its input, so the row stays readable when it wraps. */
.field--inline { display: flex; flex-direction: column; gap: 3px; }
.field--inline > span { font-size: 11px; color: var(--text-dim); }
.field--inline input { min-width: 190px; }


/* ---- Settings menu ---- */
/* The administrative links for supervisors and administrators, folded behind
   one trigger so the nav does not run past the width of the screen. */
.nav-menu { position: relative; }
.nav-menu__trigger {
  color: var(--text);
  background: none;
  border: 1px solid var(--border);
  padding: 6px 10px;
  border-radius: 4px;
  font-family: var(--font-display);
  font-size: 12px;
  text-transform: uppercase;
  letter-spacing: 0.03em;
  cursor: pointer;
}
.nav-menu__trigger::after { content: " ▾"; }
.nav-menu__trigger:hover { border-color: var(--amber-dim); color: var(--text-bright); }
.nav-menu[data-open="yes"] .nav-menu__trigger { border-color: var(--amber-dim); color: var(--text-bright); }

.nav-menu__panel {
  position: absolute;
  top: calc(100% + 6px);
  right: 0;
  z-index: 40;
  min-width: 190px;
  display: flex;
  flex-direction: column;
  gap: 4px;
  padding: 6px;
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: 6px;
  box-shadow: 0 10px 26px rgba(0, 0, 0, 0.45);
}
.nav-menu__panel[hidden] { display: none; }
/* Full-width rows inside the dropdown rather than the nav's inline pills. */
.nav-menu__panel a {
  display: block;
  border: none;
  padding: 8px 10px;
  border-radius: 4px;
  text-align: left;
}
.nav-menu__panel a:hover { background: var(--panel-raised); color: var(--text-bright); }


/* ---- Accounts panel ---- */
/* Wider than the standard dialog: an account row carries an email field, a
   reassignment picker and five buttons, and at 900px the name and role were
   being squeezed out by them. */
.modal--accounts { max-width: 1180px; }

/* "Add officer": the display name is the field people actually read back, so
   it gets the room and the fixed-vocabulary pickers give it up. */
/* Wraps rather than crushing its fields: below a certain width there is no
   arrangement in which six controls all stay readable on one line. */
.modal--accounts .modal__save-row { flex-wrap: wrap; row-gap: 8px; }
#new-officer-display-name { flex: 3 1 15rem; min-width: 12rem; }
#new-officer-username { flex: 2 1 10rem; min-width: 9rem; }
/* The pickers have a known vocabulary, so they take a fixed share and give the
   rest to the name -- but never shrink past the longest option they hold. */
#new-officer-role { flex: 0 1 10rem; min-width: 8.5rem; max-width: 10rem; }
#new-officer-unit,
#new-officer-region { flex: 0 1 12rem; min-width: 10rem; max-width: 12rem; }
#create-officer-btn { flex: 0 0 auto; }

/* An account row has too many controls to sit on one line at every width, so
   it wraps instead of clipping. The identity block keeps a floor wide enough
   for a full name and role; the controls flow underneath when they must. */
.draft-item--account { flex-wrap: wrap; align-items: flex-start; row-gap: 8px; }
.draft-item--account .draft-item__info { flex: 1 1 22rem; min-width: 16rem; }
/* Names are read, not scanned as codes — let them wrap rather than ellipsise. */
.draft-item--account .draft-item__label { white-space: normal; overflow: visible; }
.draft-item--account .draft-item__actions {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 6px;
  justify-content: flex-end;
  flex: 1 1 auto;
}
.draft-item--account .draft-item__actions select { max-width: 12rem; }
.draft-item--account .draft-item__actions button { flex: 0 0 auto; white-space: nowrap; }


/* ---- Archived NOTAMs: the recorded checks ---- */
.archive__export { display: flex; align-items: center; gap: 10px; }
.archive-detail__actions { margin: 12px 0 4px; }

/* Read-only by construction: text and nothing that posts a change back. */
.archive-checks { border-top: 1px solid var(--border); margin-top: 14px; }
.archive-checks__summary { font-size: 12px; font-weight: 600; margin: 0 0 8px; }
.archive-checks__summary[data-ok="yes"] { color: var(--ok, #34d399); }
.archive-checks__summary[data-ok="no"] { color: var(--warn, #fbbf24); }
.archive-checks__group { margin-bottom: 8px; }
.archive-checks__group b { font-size: 11px; text-transform: uppercase; letter-spacing: 0.05em; }
.archive-checks__list { margin: 3px 0 0; padding-left: 16px; }
.archive-checks__list li { font-size: 12px; margin-bottom: 2px; }
/* The verdict is carried by a marker rather than colour alone, so it survives
   printing and does not depend on distinguishing green from amber. */
.archive-checks__list li[data-verdict="pass"] { color: var(--text-dim); }
.archive-checks__list li[data-verdict="pass"]::marker { content: "\2713  "; }
.archive-checks__list li[data-verdict="fail"] { color: var(--red); }
.archive-checks__list li[data-verdict="fail"]::marker { content: "\2717  "; }
.archive-checks__list li[data-verdict="advisory"] { color: var(--amber); }
.archive-checks__list li[data-verdict="advisory"]::marker { content: "!  "; }

.archive-checks__table { width: 100%; border-collapse: collapse; font-size: 11px; }
.archive-checks__table th,
.archive-checks__table td {
  border: 1px solid var(--border);
  padding: 4px 6px;
  text-align: left;
  vertical-align: top;
}
.archive-checks__table th { background: var(--panel-raised); }
.archive-checks__table tr[data-verdict="NC"] { color: var(--red); }
.archive-checks__table tr[data-verdict="ASSIGNED"] { color: var(--text-dim); }

/* Where the finding came from — said plainly, because a result captured after
   the fact is weaker evidence than one taken at publication. */
.archive-checks__note {
  font-size: 11px;
  color: var(--text-dim);
  font-style: italic;
  margin-top: 10px;
}


/* ---- AFTN transmission ---- */
.aftn-panel { border-top: 1px solid var(--border); margin-top: 14px; }
.aftn-state { font-size: 12px; font-weight: 600; margin: 0 0 8px; }
.aftn-state[data-state="sent"] { color: var(--ok, #34d399); }
/* Untransmitted and failed are both "not on the network" — the state worth
   being loud about, since nobody goes looking for a NOTAM that never went. */
.aftn-state[data-state="pending"] { color: var(--amber); }
.aftn-state[data-state="failed"] { color: var(--red); }
.aftn-message {
  font-family: var(--font-mono);
  font-size: 12px;
  line-height: 1.45;
  white-space: pre;
  overflow-x: auto;
  padding: 10px 12px;
  border: 1px solid var(--border);
  border-radius: 4px;
  background: var(--panel-raised);
}

/* A paused addressee stays visible — it may resume — but reads as not in use. */
.draft-item[data-paused="yes"] { opacity: 0.55; }

/* ---- AFTN transport settings ---- */
.aftn-transport-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(15rem, 1fr));
  gap: 10px 14px;
  padding: 0 20px 6px;
}
.aftn-transport-grid .checkline { align-self: end; }

/* ===== Fitting the screen it is opened on =====================================
   Three things were wrong, in descending order of how much they hurt.

   The nav did not wrap. Ten links in a non-wrapping flex row are 1240px wide,
   so on a 375px phone the page was 1292px wide and every screen scrolled
   sideways — the single biggest cause.

   The stacked layout used `1fr`, whose floor is min-content, so a row of
   fields with minimum widths pushed the column past the viewport instead of
   the fields giving way. `minmax(0, 1fr)` lets the track shrink and the
   content reflow, which is what every other breakpoint here assumed.

   And the console was capped at 1400px, which on a 2560px monitor left 573px
   of empty background down each side. The cap is gone: a NOTAM office with a
   big screen bought the width to use it.
   ============================================================================= */

/* Wide screens: use them. */
.layout { max-width: none; }

/* Narrow screens: let every track shrink rather than pushing the page wider. */
@media (max-width: 980px) {
  .layout { grid-template-columns: minmax(0, 1fr); }
}

/* Tablet and below. */
@media (max-width: 820px) {
  .topbar { padding: 14px 16px; }
  .layout { padding: 16px 16px 48px; gap: 16px; }
  /* The nav wraps at every width (see .officer-menu); here it only tightens,
     because several rows of links need less air between them. */
  .officer-menu { gap: 6px; }
  .topbar__status { gap: 10px; }
}

/* Phones. */
@media (max-width: 620px) {
  .topbar { padding: 12px 12px; gap: 8px; }
  .topbar__titles p { display: none; }   /* the strapline is not worth a line here */
  .layout { padding: 12px 12px 40px; }
  .form-panel { padding: 16px 14px; gap: 18px; }
  .preview-panel { padding: 14px; position: static; max-height: none; }
  .officer-menu { width: 100%; }
  .officer-menu span { flex: 1 1 100%; }
  /* A dialog on a phone is the screen, so it may as well use it. */
  .modal-overlay { padding: 8px 6px; }
  .modal { max-height: calc(100vh - 16px); }
  /* Two columns of 190px-minimum fields do not fit 375px; one column does. */
  .grid--2, .grid--3, .grid--4 { grid-template-columns: minmax(0, 1fr); }
  .identification-row { grid-template-columns: minmax(0, 1fr); }
  .archive__filters { grid-template-columns: minmax(0, 1fr); }
  .posteriori__filters { flex-wrap: wrap; }
  /* Minimum widths that were reasonable on a desktop row and are not here. */
  .posteriori__filters input,
  .field--inline input,
  .owner__mail input,
  .modal__save-row input,
  #new-officer-display-name, #new-officer-username,
  #new-officer-role, #new-officer-unit, #new-officer-region {
    min-width: 0;
    max-width: none;
  }
  .checkgroup { flex-wrap: wrap; }
  .tabs { flex-wrap: wrap; }
  /* The Settings dropdown hangs off the right of its trigger. Once the nav
     wraps, that trigger can sit anywhere along the row — at 375px it landed at
     x=0 and the menu opened at -89px, off the side of the screen. Anchored to
     the header instead, it cannot leave the viewport wherever the trigger
     ends up. */
  .topbar { position: relative; }
  .nav-menu { position: static; }
  .nav-menu__panel { left: 12px; right: 12px; min-width: 0; }
  /* Tables carry more columns than a phone has room for: scroll the table,
     not the page. */
  .posteriori__detail, .archive-checks, #audit-list { overflow-x: auto; }
}

/* Phone browsers hide and show their chrome, so 100vh is taller than what you
   can actually see; 100dvh is the visible part. */
@supports (height: 100dvh) {
  .preview-panel { max-height: calc(100dvh - 40px); }
  .modal { max-height: calc(100dvh - 48px); }
  @media (max-width: 620px) {
    .preview-panel { max-height: none; }
    .modal { max-height: calc(100dvh - 16px); }
  }
}

/* ===== NOTAM map =========================================================
   The map is tiles in a pane and an SVG overlay on top of them, both
   positioned absolutely inside a frame that owns the size. Colours match the
   rest of the console: amber for what the NOTAM draws, red for a position it
   names, blue for the Q-line's rounded fallback.
   ========================================================================= */
.map-panel { display: flex; flex-direction: column; gap: 10px; }
.notam-map {
  position: relative;
  overflow: hidden;
  height: 360px;
  min-height: 240px;
  border: 1px solid var(--border);
  border-radius: 4px;
  background: #0c0f14;
  cursor: grab;
  touch-action: none;   /* the pane pans itself; the page must not */
}
.notam-map.is-dragging { cursor: grabbing; }
.notam-map__tiles, .notam-map__overlay { position: absolute; inset: 0; }
.notam-map__tile { position: absolute; width: 256px; height: 256px; user-select: none; }
.notam-map__tile.is-missing { visibility: hidden; }
.notam-map__overlay { pointer-events: none; }

.notam-map__area { fill: rgba(232, 163, 61, 0.18); stroke: var(--amber); stroke-width: 2; }
.notam-map__vertex { fill: var(--amber); }
.notam-map__radius {
  fill: rgba(232, 163, 61, 0.12);
  stroke: var(--amber);
  stroke-width: 1.5;
}
.notam-map__radius--qualifier { fill: rgba(74, 155, 232, 0.12); stroke: #4a9be8; }
.notam-map__position { fill: var(--red); stroke: #fff; stroke-width: 2; }
.notam-map__qualifier { fill: #4a9be8; stroke: #fff; stroke-width: 2; }

.notam-map__controls {
  position: absolute; top: 8px; left: 8px;
  display: flex; flex-wrap: wrap; gap: 4px;
}
.notam-map__layer {
  font-family: var(--font-display);
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  padding: 4px 8px;
  border-radius: 3px;
  border: 1px solid var(--border);
  background: rgba(12, 15, 20, 0.85);
  color: var(--text-dim);
  cursor: pointer;
}
.notam-map__layer.is-active { border-color: var(--amber-dim); color: var(--amber); }
.notam-map__zoom {
  position: absolute; top: 8px; right: 8px;
  display: flex; flex-direction: column; gap: 4px;
}
.notam-map__zoom button {
  width: 30px; height: 30px;
  border: 1px solid var(--border);
  background: rgba(12, 15, 20, 0.85);
  color: var(--text);
  border-radius: 3px;
  cursor: pointer;
  font-size: 15px;
}
.notam-map__zoom .notam-map__fit { width: auto; padding: 0 8px; font-size: 11px; }
.notam-map__attribution {
  position: absolute; right: 4px; bottom: 2px; margin: 0;
  font-size: 10px;
  color: var(--text-dim);
  background: rgba(12, 15, 20, 0.7);
  padding: 1px 5px;
  border-radius: 2px;
  pointer-events: none;
}

.map-panel__msg { margin: 0; font-size: 12px; color: var(--text-dim); }
.map-panel__msg[data-state="warning"] { color: var(--amber); }
.map-panel__actions { display: flex; gap: 8px; flex-wrap: wrap; }
.map-panel__legend { list-style: none; margin: 0; padding: 0; display: flex;
                     flex-direction: column; gap: 4px; font-size: 11px;
                     color: var(--text-dim); }
.map-panel__legend li { display: flex; align-items: center; gap: 8px; }
.map-key { width: 12px; height: 12px; border-radius: 50%; flex-shrink: 0; }
.map-key--position { background: var(--red); }
.map-key--area { background: rgba(232, 163, 61, 0.35); border: 1px solid var(--amber); }
.map-key--qualifier { background: #4a9be8; }

@media (max-width: 620px) {
  .notam-map { height: 260px; }
}

/* A base layer with no imagery for the area on screen. Says so, rather than
   leaving a blank pane that reads as a broken map. */
.notam-map__note {
  position: absolute;
  left: 50%; top: 50%;
  transform: translate(-50%, -50%);
  max-width: 20rem;
  margin: 0;
  padding: 8px 12px;
  text-align: center;
  font-size: 12px;
  color: var(--text-dim);
  background: rgba(12, 15, 20, 0.9);
  border: 1px solid var(--border);
  border-radius: 4px;
  pointer-events: none;
}

/* The cursor's own position, always on, bottom left; and the label for the
   shape under the pointer, which follows it. Both are readouts of coordinates
   an officer is checking against the message, so both are monospaced and
   written the way a NOTAM writes them. */
.notam-map__readout {
  position: absolute; left: 4px; bottom: 2px; margin: 0;
  font-family: var(--font-mono);
  font-size: 10px;
  color: var(--text-dim);
  background: rgba(12, 15, 20, 0.7);
  padding: 1px 5px;
  border-radius: 2px;
  pointer-events: none;
}
.notam-map__tip {
  position: absolute; margin: 0;
  max-width: 16rem;
  font-family: var(--font-mono);
  font-size: 11px;
  color: var(--text);
  background: rgba(12, 15, 20, 0.95);
  border: 1px solid var(--amber-dim);
  padding: 4px 7px;
  border-radius: 3px;
  pointer-events: none;
  z-index: 5;
}
/* The overlay ignores the pointer so dragging works anywhere; the shapes
   themselves take it back, so they can answer a hover. */
.notam-map__overlay { pointer-events: none; }
.notam-map__position, .notam-map__qualifier, .notam-map__vertex { pointer-events: auto; }
.notam-map__position:hover, .notam-map__qualifier:hover, .notam-map__vertex:hover {
  stroke: var(--text-bright);
  stroke-width: 3;
}
/* Tiles are images: without this the browser drags them instead of panning. */
.notam-map__tile { -webkit-user-drag: none; user-select: none; pointer-events: none; }

/* Full-size: the dialog gives the height, the map fills it. */
.map-large__slot { display: flex; flex-direction: column; flex: 1 1 auto; min-height: 0; }
.notam-map--large { height: auto; flex: 1 1 auto; min-height: 60vh; }
#map-large-modal .modal__body { display: flex; flex-direction: column; min-height: 70vh; }

/* ===== Source of a request =================================================
   Above the console and outside the form: what the unit established before
   drafting began. Bordered in amber so it reads as a step of its own rather
   than as the first card of the NOTAM.
   ========================================================================= */
.provenance-panel {
  grid-column: 1 / -1;
  padding: 16px 20px;
  display: flex;
  flex-direction: column;
  gap: 10px;
  border-left: 3px solid var(--amber-dim);
}
.provenance-panel__title {
  font-family: var(--font-display);
  font-size: 13px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  margin: 0;
  color: var(--text);
}
.provenance-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 18rem), 1fr));
  gap: 12px;
}
.provenance-checks {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 14px;
}
.provenance-checks__label {
  font-size: 12px;
  color: var(--text-dim);
  font-family: var(--font-display);
  text-transform: uppercase;
  letter-spacing: 0.04em;
}
.provenance-panel__msg { margin: 0; font-size: 12px; color: var(--amber); }

/* The unit's own record of a source, on an approved NOTAM. Never shown to the
   region, so it is styled as an aside rather than as part of the message. */
.provenance-record {
  border: 1px dashed var(--border);
  border-radius: 4px;
  padding: 8px 10px;
  font-size: 12px;
  color: var(--text-dim);
}
.provenance-record b { color: var(--text); font-weight: 600; }
.provenance-record__checks { display: flex; flex-wrap: wrap; gap: 10px; margin-top: 4px; }
.provenance-record__check[data-ok="no"] { color: var(--red); }
.provenance-record__check[data-ok="yes"] { color: var(--green); }

/* ===== Performance indicators ==============================================
   One card per indicator, four to a group, groups never split. The colour says
   which way the number points — `direction` from the API, because zero is good
   on every indicator here except the one that counts publications made in
   time, where zero is the worst reading on the screen.
   ========================================================================= */
.kpi__period { display: flex; flex-wrap: wrap; gap: 8px; align-items: end;
               padding-bottom: 8px; border-bottom: 1px solid var(--border); }
.kpi__period .btn.is-active { border-color: var(--amber-dim); color: var(--amber); }
.kpi__group { margin-top: 16px; }
.kpi__grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 15rem), 1fr));
  gap: 10px;
  margin-top: 8px;
}
.kpi__card {
  border: 1px solid var(--border);
  border-radius: 4px;
  background: var(--panel-raised);
  padding: 10px 12px;
  display: flex;
  flex-direction: column;
  gap: 4px;
}
.kpi__head { display: flex; align-items: baseline; gap: 8px; }
.kpi__key { font-family: var(--font-mono); font-size: 11px; color: var(--text-faint); }
.kpi__label { font-size: 12px; color: var(--text-dim); }
.kpi__value { margin: 0; font-family: var(--font-display); font-size: 20px; }
.kpi__value[data-tone="good"] { color: var(--green); }
.kpi__value[data-tone="warn"] { color: var(--amber); }
.kpi__value[data-tone="unknown"] { color: var(--text-faint); }
.kpi__detail { margin: 0; font-size: 11px; color: var(--text-faint); }
