/* ── Reset & base ──────────────────────────────────────────────── */
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }

:root {
  /* Shell (navy) */
  --color-shell:       #152240;
  --color-shell-deep:  #0e1a30;
  --color-shell-hover: rgba(255,255,255,0.07);
  --color-shell-border:#1e3260;
  --color-shell-text:  #e8edf8;
  --color-shell-muted: #7b92bc;

  /* Content (light) */
  --color-bg:          #f0f3f8;
  --color-surface:     #ffffff;
  --color-border:      #dde2ed;
  --color-text:        #111827;
  --color-muted:       #5b6472;   /* 4.8:1 on the pill grey, 5.4:1 on the table grey (was #6b7280, 3.9:1) */

  /* Brand */
  --color-brand:       #0034A5;
  --color-brand-cream: #FAF9F5;

  /* Accent */
  --color-accent:      #3b7eff;
  --color-accent-pill: #2563eb;   /* the accent's text-bearing form: white on it reads 5.2:1 */
  --color-accent-dim:  rgba(59,126,255,0.12);
  --color-accent-nav:  #7eb3ff;

  /* Badges */
  --color-badge-new:   #0ea96a;
  --color-badge-upd:   #d97706;

  /* Layout */
  --rail-width:        240px;
  --header-height:     56px;
  --font:              'Inter', system-ui, -apple-system, sans-serif;
  --radius:            8px;
  --transition:        180ms ease;

  /* ── Site-wide design system tokens (added 2026-05-01) ──────────
     Consumed by content pages (SEC explorer, FRED dashboard,
     Prospectus issuance) when they <link> this stylesheet.
     Shell tokens above are unchanged. ────────────────────────── */

  /* Accent — content pages on light backgrounds */
  --color-accent-strong:     #1e40af;
  --color-accent-active-bg:  #dbeafe;
  --color-accent-hover-bg:   #f5f5f5;
  --color-accent-hover-bg-2: #e2e8f0;
  --color-row-hover:         #f0f7ff;

  /* Surfaces */
  --color-surface-alt:       #f8fafc;
  --color-surface-table-hdr: #f1f5f9;

  /* Borders (additional roles) */
  --color-border-soft:       #f0f0f0;
  --color-border-strong:     #94a3b8;

  /* Type scale */
  --type-xs:   11px;
  --type-sm:   12px;
  --type-base: 13px;
  --type-md:   14px;
  --type-lg:   16px;
  --type-xl:   18px;

  /* Radii (existing --radius is the lg = 8px) */
  --radius-sm: 4px;
  --radius-md: 6px;

  /* Spacing scale */
  --space-1: 4px;
  --space-2: 8px;
  --space-3: 12px;
  --space-4: 16px;
  --space-5: 24px;

  /* Shadows */
  --shadow-popover: 0 4px 14px rgba(0,0,0,0.12);
  --shadow-tooltip: 0 4px 14px rgba(0,0,0,0.25);

  /* Touch target minimums (Apple HIG = 44px) */
  --touch-target:    44px;
  --touch-target-sm: 36px;
}

html, body {
  height: 100%;
  background: var(--color-shell);
  color: var(--color-text);
  font-family: var(--font);
  font-size: 14px;
  line-height: 1.5;
  -webkit-font-smoothing: antialiased;
}

/* ── Layout shell ──────────────────────────────────────────────── */
#app {
  display: grid;
  grid-template-rows: calc(var(--header-height) + env(safe-area-inset-top, 0px)) 1fr;
  grid-template-columns: var(--rail-width) 1fr;
  grid-template-areas:
    "header header"
    "rail   main";
  height: 100dvh;
  overflow: hidden;
}

/* ── Header ────────────────────────────────────────────────────── */
#header {
  grid-area: header;
  display: flex;
  align-items: center;
  /* Honor iOS notch — viewport-fit=cover lets content extend edge-to-edge
     so the page can bleed under the side bars; this keeps header content
     out of the notch while still using the full viewport. The top inset
     is here too: in home-screen (standalone) mode iOS draws its status bar
     over the top of the page, so the header plate extends under it and the
     logo and Subscribe button sit below it. */
  padding: env(safe-area-inset-top, 0px) max(20px, env(safe-area-inset-right)) 0 max(20px, env(safe-area-inset-left));
  background: var(--color-shell-deep);
  border-bottom: 1px solid var(--color-shell-border);
  gap: 12px;
  z-index: 10;
}

#header .brand {
  display: flex;
  align-items: center;
  text-decoration: none;
}

#header .brand-logo {
  height: 36px;
  width: auto;
  display: block;
}

#header .header-right {
  margin-left: auto;
  display: flex;
  align-items: center;
  gap: 16px;
}

#header .header-right a {
  font-size: 13px;
  color: var(--color-shell-muted);
  text-decoration: none;
  transition: color var(--transition);
}

#header .header-right a:hover { color: var(--color-shell-text); }

/* SUBSCRIBE CTA — emerald green to distinguish from the blue
   selected-nav-pill state (both used the same accent blue before, which
   read as the same UI affordance). Green is the convention for
   subscribe/sign-up CTAs across SaaS (Substack, MailChimp, etc.). */
#header .header-right .btn-primary {
  background: #10b981;
  color: #0b1a2e;   /* navy on the brand green: 6.9:1; white was 2.5:1 */
  padding: 6px 14px;
  border-radius: var(--radius);
  font-weight: 600;
  font-size: 12px;
  letter-spacing: 0.03em;
  text-transform: uppercase;
}

#header .header-right .btn-primary:hover {
  background: #059669;
  color: #0b1a2e;
}

