/* ============================================================
   Festival Circuit — Midnight Aurora shared theme
   Loaded by every sub-page. A "direction" is just the token
   blocks below; the primitives read from those variables.
   ============================================================ */
:root{
  --bg:#181722; --bg2:#201e2e;
  --aurora1:rgba(139,108,255,.10); --aurora2:rgba(90,120,180,.09); --aurora3:rgba(120,110,150,.09);
  --glass:rgba(16,26,56,.62); --glass2:rgba(22,34,78,.70); --glass3:rgba(30,45,98,.80);
  --glass-brd:rgba(110,120,175,.16); --glass-hi:rgba(245,245,255,.05);
  --cardbg:rgba(16,26,56,.75); --cardbg2:rgba(22,34,78,.82);
  --text:#ece9f4; --muted:#a6a2ba; --faint:#726e88;
  --accent:#8B6CFF; --accent2:#6B4CE0; --ink:#16141e;
  --art:#E0598A; --market:#3FC7D9; --healing:#9B5FD9; --community:#4FD1A5; --rodeo:#D9843F;
  --open:#4FD1A5; --closed:#726e88; --good:#4FD1A5; --warn:#FFB067; --info:#4EA8FF;
  /* Text color to use ON TOP OF a solid fill of --closed/--warn (badges) -
     --ink alone only clears 3.73:1 on --closed, below the 4.5:1 WCAG AA text
     minimum; white clears 4.88:1. --open/--warn are light enough that --ink
     already passes on them directly, so only --closed needs its own token. */
  --closed-ink:#ffffff;
  --blur:20px; --ease:cubic-bezier(.2,.7,.3,1);
}
body.light{
  --bg:#eeedf5; --bg2:#e2e0ec;
  --aurora1:rgba(139,108,255,.14); --aurora2:rgba(90,120,180,.12); --aurora3:rgba(120,110,150,.10);
  --glass:rgba(255,254,255,.66); --glass2:rgba(255,254,255,.82); --glass3:rgba(255,252,255,.92);
  --glass-brd:rgba(90,80,150,.15); --glass-hi:rgba(255,255,255,.85);
  --text:#1a1826; --muted:#5f5b74; --faint:#918da8;
  --accent:#5A44C2; --accent2:#4C34A0; --ink:#16141e;
  --art:#B83A6A; --market:#1C8B9C; --healing:#7A3FB0; --community:#1F9E76; --rodeo:#A85A1E;
  --open:#1F9E76; --closed:#918da8; --good:#1F9E76; --warn:#c07a1e; --info:#1868C7;
  --closed-ink:#16141e;
}

*{box-sizing:border-box}
/* Always reserve the scrollbar gutter, on EVERY page, whether or not that page
   scrolls. .topbar is position:fixed;left:0;right:0, so its width is the
   viewport MINUS any scrollbar - which meant the scrolling pages (Your CPK,
   Trust Layer, Submit, Pricing, Settings, Deadline Calendar) had a 1430px bar
   while the non-scrolling map/globe pages had a 1440px one, sliding the whole
   centred nav 5px sideways every time you toggled between the two kinds.
   overflow:hidden still counts as a scroll container, so this reserves the
   gutter on the map/globe pages too and every bar is now the same width. */
html{scrollbar-gutter:stable}
html,body{margin:0;color:var(--text);
  font-family:var(--font-body);line-height:1.45}
body{
  background:#070d1e;
  background-attachment:fixed;padding-top:62px;
}
body.light{
  background:
    radial-gradient(60vw 55vh at 8% -8%, var(--aurora2), transparent 60%),
    radial-gradient(55vw 50vh at 92% 4%, var(--aurora3), transparent 60%),
    radial-gradient(60vw 60vh at 50% 112%, var(--aurora1), transparent 62%),
    linear-gradient(160deg, var(--bg2), var(--bg) 60%);
  background-attachment:fixed;
}
/* Quiet dot texture, OPT-IN via <body class="dotbg"> (2026-09-27): the same treatment as
   index.html's .belowfold, for the content pages (App Tracker, Your CPK, Vendor View, Submit Your
   Event). Opt-in on purpose - this file is shared by pages whose look must not change underneath
   them. A fixed layer at z-index:-1 sits above the root background and below all page content, and
   pointer-events:none keeps it out of every interaction. 1x screens get bigger, brighter dots: a 1px
   dot anti-aliases to near-invisible there (see CLAUDE.md, the dot texture / star field notes). */
