* { box-sizing: border-box; margin: 0; padding: 0; -webkit-tap-highlight-color: transparent; }

:root {
  /* Tells the OS this page is dark-themed, which is the only lever a web
     page has over the software keyboard's own colors — iOS/Android render
     the keyboard itself (numeric or full alphanumeric) in dark chrome to
     match rather than popping up a bright white keyboard over a dark app.
     There's no API to recolor the keyboard with the app's own accent/panel
     colors beyond that; this is as far as the platform allows. */
  color-scheme: dark;
  --bg: #0f172a;
  --panel: #16213a;
  --panel-2: #1c2a47;
  --border: #2a3a5c;
  --text: #e6ebf5;
  --muted: #93a2c2;
  --accent: #e2b93b;
  --vfr: #16a34a;
  --mvfr: #2563eb;
  --ifr: #dc2626;
  --lifr: #d946ef;
  --g: #16a34a;
  --y: #ca9a12;
  --r: #dc2626;
  /* True screen height, set by JS in app.js from window.screen.height before
     paint. On this device: innerHeight/dvh report 812 but the physical
     screen is 874 — iOS standalone PWAs can under-report the visible
     viewport by the status-bar height even though the page renders
     full-bleed. The 100dvh fallback keeps things sane before JS runs. THE
     EARLIER ATTEMPT to use screen.height here was correctly reverted, but
     not because screen.height was wrong — it's because html/body below used
     `inset:0`, which forces bottom:0 against the viewport (812) and silently
     overrides any `height` also set on it. That kept body's own box (and
     its overflow:hidden clip) pinned at 812 no matter what #app or .mob-nav
     claimed, so anything positioned past 812 got clipped off, not just
     shifted down. Fixed below by giving html/body an explicit height instead
     of a bottom-anchored inset. Don't revert this again without checking
     that fix is still in place. */
  --true-vh: 100dvh;
  --nav-h: 66px;
  --nav-gap: 16px;
  --nav-clear: calc(var(--nav-h) + var(--nav-gap) + max(14px, env(safe-area-inset-bottom, 0px)) + 4px);
}

/* Locks the document so iOS can't rubber-band the outer page (screens scroll
   inside .scroll). See the note inside the rule: html/body must NOT be
   position:fixed or carry a fixed height, or they clip the bottom pill. */
html, body {
  height: 100%;
  background: var(--bg); color: var(--text);
  /* No position:fixed and no fixed height on html/body: any box here with a
     short height (iOS reports 812 on a 874 screen) becomes a clip rectangle
     for everything past it, including the bottom pill. Overflow on body
     propagates to the viewport, so #app (true screen height) and the fixed
     pill paint past the short figure. */
  /* NO overflow:hidden here: on iOS standalone the viewport is 812 on an 874
     screen, and overflow:hidden on the root clips painting at 812, cutting
     off the bottom pill. #app below is the real clipping/scrolling shell;
     JS pins window scroll at 0 so the 62px overhang can't be dragged. */
  overscroll-behavior: none;
}
body {
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
  font-size: 16px; /* prevents iOS auto-zoom on input focus */
}

#app {
  display: flex;
  flex-direction: column;
  /* True screen height from --true-vh (JS, window.screen.height). Not 100dvh
     or 100% — those are the short figure on iOS standalone. */
  height: 100%;
  height: var(--true-vh);
  overflow: hidden;
}

.app-bar {
  flex-shrink: 0;
  padding: max(14px, env(safe-area-inset-top, 0px)) 16px 12px;
  background: var(--panel);
  border-bottom: 1px solid var(--border);
  display: grid;
  grid-template-columns: 1fr auto 1fr;
  align-items: center;
  column-gap: 8px;
}
.app-bar-left { display: flex; align-items: center; min-width: 0; }
.brand { font-size: 21px; font-weight: 800; letter-spacing: 0.5px; color: var(--accent); white-space: nowrap; }
.app-bar-right {
  display: flex; align-items: center; justify-content: flex-end; gap: 6px;
  justify-self: end; min-width: 0;
}
.header-username {
  font-size: 12px; color: var(--muted); font-weight: 600;
  max-width: 84px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}