/* ── Left rail ─────────────────────────────────────────────────── */
#rail {
  grid-area: rail;
  background: var(--color-shell);
  border-right: 1px solid var(--color-shell-border);
  overflow-y: auto;
  overflow-x: hidden;
  padding: 12px 0 24px;
  scrollbar-width: thin;
  scrollbar-color: var(--color-shell-border) transparent;
}

#rail::-webkit-scrollbar { width: 4px; }
#rail::-webkit-scrollbar-thumb { background: var(--color-shell-border); border-radius: 2px; }

/* ── Accordion section ─────────────────────────────────────────── */
.nav-section { margin-bottom: 2px; }

.nav-section-header {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 9px 16px;
  cursor: pointer;
  user-select: none;
  transition: background var(--transition);
  position: relative;
}

.nav-section-header:hover { background: var(--color-shell-hover); }
.nav-section-header.open  { background: var(--color-shell-hover); }

.nav-section-icon {
  width: 18px;
  height: 18px;
  flex-shrink: 0;
  color: var(--color-accent-nav);
  opacity: 0.9;
}

.nav-section-label {
  flex: 1;
  font-size: 13px;
  font-weight: 600;
  color: var(--color-shell-text);
  letter-spacing: 0.01em;
}

.nav-chevron {
  width: 14px;
  height: 14px;
  color: var(--color-shell-muted);
  transition: transform var(--transition);
  flex-shrink: 0;
}

.nav-section-header.open .nav-chevron { transform: rotate(90deg); }

/* ── Badge ─────────────────────────────────────────────────────── */
.badge {
  font-size: 9px;
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  padding: 2px 6px;
  border-radius: 3px;
  flex-shrink: 0;
}

.badge-new     { background: var(--color-badge-new); color: #fff; }
.badge-updated { background: var(--color-badge-upd); color: #fff; }

/* ── Nav items (inside accordion) ─────────────────────────────── */
.nav-items {
  display: none;
  padding: 2px 0 6px;
}

.nav-items.open { display: block; }

.nav-item {
  display: flex;
  align-items: center;
  gap: 9px;
  padding: 7px 16px 7px 38px;
  cursor: pointer;
  color: var(--color-shell-muted);
  font-size: 13px;
  transition: background var(--transition), color var(--transition);
  text-decoration: none;
  position: relative;
}

.nav-item-icon {
  width: 14px;
  height: 14px;
  flex-shrink: 0;
  color: var(--color-accent-nav);
  opacity: 0.85;
}

.nav-item:hover {
  background: var(--color-shell-hover);
  color: var(--color-shell-text);
}

.nav-item.active {
  color: var(--color-accent-nav);
  background: rgba(59,126,255,0.15);
}

.nav-item.active::before {
  content: '';
  position: absolute;
  left: 0;
  top: 0;
  bottom: 0;
  width: 3px;
  background: var(--color-accent-nav);
  border-radius: 0 2px 2px 0;
}

.nav-item-link-icon {
  width: 11px;
  height: 11px;
  color: var(--color-shell-muted);
  flex-shrink: 0;
  margin-left: auto;
}

/* ── Section-level link (Newsletter, Podcast) ──────────────────── */
.nav-section-link {
  text-decoration: none;
}

/* ── Rail divider ──────────────────────────────────────────────── */
.rail-divider {
  height: 1px;
  background: var(--color-shell-border);
  margin: 10px 16px;
}

/* ── Main content panel ────────────────────────────────────────── */
#main {
  grid-area: main;
  display: flex;
  flex-direction: column;
  overflow: hidden;
  background: var(--color-bg);
}

/* ── Panel breadcrumb bar ──────────────────────────────────────── */
#panel-bar {
  display: flex;
  align-items: center;
  padding: 0 24px;
  height: 40px;
  border-bottom: 1px solid var(--color-border);
  background: var(--color-surface);
  gap: 8px;
  flex-shrink: 0;
  box-shadow: 0 1px 0 var(--color-border);
}

#panel-title {
  font-size: 13px;
  font-weight: 600;
  color: var(--color-text);
}

#panel-section-label {
  font-size: 12px;
  color: var(--color-muted);
}

.panel-sep {
  color: var(--color-border);
  font-size: 14px;
}

/* ── Content area ──────────────────────────────────────────────── */
#panel-content {
  flex: 1;
  position: relative;
  overflow: auto;                 /* the page's content scrolls here on desktop (it was an iframe) */
  -webkit-overflow-scrolling: touch;
}

/* The rail and pills are links now (the frame is stamped into every page by
   src/utils/site_frame.py); they keep the look they had as buttons. */
a.nav-section-header, a.nav-item, a.mobile-nav-pill, a.mobile-nav-sub, a.tile { text-decoration: none; }
a.nav-section-header, a.tile { color: inherit; }   /* .nav-item, .mobile-nav-pill and .mobile-nav-sub set their own muted colour */
.nav-section-header.active { color: var(--color-accent-nav); background: rgba(59,126,255,0.15); }
.mobile-nav-items { display: flex; overflow-x: auto; padding: 5px 10px; gap: 6px; scrollbar-width: none;
  border-top: 1px solid var(--color-shell-border); padding-top: 5px; padding-bottom: 6px; }
.mobile-nav-items::-webkit-scrollbar { display: none; }
.mobile-nav-items[hidden] { display: none !important; }