body.dotbg::before{content:'';position:fixed;inset:0;z-index:-1;pointer-events:none;
  background-image:radial-gradient(circle,rgba(236,233,244,.075) 1px,transparent 1.5px);
  background-size:22px 22px;background-position:center top}
@media(max-resolution:1.5dppx){body.dotbg::before{
  background-image:radial-gradient(circle,rgba(236,233,244,.24) 1.2px,transparent 1.7px)}}
body.light.dotbg::before{display:none}
/* Never in print: Your CPK has "Print / Save as PDF", and a fixed layer would repeat the dots on
   every printed page of someone's press kit. */
@media print{body.dotbg::before{display:none}}
a{color:var(--accent);text-decoration:none}
a:hover{color:var(--accent);text-decoration:underline}
::selection{background:color-mix(in srgb,var(--accent) 40%,transparent)}
::-webkit-scrollbar{width:10px;height:10px}
::-webkit-scrollbar-thumb{background:var(--accent2);border-radius:20px;border:2px solid transparent;background-clip:content-box}
::-webkit-scrollbar-thumb:hover,::-webkit-scrollbar-thumb:active{background:var(--glass3)}

/* ---------- theme toggle ---------- */
.themebtn{background:var(--glass3);color:var(--text);border:1px solid var(--glass-brd);border-radius:20px;
  font-size:11px;padding:6px 12px;cursor:pointer;transition:.2s var(--ease);backdrop-filter:blur(8px)}
.themebtn:hover{border-color:var(--accent);color:var(--accent);box-shadow:0 0 12px -4px var(--accent)}

/* ---------- glass surfaces ---------- */
.panel,.card{background:var(--glass);border:1px solid var(--glass-brd);border-radius:15px;
  box-shadow:0 1px 0 var(--glass-hi) inset;backdrop-filter:blur(var(--blur)) saturate(1.2);
  -webkit-backdrop-filter:blur(var(--blur)) saturate(1.2)}

/* ---------- form controls ---------- */
input,textarea,select{width:100%;padding:11px 12px;border-radius:12px;border:1px solid var(--glass-brd);
  background:var(--glass);color:var(--text);font-size:13px;font-family:inherit;transition:.2s var(--ease);
  box-shadow:0 1px 0 var(--glass-hi) inset}
textarea{resize:vertical}
input::placeholder,textarea::placeholder{color:var(--faint)}
input:focus,textarea:focus,select:focus{outline:none;border-color:var(--accent);
  box-shadow:0 0 0 3px color-mix(in srgb,var(--accent) 20%,transparent),0 0 22px -8px var(--accent)}
select{appearance:none;-webkit-appearance:none;cursor:pointer;padding-right:34px;
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 12 12'%3E%3Cpath d='M2 4l4 4 4-4' stroke='%238b93b5' stroke-width='1.6' fill='none' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
  background-repeat:no-repeat;background-position:right 12px center}