.header-title-btn {
  display: flex; flex-direction: column; align-items: center; gap: 1px;
  padding: 4px 6px; margin: -4px 0;
  text-align: center; min-height: 44px; justify-content: center;
  justify-self: center;
}
.header-nnumber { font-size: 22px; font-weight: 800; letter-spacing: 0.5px; color: var(--accent); line-height: 1.15; }
.icon-btn {
  min-width: 40px; min-height: 40px;
  display: flex; align-items: center; justify-content: center;
  background: none; border: none; color: var(--muted); font-size: 19px; cursor: pointer;
  flex-shrink: 0;
}
.avatar-btn { min-width: auto; min-height: auto; padding: 2px; }
.avatar-circle {
  width: 30px; height: 30px; border-radius: 50%;
  display: flex; align-items: center; justify-content: center;
  background: var(--accent); color: #fff;
  font-size: 12px; font-weight: 800; letter-spacing: 0.5px;
  flex-shrink: 0;
}
.avatar-btn:active .avatar-circle { opacity: 0.8; }

.screen { flex: 1; overflow: hidden; display: none; flex-direction: column; position: relative; }
.screen.active { display: flex; }
.scroll {
  flex: 1; overflow-y: auto; overflow-x: hidden; padding: 16px 16px var(--nav-clear);
  -webkit-overflow-scrolling: touch; overscroll-behavior-y: contain;
}

/* ---- Header gear dropdown (History + Settings) ---- */
.header-menu {
  position: absolute; top: calc(100% + 6px); right: 0; z-index: 200;
  background: var(--panel); border: 1px solid var(--border); border-radius: 12px;
  box-shadow: 0 8px 24px rgba(0,0,0,.4); overflow: hidden; min-width: 150px;
}
.header-menu[hidden] { display: none; }
.header-menu-item {
  display: block; width: 100%; text-align: left; padding: 12px 16px;
  background: none; border: none; color: var(--text); font-size: 14px; font-weight: 600;
  cursor: pointer; border-bottom: 1px solid var(--border);
}
.header-menu-item:last-child { border-bottom: none; }
.header-menu-item:active { background: var(--panel-2); }

/* ---- Bottom progress bar: 4 stages of the brief, tap any to jump there.
   Not a tab bar between unrelated sections — a position indicator for one
   continuous form, so the current stage's number is filled solid and past
   stages get a thin connecting line lit behind them. */
.mob-nav {
  /* absolute, not fixed: fixed layers are clipped to the (short) 812 layout
     viewport; absolute paints as part of the full-height document. Scroll is
     pinned at 0 in app.js so top: is measured from the true screen top. */
  position: absolute;
  /* top:, not bottom: — `bottom` on a fixed element resolves against
     whatever the browser calls "the viewport", which on this device reads
     812 even though the real screen is 874. `top` combined with an
     explicit calc from --true-vh sidesteps that: y=0 already matches the
     real top edge (confirmed by measurement), so counting down from there
     in real pixels lands the pill at the true bottom regardless of what
     innerHeight/dvh report. */
  top: calc(var(--true-vh) - var(--nav-h) - max(14px, env(safe-area-inset-bottom, 0px)) - 4px);
  bottom: auto;
  left: 50%; transform: translateX(-50%);
  width: calc(100% - 28px); max-width: 460px;
  display: flex; z-index: 105; align-items: flex-start;
  background: rgba(22, 33, 58, 0.97);
  -webkit-backdrop-filter: blur(20px); backdrop-filter: blur(20px);
  border: 1px solid var(--border);
  border-radius: 22px;
  box-shadow: 0 4px 24px rgba(0,0,0,.35);
  padding: 10px 6px 8px;
}
.stage-item {
  flex: 1; display: flex; flex-direction: column; align-items: center; justify-content: flex-start;
  gap: 4px; padding: 0 2px; background: none; border: none; cursor: pointer;
  color: var(--muted); position: relative;
}
.stage-item:active { opacity: .65; }
.stage-num {
  width: 22px; height: 22px; border-radius: 50%; flex-shrink: 0;
  display: flex; align-items: center; justify-content: center;
  font-size: 11px; font-weight: 800; background: var(--panel-2); border: 1px solid var(--border);
  color: var(--muted);
}
.stage-item::before {
  content: ''; position: absolute; top: 11px; right: 50%; width: 100%; height: 2px;
  background: var(--border); z-index: -1;
}
.stage-item:first-child::before { display: none; }
.stage-item.active .stage-num, .stage-item.done .stage-num {
  background: var(--accent); border-color: var(--accent); color: #1a1300;
}
.stage-item.done::before { background: var(--accent); }
.stage-item.active .stage-label { color: var(--accent); }
.stage-label { font-size: 9px; font-weight: 700; letter-spacing: .1px; text-align: center; line-height: 1.2; }

