:root{
  --bg:#0f1720; --card:#18232f; --line:#2a3947; --ink:#e7eef5; --mut:#93a4b5;
  --accent:#3a97e6; --red:#e0453a; --good:#2fbf71; --warn:#e8a13a;
  /* Distinct from --red on purpose: red means "this fails" (a verdict), so it
     must not also be the colour of "here's the worst-case reference figure"
     (which passes just as often as it fails). Collapsing the two onto one
     hue made a passing worst-case number look like a failure at a glance. */
  --worst:#9b6bdb;
  --field:#0e1620;
  /* Lighter than --accent: links need to stay readable on the dark card
     background. #3a97e6 is ~4.9:1 there, this is ~7:1. */
  --link:#6fb6f2;
  /* Hint text. The old #64788a was only ~3.4:1 on --card, under the 4.5:1
     minimum for small text; this is ~5.2:1. */
  --hint:#8496a8;
}
/* Without this, every link falls back to the browser default #0000EE (and
   visited purple), which on the dark card is barely legible. */
a{color:var(--link);text-decoration:none}
a:hover{color:#a5d2f7;text-decoration:underline}
a:focus-visible{outline:2px solid var(--link);outline-offset:2px;border-radius:3px}
*{box-sizing:border-box}
html,body{margin:0}
/* No sideways scroll on phones — but `clip`, and on <html> only.
   `overflow-x:hidden` on <body> makes body a SCROLL CONTAINER, because when
   one axis is not `visible` the other computes to `auto`. Everything then goes
   wrong at once: position:sticky on a body child (the header) sticks to body's
   scrollport instead of the one actually scrolling, so it never sticks;
   content slides under a header that isn't moving, so the Inputs heading gets
   clipped; and position:fixed (the phone bottom bar) re-roots onto body's box
   on some mobile engines and stops sitting at the bottom of the screen.
   `clip` suppresses the overflow WITHOUT creating a scroll container.
   `hidden` stays first as the fallback for engines that lack `clip`. */
html{overflow-x:hidden;overflow-x:clip}
body{
  background:var(--bg); color:var(--ink);
  font:15px/1.45 -apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Helvetica,Arial,sans-serif;
  -webkit-text-size-adjust:100%;               /* stop iOS auto-inflating text */
}
/* Three jobs, in order: who this is, what you are looking at, and which flight
   it is about. They wrap onto as many rows as the width needs.

   justify-content is flex-start, NOT space-between. With flex-wrap on,
   space-between pushes the two items on a short row to opposite ends — so the
   moment the tabs wrapped away, the brand was flung to the far right of the
   screen and the burger left alone on the left. The right-hand controls are
   pushed out with margin-left:auto instead, which does the intended thing on
   every row count. */
.topbar{
  display:flex;align-items:center;justify-content:flex-start;flex-wrap:wrap;
  column-gap:14px;row-gap:9px;
  padding:10px 20px;background:linear-gradient(180deg,#1b2937,#141e29);
  border-bottom:1px solid var(--line);position:sticky;top:0;z-index:5;
}
/* The flight strip: a full-width row at the foot of the header, on every
   width. The leg is the CONTEXT for the whole workspace — inputs, chart and
   results all describe it — so it sits below the view tabs and directly above
   the content it governs, rather than competing with the brand for the top
   line. */
.flightbar{
  flex:1 0 100%;order:10;display:flex;align-items:stretch;gap:6px;
  margin-top:2px;padding-top:9px;border-top:1px solid var(--line);
  overflow-x:auto;scrollbar-width:none;-webkit-overflow-scrolling:touch;
}
.flightbar::-webkit-scrollbar{display:none}
.fb-leg{
  flex:0 0 auto;display:flex;flex-direction:column;align-items:flex-start;gap:1px;
  background:var(--field);border:1px solid var(--line);border-radius:9px;
  padding:5px 12px;cursor:pointer;text-align:left;color:var(--ink);
  min-width:104px;
}
.fb-leg:hover{border-color:#4b6076}
.fb-role{font-size:9.5px;text-transform:uppercase;letter-spacing:.09em;
  font-weight:800;color:var(--mut);line-height:1.5}
.fb-icao{font-size:14px;font-weight:700;line-height:1.15}
.fb-mass{font-size:10.5px;color:var(--hint);font-variant-numeric:tabular-nums;line-height:1.5}
/* The selected leg wears the SAME accent fill the active chart tab wears.
   Two selection languages on one bar would read as two unrelated controls. */
.fb-leg.on{background:var(--accent);border-color:var(--accent);color:#fff}
.fb-leg.on .fb-role,.fb-leg.on .fb-mass{color:rgba(255,255,255,.85)}
/* A leg with no aerodrome yet says what to do; muted, because it is a prompt
   rather than a value. */
.fb-empty .fb-icao{font-weight:600;font-size:12.5px;color:var(--hint)}
.fb-leg.on.fb-empty .fb-icao{color:rgba(255,255,255,.9)}
.fb-add{
  flex:0 0 auto;align-self:center;background:none;color:var(--mut);
  border:1px dashed var(--line);border-radius:9px;
  padding:8px 12px;font-size:12px;font-weight:700;cursor:pointer;white-space:nowrap;
}
.fb-add:hover{color:var(--ink);border-color:var(--accent)}
.fb-add.locked:hover{color:var(--warn);border-color:var(--warn)}

/* A masthead, not another control. The accent rule gives the wordmark a left
   edge to sit against so it reads as the app's name rather than as the first
   of several buttons — and it earns its place without a logo, which would have
   to be drawn genuinely well to beat plain type. Stacking the two lines also
   makes the brand a third narrower, which is what lets the tabs share the top
   row on a wide screen instead of being pushed onto their own. */
.brand{display:flex;align-items:center;gap:10px;min-width:0}
.brand::before{content:'';width:3px;align-self:stretch;min-height:28px;
  background:var(--accent);border-radius:2px;flex:0 0 auto}
.brand-txt{display:flex;flex-direction:column;line-height:1.16;min-width:0}
.brand-link{display:flex;align-items:center;gap:10px;color:inherit;text-decoration:none}
.brand-link:hover{text-decoration:none;color:inherit}
.brand .ac{font-size:16.5px;font-weight:800;letter-spacing:-.1px;white-space:nowrap}
.brand .sub{margin:0;color:var(--mut);font-size:9.5px;font-weight:700;
  text-transform:uppercase;letter-spacing:.13em;white-space:nowrap}
/* Their own row, centred. flex:1 0 100% forces the break; order puts them
   AFTER the actions group in the flex order even though they come before it in
   the DOM, so row one is always brand-left / actions-right and the tabs can
   never push those around by growing.

   Centred only here. The phone rule below turns this into a horizontally
   scrolling strip, and justify-content:center on an overflow container puts
   the first item out of reach of the scroll — you cannot get back to Take-off
   once it has overflowed to the left. */
.tabs{display:flex;gap:6px;flex-wrap:wrap;flex:1 0 100%;order:5;justify-content:center}
.tabs button{
  background:var(--field);color:var(--mut);border:1px solid var(--line);
  padding:8px 14px;border-radius:8px;cursor:pointer;font-size:13px;font-weight:600;
}
.tabs button:hover{color:var(--ink)}
.tabs button.active{background:var(--accent);color:#fff;border-color:var(--accent)}
/* Not applicable to the leg on screen — distinct from .locked, which is a
   paywall. This one is about the flight, not the account, so it reads as
   dimmed rather than as barred. */
.tabs button.na{opacity:.4}
.tabs button.na:hover{opacity:.7;color:var(--mut)}
.tabs button.locked{opacity:.55;border-style:dashed;cursor:pointer}
.tabs button.locked:hover{opacity:.8;border-color:var(--warn);color:var(--warn)}
/* Primary call-to-action, so it's styled as a button rather than muted text —
   it was previously --mut, which read as disabled/secondary. */
/* aircraft variant switch (GFC700 / TDI) */
.variant-wrap{display:flex;align-items:center;gap:7px}
.variant-lbl{font-size:10.5px;text-transform:uppercase;letter-spacing:.08em;color:var(--mut);font-weight:700}
.variant-switch{display:inline-flex;background:var(--field);border:1px solid var(--line);
  border-radius:8px;padding:2px;gap:2px}
.var-btn{background:none;border:none;color:var(--mut);border-radius:6px;
  padding:5px 11px;font-size:12.5px;font-weight:700;cursor:pointer;white-space:nowrap}
.var-btn:hover{color:var(--ink)}
.var-btn.on{background:var(--accent);color:#fff}
/* TDI caveat under the chart — the image is the GFC700 print */
.variant-note{margin-top:8px;font-size:12px;line-height:1.55;color:#f0c274;
  background:rgba(232,161,58,.1);border:1px solid rgba(232,161,58,.4);
  border-radius:8px;padding:9px 11px}
.variant-note strong{color:var(--ink)}

.nav-auth a{
  display:inline-block;background:var(--field);color:var(--ink);
  border:1px solid var(--line);border-radius:8px;
  padding:8px 12px;font-size:13px;font-weight:600;text-decoration:none;
  max-width:220px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;vertical-align:middle;
}
.nav-auth a:hover{border-color:var(--accent);color:#fff;text-decoration:none}
/* Signed in. Two classes so it beats `.nav-auth a` above, which is the Log-in
   button and is deliberately shaped differently — one is a call to action, the
   other is a status. */
.nav-auth .who{
  display:inline-flex;align-items:center;gap:7px;
  border-radius:999px;padding:3px 13px 3px 3px;max-width:200px;
  font-size:12.5px;font-weight:600;
}
.nav-auth .who-dot{
  width:23px;height:23px;border-radius:50%;background:var(--accent);color:#fff;
  display:grid;place-items:center;font-size:11.5px;font-weight:800;
  flex:0 0 auto;text-transform:uppercase;
}
.nav-auth .who-txt{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}

/* The right-hand controls travel as one group. Loose in the flex row they were
   separated by whatever wrapped between them, which is how a signed-in email
   ended up alone on the left of its own line with Print at the far right. */
.topbar-actions{margin-left:auto;display:flex;align-items:center;gap:8px;flex-wrap:wrap}
/* The full label stays at every width down to the phone rule, which collapses
   the button to its glyph. It used to be trimmed below 1600px to keep the tabs
   and these controls on one line; the tabs have their own row now, so row one
   is just the brand and these, and there is room to spare. */

.layout{
  display:grid;grid-template-columns:320px minmax(0,1fr) 340px;gap:16px;
  padding:16px;max-width:1500px;margin:0 auto;align-items:start;
}
@media(max-width:1180px){ .layout{grid-template-columns:1fr} }
/* grid/flex children must be allowed to shrink below their content width,
   otherwise a wide field forces the whole page wider than a phone screen */
.layout > *{min-width:0}
.card{background:var(--card);border:1px solid var(--line);border-radius:12px;padding:16px;min-width:0}
.card h2{margin:0 0 12px;font-size:15px;text-transform:uppercase;letter-spacing:.08em;color:var(--mut)}

.grp{margin-bottom:12px}
/* Paired fields. Scoped to .grp.two until now, which meant the .two rows
   nested inside fieldsets (wind direction/speed, cruise altitude/power) never
   actually gridded and stacked instead — a good part of why the input panel
   was so tall. */
.two,.grp.two{display:grid;grid-template-columns:1fr 1fr;gap:10px}
label{display:block;font-size:12px;color:var(--mut);font-weight:600}
.u{color:var(--hint);font-weight:500}
input,select{
  width:100%;margin-top:4px;background:var(--field);border:1px solid var(--line);
  color:var(--ink);border-radius:8px;padding:9px 10px;font-size:15px;font-variant-numeric:tabular-nums;
}
input:focus,select:focus{outline:none;border-color:var(--accent)}
input[readonly]{color:var(--accent);font-weight:700;background:#0b131b}
fieldset{border:1px solid var(--line);border-radius:10px;padding:10px 12px 12px;margin:0 0 12px}
legend{font-size:11px;text-transform:uppercase;letter-spacing:.08em;color:var(--mut);padding:0 6px}
.wind-read{display:flex;flex-direction:column;justify-content:center;font-size:13px}
.wind-read .hw{font-size:18px;font-weight:700;color:var(--accent)}
.wind-read .xw{color:var(--mut);font-size:12px}
.ovr{display:flex;flex-wrap:wrap;align-items:center;gap:8px;margin-top:8px;font-size:12px}
.ovr input[type=checkbox]{width:auto;margin:0}
.ovr input[type=number]{width:90px}

.chart-title{font-size:18px;font-weight:700;margin-bottom:6px}
.chart-legend{display:flex;flex-wrap:wrap;gap:14px;margin-bottom:10px;font-size:12px;color:var(--mut)}
.chart-legend .lg{display:inline-flex;align-items:center;gap:6px}
.chart-legend .ln{width:18px;height:0;border-top:3px solid;border-radius:2px}
.chart-legend .ln-act{border-color:#2f7fe0}
.chart-legend .ln-worst{border-color:var(--worst)}
.worst-note{color:var(--warn);font-weight:600}
.mass-note{margin-top:-4px;margin-bottom:10px;font-size:11.5px;line-height:1.4;color:#f0c274;
  background:rgba(232,161,58,.1);border:1px solid rgba(232,161,58,.35);border-radius:7px;padding:6px 9px}
.chart-wrap{position:relative;width:100%;background:#fff;border-radius:8px;overflow:hidden}
.chart-wrap img{display:block;width:100%;height:auto}
#overlay{position:absolute;inset:0;width:100%;height:100%;pointer-events:none}
.conditions{margin-top:10px;color:var(--mut);font-size:12.5px}

.resulttbl{width:100%;border-collapse:collapse;font-size:14px}
.resulttbl td{border:1px solid var(--line);padding:8px 10px;vertical-align:middle}
.resulttbl td.k{color:var(--mut);font-weight:600;width:44%}
.resulttbl td.v{text-align:right;font-variant-numeric:tabular-nums;font-weight:700}
/* comparison header: Actual vs Worst-case legend chips */
.resulttbl tr.res-head td{background:#0e1620;padding:6px 10px}
.leg{display:inline-block;font-size:11px;font-weight:700;text-transform:uppercase;letter-spacing:.05em;
  padding:2px 8px;border-radius:20px}
.leg-act{color:#cfe4fb;background:rgba(47,127,224,.22);border:1px solid rgba(47,127,224,.55)}
.leg-worst{color:#e2d0f7;background:rgba(155,107,219,.18);border:1px solid rgba(155,107,219,.5)}
/* headline result cells, tinted by column: actual = blue, worst-case = violet.
   .pass/.fail carry !important so a genuine verdict always wins over the
   column tint — a passing worst-case figure must never read as a failure
   just for sitting in the worst-case column. */
.resulttbl td.res{font-size:17px;background:rgba(255,255,255,.02)}
.resulttbl td.res:nth-child(2){color:var(--accent)}
.resulttbl td.res:nth-child(3){color:var(--worst);background:rgba(155,107,219,.10)}
.resulttbl td.pass{color:var(--good) !important}
.resulttbl td.fail{color:var(--red) !important;background:rgba(224,69,58,.14) !important}
.badge{display:inline-block;padding:2px 8px;border-radius:20px;font-size:12px;font-weight:700;margin-left:6px}
.badge.ok{background:rgba(47,191,113,.18);color:var(--good)}
.badge.no{background:rgba(224,69,58,.18);color:var(--red)}
/* The headline verdict — deliberately the loudest thing on the page. A pilot
   scanning fast should get the answer before reading a single table row. */
.headline{display:flex;align-items:center;gap:12px;margin-bottom:14px;padding:14px 16px;
  border-radius:10px;font-size:19px;font-weight:800;line-height:1.3}
.headline .hl-icon{font-size:28px;line-height:1}
.headline .hl-sub{display:block;font-size:12.5px;font-weight:600;opacity:.85;margin-top:2px}
.headline.pass{background:rgba(47,191,113,.14);border:1px solid rgba(47,191,113,.55);color:#8fe8b4}
.headline.fail{background:rgba(224,69,58,.16);border:1px solid rgba(224,69,58,.6);color:#f7b3ac}
.warnbox{margin-bottom:12px;font-size:12.5px;line-height:1.5;color:#f0c274;
  background:rgba(232,161,58,.12);border:1px solid rgba(232,161,58,.45);border-radius:8px;padding:9px 11px}
.disclaimer{margin-top:14px;font-size:12px;line-height:1.5;color:var(--mut);
  background:rgba(232,161,58,.08);border:1px solid rgba(232,161,58,.3);border-radius:8px;padding:10px}
.hide{display:none !important}

/* buttons */
.btn{background:var(--field);color:var(--ink);border:1px solid var(--line);border-radius:8px;
  padding:8px 12px;font-size:13px;font-weight:600;cursor:pointer}
.btn:hover{border-color:var(--accent);color:#fff}

/* account.html */
/* Wide enough for the five account tabs to sit on one line. The sign-in /
   sign-up / reset cards stay narrow below — a full-width login form looks
   wrong and is harder to scan. */
.account-layout{grid-template-columns:1fr;max-width:680px;margin:0 auto}
.account-layout #view-signin,
.account-layout #view-signup,
.account-layout #view-reset,
.account-layout #view-new-password{max-width:420px;margin:0 auto;width:100%}
/* .card h2 is --mut uppercase, which is right for the calculator's panel
   labels but too faint for this page's actual headings. */
.account-layout .card h2{color:var(--ink);font-size:16px;text-transform:none;letter-spacing:0}
.account-layout label{color:var(--ink);margin-bottom:4px}
.account-layout p{margin:10px 0}
.account-layout .btn{width:100%;padding:10px 12px;font-size:14px}
/* the primary submit in each form */
.account-layout form .btn{background:var(--accent);border-color:var(--accent);color:#fff}
.account-layout form .btn:hover{background:#2f86d1;border-color:#2f86d1}
/* "back to calculator" in the header must stay auto-width */
.topbar .btn{width:auto}
/* make the header back-link read as a real action, not just another chip */
.topbar .btn-back{background:var(--accent);border-color:var(--accent);color:#fff;font-weight:700}
.topbar .btn-back:hover{background:#2f86d1;border-color:#2f86d1;color:#fff;text-decoration:none}
/* second exit at the foot, so a long settings page doesn't strand you */
.btn-back-foot{display:block;text-align:center;margin-top:24px;padding:11px;
  background:var(--field);border:1px solid var(--line);border-radius:8px;
  color:var(--ink);font-weight:600;font-size:13.5px;text-decoration:none}
.btn-back-foot:hover{border-color:var(--accent);color:#fff;text-decoration:none}
.brand-link{color:inherit;text-decoration:none}
.card h2.subhead{margin-top:20px}
.okbox{margin-bottom:12px;font-size:12.5px;line-height:1.5;color:var(--good);
  background:rgba(47,191,113,.12);border:1px solid rgba(47,191,113,.4);border-radius:8px;padding:9px 11px}
.mt-btn{margin-top:16px}
.plan-list{margin:6px 0 10px;padding-left:20px;font-size:13px;line-height:1.6}

/* free-weather demo aerodromes hint (index.html, free tier only) */
.demo-hint{margin-top:8px;font-size:12px;line-height:1.6;color:var(--mut);
  background:rgba(58,151,230,.08);border:1px solid rgba(58,151,230,.35);
  border-radius:8px;padding:8px 10px}
.demo-hint strong{color:var(--ink);font-weight:600}
.demo-hint a.demo-ad{white-space:nowrap}

/* admin role-preview bar */
.admin-bar{display:flex;align-items:center;flex-wrap:wrap;gap:8px;
  padding:8px 20px;font-size:12px;color:var(--ink);
  background:rgba(232,161,58,.12);border-bottom:1px solid rgba(232,161,58,.45)}
.admin-tag{font-weight:700;letter-spacing:.08em;color:var(--warn)}
.admin-role{background:var(--field);color:var(--mut);border:1px solid var(--line);
  border-radius:6px;padding:4px 9px;font-size:12px;font-weight:600;cursor:pointer}
.admin-role:hover{color:var(--ink);border-color:var(--warn)}
.admin-role.on{background:var(--warn);border-color:var(--warn);color:#221604}
.admin-note{color:var(--mut);font-style:italic}

/* upgrade prompt */
.upsell{position:fixed;inset:0;z-index:60;display:flex;align-items:center;justify-content:center;
  background:rgba(6,10,15,.72);padding:20px}
.upsell-box{position:relative;background:var(--card);border:1px solid var(--line);
  border-radius:14px;padding:22px;max-width:420px;width:100%;
  box-shadow:0 18px 50px rgba(0,0,0,.55)}
.upsell-box h3{margin:0 0 10px;font-size:18px;color:var(--ink)}
.upsell-why{margin:0 0 10px;color:var(--warn);font-size:13px}
.upsell-box ul{margin:0 0 14px;padding-left:20px;font-size:13.5px;line-height:1.7;color:var(--ink)}
.upsell-price{font-size:15px;margin:0 0 4px;color:var(--ink)}
/* Checkout. The monthly button is primary and the annual one is not: monthly
   is the honest default for a training subscription that gets used for the
   length of a rating, not forever, and pushing the annual commitment at
   someone who needs six weeks is how you earn a refund request. */
.plan-buy{display:flex;gap:10px;flex-wrap:wrap;margin:10px 0 6px}
.plan-buy .btn{width:auto;flex:0 1 auto}
.plan-buy .btn:disabled{opacity:.6;cursor:default}
.checkout-err{color:var(--red)}
.upsell-x{position:absolute;top:10px;right:12px;background:none;border:none;
  color:var(--mut);font-size:22px;line-height:1;cursor:pointer;padding:2px 6px}
.upsell-x:hover{color:var(--ink)}
.upsell-cta{display:block;text-align:center;margin-top:14px;
  background:var(--accent);border-color:var(--accent);color:#fff;padding:11px;font-size:14px}
.upsell-cta:hover{background:#2f86d1;color:#fff;text-decoration:none}
.upsell-later{display:block;width:100%;margin-top:8px;background:none;border:none;
  color:var(--mut);font-size:12.5px;cursor:pointer;padding:6px}
.upsell-later:hover{color:var(--ink)}

/* historic-plan banner — deliberately high-contrast and full width, because
   mistaking historic conditions for live weather is the failure mode here */
.plan-banner{display:flex;align-items:center;flex-wrap:wrap;gap:10px;
  padding:10px 20px;font-size:13px;color:#12202c;
  background:linear-gradient(180deg,#f0c274,#e8a13a);
  border-bottom:2px solid #b87d1c;position:sticky;top:0;z-index:6}
.pb-tag{font-weight:800;letter-spacing:.09em;font-size:11px;
  background:#12202c;color:#f0c274;padding:3px 8px;border-radius:4px}
.pb-txt{flex:1 1 260px}
.pb-txt strong{font-weight:700}
.pb-exit{color:#12202c;font-weight:700;text-decoration:underline;white-space:nowrap}
.pb-exit:hover{color:#000;text-decoration:underline}
/* the topbar is sticky too — push it below the banner so both stay visible */
body.viewing-plan .topbar{top:0}

/* account page: header + tabs */
.acct-head{display:flex;align-items:flex-start;justify-content:space-between;gap:12px;margin-bottom:14px}
.acct-head h2{margin:0 0 2px}
.acct-email-line{margin:0;font-size:12.5px}
.acct-email-line strong{color:var(--ink)}
.account-layout .btn-logout{width:auto;padding:7px 11px;font-size:12.5px;flex:none}
/* One line at normal widths; on a narrow phone it scrolls sideways rather
   than wrapping into a ragged second row. */
.acct-tabs{display:flex;flex-wrap:nowrap;gap:2px;margin-bottom:16px;
  border-bottom:1px solid var(--line);padding-bottom:0;
  overflow-x:auto;scrollbar-width:none}
.acct-tabs::-webkit-scrollbar{display:none}
.acct-tab{background:none;border:none;border-bottom:2px solid transparent;
  color:var(--mut);padding:9px 12px;font-size:13px;font-weight:600;cursor:pointer;
  border-radius:6px 6px 0 0;white-space:nowrap;flex:0 0 auto}
.acct-tab:hover{color:var(--ink);background:rgba(255,255,255,.03)}
.acct-tab.active{color:var(--accent);border-bottom-color:var(--accent)}
.acct-pane h3{margin:0 0 10px;font-size:14px;color:var(--ink);font-weight:700}
.acct-pane h3.pane-sub{margin-top:22px;padding-top:16px;border-top:1px solid var(--line)}
/* Fields fill the card width — a 460px cap left a dead gutter down the right
   of the wider card. Explanatory paragraphs keep a reading-width limit,
   because full-width prose at this size is genuinely harder to read. */
.acct-pane .grp,
.acct-pane form,
.acct-pane .pw-rules{max-width:none}
.acct-pane > p.u{max-width:62ch}
.account-layout .acct-pane .btn{max-width:none}
/* the primary action in a pane should read as primary, like the form submits */
.account-layout #btn-save-prefs{background:var(--accent);border-color:var(--accent);color:#fff}
.account-layout #btn-save-prefs:hover{background:#2f86d1;border-color:#2f86d1}
/* paired fields get more breathing room at the wider size */
.acct-pane .grp.two{gap:14px}
/* labels sit closer to their field than to the block above */
.acct-pane .grp{margin-bottom:14px}

/* public plans & pricing (signed out) */
.plan-grid{display:grid;grid-template-columns:1fr 1fr;gap:12px;margin:4px 0 14px}
@media(max-width:560px){ .plan-grid{grid-template-columns:1fr} }
.plan-col{background:var(--field);border:1px solid var(--line);border-radius:10px;padding:14px}
.plan-col.plan-paid{border-color:rgba(58,151,230,.55);background:rgba(58,151,230,.07)}
.plan-name{font-size:12px;text-transform:uppercase;letter-spacing:.08em;color:var(--mut);font-weight:700}
.plan-price{font-size:26px;font-weight:700;color:var(--ink);margin-top:4px}
.plan-per{font-size:13px;font-weight:500;color:var(--mut)}
.plan-alt{font-size:12.5px;color:var(--mut);margin-top:2px}
.plan-save{color:var(--good);font-weight:700}
.plan-feats{list-style:none;margin:12px 0 0;padding:0;font-size:12.5px;line-height:1.75}
.plan-feats li::before{content:'✓ ';color:var(--good);font-weight:700}
.plan-feats li.no{color:var(--mut)}
.plan-feats li.no::before{content:'✗ ';color:var(--mut)}
.plan-trial{margin-top:12px;font-size:12px;font-weight:700;color:var(--accent)}
.pricing-cta{display:flex;flex-direction:column;gap:8px;margin-top:4px}
.pricing-cta .btn{width:100%;padding:11px;font-size:14px}
.btn-primary{background:var(--accent);border-color:var(--accent);color:#fff}
.btn-primary:hover{background:#2f86d1;border-color:#2f86d1;color:#fff}
.pricing-foot{text-align:center;margin-top:14px}

/* feedback: header button, modal, admin list */
/* .topbar-actions is defined once with the header, above — a second copy here
   came later in the cascade and quietly dropped its margin-left:auto. */
.fb-open{width:auto;flex:none}
.fb-box textarea{width:100%;margin-top:4px;background:var(--field);border:1px solid var(--line);
  color:var(--ink);border-radius:8px;padding:9px 10px;font-size:14px;
  font-family:inherit;line-height:1.5;resize:vertical;min-height:110px}
.fb-box textarea:focus{outline:none;border-color:var(--accent)}
.fb-send{width:100%;background:var(--accent);border-color:var(--accent);color:#fff;
  padding:11px;font-size:14px;margin-top:4px}
.fb-send:hover{background:#2f86d1;border-color:#2f86d1;color:#fff}
.fb-send:disabled{opacity:.6;cursor:default}

.fb-unread{display:inline-block;background:rgba(58,151,230,.18);color:var(--accent);
  border-radius:10px;padding:2px 9px;font-size:11.5px;font-weight:700;margin:0 0 10px}
.fb-list{list-style:none;margin:0;padding:0}
.fb-item{padding:11px 0;border-bottom:1px solid var(--line)}
.fb-item:last-child{border-bottom:none}
.fb-item.fb-done{opacity:.55}
.fb-msg{font-size:13.5px;line-height:1.55;color:var(--ink);white-space:pre-wrap;word-break:break-word}
.fb-item.fb-new .fb-msg{border-left:3px solid var(--accent);padding-left:10px}
.fb-meta{font-size:11.5px;margin-top:5px}
.fb-actions{display:flex;gap:4px;margin-top:7px}
.fb-status{background:var(--field);border:1px solid var(--line);color:var(--mut);
  border-radius:5px;padding:3px 9px;font-size:11px;font-weight:600;cursor:pointer;text-transform:capitalize}
.fb-status:hover{color:var(--ink);border-color:var(--accent)}
.fb-status.on{background:var(--accent);border-color:var(--accent);color:#fff}

/* admin error log */
.err-h{margin:16px 0 8px;font-size:12px;text-transform:uppercase;letter-spacing:.07em;color:var(--mut)}
.err-list{list-style:none;margin:0;padding:0}
.err-list li{padding:9px 0;border-bottom:1px solid var(--line);font-size:12.5px;line-height:1.5}
.err-list li:last-child{border-bottom:none}
.err-count{display:inline-block;background:rgba(224,69,58,.18);color:var(--red);
  border-radius:10px;padding:1px 7px;font-weight:700;font-size:11.5px;margin-right:6px}
.err-badge{display:inline-block;border-radius:4px;padding:1px 6px;font-size:11px;
  font-weight:700;margin-right:6px;background:rgba(224,69,58,.18);color:var(--red)}
.err-badge.err-warn{background:rgba(232,161,58,.18);color:var(--warn)}
.err-msg{color:var(--ink);word-break:break-word}
.err-meta{display:block;font-size:11.5px;margin-top:2px}
.err-stack{white-space:pre-wrap;word-break:break-word;font-size:11px;color:var(--mut);
  background:var(--field);border:1px solid var(--line);border-radius:6px;
  padding:8px;margin:6px 0 0;max-height:220px;overflow:auto}

/* feature-usage table (admin) */
.usage-tbl{width:100%;border-collapse:collapse;font-size:12.5px}
.usage-tbl th{text-align:left;font-weight:600;color:var(--mut);font-size:11px;
  text-transform:uppercase;letter-spacing:.06em;padding:0 8px 6px 0;border-bottom:1px solid var(--line)}
.usage-tbl td{padding:7px 8px 7px 0;border-bottom:1px solid var(--line);
  vertical-align:middle;position:relative}
.usage-tbl td:first-child{min-width:180px}
.usage-tbl tr:last-child td{border-bottom:none}
.usage-bar{position:absolute;left:0;top:4px;bottom:4px;background:rgba(58,151,230,.14);
  border-radius:3px;z-index:0}
.usage-name{position:relative;z-index:1;font-family:ui-monospace,Menlo,Consolas,monospace;
  font-size:12px;color:var(--ink)}
.usage-label{position:relative;z-index:1;display:block;font-size:11px}

/* selected-aerodrome chips (profile: home + favourites) */
.chips{display:flex;flex-wrap:wrap;gap:6px;margin-top:8px}
.chip{display:inline-flex;align-items:center;gap:6px;
  background:rgba(58,151,230,.14);border:1px solid rgba(58,151,230,.45);
  border-radius:20px;padding:4px 6px 4px 11px;font-size:12.5px;color:var(--ink)}
.chip-x{background:none;border:none;color:var(--mut);font-size:16px;line-height:1;
  cursor:pointer;padding:0 4px;border-radius:50%}
.chip-x:hover{color:var(--red)}
/* the account page's autocomplete list must clear the label above it */
.account-layout .ac-wrap .ac-list{top:auto}

/* live password-requirement checklist */
.pw-rules{list-style:none;margin:0 0 12px;padding:0;font-size:12px;line-height:1.8;color:var(--mut)}
.pw-rules li::before{content:'○ ';color:var(--mut)}
.pw-rules li.met{color:var(--good)}
.pw-rules li.met::before{content:'✓ ';color:var(--good)}
.pw-rules li.unmet{color:var(--warn)}
.pw-rules li.unmet::before{content:'✗ ';color:var(--warn)}

/* saved flight-plan history (account page) */
.plan-history{list-style:none;margin:0;padding:0}
.plan-history li{display:flex;align-items:center;justify-content:space-between;gap:10px;
  padding:10px 0;border-bottom:1px solid var(--line);font-size:13px}
.plan-history li:last-child{border-bottom:none}
.plan-meta{min-width:0}
.plan-actions{display:flex;gap:6px;flex:none}
.plan-history .btn{width:auto;padding:5px 10px;font-size:12px;background:var(--field);
  border-color:var(--line);color:var(--mut)}
.plan-history .plan-open{color:var(--link);border-color:var(--line);text-decoration:none}
.plan-history .plan-open:hover{border-color:var(--accent);color:#fff;text-decoration:none}
.plan-history .plan-del:hover{border-color:var(--red);color:var(--red)}
.print-btn{margin-left:8px}

/* aerodrome autocomplete */
.ac-wrap{position:relative}
/* Above the phone bottom bar (z-index 40) — a long suggestion list on a
   scrolled page would otherwise disappear behind it — but still below the
   upgrade modal and the entry gate. */
.ac-list{position:absolute;left:0;right:0;top:100%;z-index:45;margin-top:2px;max-height:260px;overflow:auto;
  background:#0c1520;border:1px solid var(--line);border-radius:8px;box-shadow:0 8px 24px rgba(0,0,0,.5)}
.ac-item{padding:8px 10px;font-size:13px;cursor:pointer;border-bottom:1px solid rgba(255,255,255,.04)}
.ac-item:hover{background:var(--accent);color:#fff}
.ac-item b{font-variant-numeric:tabular-nums}
.ac-pin{display:inline-block;width:14px;color:var(--warn);font-size:12px}
.ac-pin.ac-fav{color:var(--accent)}
.ac-item:hover .ac-pin{color:#fff}
.ac-sub{display:block;font-size:11px;color:var(--mut);margin-left:14px}
.ac-item:hover .ac-sub{color:#dbe9f7}
.ad-info{margin-top:6px;font-size:12px;color:var(--mut)}
.ad-info b{color:var(--ink)}

/* metar */
.metar-blk{margin-bottom:12px}
.metar-row{display:flex;align-items:center;gap:10px}
.metar-status{font-size:12px;color:var(--mut)}
.metar-status.warn{color:var(--warn)}
.metar-raw{margin-top:8px;font-size:12px;background:#0b131b;border:1px solid var(--line);border-radius:8px;padding:8px 10px}
.metar-raw code{color:var(--accent);font-size:12px;word-break:break-word}
.metar-meta{margin-top:4px;color:var(--mut)}
.metar-meta .src{color:#6f8296}
.metar-age{font-weight:700}
.metar-age.fresh{color:var(--good)}
.metar-age.stale{color:var(--red)}
.metar-paste{margin-top:8px}
.metar-paste summary{font-size:12px;color:var(--mut);cursor:pointer}
.metar-paste textarea{width:100%;margin:6px 0;background:var(--field);border:1px solid var(--line);color:var(--ink);
  border-radius:8px;padding:8px;font-size:12px;font-family:ui-monospace,Menlo,monospace}

.rwysel-wrap{margin-bottom:10px;display:flex;align-items:center;gap:12px;flex-wrap:wrap}
.rwysel-wrap label{flex:1;min-width:160px}
.link-btn{background:none;border:none;color:var(--link);font-size:12px;font-weight:600;
  cursor:pointer;padding:2px 0;margin-top:14px}
.link-btn:hover{text-decoration:underline}
.rwy-compare{margin:-2px 0 12px;background:var(--field);border:1px solid var(--line);
  border-radius:8px;padding:8px 10px}
.rwy-compare table{width:100%;border-collapse:collapse;font-size:12.5px}
.rwy-compare th{text-align:left;color:var(--mut);font-weight:600;font-size:11px;
  text-transform:uppercase;letter-spacing:.04em;padding:3px 6px;border-bottom:1px solid var(--line)}
.rwy-compare td{padding:4px 6px;border-bottom:1px solid var(--line);vertical-align:middle}
.rwy-compare tr:last-child td{border-bottom:none}
.rwy-compare tr.rc-current{background:rgba(58,151,230,.08)}
.rwy-compare td.v{text-align:right;font-variant-numeric:tabular-nums}
.rwy-compare .u{color:var(--mut);font-size:11px}
.dist-note{margin-top:6px;font-size:11.5px;line-height:1.45;color:#f0c274;
  background:rgba(232,161,58,.1);border:1px solid rgba(232,161,58,.3);border-radius:7px;padding:7px 9px}
.dist-note em{color:#f5b74e;font-style:normal;font-weight:700}
/* AIP declared-distance block */
.dist-note.dd-aip{color:var(--ink);background:rgba(58,151,230,.08);border-color:rgba(58,151,230,.4)}
.dd-head{font-size:11px;text-transform:uppercase;letter-spacing:.05em;color:var(--accent);font-weight:700;margin-bottom:5px}
.dd-eff{float:right;text-transform:none;letter-spacing:0;color:var(--mut);font-weight:600}
.dd-row{display:flex;flex-wrap:wrap;gap:6px 10px;align-items:baseline}
.dd-cell{font-size:12px;color:var(--mut)}
.dd-cell b{color:var(--ink);font-variant-numeric:tabular-nums}
.dd-cell.dd-use{background:rgba(58,151,230,.22);border-radius:4px;padding:1px 6px}
.dd-cell.dd-use b{color:#fff}
.dd-unit{color:#64788a;font-size:11px}
.dd-foot{margin-top:5px;font-size:11px;color:var(--mut)}
.aip-tag{display:inline-block;background:rgba(58,151,230,.2);color:var(--accent);border-radius:20px;
  padding:1px 8px;font-size:10.5px;font-weight:700}

.sources{margin-top:4px;font-size:11.5px;line-height:1.55;color:var(--mut);
  border-top:1px dashed var(--line);padding-top:10px}
.sources .src-title{text-transform:uppercase;letter-spacing:.06em;font-size:10.5px;color:#6f8296;margin-bottom:4px}
.sources a{color:var(--accent);text-decoration:none}
.sources a:hover{text-decoration:underline}

.print-only{display:none}

/* ---------- print / save-as-PDF : #print-root, one chart per page ---------- */
#print-root{display:none}
@media print{
  @page{size:A4 portrait;margin:9mm}
  html,body{background:#fff !important;color:#000 !important;
    -webkit-print-color-adjust:exact;print-color-adjust:exact}
  /* Hide the live app. This must cover every body-level element, not just the
     topbar/layout — the admin bar, upgrade modal, saved-plan banner and
     disclaimer gate all sit outside .layout and would otherwise print on
     page 1. Anything new added at body level needs adding here too. */
  .topbar,.layout,
  #admin-bar,#upsell,#plan-banner,#disclaimer-gate{display:none !important}
  #print-root{display:block}

  /* Deliberately NO fixed height. It used to be 279mm — A4 minus the 9mm @page
     margin above — which only holds where that margin is honoured. iOS Safari
     ignores @page margins entirely and uses its own larger ones, so a box sized
     for ours overflowed the real printable area and spilled EVERY chart onto a
     second sheet (reported from iPad). Content height plus break-after gives
     exactly one page per chart on every browser; the trade is that a short page
     sits top-aligned instead of filling the sheet. */
  .print-page{break-after:page;break-inside:avoid;display:flex;flex-direction:column;
    box-sizing:border-box;
    font:12px/1.35 -apple-system,"Segoe UI",Roboto,Arial,sans-serif;color:#000}
  .print-page:last-child{break-after:auto}

  .pp-head{font-size:15px;font-weight:700;border-bottom:1.5px solid #000;padding-bottom:4px;margin-bottom:6px}
  .pp-ac{letter-spacing:.3px}
  /* Which leg this sheet is about. On a kneeboard, mistaking the departure
     page for the destination page is the most dangerous way this pack can be
     misread, so the leg is named in the heading rather than left to be
     inferred from the aerodrome row in the table below. */
  .pp-leg{float:right;font-weight:600;font-size:13px;padding:1px 7px;
    border:1px solid #000;border-radius:4px}
  /* These caps are the whole reason a chart page fits one sheet, and they are
     set for the SMALLEST printable area any target has, not for A4.
     @page margins above are honoured by desktop browsers but ignored by iOS
     Safari, which substitutes its own larger ones; an iPad may also default to
     US Letter, which is 18mm shorter than A4 before margins. Worst case is
     therefore ~250mm of usable height, not the 279mm A4-minus-9mm suggests.
     At 150mm the tallest take-off page came to ~249mm and spilled its last
     footer line onto a second sheet on iPad while fitting everywhere else.
     130mm leaves ~20mm of headroom on the worst combination.
     If you raise this, print a take-off page from an iPad before believing it. */
  .pp-chart{position:relative;flex:0 1 auto;max-height:130mm;text-align:center}
  .pp-chart img{max-width:100%;max-height:130mm;height:auto;border:1px solid #ccc}
  .pp-chart svg{position:absolute;left:50%;top:0;height:100%;width:auto;transform:translateX(-50%)}
  /* the crosswind chart is portrait — cap its height so the tables still fit the page */
  .pp-chart-portrait,.pp-chart-portrait img{max-height:108mm}
  .pp-cond{font-size:11px;color:#444;margin:5px 0 2px}
  .pp-warn{font-size:11px;color:#8a5a00;background:#fdf4e0;border:1px solid #e0b866;
    border-radius:5px;padding:5px 8px;margin:4px 0}

  .pp-tables{display:flex;gap:12px;margin-top:8px;align-items:flex-start}
  .pp-tables table{flex:1;border-collapse:collapse;width:50%}
  .pp-tables caption{text-align:left;font-size:10px;text-transform:uppercase;letter-spacing:.08em;
    color:#555;font-weight:700;padding-bottom:3px}
  .pp-tables td{border:1px solid #aaa;padding:4px 7px;font-size:12px}
  .pp-tables td.k{color:#333;width:55%}
  .pp-tables td.v{text-align:right;font-weight:700;font-variant-numeric:tabular-nums;color:#000}
  /* tr.res marks the headline figure — not a verdict, so it's tinted neutral
     (violet-ish, matching --worst on screen) rather than red. tr.pass/tr.fail
     carry the actual verdict colour and win via source order + !important. */
  .pp-tables tr.res td{background:#f1eafb !important}
  .pp-tables tr.res td.k,.pp-tables tr.res td.v{color:#5b3a91 !important}
  .pp-tables tr.pass td{background:#eaf6ee !important}
  .pp-tables tr.pass td.v{color:#1c7a44 !important}
  .pp-tables tr.fail td{background:#fbeceb !important}
  .pp-tables tr.fail td.v{color:#b3261e !important}
  .pp-tables .badge{display:inline-block;padding:1px 6px;border-radius:10px;font-size:10px;
    font-weight:700;margin-left:5px;border:1px solid #999}
  .pp-tables .badge.ok{background:#e4f6ec !important;color:#1c7a44 !important}
  .pp-tables .badge.no{background:#fbe3e1 !important;color:#b3261e !important}

  .pp-tables td{padding:3px 6px;font-size:11.5px}

  /* ---- factoring-basis page ---- */
  .pp-basis{width:100% !important}
  .pp-basis td{font-size:11px;padding:3px 6px}
  .pp-basis td.k{width:auto}
  .pp-basis tr.res-head td{background:#f2f4f7 !important;font-size:9.5px;font-weight:700;
    text-transform:uppercase;letter-spacing:.06em;color:#555 !important}
  .pp-src{display:block;font-size:9px;color:#777;font-weight:400;margin-top:1px}
  .pp-auth{font-size:10px;color:#555;white-space:nowrap}
  .pp-nil{color:#999}
  /* The note is the argument-settling sentence, not a hazard warning, so it
     drops the amber and reads as a footnote. */
  .pp-basis-note{background:#f7f9fb !important;border-color:#ccd6e0 !important;
    color:#333 !important;font-size:10px;line-height:1.45}

  .pp-foot{margin-top:auto;padding-top:6px;border-top:1px solid #ccc;font-size:10px;color:#666}
}

/* ── Entry disclaimer gate ─────────────────────────────── */
.disclaimer-gate{
  position:fixed;inset:0;z-index:100;
  display:flex;align-items:center;justify-content:center;padding:20px;
  background:rgba(6,11,16,.82);backdrop-filter:blur(4px);
}
body.dg-locked{overflow:hidden}
.disclaimer-box{
  background:var(--card);border:1px solid var(--line);border-top:3px solid var(--warn);
  border-radius:12px;padding:24px 24px 22px;max-width:480px;width:100%;
  box-shadow:0 20px 60px rgba(0,0,0,.5);
}
.disclaimer-box h2{margin:0 0 14px;font-size:19px;color:var(--ink)}
.dg-body p{margin:0 0 12px;color:var(--mut);font-size:14px;line-height:1.55}
.dg-body strong{color:var(--ink)}
.dg-accept{
  width:100%;margin-top:6px;background:var(--accent);color:#fff;border:1px solid var(--accent);
  padding:12px 16px;border-radius:8px;font-size:15px;font-weight:700;cursor:pointer;
}
.dg-accept:hover{filter:brightness(1.08)}

/* ── First-run welcome + aircraft picker ───────────────────
   Shown once ever, before the disclaimer gate above — see index.html's boot
   script. Opaque, not a translucent overlay like the disclaimer: this is the
   very first thing a new visitor sees, nothing meaningful sits behind it yet,
   so it gets to be its own full "arrival" moment rather than a dialog laid
   over content. */
.welcome-gate{
  position:fixed;inset:0;z-index:100;overflow:hidden;
  display:flex;align-items:center;justify-content:center;padding:20px;
  background:
    radial-gradient(ellipse 900px 600px at 50% 105%,rgba(58,151,230,.16),transparent 60%),
    radial-gradient(ellipse 700px 500px at 15% -10%,rgba(232,161,58,.10),transparent 55%),
    linear-gradient(180deg,#0a1017 0%,#0f1720 55%,#0c141c 100%);
}
.wg-scene{position:absolute;left:0;right:0;bottom:0;height:46%;min-height:220px;
  display:flex;align-items:flex-end;justify-content:center;pointer-events:none}
.wg-runway{width:min(900px,140vw);height:100%;opacity:.9}
.wg-lights circle{fill:#ffd98a;filter:drop-shadow(0 0 4px rgba(255,217,138,.85));
  animation:wg-pulse 2.6s ease-in-out infinite}
.wg-lights circle:nth-child(odd){animation-delay:.35s}
.wg-lights circle:nth-child(3n){animation-delay:.7s}
@keyframes wg-pulse{0%,100%{opacity:.5}50%{opacity:1}}
.wg-box{position:relative;z-index:1;background:rgba(24,35,47,.82);
  border:1px solid rgba(255,255,255,.08);border-radius:16px;
  padding:34px 30px 30px;max-width:440px;width:100%;text-align:center;
  box-shadow:0 30px 80px rgba(0,0,0,.6),0 1px 0 rgba(255,255,255,.06) inset;
  backdrop-filter:blur(6px)}
.wg-badge{display:inline-block;font-size:11px;font-weight:800;letter-spacing:.12em;
  color:var(--accent);text-transform:uppercase;margin-bottom:14px}
.welcome-gate h1{margin:0 0 12px;font-size:25px;line-height:1.28;color:var(--ink)}
.welcome-gate h2{margin:0 0 10px;font-size:20px;color:var(--ink)}
.wg-sub{margin:0 0 22px;color:var(--mut);font-size:14px;line-height:1.6}
.wg-cta{width:100%;background:var(--accent);color:#fff;border:1px solid var(--accent);
  padding:13px 16px;border-radius:999px;font-size:15px;font-weight:700;cursor:pointer}
.wg-cta:hover{filter:brightness(1.08)}
.wg-skip{width:auto;display:block;margin:14px auto 0;background:none;border:none;
  color:var(--mut);font-size:12.5px;font-weight:600;cursor:pointer;padding:4px}
.wg-skip:hover{color:var(--ink);text-decoration:underline}

.wg-aircraft{display:grid;grid-template-columns:1fr 1fr;gap:10px;margin-bottom:4px}
.wg-ac{width:auto;position:relative;display:flex;flex-direction:column;align-items:flex-start;
  gap:4px;background:var(--field);border:1px solid var(--line);border-radius:12px;
  padding:14px 12px;cursor:pointer;text-align:left}
.wg-ac:hover{border-color:var(--accent)}
.wg-ac-tag{font-size:9.5px;font-weight:800;text-transform:uppercase;letter-spacing:.06em;
  padding:2px 7px;border-radius:20px;margin-bottom:2px}
.wg-ac-live{background:rgba(47,191,113,.16);color:var(--good)}
.wg-ac-soon-tag{background:rgba(147,164,181,.18);color:var(--mut)}
.wg-ac-name{font-size:14.5px;font-weight:700;color:var(--ink)}
.wg-ac-sub{font-size:11.5px;color:var(--hint)}
.wg-ac-soon{opacity:.72}
.wg-note{margin:14px 0 0;font-size:12.5px;color:var(--warn);line-height:1.5}
.wg-link{width:auto;background:none;border:none;color:var(--accent);font-weight:700;
  font-size:12.5px;cursor:pointer;padding:0;text-decoration:underline}
@media(max-width:420px){
  .wg-box{padding:28px 20px 24px}
  .welcome-gate h1{font-size:22px}
  .wg-aircraft{grid-template-columns:1fr}
}

/* ── Phone layout (Android / iOS) ──────────────────────── */
@media(max-width:560px){
  .topbar{padding:12px 14px}
  .brand .ac{font-size:18px}
  .brand .sub{display:block;margin-left:0;margin-top:2px}
  .layout{padding:12px;gap:12px}
  .card{padding:13px;border-radius:10px}
  /* Paired fields stay two-up on a modern phone — at 412px each column is
     still ~180px, which OAT/QNH and wind dir/speed fit comfortably, and
     stacking them cost about 230px of scroll. Only genuinely narrow screens
     stack now. */
  .two,.grp.two{grid-template-columns:1fr 1fr}
  input,select{font-size:16px}                 /* ≥16px stops iOS zoom-on-focus */
  .results{overflow-x:auto}                     /* results table never clips */
  .resulttbl{font-size:13px}
  .resulttbl td{padding:7px 8px}
  .resulttbl td.res{font-size:15px}
  .tabs{width:100%;flex-wrap:nowrap;overflow-x:auto;-webkit-overflow-scrolling:touch}
  .tabs button{flex:0 0 auto;white-space:nowrap}
}
/* Device safe-areas (notch / home indicator).

   These must apply ONLY where the app really does draw under the system UI:
   an installed PWA, or the Capacitor WebView (which sets html.native). This
   block used to be gated on @supports(padding:max(0px)) alone, which is true
   in every modern browser — so an ordinary browser tab got the lot. Android
   browsers report a non-zero env(safe-area-inset-*) under viewport-fit=cover
   even though their own chrome already occupies that space, which produced
   two reported bugs at once: an empty navy strip above the header, and the
   floating bottom bar parked ~60px above the bottom of the screen.

   Everything downstream reads the two variables rather than env() directly,
   so a browser tab gets 0 and only a real fullscreen surface gets an inset. */
:root{--sa-top:0px;--sa-bottom:0px}
@supports(padding:max(0px)){
  @media (display-mode:standalone),(display-mode:fullscreen),(display-mode:minimal-ui){
    :root{--sa-top:env(safe-area-inset-top,0px);--sa-bottom:env(safe-area-inset-bottom,0px)}
  }
  /* Capacitor reports display-mode: browser, so the native shell opts in
     explicitly — see the class set in index.html. */
  html.native{--sa-top:env(safe-area-inset-top,0px);--sa-bottom:env(safe-area-inset-bottom,0px)}

  /* Left/right stay on env() unconditionally: a landscape notch really does
     eat into the page in an ordinary browser tab too, and these are 0 the rest
     of the time. */
  .topbar{padding-left:max(14px,env(safe-area-inset-left));padding-right:max(14px,env(safe-area-inset-right))}
  .layout{padding-bottom:max(16px,var(--sa-bottom))}

  /* Top inset. `viewport-fit=cover` lets the WebView draw under the status bar,
     so whatever comes first in the document — the admin bar, a plan banner, or
     the header itself — sits beneath the clock and battery icons. Pad the body
     down and paint the strip in the header's own colour so it reads as chrome
     rather than a gap. The sticky header then parks below the strip, not under
     it. All three collapse to nothing in a browser tab. */
  body{padding-top:var(--sa-top)}
  body::before{content:'';position:fixed;left:0;right:0;top:0;
    height:var(--sa-top);background:#1b2937;z-index:9500;pointer-events:none}
  .topbar{top:var(--sa-top)}
}

/* print chart picker */
.pp-picker .pp-list{list-style:none;margin:10px 0 12px;padding:0}
.pp-picker .pp-list li{padding:2px 0}
.pp-picker .pp-list label{display:flex;align-items:center;gap:9px;font-size:14px;
  color:var(--ink);font-weight:500;cursor:pointer;padding:6px 8px;border-radius:7px}
.pp-picker .pp-list label:hover{background:rgba(255,255,255,.04)}
.pp-picker .pp-list input{width:auto;margin:0;accent-color:var(--accent)}
.pp-quick{display:flex;gap:6px;margin-bottom:12px}
.pp-mini{background:var(--field);border:1px solid var(--line);color:var(--mut);
  border-radius:6px;padding:4px 12px;font-size:12px;font-weight:600;cursor:pointer}
.pp-mini:hover{color:var(--ink);border-color:var(--accent)}
.pp-go{width:100%;background:var(--accent);border-color:var(--accent);color:#fff;
  padding:11px;font-size:14px}
.pp-go:hover{background:#2f86d1;border-color:#2f86d1;color:#fff}
/* The .pptx export is the same choice sent somewhere else, so it sits directly
   under Print as a secondary action rather than competing with it. */
.pp-go-alt{margin-top:8px;background:none;color:var(--ink);border-color:var(--line)}
.pp-go-alt:hover{background:rgba(255,255,255,.06);border-color:var(--accent);color:var(--ink)}
.pp-status{margin-top:10px;font-size:13px}
.pp-status-err{color:var(--red)}
/* the picker itself must never appear in the printed output */
@media print{ #print-picker{display:none !important} }

/* ---------- the flight view ---------- */
/* Full width like #learn-view, because it replaces the whole workspace — but
   capped: a four-column table stretched across 1500 px puts the verdict half
   a screen from the leg it belongs to. */
.route{grid-column:1 / -1;max-width:980px}

/* Learn tab (Student mode) — same full-width override as .route above, for
   the same reason: it replaces the chart panel, not just fills its column. */
#learn-view{grid-column:1 / -1;max-width:760px}
.route-intro{max-width:70ch;margin:0 0 14px}
@media print{
  .pp-rt-grp td{background:#eee;font-weight:700;padding-top:7px}
}

/* The whole-flight table — one row per leg, clickable to open that leg on the
   charts. Every chart page gets its verdict for free from its single
   headline; this view has to build one explicitly because it has an answer
   per leg rather than one. Same .resulttbl convention as every other result
   on the page, not a differently-styled row of chips. */
.route-summary{margin:0 0 14px}
/* Same control as the per-leg fold below (js/bases-ui.js's .bx-controls),
   shown here too so changing it doesn't require opening a fold first. */
.rt-fw-toggle{margin-bottom:10px}
.rt-summary-tbl tr.rt-sum-row{cursor:pointer}
.rt-summary-tbl tr.rt-sum-row:hover td{background:rgba(255,255,255,.04)}
.rt-summary-tbl tr.rt-sum-row:focus-visible{outline:2px solid var(--accent);outline-offset:-2px}
.rt-summary-tbl tr.pass td{background:rgba(47,191,113,.07)}
.rt-summary-tbl tr.fail td{background:rgba(224,69,58,.09)}
/* Part-CAT (or any framework with more than one gated row) expands into a
   group row plus one sub-row per factor, so "1 of 3 exceed" never hides
   which two actually fit — the same reason the toggle can't drive the
   headline off a single Part-CAT row either. */
.rt-summary-tbl tr.rt-sum-grp td{font-weight:700;border-bottom:0}
.rt-summary-tbl tr.rt-sum-sub td{font-size:12.5px;color:var(--mut);padding-top:4px;padding-bottom:4px}
.rt-summary-tbl tr.rt-sum-sub:last-of-type td{border-bottom:1px solid var(--line)}
.rt-sum-indent{padding-left:22px !important}

/* ATO organisation pricing */
.ato-h{margin:22px 0 6px;padding-top:18px;border-top:1px solid var(--line);
  font-size:15px;color:var(--ink);font-weight:700}
.ato-calc{max-width:220px}
.ato-quote{background:rgba(58,151,230,.08);border:1px solid rgba(58,151,230,.4);
  border-radius:10px;padding:12px 14px;margin-bottom:12px}
.ato-total{font-size:24px;color:var(--ink)}
.ato-note{margin-top:4px}
.ato-tbl{width:100%;border-collapse:collapse;font-size:12.5px;margin-bottom:14px}
.ato-tbl th{text-align:left;color:var(--mut);font-size:11px;text-transform:uppercase;
  letter-spacing:.06em;padding:0 8px 6px 0;border-bottom:1px solid var(--line)}
.ato-tbl td{padding:6px 8px 6px 0;border-bottom:1px solid var(--line)}
.ato-tbl tr.on td{background:rgba(58,151,230,.12);font-weight:700;color:var(--ink)}
.ato-tbl td.save{color:var(--good);font-weight:700}
.rt-table tr.rt-warn td{background:rgba(232,161,58,.14);color:#f0c274;font-size:12px;
  line-height:1.5;border-left:3px solid var(--warn)}

/* ---------- new-user tutorial ---------- */
.tour-btn{width:auto;padding:8px 12px}
/* Transparent — exists only to swallow clicks so the rest of the page stays
   inert while the tour is open. The dimming itself is the spotlighted
   element's own box-shadow (below), not this. */
.tutorial-scrim{position:fixed;inset:0;z-index:9000;background:transparent;cursor:default}
.tutorial-scrim.hide{display:none}
/* Zero-size, fixed at viewport centre — spotlighting THIS (rather than a
   real element) for the welcome/done steps reuses the exact same mechanism
   to dim the whole page uniformly, no separate code path needed. */
#tutorial-anchor{position:fixed;top:50%;left:50%;width:0;height:0;pointer-events:none}
.tutorial-spot{position:relative !important;z-index:9001;
  box-shadow:0 0 0 9999px rgba(15,23,32,.84);border-radius:10px;
  transition:box-shadow .2s ease}
.tutorial-tip{position:fixed;z-index:9002;width:340px;max-width:calc(100vw - 28px);
  background:var(--card);border:1px solid var(--line);border-radius:12px;
  padding:16px 18px;box-shadow:0 16px 40px rgba(0,0,0,.5)}
.tutorial-tip.hide{display:none}
.tutorial-tip.tutorial-tip-center{top:50%;left:50%;transform:translate(-50%,-50%)}
.tutorial-step{font-size:11px;text-transform:uppercase;letter-spacing:.06em;
  color:var(--mut);font-weight:700;margin-bottom:8px}
.tutorial-tip h3{margin:0 0 8px;font-size:16px;color:var(--ink)}
.tutorial-tip p{margin:0 0 16px;font-size:13.5px;line-height:1.55;color:var(--ink)}
.tutorial-actions{display:flex;align-items:center;justify-content:space-between;gap:10px}
.tutorial-actions>div{display:flex;align-items:center;gap:6px}
.tutorial-actions .btn{width:auto}
.btn-ghost{background:none;border:none;color:var(--mut);font-size:13px;
  font-weight:600;cursor:pointer;padding:8px 6px}
.btn-ghost:hover{color:var(--ink)}
body.tutorial-open{overflow:hidden}
@media (max-width:640px){
  .tutorial-tip{left:14px !important;right:14px;width:auto;max-width:none}
  /* The no-target steps (welcome/done) centre themselves with a transform that
     offsets them by half their width from left:50%. The override above replaces
     the 50% but not the transform, so without dropping the horizontal half of it
     they land half a panel-width off the left edge. Vertical centring stays. */
  .tutorial-tip.tutorial-tip-center{transform:translateY(-50%)}
}

/* Student mode — Learn tab (js/training.js) */
.lesson-list-menu{list-style:none;margin:0;padding:0;display:flex;flex-direction:column;gap:6px}
.lesson-row{display:flex;align-items:center;gap:10px;padding:10px 12px;border:1px solid var(--line);
  border-radius:8px;background:var(--field);cursor:pointer}
.lesson-row:hover{border-color:var(--accent)}
.lesson-row.locked{cursor:pointer;opacity:.75}
.lesson-check{width:1.2em;color:var(--good);font-weight:700}
.lesson-row-title{flex:1;color:var(--ink);font-weight:600}
.lesson-tag{font-size:11px;text-transform:uppercase;letter-spacing:.04em;color:var(--mut);
  border:1px solid var(--line);border-radius:5px;padding:2px 6px}
.lesson-tag.locked{color:var(--warn);border-color:rgba(232,161,58,.45)}
.lesson-reader h3{margin:4px 0 12px;font-size:18px;color:var(--ink)}
.lesson-body{font-size:14px;line-height:1.65;color:var(--ink)}
.lesson-body h4{margin:20px 0 8px;font-size:14px;color:var(--ink)}
.lesson-body p{margin:0 0 12px}
.lesson-body .lesson-lead{font-size:15px;color:var(--ink)}
.lesson-list{margin:0 0 14px;padding-left:20px}
.lesson-list li{margin-bottom:6px}
.lesson-callout{margin:14px 0;font-size:13px;line-height:1.55;color:var(--ink);
  background:rgba(58,151,230,.08);border:1px solid rgba(58,151,230,.35);border-radius:8px;padding:10px 12px}
.lesson-next{color:var(--mut);font-style:italic}
.lesson-try{margin-top:4px}
.lesson-sources{margin-top:18px;padding-top:14px;border-top:1px solid var(--line)}
.lesson-sources h4{margin:0 0 8px;font-size:12px;text-transform:uppercase;letter-spacing:.05em;color:var(--mut)}
.lesson-sources ul{margin:0;padding-left:20px;font-size:12.5px}
.lesson-sources li{margin-bottom:4px}
.lesson-complete{margin-top:18px}
.lesson-complete[disabled]{opacity:.6;cursor:default}
.lesson-back{margin-bottom:10px;padding-left:0}

/* ---------- collapsible panels (js/panels.js) ---------- */
[data-panel]{position:relative}
.panel-toggle{
  position:absolute;top:10px;right:10px;width:30px;height:30px;padding:0;
  background:var(--field);color:var(--mut);border:1px solid var(--line);
  border-radius:8px;cursor:pointer;line-height:1;z-index:2;
}
.panel-toggle:hover{color:var(--ink);border-color:var(--accent)}
/* Chevron drawn in CSS rather than typed as a glyph, so it can rotate. */
.panel-toggle::before{
  content:'';display:block;width:7px;height:7px;margin:0 auto;
  border-right:2px solid currentColor;border-bottom:2px solid currentColor;
  transform:translateY(-2px) rotate(45deg);transition:transform .18s ease;
}
[data-panel].collapsed > .panel-toggle::before{transform:translateY(1px) rotate(-135deg)}
.panel-head{cursor:pointer;padding-right:36px}
.panel-head:hover{color:var(--ink)}
/* Hidden, never detached — see the header comment in js/panels.js. */
[data-panel].collapsed > *:not(.panel-head):not(.panel-toggle){display:none}
[data-panel].collapsed{padding-bottom:12px}
.wind-f .panel-toggle{top:2px;right:2px}
@media print{
  .panel-toggle{display:none !important}
  /* A panel folded on screen must still print in full — the print view is a
     separate document, but this guards the live one being printed directly. */
  [data-panel].collapsed > *{display:revert}
}

/* ---------- drawer menu (js/menu.js) ---------- */
.burger{
  display:none;width:auto;background:var(--field);color:var(--ink);
  border:1px solid var(--line);border-radius:8px;padding:8px 12px;
  font-size:18px;line-height:1;cursor:pointer;
}
.burger:hover{border-color:var(--accent)}
.nav-drawer{position:fixed;inset:0;z-index:9400}
.nav-drawer.hide{display:none}
.drawer-scrim{position:absolute;inset:0;background:rgba(8,13,19,.6)}
.drawer-panel{
  position:absolute;top:0;bottom:0;left:0;width:min(320px,86vw);
  background:var(--card);border-right:1px solid var(--line);
  box-shadow:6px 0 30px rgba(0,0,0,.5);overflow-y:auto;
  padding:14px 14px calc(18px + var(--sa-bottom));
  padding-top:calc(14px + var(--sa-top));
}
.drawer-head{display:flex;align-items:center;justify-content:space-between;margin-bottom:6px}
.drawer-title{font-size:13px;text-transform:uppercase;letter-spacing:.08em;color:var(--mut);font-weight:700}
.drawer-x{background:none;border:none;color:var(--mut);font-size:26px;line-height:1;cursor:pointer;padding:0 4px;width:auto}
.drawer-x:hover{color:var(--ink)}
.drawer-sect{margin-top:14px}
.drawer-sect h3{margin:0 0 6px;font-size:11px;text-transform:uppercase;letter-spacing:.08em;color:var(--mut)}
.drawer-tabs{display:flex;flex-direction:column;gap:6px}
.drawer-row{
  display:block;width:100%;text-align:left;background:var(--field);color:var(--ink);
  border:1px solid var(--line);border-radius:8px;padding:11px 12px;
  font-size:14px;font-weight:600;cursor:pointer;margin-bottom:6px;
}
.drawer-row:hover{border-color:var(--accent);text-decoration:none;color:var(--ink)}
.drawer-row.active{background:var(--accent);border-color:var(--accent);color:#fff}
.drawer-row.locked{opacity:.6;border-style:dashed}
body.menu-open{overflow:hidden}

/* Below this width the header can't hold the tab strip without wrapping into
   several rows, so the tabs move into the drawer and the ☰ appears. */
@media(max-width:900px){
  .burger{display:block}
  /* The tabs come back into the sticky header as a scrollable strip. They
     were the primary navigation hidden behind a hamburger; one tap beats two,
     and a strip that scrolls sideways holds all eight without wrapping. */
  .topbar .tabs{display:flex;order:9;flex:1 0 100%;gap:5px;justify-content:flex-start;
    overflow-x:auto;overflow-y:hidden;scrollbar-width:none;
    -webkit-overflow-scrolling:touch;margin:1px -14px -9px;padding:0 14px 7px;
    scroll-snap-type:x proximity}
  .topbar .tabs::-webkit-scrollbar{display:none}
  .topbar .tabs button{flex:0 0 auto;scroll-snap-align:start;
    padding:6px 11px;font-size:12.5px}
}
@media print{ .burger,.nav-drawer{display:none !important} }

/* ---------- declared distances (four fields, not one) ---------- */
.dd-grid{display:grid;grid-template-columns:1fr 1fr;gap:8px}
.dd-grid label{font-size:11.5px;text-transform:uppercase;letter-spacing:.06em}
/* The one this chart's headline verdict actually gates on. The other three
   are still live — Part-CAT needs them — but only one drives the big answer. */
.dd-grid label.dd-primary{color:var(--accent);font-weight:700}
.dd-grid label.dd-primary input{border-color:var(--accent)}

/* ---------- required distance by basis ---------- */
.bx{margin-top:18px;border-top:1px solid var(--line);padding-top:14px}
.bx-title{margin:0 0 10px;font-size:13px;text-transform:uppercase;letter-spacing:.08em;color:var(--mut)}
.bx-title .bx-sub{display:block;text-transform:none;letter-spacing:0;font-size:12px;
  color:var(--hint);font-weight:400;margin-top:3px}

.bx-headline{display:flex;gap:10px;align-items:flex-start;padding:10px 12px;
  border-radius:9px;border:1px solid var(--line);margin-bottom:12px}
.bx-headline.ok{background:rgba(47,191,113,.10);border-color:rgba(47,191,113,.45)}
.bx-headline.no{background:rgba(224,69,58,.12);border-color:rgba(224,69,58,.5)}
.bx-headline.bx-quiet{color:var(--hint);font-size:13px}
.bx-hl-icon{font-size:17px;line-height:1.2}
.bx-hl-head{display:block;font-weight:700;font-size:15px}
.bx-hl-sub{display:block;font-size:12.5px;color:var(--mut);margin-top:1px}

.bx-controls{display:flex;flex-wrap:wrap;gap:10px;align-items:center;
  justify-content:space-between;margin-bottom:10px}
.bx-mode{display:flex;flex-wrap:wrap;gap:8px;align-items:center}
.bx-ctl-lbl{font-size:11px;text-transform:uppercase;letter-spacing:.07em;color:var(--mut);font-weight:700}
.bx-seg{display:inline-flex;background:var(--field);border:1px solid var(--line);
  border-radius:8px;padding:2px;gap:2px}
.bx-seg-btn{background:none;border:none;color:var(--mut);border-radius:6px;
  padding:5px 10px;font-size:12px;font-weight:600;cursor:pointer;white-space:nowrap}
.bx-seg-btn:hover{color:var(--ink)}
.bx-seg-btn.on{background:var(--accent);color:#fff}
.bx-filter-btn{background:var(--field);border:1px solid var(--line);color:var(--mut);
  border-radius:8px;padding:6px 11px;font-size:12px;font-weight:600;cursor:pointer}
.bx-filter-btn:hover{color:var(--ink);border-color:var(--accent)}
/* What the selected framework means — e.g. Part-CAT's "all three together",
   or Part-NCO's "no number, this is guidance". Full-width prose, unlike the
   36ch-capped .bx-note used inside each table row. */
.bx-fw-note{font-size:12px;color:var(--hint);margin:0 0 11px;max-width:64ch}
.bx-filter{display:flex;flex-direction:column;gap:5px;margin-bottom:11px;
  background:var(--field);border:1px solid var(--line);border-radius:9px;padding:10px 12px}
.bx-filter label{display:flex;align-items:center;gap:8px;font-size:13px;
  color:var(--ink);font-weight:500;cursor:pointer;text-transform:none;letter-spacing:0}
.bx-filter input{width:auto;margin:0;accent-color:var(--accent)}

.bx-scroll{overflow-x:auto}
.bx-table{width:100%;border-collapse:collapse;font-size:13px;min-width:620px}
.bx-table th{text-align:left;font-size:10.5px;text-transform:uppercase;letter-spacing:.07em;
  color:var(--mut);font-weight:700;padding:0 9px 6px;border-bottom:1px solid var(--line)}
.bx-table th.v,.bx-table td.v{text-align:right}
.bx-table td{padding:8px 9px;border-bottom:1px solid var(--line);vertical-align:top}
.bx-table tr:last-child td{border-bottom:0}
.bx-basis{font-weight:600;color:var(--ink);min-width:150px}
.bx-note{display:block;font-weight:400;font-size:11.5px;color:var(--hint);margin-top:2px;
  max-width:36ch;white-space:normal}
.bx-k,.bx-req,.bx-avail{font-variant-numeric:tabular-nums;white-space:nowrap}
.bx-req{font-weight:700;color:var(--ink)}
.bx-avail{color:var(--mut)}
.bx-wet{color:var(--warn);font-size:11.5px}
.bx-none{color:var(--hint)}
.bx-table tr.bx-pass .bx-req{color:var(--good)}
.bx-table tr.bx-fail .bx-req{color:var(--red)}
.bx-table tr.bx-fail td{background:rgba(224,69,58,.07)}
.bx-source a{font-size:12px}
.bx-src-plain{font-size:12px;color:var(--hint)}

/* Force of the source, not how conservative it is — the most demanding
   figure here (Safety Sense ×1.33) carries the least legal weight. */
.bx-chip{display:inline-block;padding:2px 7px;border-radius:10px;font-size:10px;
  font-weight:700;text-transform:uppercase;letter-spacing:.05em;white-space:nowrap}
.bx-law{background:rgba(58,151,230,.16);color:#8cc4f5}
.bx-contract{background:rgba(155,107,219,.18);color:#c3a4ec}
.bx-guidance{background:rgba(232,161,58,.15);color:#eebd77}
.bx-data{background:rgba(147,164,181,.15);color:var(--mut)}

@media(max-width:640px){
  .bx-controls{flex-direction:column;align-items:stretch}
  .bx-mode{justify-content:space-between}
}
/* the basis panel is a decision aid on screen; the print pages carry their
   own factor rows, so it must not appear twice in the PDF */
@media print{ .bx{display:none !important} }

/* ================= progressive disclosure =================
   Three tiers in the input panel: what you must type stays visible, what the
   app worked out becomes a chip, and everything rarely touched folds away —
   but never silently. Every fold carries its own value in the summary, so a
   setting that changes the answer is legible while shut. */

/* ---- derived chips: computed, not entered ---- */
.derived{display:flex;flex-wrap:wrap;gap:6px;margin:0 0 12px}
.der{display:flex;flex-direction:column;align-items:flex-start;gap:1px;
  background:linear-gradient(180deg,rgba(58,151,230,.10),rgba(58,151,230,.05));
  border:1px solid rgba(58,151,230,.30);border-radius:9px;
  padding:6px 10px;cursor:pointer;text-align:left;flex:1 1 auto;min-width:88px}
.der:hover{border-color:var(--accent);background:rgba(58,151,230,.16)}
.der:focus-visible{outline:2px solid var(--accent);outline-offset:2px}
.der-k{font-size:9.5px;text-transform:uppercase;letter-spacing:.09em;color:var(--mut);font-weight:700}
.der-v{font-size:15px;font-weight:700;color:var(--accent);font-variant-numeric:tabular-nums;
  white-space:nowrap}

/* ---- folds ---- */
.fold{border:1px solid var(--line);border-radius:10px;background:var(--field);
  padding:0;margin-bottom:10px}
.fold>summary{list-style:none;cursor:pointer;padding:10px 12px;
  display:flex;align-items:center;gap:10px;justify-content:space-between;
  font-size:13px;font-weight:600;color:var(--ink);border-radius:10px}
.fold>summary::-webkit-details-marker{display:none}
/* the disclosure triangle, drawn rather than inherited so it can sit left */
.fold>summary::before{content:'▸';color:var(--mut);font-size:11px;flex:0 0 auto;
  transition:transform .15s ease}
.fold[open]>summary::before{transform:rotate(90deg)}
.fold>summary:hover{color:var(--accent)}
.fold>summary:focus-visible{outline:2px solid var(--accent);outline-offset:-2px}
.fold-val{margin-left:auto;font-weight:600;font-size:12px;color:var(--mut);
  font-variant-numeric:tabular-nums;text-align:right;white-space:nowrap;
  overflow:hidden;text-overflow:ellipsis;max-width:56%}
/* Non-default contents get an accent so a grass/slope correction is obvious
   from the shut summary alone. */
.fold-active{border-color:rgba(232,161,58,.55)}
.fold-active>summary .fold-val{color:var(--warn)}
.fold-body{padding:2px 12px 12px}
.fold-body>label,.fold-body>.two,.fold-body>.ovr{margin-bottom:9px}
.fold-body>*:last-child{margin-bottom:0}
.fold-sub{font-size:10.5px;text-transform:uppercase;letter-spacing:.08em;
  color:var(--mut);font-weight:700;margin:12px 0 5px}
.fold-cite{font-size:11px;margin-top:8px}
.fold-why{font-size:12px;margin:0 0 8px}
.dd-block{margin-top:4px}

/* results-side folds sit flush in the card rather than as inset boxes */
.res-fold{background:none;border:0;border-top:1px solid var(--line);border-radius:0;margin:0}
.res-fold>summary{padding:10px 2px;border-radius:0;font-size:12.5px;color:var(--mut)}
.res-fold>summary:hover{color:var(--ink)}
.res-fold .fold-body{padding:0 0 12px}

/* ---- headline now carries the number and the basis ---- */
.hl-basis{display:inline-flex;align-items:center;gap:7px;margin-top:7px;
  background:rgba(255,255,255,.06);border:1px solid var(--line);border-radius:20px;
  padding:3px 11px;font-size:11.5px;font-weight:600;color:var(--mut);cursor:pointer}
.hl-basis:hover{color:var(--ink);border-color:var(--accent)}
.hl-chg{color:var(--accent);font-weight:700}
.headline.quiet{background:rgba(255,255,255,.03);border-color:var(--line)}
.headline.quiet .hl-head{color:var(--mut)}

/* the basis panel is inside a fold now — drop its own framing */
.bx{margin-top:0;border-top:0;padding-top:0}
.bx-sub{font-size:12px;color:var(--hint);margin:0 0 10px}

/* Worst-case fold's compact framework-linked verdict — a line, not a second
   headline; the fold's own point is to stay a quiet reference. */
.worst-verdict{font-size:12.5px;color:var(--mut);margin:0 0 9px}
.worst-verdict.fail{color:var(--red)}
.worst-verdict.pass{color:var(--good)}

@media print{ .derived,.fold,.res-fold{display:none !important} }

/* ---- header: fewer competing controls ---- */
/* Tour and Feedback live in the drawer at every width now. The elements stay
   in the DOM because js/menu.js clicks them to do the actual work. */
.hdr-hide{display:none !important}
/* The burger is no longer phone-only: it is how the desktop reaches the drawer
   now that two of the header's buttons moved into it. */
.burger{display:block}
/* Charts on the left, a rule, then Route/Learn — six charts plus two other
   places to be, rather than eight equivalent-looking things. */
.tab-sep{width:1px;align-self:stretch;margin:2px 5px;background:var(--line);flex:0 0 auto}
@media(max-width:900px){ .tab-sep{display:none} }

/* ================= phone navigation =================
   On a phone the sticky header used to wrap to three rows (burger, brand,
   variant switch, account), which ate the top of the scrolled content — that
   was the "inputs box half cut off" bug — and left the bright blue GFC700
   button sitting in a band of its own across the top. The variant switch has
   since moved into the Inputs panel (it's an input, set once per aeroplane,
   not a header/tab concern), which took the widest offender out of this row
   entirely; the rest of the header is now one compact row on a phone. */
@media(max-width:900px){
  /* Wrap is kept — clipping the account button would be worse than a second
     row — but everything is compact enough to make one row the normal case. */
  /* A shadow under the sticky header, so content passing beneath it reads
     as intentional depth rather than as a heading that has been chopped. */
  .topbar{padding:9px 14px;gap:8px;box-shadow:0 6px 16px -8px rgba(0,0,0,.8)}
  /* Two lines, not three: on a phone the header is already carrying the tabs,
     and the mass is in the input panel a thumb-flick away. */
  .flightbar{padding-top:7px;gap:5px}
  .fb-leg{min-width:0;padding:4px 10px}
  .fb-mass{display:none}
  .fb-add{padding:6px 10px;font-size:11.5px}
  .brand .ac{font-size:16px}
  .brand .sub{display:none}                     /* the tab already says where you are */
  /* The account chip and Print collapse to their glyphs and ride the brand
     row. Spelled out they claimed a row of their own for two small controls,
     with a wide dead gap beside them where the workspace should be — about
     45px of a phone screen to say nothing. Both keep their title attribute,
     and both are also in the drawer. */
  .nav-auth .who{padding:3px;max-width:none}
  .nav-auth .who-txt{display:none}
  /* BOTH halves of the label, not just the word: hiding "Print" alone left
     the button reading "[glyph] / PDF / PPT", which is not a thing. */
  .pb-word,.pb-more{display:none}
  .nav-auth a{max-width:120px;padding:6px 10px;font-size:12px}
  /* Cards must clear the sticky header when jumped to, or the heading lands
     underneath it — the same overlap, arrived at a different way. */
  .card{scroll-margin-top:72px}
  /* Room for the bottom bar, plus the home-indicator inset on a notched phone. */
  body{padding-bottom:calc(66px + var(--sa-bottom))}
}

/* Belt and braces: a banner element that has been emptied rather than hidden
   must not leave a coloured strip across the top of the page. */
#admin-bar:empty,#plan-banner:empty{display:none !important}

.mobilebar{display:none}
@media(max-width:900px){
  /* A floating pill, not a strip welded to the bottom edge. Inset, rounded,
     bordered and lifted, so it reads as a panel sitting over the page rather
     than as the end of it. */
  .mobilebar{
    display:grid;grid-template-columns:repeat(3,1fr);gap:3px;
    position:fixed;left:10px;right:10px;z-index:40;
    bottom:calc(9px + var(--sa-bottom));
    background:#2a3a4d;
    border:1px solid #46596e;border-radius:999px;
    padding:5px;
    box-shadow:0 12px 30px -6px rgba(0,0,0,.85),0 1px 0 rgba(255,255,255,.07) inset;
    backdrop-filter:blur(10px);
  }
  /* Route: four legs, not three panels — no icon (nothing reads at a glance
     the way a chart-shaped glyph does for four interchangeable aerodromes),
     so the label stacks role-name over ICAO instead of sitting beside an
     icon on one line. */
  .mb-route .mb-item{flex-direction:column;gap:1px;padding:7px 2px}
  .mb-sub{font-size:10.5px;font-weight:600;color:inherit;opacity:.85}
  .mb-route .mb-item .mb-dot{width:6px;height:6px;margin-top:1px}
  /* Icon and label on ONE line. Stacked, each item was two lines tall and the
     bar took more of the screen than the panel it points at. */
  /* Brighter than --mut: this is navigation, read at a glance from the
     bottom of a phone, not secondary body text. */
  .mb-item{position:relative;background:none;border:0;color:#b8c6d4;
    display:flex;align-items:center;justify-content:center;gap:7px;
    padding:9px 4px;cursor:pointer;border-radius:999px;min-height:42px;
    -webkit-tap-highlight-color:transparent}
  .mb-item:active{background:rgba(255,255,255,.12)}
  /* The section you are actually looking at, updated as you scroll — the bar
     was legible but gave no sense of place. Neutral fill, so the Result item
     can still carry its verdict colour through it. */
  .mb-item.on{background:var(--accent);color:#fff;
    box-shadow:0 2px 8px -2px rgba(58,151,230,.55)}
  .mb-item.on .mb-lbl{font-weight:800}
  .mb-item.on .mb-ico{stroke-width:2.4}
  .mb-item:focus-visible{color:var(--ink);background:rgba(255,255,255,.07);
    outline:2px solid var(--accent);outline-offset:-2px}
  /* Hover only where there IS a hover. On a touchscreen :hover sticks after a
     tap, which left whichever item you last pressed looking permanently
     selected. */
  @media (hover:hover){ .mb-item:hover{color:var(--ink);background:rgba(255,255,255,.06)} }
  .mb-ico{width:19px;height:19px;flex:0 0 auto}
  .mb-lbl{font-size:13px;font-weight:700;letter-spacing:.01em;
    max-width:100%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
  /* The verdict, legible from the bottom of the screen while you are still
     editing inputs at the top — the single most useful thing this bar carries.
     Inline beside the label now that the item is one line. */
  .mb-dot{width:9px;height:9px;border-radius:50%;flex:0 0 auto}
  .mb-pass{background:var(--good);box-shadow:0 0 0 3px rgba(47,191,113,.22)}
  .mb-fail{background:var(--red);box-shadow:0 0 0 3px rgba(224,69,58,.22)}
  .mb-quiet{background:var(--mut)}
  .mb-none{display:none}
  .mobilebar.mb-off{display:none}
  /* The whole item takes the verdict colour, so the answer is readable from
     the corner of your eye rather than needing the dot to be found. */
  .mb-item:not(.on):has(.mb-pass){color:var(--good)}
  .mb-item:not(.on):has(.mb-fail){color:var(--red)}
  /* The drawer and any modal must sit above the bar, not behind it. */
  .nav-drawer{z-index:50}
}
@media print{ .mobilebar{display:none !important} }

/* ---- mass: an assumption until the pilot owns it ----
   Every other number on the page is fetched, looked up or computed. Mass can
   only come from the pilot's own weight and balance, and left at its default
   it produces a complete, confident-looking answer worked out from a number
   nobody entered. Amber rather than red: the 1780 kg default is conservative
   for distance, so this is unowned, not wrong. */
#in-mass.assumed{border-color:rgba(232,161,58,.65);
  background:linear-gradient(180deg,rgba(232,161,58,.10),var(--field))}
#in-mass.assumed:focus{border-color:var(--accent);background:var(--field)}
.mass-hint{margin-top:5px;font-size:11.5px;font-weight:600;color:var(--warn);
  display:flex;align-items:center;gap:6px}
.mass-hint::before{content:'▲';font-size:9px}
.mass-hint.hide{display:none}

/* Below this the two-up pairs genuinely do not fit. */
@media(max-width:379px){ .two,.grp.two{grid-template-columns:1fr} }

/* ================= full-screen chart viewer =================
   The construction lines are the answer — they are how you check the app read
   the nomogram the way you would have — and on a phone the chart is a couple
   of inches wide. See js/chartzoom.js. */

/* The affordance, on the chart itself. Tap-anywhere also works, but an
   invisible target is not a feature. */
.cz-expand{position:absolute;right:8px;bottom:8px;z-index:2;
  width:34px;height:34px;line-height:1;border-radius:9px;cursor:pointer;
  background:rgba(15,23,32,.78);color:#fff;border:1px solid rgba(255,255,255,.28);
  font-size:15px;font-weight:700;backdrop-filter:blur(3px)}
.cz-expand:hover{background:rgba(15,23,32,.92);border-color:var(--accent)}
.cz-expand:focus-visible{outline:2px solid var(--accent);outline-offset:2px}
.chart-wrap{cursor:zoom-in}
@media print{ .cz-expand{display:none !important} }

.cz{position:fixed;inset:0;z-index:200;display:flex;flex-direction:column;
  background:rgba(8,12,17,.97)}
.cz.hide{display:none}
body.cz-lock{overflow:hidden}          /* deliberate: a modal, like the others */

.cz-bar{display:flex;align-items:center;gap:10px;justify-content:space-between;
  padding:calc(8px + var(--sa-top)) 12px 8px;border-bottom:1px solid var(--line);
  background:#141e29}
.cz-cap{font-size:13px;font-weight:700;color:var(--ink);
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.cz-tools{display:flex;gap:6px;flex:0 0 auto}
.cz-btn{min-width:38px;height:38px;border-radius:9px;cursor:pointer;
  background:var(--field);border:1px solid var(--line);color:var(--ink);
  font-size:16px;font-weight:700;padding:0 9px}
.cz-btn:hover{border-color:var(--accent)}
.cz-btn:focus-visible{outline:2px solid var(--accent);outline-offset:2px}
.cz-pct{font-size:12px;font-variant-numeric:tabular-nums;min-width:56px}
.cz-x{background:var(--accent);border-color:var(--accent);color:#fff}

/* touch-action:none so the browser hands us the pinch instead of zooming the
   whole page out from under the viewer. */
.cz-viewport{position:relative;flex:1 1 auto;overflow:hidden;touch-action:none;
  cursor:zoom-out}
.cz-viewport.cz-grab{cursor:grab}
.cz-viewport.cz-grab:active{cursor:grabbing}
/* The image and its overlay move as ONE stage. Transforming them separately is
   how a construction line ends up a few pixels off the curve it was read from. */
.cz-stage{position:absolute;left:0;top:0;transform-origin:50% 50%;
  background:#fff;border-radius:4px;will-change:transform}
.cz-stage img{display:block;width:100%;height:100%}
.cz-stage svg{position:absolute;inset:0;width:100%;height:100%;pointer-events:none}

.cz-hint{padding:7px 12px calc(9px + var(--sa-bottom));text-align:center;
  font-size:11.5px;color:var(--hint);border-top:1px solid var(--line);background:#141e29}
@media (hover:hover){ .cz-hint{display:none} }

/* ---------- Mass & Balance (#mb-view) ---------- */
.mb-sub{margin:18px 0 8px;font-size:12px;text-transform:uppercase;letter-spacing:.07em;color:var(--mut)}
.mb-layout{display:grid;grid-template-columns:1fr 1fr;gap:20px;align-items:start}
@media(max-width:820px){ .mb-layout{grid-template-columns:1fr} }

.mb-fuel-unit{display:flex;align-items:center;gap:10px;margin-bottom:10px}

.mb-envelope{width:100%;max-width:360px;display:block;margin:0 auto 12px}
.mb-grid{stroke:var(--line);stroke-width:1}
.mb-axis{fill:var(--hint);font-size:9px}
.mb-axis-title{fill:var(--mut);font-size:9.5px;text-transform:uppercase;letter-spacing:.06em}
.mb-poly{fill:rgba(58,151,230,.12);stroke:var(--accent);stroke-width:1.5}
.mb-pt{stroke:var(--card);stroke-width:1.5}
.mb-pt-zfm{fill:var(--accent)}
.mb-pt-tow{fill:var(--warn)}
.mb-pt-ldg{fill:var(--good)}
.mb-pt-lbl{font-size:9.5px;font-weight:700}
.mb-pt-lbl.mb-pt-zfm{fill:var(--accent)}
.mb-pt-lbl.mb-pt-tow{fill:var(--warn)}
.mb-pt-lbl.mb-pt-ldg{fill:var(--good)}

.mb-weights td.v{text-align:right;font-variant-numeric:tabular-nums;white-space:nowrap}
.mb-weights tr.fail td{color:var(--red)}
tr.mb-reason td{padding-top:0;font-size:11.5px}

.mb-apply-btn{width:100%;margin-top:10px}