select:hover{border-color:color-mix(in srgb,var(--accent) 50%,var(--glass-brd))}
option{background:var(--bg2);color:var(--text)}
option:checked{background:var(--accent);color:#fff}
option:hover{background:color-mix(in srgb,var(--accent) 25%,var(--bg2))}
body.light option{background:#fff}
body.light option:checked{background:var(--accent);color:#fff}
body.light option:hover{background:color-mix(in srgb,var(--accent) 16%,#fff)}
input[type=checkbox]{width:auto;box-shadow:none;accent-color:var(--accent)}
input[type=date]{color-scheme:dark}
body.light input[type=date]{color-scheme:light}

/* ---------- buttons ---------- */
.btn{display:inline-block;color:var(--text);
  font-weight:800;border:1.5px solid transparent;border-radius:999px;padding:10px 15px;font-size:12.5px;cursor:pointer;
  transition:.2s var(--ease);
  background:linear-gradient(var(--glass2),var(--glass2)) padding-box,
             linear-gradient(135deg,var(--accent),var(--accent2)) border-box;
  box-shadow:0 0 18px -5px color-mix(in srgb,var(--accent) 70%,transparent),
             inset 0 0 12px -7px var(--accent)}
.btn:hover{transform:translateY(-1px);text-decoration:none;color:var(--text);
  box-shadow:0 0 26px -4px color-mix(in srgb,var(--accent) 82%,transparent),inset 0 0 14px -6px var(--accent)}
.btn:active{transform:translateY(0);box-shadow:inset 0 0 13px -4px var(--accent)}
.btn:focus-visible{outline:none;box-shadow:0 0 0 2px color-mix(in srgb,var(--accent) 55%,transparent)}
.btn.ghost{background:var(--glass);color:var(--text);border:1px solid var(--glass-brd);font-weight:700;box-shadow:0 1px 0 var(--glass-hi) inset}
.btn.ghost:hover{border-color:var(--accent);color:var(--accent);filter:none;box-shadow:0 0 14px -6px var(--accent)}
.pbtn{background:var(--glass);color:var(--text);border:1px solid var(--glass-brd);border-radius:10px;
  font-size:11px;padding:6px 11px;cursor:pointer;transition:.18s var(--ease)}
.pbtn:hover{border-color:var(--accent);color:var(--accent);transform:translateY(-1px)}
.pbtn.primary{color:var(--text);font-weight:800;border:1.5px solid transparent;
  background:linear-gradient(var(--glass2),var(--glass2)) padding-box,
             linear-gradient(135deg,var(--accent),var(--accent2)) border-box;
  box-shadow:0 0 16px -6px color-mix(in srgb,var(--accent) 70%,transparent),
             inset 0 0 10px -7px var(--accent)}
.pbtn.primary:hover{color:var(--text);transform:translateY(-1px);
  box-shadow:0 0 22px -4px color-mix(in srgb,var(--accent) 80%,transparent),inset 0 0 12px -6px var(--accent)}
.pbtn.primary:active{transform:translateY(0);box-shadow:inset 0 0 12px -4px var(--accent)}
.pbtn.primary:focus-visible{outline:none;box-shadow:0 0 0 2px color-mix(in srgb,var(--accent) 55%,transparent)}
.cta{display:inline-block;background:linear-gradient(135deg,var(--accent),var(--accent2));color:var(--ink);
  font-weight:800;padding:9px 15px;border-radius:12px;font-size:12.5px;border:none;cursor:pointer;
  box-shadow:0 0 20px -6px var(--accent)}

/* ---------- role group heads ---------- */
.ghead{display:inline-flex;align-items:center;gap:8px;font-size:11px;font-weight:800;letter-spacing:.04em;
  text-transform:uppercase;color:var(--muted)}
.ghead .gdot{width:11px;height:11px;border-radius:4px;box-shadow:0 0 8px 0 currentColor}

/* ---------- glowing chip pills ---------- */
.pill{cursor:pointer;user-select:none;border:1px solid var(--glass-brd);background:var(--glass);color:var(--text);
  padding:6px 11px;border-radius:999px;font-size:11px;font-weight:600;display:inline-flex;align-items:center;gap:6px;
  transition:.18s var(--ease)}
.pill .dot{width:8px;height:8px;border-radius:50%;box-shadow:0 0 6px 0 currentColor;transition:.18s}
/* Guarded to real hover-capable pointers only (fixed 2026-09-27): without this, tapping a pill on
   a touch device engages :hover with no mouseleave to ever clear it - "sticky hover" - so a
   de-selected pill kept its lifted/colored-border look even after JS correctly removed .on. The
   .on style itself was never the bug; this was a second, unrelated highlight standing in for it. */
@media (hover:hover) and (pointer:fine){
.pill:hover{border-color:var(--pillc,currentColor);transform:translateY(-1px)}
}
.pill:focus-visible,.clearbtn:focus-visible{outline:2px solid var(--pillc,var(--accent));outline-offset:2px}
.pill.on{font-weight:800;color:var(--text);
  border:1.5px solid color-mix(in srgb,var(--pillc,currentColor) 60%,transparent);
  background:transparent!important;
  box-shadow:0 0 11px -4px var(--pillc,currentColor), inset 0 0 9px -8px var(--pillc,currentColor)}
.pill.on .dot{opacity:1}

/* ---------- neon tags ---------- */
.tag,a.tag{font-size:9.5px;padding:3px 9px;border-radius:20px;color:currentColor;font-weight:700;letter-spacing:.01em;
  border:1.5px solid color-mix(in srgb,currentColor 58%,transparent);background:transparent;
  box-shadow:0 0 9px -5px currentColor, inset 0 0 8px -8px currentColor;text-decoration:none;display:inline-block}
a.tag:hover{box-shadow:0 0 13px -3px currentColor, inset 0 0 8px -8px currentColor;text-decoration:none}
a.tag:focus{outline:none}
a.tag:focus-visible{outline:2px solid color-mix(in srgb,currentColor 55%,transparent);outline-offset:2px}
.tag.closed,.tag.tclosed{background:transparent!important;color:var(--closed);
  border:1px dashed color-mix(in srgb,var(--closed) 55%,transparent);text-decoration:line-through;box-shadow:none;font-weight:600}

/* ---------- badges ---------- */
.badge{display:inline-flex;align-items:center;gap:4px;font-size:10px;font-weight:800;letter-spacing:.02em;
  padding:3px 9px;border-radius:20px;background:var(--glass);border:1px solid var(--glass-brd);color:var(--text)}
.badge.gold{background:color-mix(in srgb,var(--accent) 16%,transparent);color:var(--accent);
  border-color:color-mix(in srgb,var(--accent) 55%,transparent)}
.badge.green{background:color-mix(in srgb,var(--good) 16%,transparent);color:var(--good);
  border-color:color-mix(in srgb,var(--good) 55%,transparent)}
.badge.purple{background:color-mix(in srgb,var(--community) 16%,transparent);color:var(--community);
  border-color:color-mix(in srgb,var(--community) 55%,transparent)}

/* ---------- chips (meta) ---------- */
.chip{font-size:9.5px;padding:3px 9px;border-radius:20px;border:1px solid var(--glass-brd);color:var(--muted);
  background:var(--glass);letter-spacing:.02em}

/* ---------- shared page nav ---------- */
.topbar{display:flex;justify-content:space-between;align-items:center;gap:12px 20px;padding:11px 20px;
  background:linear-gradient(180deg,rgba(16,20,40,.82),rgba(12,16,32,.8));
  backdrop-filter:blur(var(--blur)) saturate(1.2);-webkit-backdrop-filter:blur(var(--blur)) saturate(1.2);
  border-bottom:1px solid var(--glass-brd);box-shadow:0 1px 0 var(--glass-hi) inset;position:fixed;top:0;left:0;right:0;z-index:1100;flex-wrap:wrap}
/* ---------- nav geometry (see also: the duplicated copy of these rules inside
   festival-applications-map.html, which does NOT load this file) ----------
   The brand and the account box occupy IDENTICAL fixed-width slots, so
   .navlinks (flex:1 1 0%) lands dead-centre on the viewport by arithmetic -
   no translateX() fudge factor, and no dependence on how wide the account
   box happens to be on this page or for this user.

   Both slots are reserved HERE, in CSS, and never by account.js. That is the
   whole fix for the long-standing "nav jolt": #acctbox is a static div in
   every page's markup, but it had no width until account.js injected its
   stylesheet and filled it, so the first painted frame gave .navlinks ~111px
   too much room (logged out) or ~173px too much (logged in) and the pills
   visibly snapped left the instant that script ran - and when logged in they
   also wrapped to a second row. With the slot reserved up front, frame 1 is
   already the final layout.

   --navslot must stay >= the brand's intrinsic width and >= the widest the
   account box can get; .acctname below is ellipsised so a long display name
   can never push past it.

   BACK TO 200px HERE (2026-09-09) - this is the SHARED default, applying to
   every page that loads this file, including several (submit-festival.html,
   pricing.html, settings.html, deadline-calendar.html, claim-listing.html,
   coyote-press-kit.html, and the retired 2D map/planner pages) that never
   got the mascot icon at all. A real incident, not a hypothetical: this var
   was bumped straight to 230 then 240 to fit the icon on the six pages that
   DO show it, and that silently narrowed every OTHER theme page's nav-pill
   room too - Alex reported submit-festival.html's nav wrapping to a second
   row and overlapping the page content below it, at a window width that
   used to render fine. Fixing the six pages' own need by widening a var
   every non-mascot page also depends on was the actual bug.
   The fix: `--navslot` stays 200 HERE (unaffected, exactly as before this
   whole mascot feature existed), and the six pages that show the icon each
   carry their OWN `:root{--navslot:240px}` override in their own inline
   `<style>` block (see globe.html/circuit-planner-globe.html/tracker.html/
   my-profile.html/vendor-view.html/trust-layer.html) - a page-scoped custom
   property redeclaration, same pattern as index.html's page-scoped `--gut`
   override elsewhere in this project. Every page NOT in that list keeps
   the original, already-verified-safe 200px geometry with zero change.
   **If the mascot's footprint (size/gap) ever changes again, only touch the
   per-page override in those six files - never this shared default**, or
   this exact bug recurs on every other theme-consuming page.
   200px, not more: the brand is left-aligned inside its slot and the account
   box right-aligned inside its, so trimming both by the same amount moves
   NEITHER of them - it only hands the spare width to .navlinks, and the pills
   keep the same absolute centre. Free room: it drops the width at which the
   nav is forced to wrap onto a second row - each 10px trimmed off `--navslot`
   raises or lowers that threshold by roughly 20px (both sides move together).
   Don't go much below 200 - the brand's own text is ~186px and nowrap, so it
   would overflow rather than wrap. */
:root{--navslot:200px;
  /* Pin the nav pills to ONE family instead of letting them inherit each page's
     body font. The map/globe/calendar pages set body to Hanken Grotesk while
     the content pages use Outfit, so identical labels measured differently per
     page (+ Submit Your Event was 152.39px vs 150.53px) and the pills landed on
     slightly different x positions on every toggle. Every page now loads
     Hanken Grotesk at weight 600 for exactly this. */
  --font-nav:'Hanken Grotesk',-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Helvetica,Arial,sans-serif;

  /* ------------------------------------------------------------------
     SITE TYPOGRAPHY - the single place fonts are chosen (2026-09-25).

     These three used to be declared page-by-page: --font-head/--font-body/
     --head-ls existed only on the 5 map/planner pages as page-scoped copies,
     while the 10 content pages hardcoded 'Sora' inline in their own
     .topbar .brandtitle rule and inherited body from the literal stack that
     used to sit on html,body above. Changing a typeface therefore meant
     editing 16 files and missing one.

     Every page now reads these. A page that genuinely needs something
     different overrides the token in its OWN :root - which is exactly what
     the 4 theme-loading map pages do with --font-body, because they run
     Hanken Grotesk for body text while the content pages run Outfit.

     DO NOT put a font-family on the shared .topbar .brandtitle rule to
     "finish" this consolidation. That rule is the one a 2026-09-09 incident
     broke for 8 pages at once; the pages set their own brand font FROM these
     tokens instead, which gets the same single-point-of-change without
     touching it.

     --font-nav is deliberately NOT part of this set. It is pinned separately
     above because pill widths feed the centred nav geometry (first pill
     297.84, last-pill-right 1132.16, wrap threshold 1420px). Retyping the
     nav is a measured change, not a token swap. */
  --font-head:'Outfit',-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Helvetica,Arial,sans-serif;
  --font-body:'IBM Plex Sans',-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Helvetica,Arial,sans-serif;
  --head-ls:-.02em}

/* Headings read --font-head. This rule exists because only the map/planner
   pages ever routed their headings through that token - every content page's
   h1/h2/h3 simply INHERITED the body font, so switching --font-body would
   silently have retyped every heading on the site as well (2026-09-25).

   Deliberately element-level selectors with NO letter-spacing: the lowest
   possible specificity, so any page rule with a class still wins, and pages
   that already tune their own tracking (index.html's hero, pricing.html's
   plan names) keep it. This fills a gap; it does not impose a look. */
h1,h2,h3,h4,h5,h6{font-family:var(--font-head)}
/* flex-direction:column, NOT row - this is the SHARED default, safe for every
   page. A real incident (2026-09-09): this was briefly changed to row here so
   the mascot icon could sit beside the brand text, which broke every OTHER
   theme page that never got the mascot markup - their brandname/brandsub are
   still DIRECT children of .brandtitle (no .brandtext wrapper), so a row
   direction laid them out SIDE BY SIDE instead of stacked, and that much
   wider min-content size pushed .brandtitle's rendered width past its
   200px flex-basis (flex-shrink:0 stops it shrinking below the basis when
   space is tight, but does NOT stop it growing past the basis when content's
   own automatic minimum size is wider - a real CSS flexbox gotcha, not an
   override-precedence issue) - which in turn squeezed .navlinks and forced
   the pills to wrap, on `submit-festival.html` and everywhere else outside
   the six mascot pages. Fixed by reverting the row layout to a page-scoped
   override on just the six pages that have the icon (see each of
   globe.html/circuit-planner-globe.html/tracker.html/my-profile.html/
   vendor-view.html/trust-layer.html's own inline <style> block, right next to
   their --navslot:240px override) instead of changing the shared default. */
.topbar .brandtitle{flex:0 0 var(--navslot);text-decoration:none;display:inline-flex;flex-direction:column;justify-content:center;padding-left:0;transform:none;font-size:21px;font-weight:800;letter-spacing:.01em;color:#fff;line-height:1.1;
  white-space:nowrap;text-shadow:0 0 16px color-mix(in srgb,var(--accent) 30%,transparent)}
  /* Wraps brandname+brandsub so they still stack in a column when a page's own
     override switches .brandtitle to flex-direction:row to fit the mascot
     icon beside them (see the six mascot pages' own page-scoped overrides).
     Harmless here for every other page - nothing references this class
     without also carrying the row override. */
  .topbar .brandtext{display:inline-flex;flex-direction:column;justify-content:center;min-width:0}
  .topbar .brandsub{font-size:9px;font-weight:700;letter-spacing:.2em;text-transform:uppercase;color:var(--muted);text-shadow:none;margin-top:3px;margin-left:0;white-space:nowrap}
  .topbar .brandtitle .coyote{background:linear-gradient(100deg,var(--accent),var(--accent2));-webkit-background-clip:text;background-clip:text;color:transparent}
  /* Temporary placeholder mascot icon (2026-09-09) - see CLAUDE.md's
     coyote-mascot-placeholder.svg entry for why it's a stopgap and how to
     swap it out once the commissioned human-made logo is ready. */
  /* 40px, NOT 46px. The topbar is 11px padding + its tallest flex item, and the
     brand text block is 41.84px - so anything taller than that grows the fixed
     bar. At 46px the bar became 69px while body reserves padding-top:62px,
     putting 7px of content UNDERNEATH it on every page. The 2026-09-09 mascot
     almost certainly shipped that bug unnoticed: its verification measured pill
     positions, never topbar height. Keep this at or below the text block height
     and the documented 63.84px topbar holds. */
  .topbar .brandmascot{flex:0 0 auto;height:40px;width:auto;display:block}
/* Hidden below 640px: account.js's own @media(max-width:640px) rule pulls
   #acctbox out of flow into a small absolute corner overlay (see account.js),
   which leaves .brandtitle's flex:1 1 auto free to stretch under it - the
   mascot, sitting right after the brand text, lands at almost exactly the
   corner badge's own position and renders invisibly behind it. The text
   itself never hit this because it stays near the box's LEFT edge; the icon
   is the first thing added here that reaches far enough right to collide.
   Simplest fix: just don't show it once the corner-overlay layout is active. */
@media(max-width:640px){.topbar .brandmascot{display:none}}
.navlinks{flex:1 1 0%;min-width:0;display:flex;flex-wrap:wrap;justify-content:center;gap:8px;pointer-events:none}
/* Mascot slot beside "+ Submit Your Event" (2026-09-27, Alex's call - it used to sit beside the brand
   title, see .brandmascot above, now unused). `.navmark` is the PLACEHOLDER: keep the span and delete
   only the <img> to leave the slot reserved for a future mark.
   It must not move the pills. .navlinks centres its row, so any real width here would shift every pill
   left by half of it and change the wrap threshold. The margins cancel the slot's footprint exactly:
   gap 8 + margin-left 7 + width 31 + margin-right -46 = 0 net, so the pills sit where they always did
   and the mark simply hangs 15px to the right of the last pill (into the empty space before the account
   slot). It was 10px (margin 2/-41) until Alex asked for it 5px further right - if it moves again,
   change BOTH margins by the same amount or the pills will shift. 40px tall, the same limit as .brandmascot - taller would grow the fixed topbar past 63.84px.
   Hidden in the collapsed hamburger menu (<=1420px), where it would otherwise appear as a stray row. */
.navlinks .navmark{flex:0 0 31px;width:31px;height:40px;margin:0 -46px 0 7px;display:flex;align-items:center;pointer-events:none}
.navlinks .navmark img{height:40px;width:auto;display:block}
@media(max-width:1420px){.topbar.has-navtoggle .navmark{display:none}}
/* The account box's LAYOUT lives here so it exists from the first paint;
   account.js only styles the controls inside it. Do not move flex/width back
   into account.js - that reintroduces the jolt. */
.acctbox{flex:0 0 var(--navslot);min-width:0;display:flex;align-items:center;justify-content:flex-end;gap:8px;position:relative;z-index:1300}
.acctbox #acctContent{min-width:0;display:flex;align-items:center}
/* border-width matches .navlinks a.current's 1.5px on purpose: the current
   page's pill would otherwise be 1px wider than the rest, so every pill after
   it shifted by 1px depending on which page you were on. (At 1x DPR both round
   to 1px and nothing changes visually; at 2x they'd differ.) */
.navlinks a{pointer-events:auto;display:inline-flex;align-items:center;justify-content:center;text-align:center;gap:6px;font-family:var(--font-nav);font-size:13px;font-weight:600;white-space:nowrap;color:var(--text);
  text-decoration:none;padding:10px 16px;border-radius:999px;background:var(--glass);border:1.5px solid var(--glass-brd);transition:.2s var(--ease)}
/* Saved-circuit count badge on the Circuit Planner pill. Absolutely positioned
   ON PURPOSE: account.js sets it after first paint, and anything that changes a
   pill's width after paint shifts the whole centred row. Out of flow = no shift. */
.navlinks a{position:relative}
.navcount{position:absolute;top:-5px;right:-4px;min-width:17px;height:17px;padding:0 4px;
  display:inline-flex;align-items:center;justify-content:center;border-radius:999px;
  font-size:10px;font-weight:800;line-height:1;letter-spacing:0;color:var(--ink);
  background:linear-gradient(135deg,var(--accent),var(--accent2));
  box-shadow:0 0 0 2px color-mix(in srgb,var(--bg2) 82%,transparent),
             0 0 10px -3px color-mix(in srgb,var(--accent) 75%,transparent);
  pointer-events:none}
.topbar .brandstamp{display:none}
/* below the full map layout there isn't room for both reserved slots, so drop
   them together - keeping them in lockstep is what keeps the nav centred */
@media(max-width:1080px){
  .topbar .brandtitle{flex:0 0 auto}
  .acctbox{flex:0 0 auto}
}
/* stack + center the bar on small screens so nothing crowds the title */
@media(max-width:640px){
  .topbar{justify-content:center}
  .topbar .brandtitle{flex-basis:100%;text-align:center;padding-left:0;transform:none}
}
/* ---------- hamburger nav (opt-in via .topbar.has-navtoggle - pages that
   haven't added the checkbox+label markup yet keep the old wrapping behavior
   above untouched, so this is safe to ship before every page is converted) ---------- */
.navtoggle-btn{display:none}
/* Visually hidden but still a real Tab stop - NOT display:none/hidden, which
   would pull the checkbox out of the tab order and leave keyboard users with
   no way to reach or open this menu at all (the label next to it is never
   itself focusable). */
.navtoggle-cb{position:absolute;width:1px;height:1px;padding:0;margin:-1px;
  overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}
.navtoggle-cb:focus-visible + .navtoggle-btn{outline:2px solid var(--accent);outline-offset:2px}
/* RAISED 760px -> 1420px (2026-09-17, closing the long-known "mid-width two-row
   wrap" gap - see the long history in "Working with multiple models" above).
   Measured, not guessed: the wrap threshold is ~1400-1405px on the six mascot
   pages (--navslot 240) and ~1320-1330px on every other page (--navslot 200) -
   1420 clears both with margin. Below this width every page now gets the clean
   hamburger instead of a broken, overlapping two-row nav; above it, nothing
   changes. This fully closes the broken band rather than just shrinking it
   (option (a), shortening labels, was considered and rejected - even with
   every label shortened the band would only shrink, not close). If either
   --navslot value changes again, re-measure both thresholds before assuming
   1420 still clears them. */
@media(max-width:1420px){
  /* Overrides the generic full-width-brand rule above: with a hamburger, brand +
     toggle + account box all fit on one row, which is what keeps the topbar at
     its normal ~62px height - the fixed-position topbar doesn't push body's
     reserved padding-top, so a topbar that grows taller than that overlaps
     whatever is underneath it. That's the actual bug a wrapping nav caused. */
  .topbar.has-navtoggle{justify-content:flex-start;flex-wrap:nowrap;gap:10px}
  .topbar.has-navtoggle .brandtitle{flex-basis:auto;text-align:left;flex:1 1 auto;min-width:0}
  .navtoggle-btn{display:inline-flex;align-items:center;justify-content:center;order:-1;
    flex:0 0 auto;width:36px;height:36px;border-radius:50%;cursor:pointer;font-size:18px;line-height:1;
    background:var(--glass);border:1px solid var(--glass-brd);color:var(--text)}
  .navtoggle-btn:hover{border-color:var(--accent);color:var(--accent)}
  .navtoggle-btn::before{content:'\2630'}
  .navtoggle-cb:checked + .navtoggle-btn::before{content:'\2715'}
  .topbar.has-navtoggle .navlinks{display:none;position:absolute;top:100%;left:0;right:0;
    flex-direction:column;flex-wrap:nowrap;gap:6px;padding:10px 14px 14px;transform:none;
    background:linear-gradient(180deg,rgba(16,20,40,.97),rgba(12,16,32,.97));
    backdrop-filter:blur(var(--blur)) saturate(1.2);-webkit-backdrop-filter:blur(var(--blur)) saturate(1.2);
    border-bottom:1px solid var(--glass-brd);box-shadow:0 18px 40px -20px rgba(0,0,0,.7)}
  .topbar.has-navtoggle .navlinks a{width:100%}
  .topbar.has-navtoggle .navtoggle-cb:checked ~ .navlinks{display:flex}
}
.navlinks a:not(.current):hover{background:color-mix(in srgb,var(--accent) 10%,var(--glass));
  border-color:color-mix(in srgb,var(--accent) 45%,var(--glass-brd));color:var(--accent);transform:translateY(-1px);text-decoration:none}
.pop a.btn, .navlinks a.current{
  border-radius:999px; color:var(--text); border:1.5px solid transparent;
  background:linear-gradient(var(--glass2),var(--glass2)) padding-box,
             linear-gradient(135deg,var(--accent),var(--accent2)) border-box;
  box-shadow:0 0 18px -5px color-mix(in srgb,var(--accent) 70%,transparent),
             inset 0 0 12px -7px var(--accent);
}
.pop a.btn:hover{transform:translateY(-1px);
  background:linear-gradient(var(--glass2),var(--glass2)) padding-box,
             linear-gradient(135deg,var(--open),var(--open)) border-box;
  box-shadow:0 0 22px -3px color-mix(in srgb,var(--open) 85%,transparent),inset 0 0 14px -5px var(--open)}
.pop a.btn:active{transform:translateY(0);
  background:linear-gradient(var(--glass2),var(--glass2)) padding-box,
             linear-gradient(135deg,var(--open),var(--open)) border-box;
  box-shadow:inset 0 0 15px -3px var(--open)}
.pop a.btn:focus-visible{outline:none;box-shadow:0 0 0 2px color-mix(in srgb,var(--accent) 55%,transparent)}
.btn[disabled]{opacity:.4;cursor:not-allowed;background:var(--glass);border-color:var(--glass-brd);box-shadow:none}

/* ---------- Leaflet chrome (planner map) ---------- */
.leaflet-bar{border:none!important;box-shadow:0 6px 20px -8px rgba(0,0,0,.7)!important;border-radius:12px!important;overflow:hidden}
.leaflet-bar a{background:var(--glass2)!important;color:var(--text)!important;border-color:var(--glass-brd)!important;backdrop-filter:blur(10px);transition:.15s;border-radius:50%;box-shadow:0 0 7px -5px var(--accent)}
.leaflet-bar a:hover{background:var(--glass3)!important;color:var(--accent)!important}
.leaflet-control-attribution{background:var(--glass)!important;color:var(--muted)!important;backdrop-filter:blur(8px)}
.leaflet-control-attribution a{color:var(--accent)!important}
.leaflet-popup-content-wrapper{background:var(--cardbg2);backdrop-filter:blur(var(--blur)) saturate(1.3);
  -webkit-backdrop-filter:blur(var(--blur)) saturate(1.3);color:var(--text);border-radius:18px;
  border:1px solid var(--glass-brd);box-shadow:0 20px 50px -18px rgba(0,0,0,.75),0 0 0 1px var(--glass-hi) inset}
.leaflet-popup-tip{background:var(--cardbg2);border:1px solid var(--glass-brd)}
.leaflet-popup-close-button{color:var(--muted)!important}
.leaflet-popup-close-button:hover{color:var(--accent)!important}
.leaflet-popup-content{margin:14px 16px;font-size:13px;line-height:1.5}

/* Hover tooltip: name/city/dates on mouseover, before a click opens the full popup - matches
   globe.html/circuit-planner-globe.html's .gtip MapLibre hover popup as closely as Leaflet allows. */
.leaflet-tooltip.gtip-leaflet{background:rgba(10,12,20,.85);color:#fff;border:1px solid var(--glass-brd);
  border-radius:9px;padding:7px 10px;font-size:12px;line-height:1.35;white-space:normal;max-width:200px;
  box-shadow:0 8px 20px -8px rgba(0,0,0,.8)}
.leaflet-tooltip.gtip-leaflet b{color:var(--accent)}
.leaflet-tooltip-top.gtip-leaflet::before{border-top-color:rgba(10,12,20,.85)}
.leaflet-tooltip-bottom.gtip-leaflet::before{border-bottom-color:rgba(10,12,20,.85)}
.leaflet-tooltip-left.gtip-leaflet::before{border-left-color:rgba(10,12,20,.85)}
.leaflet-tooltip-right.gtip-leaflet::before{border-right-color:rgba(10,12,20,.85)}

@media(prefers-reduced-motion:reduce){
  *{animation-duration:.01ms!important;transition-duration:.01ms!important}
}