/* ── Welcome / hub panel ───────────────────────────────────────── */
/* Absolute fill so height is always resolved — centering works    */
#welcome {
  position: absolute;
  inset: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  /* `safe` is load-bearing. With plain `center`, a viewport shorter than the
     content pushes the overflow off BOTH ends, and the top half becomes
     physically unreachable — scrollTop:0 still leaves the logo cut off. That
     clipped the mark on laptop viewports (~750-900px) while external monitors,
     being taller, were unaffected. `safe center` centers when there is room and
     falls back to start-alignment when there is not, so the mark can never be
     clipped. Engines without `safe` ignore the second declaration and keep the
     first, so this degrades to the old behaviour rather than breaking. */
  justify-content: center;
  justify-content: safe center;
  overflow-y: auto;
  padding: 40px 40px 120px; /* pull content up to true optical center */
  gap: 40px;
  background: var(--color-bg);
}

.welcome-header {
  text-align: center;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 18px;
  max-width: 680px;
}

.welcome-brand {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 18px;
  margin-bottom: 10px;
}

.welcome-mark {
  position: relative;
  height: 140px;
  width: 140px;
  display: block;
}

.welcome-wordmark {
  font-family: 'Inter', system-ui, -apple-system, sans-serif;
  font-size: 56px;
  font-weight: 700;
  color: var(--color-brand);
  letter-spacing: -0.025em;
  line-height: 0.95;
  text-align: center;
}

.welcome-wordmark span { display: block; }

#welcome .welcome-title {
  font-size: 22px;
  font-weight: 500;
  color: var(--color-muted);
  letter-spacing: -0.005em;
  line-height: 1.3;
  margin: 0;
  max-width: 580px;
}

/* ── Welcome-screen legal line (publisher + disclaimer link) ─────── */
.welcome-legal {
  font-size: 12px;
  line-height: 1.5;
  color: var(--color-muted);
  text-align: center;
  max-width: 560px;
  margin: 0;
}
.welcome-legal a {
  color: var(--color-brand);
  text-decoration: none;
  white-space: nowrap;
}
.welcome-legal a:hover { text-decoration: underline; }

/* ── Short-viewport welcome (laptops) ───────────────────────────── */
/* Laptop viewports sit between phone and external-monitor heights: tall enough
   to miss the mobile query below, short enough that the full-size hero + 8-tile
   grid overflows. `safe center` above guarantees the mark is never clipped;
   this scales the hero so the hub actually FITS without scrolling down to
   ~780px. Same vh-clamp technique the mobile block already uses. Scoped to
   min-width:769px so phones keep their own sizing — and the mobile block comes
   later in source order, so it wins on landscape phones regardless. */
@media (min-width: 769px) and (max-height: 1000px) {
  #welcome { padding: 24px 40px 36px; gap: 22px; }
  .welcome-mark { height: clamp(72px, 11vh, 140px); width: clamp(72px, 11vh, 140px); }
  .welcome-wordmark { font-size: clamp(30px, 5.2vh, 56px); }
  #welcome .welcome-title { font-size: clamp(15px, 2.2vh, 22px); }
  .welcome-brand { gap: clamp(8px, 1.6vh, 18px); margin-bottom: 0; }
  .welcome-header { gap: clamp(8px, 1.6vh, 18px); }
}

/* ── Logo intro animation ──────────────────────────────────────── */
/* The welcome mark is an inline SVG split into 8 directional groups
   (.seg-tl … .seg-br). On load each group flies in from its own screen
   edge and assembles, then the wordmark, tagline and tiles cascade in.
   Everything is gated behind prefers-reduced-motion so motion-averse
   users get the static logo + page with no animation. fill-mode
   `backwards` keeps each element hidden only during its start delay. */
.welcome-mark { overflow: visible; }          /* let pieces fly outside the 140px box */
/* The mark is 8 stacked <svg> elements (one per direction), each carrying
   the full 1187x1080 viewBox but only its own segment's paths, so they
   overlay back into the complete logo. They're stacked rather than one
   SVG-with-<g>s on purpose: transforms on HTML-level <svg> elements honor
   px / vw / vh identically across engines, whereas the same transform on an
   inline-SVG <g> is interpreted in user-space units on WebKit but screen
   px on Blink (and vw/vh collapse to 0 on WebKit) — which made the fly-in
   "bloom from center" on whichever engine got the small interpretation. */
.welcome-mark .seg {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  display: block;
  fill: var(--color-brand);
}

@media (prefers-reduced-motion: no-preference) {
  /* Let the fly-in be seen coming from the true screen edges. The shell
     normally clips it three layers deep (#main / #panel-content / #welcome
     are all overflow:hidden), so pieces only appeared at the inset content
     panel's edge. While the intro runs, open those three so segments are
     clipped ONLY at #app — which is exactly 100dvh = the real viewport, so
     it still doubles as the scrollbar guard. Reverts when index.html drops
     the class after ~1.1s. (Mobile re-asserts the clip at the document
     root — see the phone media query below — because there the shell makes
     every container overflow:visible and html/body becomes the scroller.) */
  html.intro-running #main,
  html.intro-running #panel-content,
  html.intro-running #welcome { overflow: visible; }

  /* Offsets are viewport-relative (vw/vh) so each piece starts off its own
     screen edge and flies to center, identically on desktop and mobile.
     This works because the .seg elements are now HTML-level <svg>s — see
     the unit note above .welcome-mark .seg. */
  .logo-assemble .seg {
    animation: seg-fly-in 1.10s cubic-bezier(0.34, 1.8, 0.64, 1) backwards;
  }
  .seg-tl { --tx: -70vw; --ty: -70vh; }
  .seg-t  { --tx:    0;  --ty: -95vh; }
  .seg-tr { --tx:  70vw; --ty: -70vh; }
  .seg-l  { --tx: -95vw; --ty:    0;  }
  .seg-r  { --tx:  95vw; --ty:    0;  }
  .seg-bl { --tx: -70vw; --ty:  70vh; }
  .seg-b  { --tx:    0;  --ty:  95vh; }
  .seg-br { --tx:  70vw; --ty:  70vh; }

  /* Wordmark + tagline rise in as the logo lands (~1.10s). */
  .welcome-wordmark       { animation: ccm-rise 0.55s ease-out 0.95s backwards; }
  #welcome .welcome-title { animation: ccm-rise 0.55s ease-out 1.12s backwards; }

  /* The eight buttons cascade in after the logo lands. */
  #welcome .tile { animation: ccm-rise 0.50s ease-out backwards; }
  #welcome .tile:nth-child(1) { animation-delay: 1.25s; }
  #welcome .tile:nth-child(2) { animation-delay: 1.31s; }
  #welcome .tile:nth-child(3) { animation-delay: 1.37s; }
  #welcome .tile:nth-child(4) { animation-delay: 1.43s; }
  #welcome .tile:nth-child(5) { animation-delay: 1.49s; }
  #welcome .tile:nth-child(6) { animation-delay: 1.55s; }
  #welcome .tile:nth-child(7) { animation-delay: 1.61s; }
  #welcome .tile:nth-child(8) { animation-delay: 1.67s; }
}

