@import url('https://fonts.googleapis.com/css2?family=DM+Sans:ital,opsz,wght@0,9..40,300;0,9..40,400;0,9..40,500;0,9..40,600;0,9..40,700;0,9..40,800;1,9..40,400&family=JetBrains+Mono:wght@300;400;500;600&display=swap');
/* GovExpress shell — tokens, faces, <gx-header>, <gx-footer>. https://govexpress.ai/shell/ */
@font-face{font-family:'Space Grotesk Variable';font-style:normal;font-display:swap;font-weight:300 700;src:url(/_astro/space-grotesk-latin-wght-normal.BhU9QXUp.woff2) format('woff2-variations');unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD}
@font-face{font-family:'Instrument Serif';font-style:italic;font-display:swap;font-weight:400;src:url(/_astro/instrument-serif-latin-400-italic.DKMiL14s.woff2) format('woff2');unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD}

/* ══════════════════════════════════════════════════════════════════════
   GovExpress design tokens — SINGLE SOURCE OF TRUTH
   (feat/site-redesign-arkenstone-ia, Phase 1)

   Both theme blocks are verbatim from the live landing canon
   (reference/landing_live.html — diffed clean against this repo,
   see reference/DISCOVERY.md). Dark navy is the default theme; light
   ships via the existing [data-theme="light"] toggle. Do not invent
   colors — every component consumes these vars; hardcoded hex outside
   this file fails the hex grep gate.
   ══════════════════════════════════════════════════════════════════════ */

/* ══════════════ THEME TOKENS ══════════════ */
html[data-theme="dark"], html:not([data-theme]) {
  --bg: #0c1528;
  --bg2: #121f38;
  --bg3: #182848;
  --card: rgba(18,36,72,.72);
  --card-h: rgba(20,42,84,.85);
  --card-b: rgba(59,130,246,.16);
  --card-bh: rgba(59,130,246,.34);
  --b6: #2563eb;
  --b5: #3b82f6;
  --b4: #60a5fa;
  --b3: #93c5fd;
  --c4: #22d3ee;
  --c3: #67e8f9;
  --g4: #4ade80;
  --a4: #fbbf24;
  --tx1: #f1f5f9;
  --tx2: #cbd5e1;
  --tx3: #94a3b8;
  --tx4: #64748b;
  --tx5: #475569;
  --divider: rgba(59,130,246,.12);
  --glow: .09;
  --hero-fade: #0c1528;
  --toggle-bg: rgba(59,130,246,.12);
  --toggle-b: rgba(59,130,246,.25);
  --nav-bg: rgba(12,21,40,.90);
  --mobile-menu-bg: #0c1528;
  --sb-track: rgba(59,130,246,.08);
  --grad: linear-gradient(135deg, var(--b3), var(--c3));
}

html[data-theme="light"] {
  --bg: #f4f7fc;
  --bg2: #edf1f9;
  --bg3: #e3eaf5;
  --card: #ffffff;
  --card-h: #f0f4ff;
  --card-b: rgba(37,99,235,.18);
  --card-bh: rgba(37,99,235,.38);
  --b6: #1d4ed8;
  --b5: #2563eb;
  --b4: #2563eb;
  --b3: #1d4ed8;
  --c4: #0369a1;
  --c3: #0891b2;
  --g4: #15803d;
  --a4: #b45309;
  --tx1: #0a1628;
  --tx2: #1e293b;
  --tx3: #334155;
  --tx4: #475569;
  --tx5: #64748b;
  --divider: rgba(15,23,42,.12);
  --glow: 0;
  --hero-fade: #020b1a;
  --toggle-bg: rgba(15,23,42,.08);
  --toggle-b: rgba(15,23,42,.18);
  --nav-bg: rgba(244,247,252,.95);
  --mobile-menu-bg: #f4f7fc;
  --sb-track: rgba(37,99,235,.1);
  --grad: linear-gradient(135deg, var(--b6), var(--c4));
}