/* ---- Cards / form controls ---- */
.card {
  background: var(--panel); border: 1px solid var(--border); border-radius: 14px;
  padding: 14px; margin-bottom: 14px;
}
.card h2 { font-size: 13px; text-transform: uppercase; letter-spacing: 0.8px; color: var(--muted); margin-bottom: 10px; }
/* color baked in here rather than relying on pairing with .muted in the
   HTML — .muted's font-size is declared later in this file and was
   silently winning the cascade over this rule's font-size at equal
   specificity whenever both classes were combined on one element (the same
   class of bug the refresh-button width override hit earlier). */
.card-footer { font-size: 11px; margin-top: 10px; text-align: right; color: var(--muted); }
.card-head-row { display: flex; align-items: center; justify-content: space-between; gap: 10px; margin-bottom: 6px; }
/* Deliberately its own class, not combined with .ghost-btn/.primary-btn —
   those force width:100% later in this file, which silently wins the
   cascade over an earlier width:auto override at equal specificity and is
   exactly what made the first version of this button balloon to fill the
   card. */
.card-icon-btn {
  width: 32px; height: 32px; min-width: 32px; min-height: 32px; flex-shrink: 0;
  border-radius: 50%; border: 1px solid var(--border); background: var(--panel-2);
  color: var(--text); font-size: 16px; line-height: 1; padding: 0;
  display: flex; align-items: center; justify-content: center; cursor: pointer;
}
.card-icon-btn:active { opacity: 0.7; }
.small-action-btn {
  flex-shrink: 0; padding: 6px 12px; border-radius: 8px; border: 1px solid var(--border);
  background: var(--panel-2); color: var(--accent); font-size: 12px; font-weight: 700;
  cursor: pointer; white-space: nowrap;
}
.small-action-btn:active { opacity: 0.7; }
.row { display: flex; flex-wrap: wrap; gap: 10px; margin-bottom: 10px; min-width: 0; }
.field { flex: 1 1 140px; display: flex; flex-direction: column; gap: 4px; min-width: 0; max-width: 100%; }
.field label { font-size: 12px; color: var(--muted); }
input, select {
  background: var(--panel-2); border: 1px solid var(--border); color: var(--text);
  border-radius: 10px; padding: 10px 12px; font-size: 16px; min-height: 44px; width: 100%;
  min-width: 0; box-sizing: border-box; -webkit-appearance: none; appearance: none;
}
input:focus, select:focus { outline: 2px solid var(--accent); }
/* PIC on the Overview page: always the logged-in pilot, never typed — reads
   as a fixed value rather than an editable field. */
input[readonly] {
  background: var(--panel); color: var(--muted); font-weight: 700;
}
input[readonly]:focus { outline: none; }
textarea {
  background: var(--panel-2); border: 1px solid var(--border); color: var(--text);
  border-radius: 10px; padding: 10px 12px; font-size: 16px; width: 100%;
  min-width: 0; box-sizing: border-box; font-family: inherit; resize: vertical;
}
textarea:focus { outline: 2px solid var(--accent); }

/* ---- Crew name autocomplete: saved names offered while typing, each
   removable in place with its own × so a mistyped entry never has to be
   re-typed correctly just to get rid of the bad one. ---- */