/* Phone-only landing softening (does NOT touch desktop). On a small screen
   the logo is tiny but the vw/vh fly-in distance is large, so the desktop
   overshoot easing makes pieces blow past the small target and recoil —
   reads as a collision. Override just the timing function (the offsets and
   distance are unchanged) to a non-overshooting ease-out so pieces
   decelerate and settle into place. Same phone scope as the layout query
   below, kept inside no-preference so reduced-motion users still get none. */
@media (prefers-reduced-motion: no-preference) and (max-width: 768px),
       (prefers-reduced-motion: no-preference) and (orientation: landscape) and (max-height: 500px) {
  .logo-assemble .seg { animation-timing-function: cubic-bezier(0.16, 1, 0.3, 1); }
}

@keyframes seg-fly-in {
  from { opacity: 0; transform: translate(var(--tx), var(--ty)); }
  to   { opacity: 1; transform: translate(0, 0); }
}

@keyframes ccm-rise {
  from { opacity: 0; transform: translateY(14px); }
  to   { opacity: 1; transform: translateY(0); }
}

/* ── Tile grid ─────────────────────────────────────────────────── */
/* Flat, uniform button grid: 4 equal columns on desktop (8 buttons → 2
   rows), 2 columns on phones. Every button is the same size — icon above
   a centred label, no descriptions, no umbrella heading. */
.tile-grid {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 16px;
  width: 100%;
  max-width: 880px;
}

.tile {
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: 12px;
  padding: 22px 16px;
  min-height: 116px;
  cursor: pointer;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  text-align: center;
  gap: 12px;
  box-shadow: 0 1px 4px rgba(0,0,0,0.06);
  transition: border-color var(--transition), background var(--transition),
              transform var(--transition), box-shadow var(--transition);
  text-decoration: none;
  color: inherit;
  position: relative;
}

.tile:hover {
  border-color: var(--color-accent);
  background: var(--color-accent-dim);
  transform: translateY(-3px);
  box-shadow: 0 6px 20px rgba(59,126,255,0.12);
}

.tile-icon {
  width: 42px;
  height: 42px;
  color: var(--color-brand);
  flex-shrink: 0;
}

/* Two-tone composite icons (Auto Loan / Auto Lease) sit in a 48-unit box and
   carry a badge up top, so render them a touch larger than the flat icons to
   keep the CAR itself at least as big as the other button glyphs. */
.tile-icon-art {
  width: 48px;
  height: 48px;
}

.tile-label {
  font-size: 16px;
  font-weight: 600;
  color: var(--color-text);
  letter-spacing: 0.01em;
}

.tile-desc {
  font-size: 13px;
  color: var(--color-muted);
  line-height: 1.55;
}

/* Newsletter freshness: a dated "Issue N · Mon D" line under the label (always
   shown, so it never goes stale) + a time-decaying "New" corner pill. */
.tile-meta {
  font-size: 11.5px;
  color: var(--color-muted);
  letter-spacing: 0.01em;
  margin-top: -5px;
}
.tile-pill {
  position: absolute;
  top: 10px;
  right: 10px;
  background: var(--color-badge-new);
  color: #fff;
  font-size: 9.5px;
  font-weight: 700;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  padding: 2px 7px;
  border-radius: 999px;
  line-height: 1.5;
}

/* External-link icon next to the tile label (Newsletter / Podcast) — small,
   muted, signals "opens in new tab" without needing a verb in the footer. */
.tile-label .nav-item-link-icon {
  width: 11px;
  height: 11px;
  color: var(--color-muted);
  vertical-align: 1px;
  margin-left: 4px;
}

.tile-ext-icon {
  width: 13px;
  height: 13px;
  color: var(--color-muted);
}

/* ── Loading state ─────────────────────────────────────────────── */
#panel-loading {
  display: none;
  position: absolute;
  inset: 0;
  background: var(--color-bg);
  align-items: center;
  justify-content: center;
  z-index: 5;
}

#panel-loading.visible { display: flex; }

.spinner {
  width: 28px;
  height: 28px;
  border: 3px solid var(--color-border);
  border-top-color: var(--color-accent);
  border-radius: 50%;
  animation: spin 0.7s linear infinite;
}

@keyframes spin { to { transform: rotate(360deg); } }

/* ── Hamburger button (hidden on desktop) ───────────────────────── */
#hamburger {
  display: none;
}

/* ── Nav backdrop (mobile drawer overlay) ───────────────────────── */
#nav-backdrop {
  display: none;
  position: fixed;
  inset: 0;
  background: rgba(0, 0, 0, 0.5);
  z-index: 190;
  opacity: 0;
  transition: opacity 220ms ease;
}