/* ══════════════ SCALES (theme-independent) ══════════════ */
:root {
  /* spacing — 4/8/12/16/24/32/48/64/88 */
  --sp-1: 4px;
  --sp-2: 8px;
  --sp-3: 12px;
  --sp-4: 16px;
  --sp-6: 24px;
  --sp-8: 32px;
  --sp-12: 48px;
  --sp-16: 64px;
  --sp-22: 88px;
  /* radius */
  --r-sm: 6px;
  --r-md: 10px;
  --r-lg: 16px;
  --r-pill: 999px;
  /* shadows — derived from existing card styles (blue-tinted, low alpha) */
  --shadow-card: 0 1px 2px rgba(2, 11, 26, .18), 0 6px 24px rgba(2, 11, 26, .22);
  --shadow-card-h: 0 10px 36px rgba(37, 99, 235, .22);
}

/* ══════════════ V2 ADDITIONS (feat/site-visual-completion-v2) ══════════════ */
:root{
  /* Action accent — the "one hot color" inside the blue family.
     RESERVED for: primary CTAs (as gradient end), active nav state,
     key stat numbers, gauge needle/fill tip, focus rings. Never body text. */
  --accent-action:#22d3ee;      /* cyan-400 */
  --accent-action-soft:#67e8f9; /* cyan-300 */
  --grad-action:linear-gradient(135deg,#2563eb,#22d3ee);
  /* Foreground for anything sitting ON --grad-action / --accent-action.
     Theme-independent because the gradient itself is: .btn-p has always
     hardcoded #fff here, and this is that value given a name so components
     under the hardcoded-hex gate can use it. */
  --on-accent:#ffffff;

  /* Motion tokens */
  --dur-1:160ms; --dur-2:320ms; --dur-3:640ms;
  --ease-out:cubic-bezier(.16,1,.3,1);
  --rise:12px;                  /* reveal translateY distance */

  /* Duotone recipe (applies to persona/illustration tiles; photo-ready) */
  --duo-base:#0a1628; --duo-tone:#3b82f6; --duo-line:#67e8f9;
}

/* ══════════════ ON-DARK TEXT LADDER (Sprint 11) ══════════════
   Foreground for text that sits on a surface which stays dark in BOTH
   themes — the hero photo band above all. `.hero` has its background pinned
   with !important, so it is navy in the light theme too, while --tx1 there is
   #0a1628: the same navy. Every piece of hero copy was therefore painted
   invisible in light mode (see review/sprint-2/home-light.png, taken before
   this sprint). These are the dark-theme text values given theme-independent
   names, exactly as --on-accent and the --illo-* constants already do.
   Use them ONLY on a surface that does not re-map. */
:root{
  --on-dark-1:#f1f5f9;
  --on-dark-2:#cbd5e1;
  --on-dark-3:#94a3b8;
  --on-dark-4:#64748b;
  /* Link/accent and status equivalents. The light theme darkens its blues and
     its ok/warn pair for white cards, which is right there and wrong on navy
     (#1d4ed8 on #0a1422 is 2.6:1). These are the dark-theme values. */
  --on-dark-link:#60a5fa;
  --on-dark-emph:#93c5fd;
  --on-dark-ok:#4ade80;
  --on-dark-warn:#fbbf24;
}

/* ══════════════ FIXED CHROME (Sprint 11) ══════════════
   The announcement bar's reserved height. Four rules consume it and all four
   live in global.css: the bar's own box, the nav's top offset, <body>'s top
   padding, and the hero's min-height (which SUBTRACTS it, so the first
   screenful stays one screenful and nothing below the hero moves).
   Dismissing the bar sets data-annc="off" on <html>, which zeroes the
   reservation — the attribute selector outranks the media query below it. */
:root{ --annc-h:0px; } /* announcement bar retired 2026-09-20 — nothing dated ships until it can expire itself */
:root[data-annc="off"]{ --annc-h:0px; }


/* ══════════════ V2.1 ILLUSTRATION CONSTANTS ══════════════
   Theme-INDEPENDENT object palette for the 3D illustration set — the
   pieces read as lit objects on the navy field in both themes, so they
   must not re-map with [data-theme]. Values are copied from the token
   canon above (navy ladder from --hero-fade/--duo-base/--bg2/--bg3
   dark values; blue/cyan from the dark-theme brand scale). */
:root{
  --illo-navy-950:#020b1a;
  --illo-navy-900:#0a1628;
  --illo-navy-850:#121f38;
  --illo-navy-800:#182848;
  --illo-blue-600:#2563eb;
  --illo-blue-500:#3b82f6;
  --illo-blue-400:#60a5fa;
  --illo-blue-300:#93c5fd;
  --illo-cyan-400:#22d3ee;
  --illo-cyan-300:#67e8f9;
  --illo-green-400:#4ade80;
  --illo-amber-400:#fbbf24;
}

/* ══════════════ V3 EDITORIAL TYPE SCALE (§2 — replaces v2 clamps) ══════════
   Display face Space Grotesk 500–600 (never 700+ at display sizes),
   emphasis face Instrument Serif Italic (ONE word per major heading),
   body DM Sans, data JetBrains Mono. See BRAND_DELTA.md. */
:root{
  --font-display:'Space Grotesk Variable','Space Grotesk','DM Sans',sans-serif;
  --font-emph:'Instrument Serif',Georgia,serif;
  /* One Site S1: the body and data faces as tokens, so the app's shell and
     the site name the same stack (plan 5.1 — Inter Tight and Sora leave). */
  --font-body:'DM Sans',-apple-system,BlinkMacSystemFont,'Segoe UI',sans-serif;
  --font-mono:'JetBrains Mono',ui-monospace,monospace;
  /* The fixed header's height on both builds. 44px controls + 4px padding
     top and bottom + the 1px rule. */
  --gx-header-h:53px;
  --fs-hero:clamp(64px,9vw,108px);      /* was 68 max */
  --fs-h2:clamp(44px,5.5vw,68px);       /* was 46 max */
  --fs-h3:clamp(26px,3vw,36px);
  --lh-display:.94;
  --track-display:-0.02em;
  --fs-stat:clamp(72px,10vw,140px);     /* by-the-numbers band */
  --container:1240px;
}

/* ══════════════════════════════════════════════════════════════════════
   The shared shell: <gx-header> and <gx-footer> (One Site plan S1, 6.2).

   Every rule is scoped under one of the two elements, because in the app
   this stylesheet sits beside Tailwind and must not restyle anything it
   does not own. Colours, type and spacing come from tokens.css only; the
   published /shell/gx-shell.css carries both files.

   Phone baseline (plan S1, audit 76/77): every control in the shell is a
   44px tap target at phone widths, and no shell text is under 12px there.
   ══════════════════════════════════════════════════════════════════════ */

/* The shell sets its own type context instead of inheriting the host's:
   on the site body is DM Sans at 1.6 and antialiased, and the app's body is
   whatever the app decides. Without this the same footer measured 460px on
   one build and 426px on the other. */
gx-header, gx-footer {
  display: block;
  font-family: var(--font-body);
  line-height: 1.6;
  color: var(--tx2);
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-align: left;
}
gx-header *, gx-header *::before, gx-header *::after,
gx-footer *, gx-footer *::before, gx-footer *::after { box-sizing: border-box; }
gx-header a, gx-footer a { color: inherit; text-decoration: none; }
gx-header ul, gx-footer ul { list-style: none; margin: 0; padding: 0; }
gx-header p, gx-footer p { margin: 0; }

gx-header .gx-sr {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0,0,0,0); white-space: nowrap; border: 0;
}
gx-header .gx-ic { flex-shrink: 0; display: block; }