.autocomplete-wrap { position: relative; }
.autocomplete-list {
  position: absolute; top: 100%; left: 0; right: 0; margin-top: 4px; z-index: 60;
  background: var(--panel-2); border: 1px solid var(--border); border-radius: 10px;
  max-height: 190px; overflow-y: auto; -webkit-overflow-scrolling: touch;
  box-shadow: 0 8px 20px rgba(0,0,0,.35);
}
.autocomplete-list[hidden] { display: none; }
.autocomplete-item {
  display: flex; align-items: center; justify-content: space-between; gap: 8px;
  padding: 10px 12px; font-size: 14px; border-bottom: 1px solid var(--border); cursor: pointer;
}
.autocomplete-item:last-child { border-bottom: none; }
.autocomplete-item:active { background: var(--panel); }
.autocomplete-item-name { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.autocomplete-item-del {
  flex-shrink: 0; width: 26px; height: 26px; border-radius: 50%; border: none;
  background: none; color: var(--muted); font-size: 16px; line-height: 1; cursor: pointer;
}
.autocomplete-item-del:active { color: var(--r); }

.gyr-group { display: flex; gap: 8px; }
.gyr-btn {
  flex: 1; min-height: 44px; border-radius: 10px; border: 1px solid var(--border);
  background: var(--panel-2); color: var(--muted); font-weight: 700; cursor: pointer;
}
.gyr-btn[data-val="G"].on { background: var(--g); color: #fff; border-color: var(--g); }
.gyr-btn[data-val="Y"].on { background: var(--y); color: #1a1300; border-color: var(--y); }
.gyr-btn[data-val="R"].on { background: var(--r); color: #fff; border-color: var(--r); }

.station-table { width: 100%; border-collapse: collapse; font-size: 13px; }
.station-table th, .station-table td { padding: 8px 4px; text-align: center; border-bottom: 1px solid var(--border); }
.station-table th { color: var(--muted); font-weight: 600; font-size: 11px; text-transform: uppercase; }
.station-table td:first-child, .station-table th:first-child { text-align: left; }
.cat { font-weight: 800; padding: 2px 8px; border-radius: 6px; font-size: 12px; display: inline-block; min-width: 44px; }
.cat.VFR { color: var(--vfr); }
.cat.MVFR { color: var(--mvfr); }
.cat.IFR { color: var(--ifr); }
.cat.LIFR { color: var(--lifr); }
.cat.none { color: var(--muted); }

.taf-dots { display: inline-flex; gap: 5px; align-items: center; }
.taf-dot { width: 11px; height: 11px; border-radius: 50%; display: inline-block; background: var(--border); }
.taf-dot.VFR { background: var(--vfr); }
.taf-dot.MVFR { background: var(--mvfr); }
.taf-dot.IFR { background: var(--ifr); }
.taf-dot.LIFR { background: var(--lifr); }

.stat-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; }
.stat { background: var(--panel-2); border-radius: 10px; padding: 10px; }
.stat .k { font-size: 11px; color: var(--muted); text-transform: uppercase; }
.stat .v { font-size: 18px; font-weight: 700; margin-top: 2px; }
.stat.tappable { cursor: pointer; -webkit-tap-highlight-color: transparent; }
.stat.tappable:active { background: var(--panel); }

.notam-item { padding: 8px 0; border-bottom: 1px solid var(--border); font-size: 13px; }
.notam-item:last-child { border-bottom: none; }

/* ---- History list: content + a two-step delete control per row ---- */
.history-item { display: flex; align-items: center; gap: 10px; }
.history-item-body { flex: 1; min-width: 0; cursor: pointer; }
.history-delete-btn {
  flex-shrink: 0; border: 1px solid var(--border); background: none;
  color: var(--muted); font-size: 12px; font-weight: 700;
  padding: 7px 12px; border-radius: 10px; cursor: pointer; min-height: 32px;
}
.history-delete-btn:active { opacity: 0.7; }
.history-delete-btn.armed { border-color: var(--r); color: var(--r); }
.history-delete-btn:disabled { opacity: 0.6; cursor: default; }
.notam-meta { color: var(--muted); font-size: 11px; margin-bottom: 2px; }
.history-item:active { opacity: 0.7; }

/* Hazard cards (AIRMET/SIGMET/NOTAM) — tap to flip between raw text and a
   plain-language overview. A JS-driven rotate-swap-rotate (rather than a
   CSS 3D transform with two stacked absolutely-positioned faces) so the
   card's own vertical scrolling always works: WebKit doesn't reliably
   deliver touch-scroll gestures to a nested overflow:auto element that sits
   inside a perspective/preserve-3d/backface-hidden stack, and a fixed-height
   dual-face card clips any text taller than it. Here only one face is ever
   in the DOM, transform is applied only transiently during the flip
   animation, and the card's own overflow-y:auto scrolls normally at rest. */
.hazard-card {
  margin-bottom: 10px; cursor: pointer;
  max-height: 160px; overflow-y: auto; -webkit-overflow-scrolling: touch;
  background: var(--panel-2); border: 1px solid var(--border); border-radius: 10px;
  padding: 8px 10px; font-size: 13px;
  transition: transform 0.15s ease;
}
.hazard-card.flipping { transform: rotateY(90deg); }
.muted { color: var(--muted); font-size: 13px; }

/* Weather & Hazards Map modal — Leaflet map opened from "View Map" at the
   top of the Weather & Environmental page. Built on the app's standard
   .modal-overlay/.modal-panel chrome (same as the METAR/TAF pop-out), with
   its own sizing so the map gets real usable height instead of shrinking to
   fit content. Leaflet's own popup/control chrome is white by default so
   it's re-skinned here rather than left stock. */
.modal-panel.map-modal-panel {
  max-width: 640px;
  height: 72vh;
}
.modal-body.map-modal-body {
  display: flex; flex-direction: column; flex: 1; min-height: 0;
  overflow: hidden; /* the map fills this itself; no separate scroll region needed */
}
.hazards-map {
  flex: 1; min-height: 0;
  border-radius: 10px;
  overflow: hidden;
  border: 1px solid var(--border);
  background: var(--panel-2);
}

/* Full screen: rather than the browser's real Fullscreen API (unsupported
   for arbitrary elements in iOS Safari/PWA), the modal itself sheds its
   backdrop/centering and the panel goes edge-to-edge — same
   position:fixed;inset:0 pattern as the modal already uses, just filling the
   whole viewport instead of centering in it. Scoped to .map-modal
   specifically (not every .modal-overlay) so this never affects the
   METAR/TAF pop-out, which shares the base modal classes. */
.modal-overlay.map-modal.fullscreen { padding: 0; background: var(--bg); }
.modal-overlay.map-modal.fullscreen .map-modal-panel {
  max-width: 100%; width: 100%; height: 100%; max-height: 100%;
  border-radius: 0; border: none;
  /* A flat env(safe-area-inset-*) alone is 0px on most devices (no notch),
     which is exactly the "flush against the edge" bug reported — always add
     a baseline gutter and let the safe-area inset stack on top of it where
     one actually applies. */
  padding: calc(14px + env(safe-area-inset-top, 0px)) calc(14px + env(safe-area-inset-right, 0px))
           calc(14px + env(safe-area-inset-bottom, 0px)) calc(14px + env(safe-area-inset-left, 0px));
}
.hazards-map .leaflet-popup-content-wrapper,
.hazards-map .leaflet-popup-tip {
  background: var(--panel-2); color: var(--text);
}
.hazards-map .leaflet-popup-content { font-size: 13px; margin: 10px 12px; }
.hazards-map .leaflet-control-attribution {
  background: rgba(15, 23, 42, 0.75); color: var(--muted); font-size: 9px;
}
.hazards-map .leaflet-control-attribution a { color: var(--muted); }
.hazards-map .leaflet-control-zoom a {
  background: var(--panel-2); color: var(--text); border-color: var(--border);
}
.station-map-marker {
  width: 14px; height: 14px; border-radius: 50%;
  border: 2px solid #fff; box-shadow: 0 0 4px rgba(0,0,0,0.6);
}
.hazard-map-legend {
  display: flex; flex-wrap: wrap; gap: 10px; margin-top: 8px; font-size: 11px; color: var(--muted);
  flex-shrink: 0; /* keep the legend row from being squeezed by the map's flex:1 above it */
}
.hazard-map-legend span { display: inline-flex; align-items: center; gap: 4px; }
.hazard-map-legend i { width: 10px; height: 10px; border-radius: 50%; display: inline-block; }
.link { color: var(--accent); text-decoration: underline; }

/* ---- Save banner (toast) ---- */
.save-banner {
  position: fixed; left: 50%; top: calc(env(safe-area-inset-top, 0px) + 60px);
  transform: translateX(-50%); z-index: 300;
  background: var(--g); color: #fff; font-weight: 700; font-size: 13px;
  padding: 10px 18px; border-radius: 10px; box-shadow: 0 4px 16px rgba(0,0,0,.35);
  opacity: 1; transition: opacity .25s ease, transform .25s ease;
  max-width: calc(100% - 32px); text-align: center;
}
.save-banner.hide { opacity: 0; transform: translateX(-50%) translateY(-8px); pointer-events: none; }

/* ---- Stale weather data banner ---- */
/* Persistent (no auto-hide timer, unlike .save-banner) until the pilot
   either swipes it up or taps Refresh and gets fresh data — it's a warning
   to act on, not a confirmation to glance at. */
.stale-data-banner {
  position: fixed; top: 0; left: 0; right: 0; z-index: 250;
  padding: calc(10px + env(safe-area-inset-top, 0px)) 16px 10px;
  background: #7a3b0a; color: #ffd9a8; font-size: 13px; font-weight: 700;
  display: flex; align-items: center; justify-content: space-between; gap: 10px;
  transition: transform .2s ease, opacity .2s ease;
  touch-action: pan-y; /* the JS swipe handler needs vertical touch moves, not the browser intercepting them */
}
.stale-data-banner[hidden] { display: none; }
.stale-data-banner.dismissing { transform: translateY(-100%); opacity: 0; }
.stale-data-banner-hint { font-size: 10px; font-weight: 600; color: #ffe9c8; opacity: 0.8; white-space: nowrap; }

/* ---- METAR/TAF detail pop-out ---- */
.tappable-badge { cursor: pointer; display: inline-block; -webkit-tap-highlight-color: transparent; }
.modal-overlay {
  position: fixed; inset: 0; z-index: 500;
  background: rgba(0, 0, 0, 0.55);
  display: flex; align-items: center; justify-content: center;
  padding: 20px;
}
.modal-overlay[hidden] { display: none; }
.modal-panel {
  width: 100%; max-width: 480px; max-height: 82vh;
  background: var(--panel); border: 1px solid var(--border);
  border-radius: 18px;
  padding: 16px 16px calc(16px + env(safe-area-inset-bottom, 0px));
  display: flex; flex-direction: column; overflow: hidden;
  box-shadow: 0 8px 30px rgba(0, 0, 0, 0.5);
}
.modal-header { display: flex; align-items: flex-start; justify-content: space-between; gap: 10px; margin-bottom: 12px; flex-shrink: 0; }
.modal-title { font-size: 17px; font-weight: 800; color: var(--accent); }
.modal-body { overflow-y: auto; -webkit-overflow-scrolling: touch; }
.raw-block {
  font-family: ui-monospace, "SF Mono", Menlo, monospace; font-size: 12px; line-height: 1.5;
  background: var(--panel-2); border: 1px solid var(--border); border-radius: 10px;
  padding: 10px; margin-bottom: 14px; color: var(--text);
  white-space: pre-wrap; word-break: break-word;
}
.raw-block.cat-VFR { color: var(--vfr); }
.raw-block.cat-MVFR { color: var(--mvfr); }
.raw-block.cat-IFR { color: var(--ifr); }
.raw-block.cat-LIFR { color: var(--lifr); }
.raw-seg { display: block; }
.raw-seg.cat-VFR { color: var(--vfr); }
.raw-seg.cat-MVFR { color: var(--mvfr); }
.raw-seg.cat-IFR { color: var(--ifr); }
.raw-seg.cat-LIFR { color: var(--lifr); }
.taf-seg-divider { border: none; border-top: 3px solid var(--accent); margin: 8px 0; opacity: 0.8; }
.decoded-table { margin-bottom: 4px; }
.decoded-row {
  display: flex; justify-content: space-between; align-items: baseline; gap: 10px;
  padding: 8px 2px; border-bottom: 1px solid var(--border); font-size: 14px;
}
.decoded-row:last-child { border-bottom: none; }
.decoded-k { color: var(--muted); flex-shrink: 0; }
.decoded-v { font-weight: 600; text-align: right; }
.decoded-period { margin-bottom: 16px; }
.decoded-period:last-child { margin-bottom: 0; }
.decoded-period-head { display: flex; align-items: center; justify-content: space-between; gap: 10px; margin-bottom: 4px; }

/* ---- Med Crew Brief checklist ---- */
.med-checklist { display: flex; flex-direction: column; gap: 2px; }
.med-check-row {
  display: flex; align-items: center; gap: 12px; padding: 11px 4px;
  border-bottom: 1px solid var(--border); cursor: pointer;
}
.med-check-row:last-child { border-bottom: none; }
.med-check-row input[type="checkbox"] {
  width: 22px; height: 22px; min-height: 0; flex-shrink: 0; accent-color: var(--accent);
  cursor: pointer;
}
.med-check-row label { font-size: 14px; font-weight: 600; cursor: pointer; flex: 1; }
.med-check-row.checked { background: rgba(22, 163, 74, 0.14); border-radius: 8px; }
.med-check-row.checked label { color: var(--vfr); font-weight: 700; }

/* ---- Review & Submit: SUBMIT lives on the nav bar itself, not as a
   separate floating bar — it used to sit as its own element directly above
   the pill and visually overlapped it. It's shown only via .mob-nav.on-review
   (toggled in goScreen), and it's positioned absolute so it never joins the
   pill's own flex row of stage items.
   - Portrait phone (default here, narrow & not landscape): a round yellow
     button centered just above the pill.
   - Tablet, phone landscape, or a laptop/desktop (media query below): a
     yellow extension welded onto the right end of the pill instead. */
.mob-nav-submit {
  display: none; position: absolute; z-index: 106;
  background: var(--accent); color: #1a1300; font-weight: 800; letter-spacing: .2px;
  border: none; cursor: pointer; box-shadow: 0 4px 16px rgba(0,0,0,.35);
  text-align: center; line-height: 1.15;
}
.mob-nav.on-review .mob-nav-submit { display: flex; align-items: center; justify-content: center; }
.mob-nav-submit.submitted, .mob-nav-submit:disabled {
  background: var(--panel-2); color: var(--muted); box-shadow: none; cursor: default;
}
/* Portrait phone: round button centered above the pill. */
.mob-nav-submit {
  left: 50%; bottom: calc(100% + 12px); transform: translateX(-50%);
  width: 66px; height: 66px; border-radius: 50%; font-size: 11px; padding: 4px;
}
@media (min-width: 640px), (orientation: landscape) {
  /* Flatten the pill's right corners only while the extension is attached,
     so the two read as one continuous shape rather than a pill plus a
     separate floating chip. */
  .mob-nav.on-review { border-top-right-radius: 0; border-bottom-right-radius: 0; }
  .mob-nav-submit {
    left: 100%; right: auto; top: -1px; bottom: -1px; transform: none;
    width: 96px; height: auto; border-radius: 0 22px 22px 0;
    font-size: 13px; padding: 4px 10px;
  }
}
.review-readout { font-size: 14px; line-height: 1.6; }
.review-readout .review-row { display: flex; justify-content: space-between; gap: 10px; padding: 4px 0; }
.review-readout .review-k { color: var(--muted); }
.review-readout .review-v { font-weight: 600; text-align: right; }

.primary-btn {
  width: 100%; min-height: 48px; border-radius: 12px; border: none;
  background: var(--accent); color: #1a1300; font-weight: 800; font-size: 15px; cursor: pointer;
}
.ghost-btn {
  width: 100%; min-height: 44px; border-radius: 12px; border: 1px solid var(--border);
  background: transparent; color: var(--text); font-weight: 600; cursor: pointer;
}

.stale-badge {
  display: inline-block; font-size: 11px; background: #7a3b0a; color: #ffd9a8;
  padding: 2px 8px; border-radius: 6px; margin-bottom: 8px;
}

#login-screen { align-items: center; justify-content: center; padding: 24px; z-index: 400; }
.login-box { width: 100%; max-width: 360px; }
.login-box h1 { color: var(--accent); font-size: 28px; margin-bottom: 4px; text-align: center; }
.login-box .tagline { color: var(--muted); text-align: center; margin-bottom: 24px; font-size: 13px; }
.error-text { color: var(--ifr); font-size: 13px; margin-top: 8px; min-height: 16px; }

/* ---- Quick login: one-tap username, then just the password ---- */
.quick-login-list { display: flex; flex-direction: column; gap: 8px; }
.quick-login-row {
  display: flex; align-items: center; justify-content: space-between; gap: 10px;
  padding: 13px 14px; border-radius: 12px; border: 1px solid var(--border);
  background: var(--panel-2); cursor: pointer;
}
.quick-login-row:active { background: var(--panel); opacity: 0.85; }
.quick-login-row.confirming { border-color: var(--r); background: rgba(220, 38, 38, 0.1); cursor: default; }
.quick-login-name { font-size: 15px; font-weight: 700; }
.quick-login-del {
  flex-shrink: 0; width: 26px; height: 26px; border-radius: 50%; border: none;
  background: none; color: var(--muted); font-size: 16px; line-height: 1; cursor: pointer;
}
.quick-login-del:active { color: var(--r); }
.quick-login-confirm-del {
  flex-shrink: 0; border: none; border-radius: 8px; background: var(--r); color: #fff;
  font-size: 12px; font-weight: 800; padding: 7px 12px; cursor: pointer;
}
.quick-login-confirm-del:active { opacity: 0.8; }
.login-back-btn {
  display: block; background: none; border: none; color: var(--accent);
  font-size: 13px; font-weight: 700; padding: 0; margin-bottom: 14px; cursor: pointer;
}

/* ---- Settings: Weather Stations list (add/remove/drag-reorder) ---- */
.stations-list { display: flex; flex-direction: column; gap: 8px; }
.station-row {
  display: flex; align-items: center; gap: 10px;
  padding: 10px 12px; border-radius: 12px; border: 1px solid var(--border);
  background: var(--panel-2);
}
.station-row.dragging {
  opacity: 0.9; box-shadow: 0 6px 18px rgba(0,0,0,.45);
  position: relative; z-index: 5;
}
/* Rows within the current "shown by default" count — mirrors exactly what
   the Weather & Environmental page will display, updating live as the
   pilot edits the count above. */
.station-row.station-row-shown { border-color: var(--accent); border-width: 2px; padding: 9px 11px; }
.station-drag-handle {
  color: var(--muted); font-size: 18px; line-height: 1; padding: 6px;
  cursor: grab; touch-action: none; flex-shrink: 0;
}
.station-row-name { flex: 1; font-size: 15px; font-weight: 700; }
.station-remove-btn {
  flex-shrink: 0; width: 26px; height: 26px; border-radius: 50%; border: none;
  background: none; color: var(--muted); font-size: 16px; line-height: 1; cursor: pointer;
}
.station-remove-btn:active { color: var(--r); }

/* Note: the bottom progress bar used to hide above 701px width, on the
   assumption that a wide viewport meant a desktop browser that would show
   some other navigation instead — but there never was one, and iPad (768px+
   portrait, 1024px+ landscape) falls well past that width too. This app is
   only ever used on a phone or tablet, so the progress bar now always
   shows regardless of screen size. */