#nav-backdrop.visible {
  display: block;
  opacity: 1;
}

/* ── Mobile top nav (portrait only, built by app.js) ────────────── */
#mobile-nav {
  display: none; /* shown only in portrait media query */
  flex-direction: column;
  background: var(--color-shell);
  border-bottom: 1px solid var(--color-shell-border);
  flex-shrink: 0;
}
#mobile-nav-sections,
#mobile-nav-items {
  display: flex;
  overflow-x: auto;
  padding: 5px 10px;
  gap: 6px;
  scrollbar-width: none;
}
#mobile-nav-sections::-webkit-scrollbar,
#mobile-nav-items::-webkit-scrollbar { display: none; }
#mobile-nav-items {
  border-top: 1px solid var(--color-shell-border);
  padding-top: 5px;
  padding-bottom: 6px;
}
#mobile-nav-items[hidden] { display: none !important; }
.mobile-nav-pill,
.mobile-nav-sub {
  flex-shrink: 0;
  border: 1px solid var(--color-shell-border);
  background: transparent;
  color: var(--color-shell-muted);
  font-family: var(--font);
  font-size: 12px;
  font-weight: 500;
  padding: 4px 11px;
  border-radius: 20px;
  cursor: pointer;
  white-space: nowrap;
  text-decoration: none;
  line-height: 1.4;
}
.mobile-nav-pill:hover:not(.active),
.mobile-nav-sub:hover:not(.active) {
  background: var(--color-shell-hover);
  color: var(--color-shell-text);
}
.mobile-nav-pill.active,
.mobile-nav-sub.active {
  background: var(--color-accent-pill);   /* white text needs a deeper blue than the accent (5.2:1; the accent is 3.7:1) */
  border-color: var(--color-accent-pill);
  color: #fff;
}
/* Pill content layout — label + small affordance icon (chevron for
   accordion sections, external-link for link sections). */
.mobile-nav-pill {
  display: inline-flex;
  align-items: center;
  gap: 5px;
}
.mobile-nav-pill .pill-chevron,
.mobile-nav-pill .nav-item-link-icon {
  width: 11px;
  height: 11px;
  opacity: 0.55;
  flex-shrink: 0;
  transition: transform 0.15s ease;
}
.mobile-nav-pill.active .pill-chevron {
  transform: rotate(180deg);
  opacity: 0.85;
}
.mobile-nav-pill.active .nav-item-link-icon { opacity: 0.85; }
/* Pill-label two-form swap: full (default, landscape + desktop) vs short
   (portrait phones ≤640px). Falls back to full label when section.short_label
   isn't defined in nav_config.json. */
.pill-label-short { display: none; }
@media (max-width: 640px) {
  .pill-label-full  { display: none; }
  .pill-label-short { display: inline; }
}

/* ── Phone layout (portrait ≤768px OR landscape height ≤500px) ──── *
 * Completely replaces the desktop fixed-height app-shell with a     *
 * normal scrollable document flow. !important used throughout to    *
 * break out of the desktop architecture cleanly.                    *
 * ─────────────────────────────────────────────────────────────── */
@media (max-width: 768px), (orientation: landscape) and (max-height: 500px) {

  /* ── Document root: normal flow, no fixed height ── */
  html, body {
    height: auto !important;
    min-height: 100dvh;
    overflow-x: hidden !important;
    overflow-y: auto !important;
    max-width: 100% !important;
  }

  /* ── App shell: flex column, grows with content ── */
  #app {
    display: flex !important;
    flex-direction: column !important;
    height: auto !important;
    min-height: 100dvh;
    overflow: visible !important;
    width: 100% !important;
    max-width: 100% !important;
  }

  /* ── Header: shrink to fit narrow screens ── */
  #header {
    flex-shrink: 0;
    overflow: visible;
    padding: env(safe-area-inset-top, 0px) max(12px, env(safe-area-inset-right)) 0 max(12px, env(safe-area-inset-left));
  }
  #header .brand-logo { height: 28px; }
  /* Hide the header disclaimer link on mobile to keep the compact header
     uncluttered — the welcome-screen legal line carries the link on mobile. */
  #header .header-disclaimer { display: none; }
  #header .header-right .btn-primary {
    padding: 5px 10px;
    font-size: 11px;
    letter-spacing: 0.02em;
  }

  /* ── Show mobile pill nav, hide desktop nav ── */
  #mobile-nav   { display: flex; flex-shrink: 0; }
  #rail         { display: none !important; }
  #hamburger    { display: none !important; }
  #nav-backdrop { display: none !important; }
  #panel-bar    { display: none !important; }

  /* ── Main: flex child, grows naturally ── */
  #main {
    flex: 1;
    display: flex !important;
    flex-direction: column !important;
    overflow: visible !important;
    width: 100% !important;
  }

  /* ── Panel content: tall enough for charts to render fully ── */
  #panel-content {
    overflow: visible !important;
    position: static !important;
    width: 100% !important;
  }


  /* ── iframe: static block, tall fixed height — outer page scrolls ── */
  #panel-content iframe {
    position: static !important;
    display: block;
    width: 100% !important;
    height: 800px;
    border: none;
  }

  /* ── Welcome screen: normal flow, scrollable ── */
  #welcome {
    position: static !important;
    overflow: visible !important;
    width: 100% !important;
    /* Fluid, viewport-relative sizing (clamp min / vh / max) so the whole
       welcome screen scales to fit ANY phone without scrolling — compact on a
       small iPhone SE, larger on a Pro Max / big Android. The total of hero +
       2×4 grid stays comfortably under the screen height on every size. */
    padding: clamp(10px, 2vh, 18px) 14px clamp(8px, 1.5vh, 14px);
    gap: clamp(8px, 1.8vh, 14px);
    justify-content: flex-start;
    align-items: stretch;
  }

  /* Logo-intro scrollbar guard (mobile): the phone shell makes html/body
     the scroller and every inner container overflow:visible, so the
     desktop #app clip can't catch the off-screen fly-in pieces. Clip
     at the document root instead while the intro runs. Only present when
     motion is allowed (class is added by JS, skipped under reduced
     motion) and removed after ~1.1s, so this briefly pins the page at the
     top during the assemble, then releases. */
  html.intro-running,
  html.intro-running body { overflow: hidden !important; }

  /* #welcome is align-items:stretch on mobile (so the tile grid spans full
     width); the 680px-max header would otherwise pin to the left edge under
     stretch. align-self:center re-centers the hero horizontally. */
  .welcome-header { gap: clamp(5px, 1.2vh, 10px); align-items: center; align-self: center; }
  .welcome-brand { gap: clamp(5px, 1.2vh, 10px); margin-bottom: 0; }
  .welcome-mark { height: clamp(44px, 8vh, 76px); width: clamp(44px, 8vh, 76px); }
  .welcome-wordmark { font-size: clamp(18px, 3.5vh, 28px); line-height: 1.02; }
  #welcome .welcome-title { font-size: clamp(11px, 1.7vh, 15px); line-height: 1.3; }
  .welcome-legal { font-size: clamp(9px, 1.3vh, 11px); align-self: center; line-height: 1.4; }

  /* ── Tile grid: 2 columns of equal-size buttons ── */
  .tile-grid {
    grid-template-columns: repeat(2, 1fr);
    gap: clamp(6px, 1.3vh, 10px);
    width: 100% !important;
    max-width: 100% !important;
  }

  .tile {
    min-height: clamp(58px, 9.5vh, 92px);
    padding: clamp(8px, 1.4vh, 16px) 10px;
    gap: clamp(4px, 1vh, 9px);
    border-radius: 10px;
    box-shadow: none;
  }

  .tile .tile-icon     { width: 30px; height: 30px; }
  .tile .tile-icon-art { width: 35px; height: 35px; }
  .tile .tile-label    { font-size: 14px; }
}