gx-header a:focus-visible, gx-header button:focus-visible, gx-header input:focus-visible,
gx-footer a:focus-visible {
  outline: 2px solid var(--b4);
  outline-offset: 3px;
  border-radius: 4px;
}

/* ══════════════ HEADER BAR ══════════════ */
gx-header .gx-nav {
  position: fixed;
  top: var(--annc-h, 0px); left: 0; right: 0;
  z-index: 200;
  height: var(--gx-header-h);
  padding: 4px 0;
  background: var(--nav-bg);
  backdrop-filter: blur(16px);
  -webkit-backdrop-filter: blur(16px);
  border-bottom: 1px solid var(--divider);
  font-family: var(--font-body);
  transition: background .4s, border-color .4s;
}
gx-header .nav-i {
  max-width: var(--container);
  height: 100%;
  margin: 0 auto;
  padding: 0 24px;
  display: flex;
  align-items: center;
  gap: 16px;
}
gx-header .gx-logo {
  display: flex; align-items: center; gap: 9px; flex-shrink: 0;
  min-height: 44px;
}
gx-header .gx-logo-ic {
  width: 28px; height: 28px;
  border-radius: 6px;
  background: linear-gradient(135deg, var(--b5), var(--c4));
  display: flex; align-items: center; justify-content: center;
  font-family: var(--font-mono);
  font-weight: 700; font-size: 12px; color: var(--illo-navy-950);
  flex-shrink: 0;
}
gx-header .gx-logo-tx { font-size: 19px; color: var(--tx1); font-weight: 700; letter-spacing: -.3px; line-height: 1; }
gx-header .gx-logo-tx span { color: var(--b4); }