/* ═══════════════════════════════════════════════════════════════════
 * Site-wide content components (added 2026-05-01)
 * ───────────────────────────────────────────────────────────────────
 * Used by content pages loaded inside the shell's iframe.
 * Page-specific layouts stay inlined per generator; these are the
 * cross-page patterns: buttons, pills, dropdowns, tooltips, tables,
 * focus & touch behavior.
 * ═══════════════════════════════════════════════════════════════════ */

/* ── Buttons ──────────────────────────────────────────────────────── */
.btn,
button.btn {
  font-family: var(--font);
  font-size: var(--type-sm);
  font-weight: 500;
  padding: 4px 11px;
  border: 1px solid var(--color-border);
  border-radius: var(--radius-sm);
  background: var(--color-surface);
  color: var(--color-text);
  cursor: pointer;
  white-space: nowrap;
  user-select: none;
  line-height: 1.6;
  transition: background 0.1s, border-color 0.1s, color 0.1s;
}
.btn:hover,
.btn:active { background: var(--color-accent-hover-bg); }
.btn.active,
.btn.is-active,
.btn[aria-pressed="true"] {
  background: var(--color-accent-active-bg);
  color: var(--color-accent-strong);
  border-color: var(--color-accent-strong);
  font-weight: 600;
}
/* Icon-only buttons (camera/export/columns gear etc.). Minimal chrome —
   no permanent border, transparent background, soft tinted hover state.
   Convention used by Linear, Tableau, Stripe, Vercel, Notion, etc. for
   tertiary icon actions. Removes the off-center "outlined-square" look
   the previous border treatment created. */
.btn--icon {
  padding: 6px 8px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 5px;
  border: 1px solid transparent;
  background: transparent;
  color: var(--color-muted);
  min-height: 36px;
  min-width: 36px;
}
.btn--icon:hover,
.btn--icon:active,
.btn--icon.is-active {
  background: var(--color-accent-hover-bg);
  color: var(--color-text);
  border-color: transparent;
}

/* ── Pill group (segmented control) ──────────────────────────────── */
.pill-group {
  display: inline-flex;
  gap: 1px;
  background: #e5e7eb;
  border: 1px solid var(--color-border);
  border-radius: 5px;
  padding: 2px;
}
.pill {
  background: none;
  border: none;
  border-radius: 3px;
  padding: 2px 9px;
  font-family: var(--font);
  font-size: var(--type-xs);
  font-weight: 500;
  color: var(--color-muted);
  cursor: pointer;
  white-space: nowrap;
  line-height: 1.6;
  user-select: none;
}
.pill.active,
.pill.is-active,
.pill[aria-pressed="true"] {
  background: var(--color-surface);
  color: var(--color-accent-strong);
  box-shadow: 0 1px 2px rgba(0,0,0,0.10);
  font-weight: 600;
}

/* ── Multi-select dropdown ───────────────────────────────────────── */
.multi-sel { position: relative; display: inline-block; }
.multi-sel-btn {
  font-family: var(--font);
  font-size: var(--type-sm);
  padding: 4px 10px;
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  background: var(--color-surface);
  cursor: pointer;
  color: var(--color-text);
  white-space: nowrap;
  max-width: 320px;
  overflow: hidden;
  text-overflow: ellipsis;
  text-align: left;
  min-width: 160px;
}
.multi-sel-btn:hover,
.multi-sel-btn:active { border-color: var(--color-border-strong); }
.multi-sel-btn .dd-arrow { font-size: 9px; color: var(--color-muted); margin-left: 4px; }
.multi-sel-panel {
  display: none;
  position: absolute;
  top: calc(100% + 4px);
  left: 0;
  z-index: 200;
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-popover);
  padding: 5px 0;
  min-width: 200px;
  max-height: 280px;
  overflow-y: auto;
}
.multi-sel-panel.open,
.multi-sel-panel.is-open { display: block; }
.multi-sel-panel label {
  display: flex;
  align-items: center;
  gap: 7px;
  padding: 4px 12px;
  font-size: var(--type-sm);
  cursor: pointer;
  user-select: none;
  color: var(--color-text);
}
.multi-sel-panel label:hover,
.multi-sel-panel label:active { background: var(--color-accent-hover-bg); }
.multi-sel-panel input[type=checkbox] { cursor: pointer; accent-color: var(--color-accent-strong); }
.multi-sel-sep { height: 1px; background: var(--color-border); margin: 4px 8px; }

/* ── Info button + popover ───────────────────────────────────────── */
.info-btn {
  background: var(--color-border);
  border: none;
  cursor: pointer;
  font-family: var(--font);
  font-size: var(--type-base);
  font-weight: 600;
  color: var(--color-muted);
  border-radius: 50%;
  width: 26px;
  height: 26px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  line-height: 1;
  flex-shrink: 0;
  transition: background 0.15s, color 0.15s;
}
.info-btn:hover,
.info-btn:active { background: #d0d5dd; color: var(--color-text); }
.info-popover {
  position: absolute;
  z-index: 200;
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-popover);
  padding: 12px 14px;
  width: 340px;
  font-family: var(--font);
  font-size: var(--type-sm);
  line-height: 1.55;
  color: var(--color-text);
}
.info-popover h4 { margin: 0 0 7px; font-size: var(--type-sm); font-weight: 600; }
.info-popover ul { margin: 0; padding-left: 16px; }
.info-popover li { margin-bottom: 5px; }
.info-popover li:last-child { margin-bottom: 0; }
.info-popover b { font-weight: 600; }

/* ── Vega-Lite tooltip (id selector — Vega-Lite default element) ─── */
#vg-tooltip-element {
  visibility: hidden;
  position: fixed;
  z-index: 1000;
  pointer-events: none;
  background: rgba(31,41,55,0.92);
  color: #fff;
  border: none;
  border-radius: var(--radius);
  box-shadow: var(--shadow-tooltip);
  font-family: var(--font);
  font-size: 12.5px;
  padding: 8px 12px;
  line-height: 1.5;
  max-width: 320px;
  word-wrap: break-word;
}
#vg-tooltip-element.visible { visibility: visible; }
#vg-tooltip-element h2 { margin: 0 0 4px; padding: 0; font-size: 12.5px; font-weight: 600; color: #fff; }
#vg-tooltip-element table { border-spacing: 0; }
#vg-tooltip-element td { border: none; padding: 2px 8px 2px 0; }
#vg-tooltip-element td.key { color: rgba(255,255,255,0.7); font-weight: 400; text-align: right; }
#vg-tooltip-element td.value { color: #fff; font-weight: 600; }
.vega-embed svg .role-legend-entry rect.background { fill: none !important; }

/* ── Toast (overlay notification) ────────────────────────────────── */
.toast {
  position: fixed;
  bottom: calc(24px + env(safe-area-inset-bottom));
  left: 50%;
  transform: translateX(-50%) translateY(20px);
  background: #1f2937;
  color: #fff;
  font-family: var(--font);
  font-size: 12.5px;
  padding: 9px 16px;
  border-radius: var(--radius);
  box-shadow: var(--shadow-tooltip);
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.2s, transform 0.2s;
  z-index: 9999;
  max-width: 320px;
  text-align: center;
  line-height: 1.4;
}
.toast.is-visible {
  opacity: 1;
  transform: translateX(-50%) translateY(0);
  pointer-events: auto;
}
.toast--warn {
  background: #fef3c7;
  color: #78350f;
  border: 1px solid #fcd34d;
  border-left: 4px solid #f59e0b;
  text-align: left;
}

/* ── Data table (base) ───────────────────────────────────────────── */
.data-table {
  width: 100%;
  border-collapse: collapse;
  font-family: var(--font);
  font-size: var(--type-sm);
}
.data-table thead th {
  position: sticky;
  top: 0;
  background: var(--color-surface-table-hdr);
  border-bottom: 2px solid var(--color-border);
  padding: 6px 8px;
  font-size: var(--type-xs);
  font-weight: 600;
  color: var(--color-muted);
  text-align: left;
  white-space: nowrap;
  z-index: 1;
  user-select: none;
}
.data-table thead th.num { text-align: center; }
.data-table tbody td {
  padding: 5px 8px;
  border-bottom: 1px solid var(--color-border);
  vertical-align: middle;
}
.data-table tbody td.num {
  text-align: right;
  font-variant-numeric: tabular-nums;
}
.data-table tbody tr:hover > td { background: var(--color-row-hover); }

/* ── Source attribution footer ───────────────────────────────────── */
.source-bar {
  font-family: var(--font);
  font-size: var(--type-xs);
  color: var(--color-muted);
  line-height: 1.4;
  padding: 8px 0 6px;
  margin-top: 6px;
  border-top: 1px solid var(--color-border);
}

/* ── Chart entry animation (shared keyframes) ────────────────────── */
@keyframes chartEnter {
  from { opacity: 0; transform: translateY(6px); }
  to   { opacity: 1; transform: translateY(0); }
}
.chart-enter {
  opacity: 0;
  transform: translateY(6px);
  transition: opacity 500ms ease-out, transform 500ms ease-out;
}
.chart-enter.is-visible {
  opacity: 1;
  transform: translateY(0);
}
@media (prefers-reduced-motion: reduce) {
  .chart-enter,
  .chart-enter.is-visible {
    opacity: 1;
    transform: none;
    transition: none;
    animation: none;
  }
}