/* ── search ── */
gx-header .gx-search {
  position: relative;
  display: flex;
  align-items: center;
}
gx-header .gx-search--bar { flex: 1 1 auto; min-width: 0; max-width: 380px; }
gx-header .gx-search-in {
  width: 100%;
  height: 36px;
  padding: 0 40px 0 12px;
  font: 400 13px/1 var(--font-body);
  color: var(--tx1);
  background: var(--toggle-bg);
  border: 1px solid var(--toggle-b);
  border-radius: var(--r-sm);
  -webkit-appearance: none;
  appearance: none;
  text-overflow: ellipsis;
}
gx-header .gx-search-in::placeholder { color: var(--tx3); opacity: 1; }
gx-header .gx-search-in::-webkit-search-cancel-button { display: none; }
gx-header .gx-search-in:focus { border-color: var(--b4); outline: none; }
gx-header .gx-search-in:focus-visible { outline: 2px solid var(--b4); outline-offset: 1px; }
gx-header .gx-search-go {
  position: absolute;
  right: 0; top: 50%;
  transform: translateY(-50%);
  width: 40px; height: 36px;
  display: flex; align-items: center; justify-content: center;
  background: none; border: 0; padding: 0;
  color: var(--tx3);
  cursor: pointer;
}
gx-header .gx-search-go:hover { color: var(--tx1); }

/* ── links ── */
gx-header .nlinks {
  display: flex;
  align-items: center;
  gap: 18px;
  margin-left: auto;
}
gx-header .gx-link, gx-header .ndrop-btn {
  font: 500 13px/1 var(--font-body);
  color: var(--tx3);
  transition: color .2s;
  white-space: nowrap;
}
gx-header .gx-link:hover { color: var(--tx1); }
gx-header .nlinks a[aria-current="page"] { color: var(--accent-action); }
gx-header .gx-cta {
  display: inline-flex; align-items: center; justify-content: center;
  height: 36px;
  padding: 0 16px;
  background: var(--grad-action);
  border-radius: var(--r-sm);
  color: var(--on-accent);
  font: 600 13px/1 var(--font-body);
  white-space: nowrap;
  transition: filter .2s;
}
gx-header .gx-cta:hover { filter: brightness(1.08); }

/* ── dropdowns ──
   CSS-only open (:hover/:focus-within) so they work before any script; the
   client adds .is-open for click and keyboard. */
gx-header .ndrop { position: relative; }
/* The menu hangs 10px below the button. Without something occupying that
   gap the pointer leaves .ndrop on the way down, :hover drops, and the menu
   disappears before it can be clicked — reported live 2026-09-20. This strip
   spans the gap only while the menu is open. */
gx-header .ndrop:hover::after,
gx-header .ndrop:focus-within::after,
gx-header .ndrop.is-open::after {
  content: '';
  position: absolute;
  top: 100%;
  left: -12px;
  right: -12px;
  height: 16px;
}
gx-header .ndrop-btn {
  display: inline-flex; align-items: center; gap: 4px;
  min-height: 44px;
  background: none; border: none; padding: 0;
  cursor: pointer;
}
gx-header .ndrop:hover .ndrop-btn, gx-header .ndrop:focus-within .ndrop-btn, gx-header .ndrop.is-open .ndrop-btn { color: var(--tx1); }
gx-header .ndrop-menu {
  display: none;
  position: absolute;
  top: calc(100% + 4px);
  left: 50%;
  transform: translateX(-50%);
  z-index: 210;
  min-width: 190px;
  padding: 8px;
  background: var(--mobile-menu-bg);
  border: 1px solid var(--card-b);
  border-radius: var(--r-md);
  box-shadow: var(--shadow-card);
}
gx-header .ndrop:hover .ndrop-menu,
gx-header .ndrop:focus-within .ndrop-menu,
gx-header .ndrop.is-open .ndrop-menu { display: block; }
/* Resources: two columns, anchored to the right edge of its button so it
   never runs off the viewport at the narrowest desktop width. */