/* ── Focus-visible (keyboard / accessibility) ────────────────────── */
/* Every control shows where keyboard focus is, on every page. */
a:focus-visible,
button:focus-visible,
select:focus-visible,
input:focus-visible,
[tabindex]:focus-visible,
.btn:focus-visible,
.pill:focus-visible,
.multi-sel-btn:focus-visible,
.info-btn:focus-visible {
  outline: 2px solid var(--color-accent-strong);
  outline-offset: 2px;
}

/* ── Touch widths: feedback + 44px Apple HIG targets ─────────────── */
@media (max-width: 640px) {
  .btn,
  .pill,
  .multi-sel-btn {
    min-height: var(--touch-target);
    padding: 10px 14px;
    font-size: var(--type-md);
  }
  .pill { min-height: var(--touch-target-sm); }
  .info-btn {
    width: var(--touch-target);
    height: var(--touch-target);
    font-size: var(--type-lg);
  }
  .multi-sel-panel { max-width: calc(100vw - 24px); }
  .multi-sel-panel label { padding: 10px 14px; font-size: var(--type-md); }

  .btn:active,
  .pill:active,
  .multi-sel-btn:active,
  .info-btn:active {
    transform: scale(0.97);
    transition: transform 0.08s;
  }
}

/* ── Landscape phones: compact mode ──────────────────────────────── */
@media (max-height: 500px) and (orientation: landscape) {
  .btn,
  .pill,
  .multi-sel-btn {
    min-height: var(--touch-target-sm);
    padding: 6px 10px;
    font-size: var(--type-sm);
  }
}

/* ── Landscape phones: scroll fix ─────────────────────────────────────
   In portrait the mobile block (top of file) lets the page <body> scroll and
   grows the tool iframe to full height. iOS Safari will NOT reliably chain a
   touch-drag out of a nested iframe to the <body> in landscape, so the page
   locks up. Fix: pin the shell to the viewport and scroll a DEDICATED
   container (#main) that holds the grown iframe, with
   -webkit-overflow-scrolling:touch. Touch then drives #main's own momentum
   scroller — the established iOS workaround for scrollable iframes. This is
   landscape-only; portrait keeps the body-scroll model untouched. */
@media (orientation: landscape) and (max-height: 500px) {
  /* NOTE: do not set overflow/height on html,body here. Leaving them to the
     mobile block above (overflow-y:auto) keeps the navy background painting
     into the iPhone notch/rounded-corner safe-area zones in landscape; setting
     overflow:hidden on the root left light bars on those edges. The
     fixed-viewport box that drives the scroller is #app below. */
  #app {
    height: 100dvh !important;
    min-height: 0 !important;
    overflow: hidden !important;
  }
  #main {
    flex: 1;
    min-height: 0;
    overflow-y: auto !important;
    -webkit-overflow-scrolling: touch;
  }
  #panel-content {
    flex: none;
    overflow: visible !important;
    min-height: 0 !important;
  }
}

/* ── Landscape phones: compact the welcome hero so the buttons fit ──────
   In landscape the usable height is ~300px (viewport minus Safari chrome).
   The portrait-sized hero (88px logo + 3-line wordmark + tagline) eats all
   of it and shoves the buttons off-screen. Shrink the lockup, lay the logo
   and wordmark side-by-side, and spread the eight buttons across 4 columns
   (there's ample width) so the whole landing fits without scrolling. The
   navy site header still carries the brand, so a smaller hero loses nothing. */
@media (orientation: landscape) and (max-height: 500px) {
  #welcome {
    padding: 10px 16px 16px;
    gap: 8px;
    justify-content: flex-start;
  }
  .welcome-header { gap: 6px; }
  .welcome-brand {
    flex-direction: row;
    align-items: center;
    gap: 10px;
    margin-bottom: 0;
  }
  .welcome-mark { height: 40px; width: 40px; }
  .welcome-wordmark { font-size: 16px; line-height: 0.98; text-align: left; }
  #welcome .welcome-title { font-size: 12px; line-height: 1.3; }

  .tile-grid { grid-template-columns: repeat(4, 1fr); gap: 8px; }
  .tile {
    min-height: 62px;
    padding: 10px 8px;
    gap: 6px;
  }
  .tile .tile-icon     { width: 24px; height: 24px; }
  .tile .tile-icon-art { width: 28px; height: 28px; }
  .tile .tile-label    { font-size: 12.5px; }
}

/* ── iOS home-screen ("standalone") app ──────────────────────────────
   Since iOS 26 WebKit fades a Liquid Glass edge blur roughly 40pt down from
   the top of the web view, over whatever sits there; no CSS or meta switch
   turns it off. The page does not draw under the status bar in this mode
   (the top inset is 0), so the only remedies are to give WebKit a real
   sticky full-width solid element at the top edge, which lets it colour the
   status bar from the page, and to start the header's content below the
   fade. A fixed 12px band tried first (2026-10-23) painted over the logo
   and did not stop the blur. Must stay at the END of this file: the phone
   block sets the padding shorthand on #header and this has to win. Inert
   outside standalone mode and outside iOS. */
@media (display-mode: standalone) {
  @supports (-webkit-touch-callout: none) {
    #app {
      grid-template-rows: calc(var(--header-height) + env(safe-area-inset-top, 0px) + 32px) 1fr;
    }
    #header {
      position: sticky;
      top: 0;
      padding-top: calc(env(safe-area-inset-top, 0px) + 32px);
    }
  }
}