gx-header .ndrop--end .ndrop-menu { left: auto; right: -40px; transform: none; }
gx-header .ndrop:hover .ndrop-menu--cols,
gx-header .ndrop:focus-within .ndrop-menu--cols,
gx-header .ndrop.is-open .ndrop-menu--cols {
  display: grid;
  grid-template-columns: 200px 180px;
  gap: 8px;
}
gx-header .ndrop-head {
  font: 500 12px/1 var(--font-mono);
  letter-spacing: 2px;
  text-transform: uppercase;
  color: var(--tx3);
  padding: 10px 12px 8px;
}
gx-header .ndrop-col { border-left: 1px solid var(--divider); padding-left: 8px; }
gx-header .ndrop-menu a {
  display: block;
  padding: 8px 12px;
  border-radius: var(--r-sm);
  font: 400 13px/1.4 var(--font-body);
  color: var(--tx2);
  white-space: nowrap;
}
gx-header .ndrop-menu a:hover { color: var(--tx1); background: var(--bg3); }
gx-header .ndrop-menu a[aria-current="page"] { color: var(--accent-action); }

/* ── theme switch ──
   44px hit area; the pill is ::before, the knob ::after. House rule
   2026-09-20: the knob is a hollow ring, never a filled disc. The side it
   sits on says which theme is live and the ring colour follows it. */
gx-header .gx-nav-end { display: flex; align-items: center; gap: 4px; flex-shrink: 0; }
gx-header .gx-toggle {
  position: relative;
  width: 44px; height: 44px;
  background: none; border: 0; padding: 0;
  cursor: pointer;
  flex-shrink: 0;
}
gx-header .gx-toggle::before {
  content: '';
  position: absolute;
  left: 3px; top: 11px;
  width: 38px; height: 22px;
  border-radius: 11px;
  background: var(--toggle-bg);
  border: 1px solid var(--toggle-b);
}
gx-header .gx-toggle::after {
  content: '';
  position: absolute;
  top: 14px; left: 6px;
  width: 16px; height: 16px;
  border-radius: 50%;
  background: transparent;
  border: 2px solid var(--b4);
  transition: left .3s, border-color .3s;
}
[data-theme="light"] gx-header .gx-toggle::after { left: 22px; border-color: var(--a4); }

/* ── hamburger ── */
gx-header .hamburger {
  display: none;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 5px;
  width: 44px; height: 44px;
  padding: 0;
  background: none; border: none;
  cursor: pointer;
  flex-shrink: 0;
}
gx-header .hamburger span {
  display: block;
  width: 22px; height: 2px;
  border-radius: 2px;
  background: var(--tx2);
  transition: transform .3s, opacity .3s;
}
gx-header .hamburger span:nth-child(2) { width: 16px; }
gx-header .hamburger.open span:nth-child(1) { transform: translateY(7px) rotate(45deg); }
gx-header .hamburger.open span:nth-child(2) { opacity: 0; transform: scaleX(0); }
gx-header .hamburger.open span:nth-child(3) { transform: translateY(-7px) rotate(-45deg); }

/* ── phone drawer ── */
gx-header .mobile-menu {
  display: none;
  position: fixed;
  top: calc(var(--gx-header-h) + var(--annc-h, 0px)); left: 0; right: 0;
  z-index: 190;
  flex-direction: column;
  padding: 16px 24px 28px;
  background: var(--mobile-menu-bg);
  border-bottom: 1px solid var(--divider);
  font-family: var(--font-body);
  /* Taller than a phone screen, and the body is scroll-locked while it is
     open, so it scrolls inside the viewport. */
  max-height: calc(100vh - var(--gx-header-h) - var(--annc-h, 0px));
  max-height: calc(100dvh - var(--gx-header-h) - var(--annc-h, 0px));
  overflow-y: auto;
  overscroll-behavior: contain;
}
gx-header .mobile-menu.open { display: flex; }
gx-header .gx-search--drawer { margin-bottom: 8px; }
gx-header .gx-search--drawer .gx-search-in { height: 44px; font-size: 16px; }
gx-header .gx-search--drawer .gx-search-go { width: 44px; height: 44px; }
gx-header .mm-link {
  display: flex; align-items: center;
  min-height: 44px;
  font-size: 15px;
  font-weight: 500;
  color: var(--tx2);
  border-bottom: 1px solid var(--divider);
}
gx-header .mm-link:hover { color: var(--b4); }
gx-header .mm-link[aria-current="page"] { color: var(--accent-action); }
/* Cyan is the active state on navy; on the light ground it measures under
   4.5:1, so the light theme marks the current page in its own blue. */
[data-theme="light"] gx-header a[aria-current="page"] { color: var(--b6); }
gx-header .mm-link--sub { padding-left: var(--sp-3); }
gx-header .mm-group {
  font: 500 12px/1 var(--font-mono);
  letter-spacing: 2.5px;
  text-transform: uppercase;
  color: var(--tx3);
  margin-top: var(--sp-4);
  padding-bottom: 4px;
}
gx-header .mm-foot { display: grid; gap: 10px; padding-top: 20px; }
gx-header .gx-link--block {
  display: flex; align-items: center; justify-content: center;
  min-height: 44px;
  border: 1px solid var(--toggle-b);
  border-radius: var(--r-sm);
  font-size: 14px;
  color: var(--tx1);
}
gx-header .gx-cta--block { display: flex; height: 44px; font-size: 14px; }

/* The desktop row collapses to the hamburger here. 1080 is measured, not a
   device width: below it the five entries, the switch and the button leave
   the search field too narrow to read its own placeholder. site_gates
   measures the row down to the collapse point it discovers. */
@media (max-width: 1080px) {
  gx-header .nlinks { display: none; }
  gx-header .hamburger { display: flex; }
  gx-header .gx-nav-end { margin-left: auto; }
  gx-header .gx-search--bar { max-width: none; }
}
/* On a phone the bar keeps the logo, the switch and the menu; the search
   field moves to the top of the drawer. */
@media (max-width: 640px) {
  gx-header .nav-i { padding: 0 12px 0 16px; gap: 8px; }
  gx-header .gx-search--bar { display: none; }
}

/* ══════════════ FOOTER ══════════════ */
gx-footer .gx-footer {
  padding: var(--sp-16) 0 var(--sp-8);
  border-top: 1px solid var(--divider);
  background: var(--bg2);
  font-family: var(--font-body);
  transition: background .4s;
}
gx-footer .gx-ctr { max-width: var(--container); margin: 0 auto; padding: 0 24px; }
gx-footer .fcols {
  display: grid;
  grid-template-columns: repeat(6, minmax(0, 1fr));
  gap: var(--sp-6);
  margin-bottom: var(--sp-8);
}
gx-footer .fhead {
  font: 500 12px/1 var(--font-mono);
  letter-spacing: 2.5px;
  color: var(--tx3);
  margin-bottom: var(--sp-3);
}
gx-footer .fcol ul { display: grid; gap: 8px; }
gx-footer .fcol ul + ul { margin-top: 8px; padding-top: 8px; border-top: 1px solid var(--divider); }
gx-footer .fcol a { color: var(--tx2); font-size: 13.5px; line-height: 1.4; }
gx-footer .fcol a:hover { color: var(--tx1); }
gx-footer .fmail a {
  font-family: var(--font-mono);
  font-size: 12px;
  letter-spacing: 0.3px;
  color: var(--tx3);
  overflow-wrap: anywhere;
}
gx-footer .fmail a:hover { color: var(--tx1); }
gx-footer .flegal {
  display: flex;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: var(--sp-3);
  font-size: 12.5px;
  color: var(--tx3);
  border-top: 1px solid var(--divider);
  padding-top: var(--sp-6);
}
gx-footer .fmono {
  font-family: var(--font-mono);
  font-size: 12px;
  letter-spacing: 1px;
  color: var(--tx3);
}
@media (max-width: 1100px) {
  gx-footer .fcols { grid-template-columns: repeat(3, minmax(0, 1fr)); }
}
@media (max-width: 640px) {
  gx-footer .gx-footer { padding-top: var(--sp-12); }
  gx-footer .gx-ctr { padding: 0 16px; }
  gx-footer .fcols { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--sp-6) var(--sp-4); }
  /* 44px tap targets: each link is a full-height row, so the list gap goes. */
  gx-footer .fcol ul { gap: 0; }
  gx-footer .fcol a { display: flex; align-items: center; min-height: 44px; }
}
