/* OSR Project Tracker
   styles.css — Interface styling

   A public-ledger aesthetic for Louisiana's orphan-well program, built on the
   design system: Archivo for display, IBM Plex Sans for body, IBM Plex Mono
   for data. Colors are tokens emitted by ei_core_css() or palette_css(), apart
   from the type, rules and scrim that sit on the hero photograph, and the white
   veil the loading spinner draws over an output. */

/* Design tokens --------------------------------------------------------- */
:root{
  /* eitheme's footer reads this to work out its own gutter. */
  --ei-app-content-max: 1400px;

  --c-bg: var(--paper-0);

  /* Scale. The two display steps are the suite's landing scale, shared with
     la-electricity so a reader moving between the applications does not meet
     a different size for the same rank of heading. */
  --fs-display-2:  clamp(1.45rem, 2.6vw, 1.85rem);   /* section heading */
  --fs-display-3:  clamp(1.35rem, 2.2vw, 1.65rem);   /* analytics heading */
  --fs-body:  15px;

  --ease: cubic-bezier(.2,.7,.2,1);
}

/* The footer's side gutter matches .gr-section's own padding so the two line
   up. Below 640px the design system settles the gutter at 16px, so this value
   stops at the fold rather than overriding eitheme there. */
@media (min-width:641px){
  :root{ --ei-footer-min-gutter:32px; }
}

/* Base ------------------------------------------------------------------ */
*,*::before,*::after{ box-sizing:border-box; }
html{ -webkit-text-size-adjust:100%; }
body{
  margin:0;
  background:var(--c-bg);
  color:var(--ink-0);
  font-size:var(--fs-body);
  line-height:1.55;
  font-feature-settings:"ss01","ss02","cv11";
  text-rendering:optimizeLegibility;
  -webkit-font-smoothing:antialiased;
  -moz-osx-font-smoothing:grayscale;
}
img{ max-width:100%; display:block; }
a{ color:inherit; text-decoration:none; }
a:focus-visible,button:focus-visible,[role="link"]:focus-visible{
  outline:2px solid var(--azure);
  outline-offset:3px; border-radius:var(--radius);
}
::selection{ background:var(--tint-crimson); color:var(--ink-0); }
hr{ border:0; border-top:1px solid var(--hair-0); }

/* Paper and card are the only page backgrounds. */
.navbar,.ei-footer,.navbar-collapse{ position:relative; z-index:2; }
/* No z-index on these two: they are ancestors of every card(full_screen = TRUE),
   and a stacking context there traps the expanded card behind the masthead. */
.container-fluid,.tab-content{ position:relative; }
/* Edge-to-edge: drop Bootstrap's default 15px L/R padding on EVERY container-fluid
   (fluidPage wraps content in one, navbarPage adds another wrapping the tab-content) */
.container-fluid{ padding-left:0; padding-right:0; margin-left:0; margin-right:0; max-width:none; }
.tab-content{ padding-left:0; padding-right:0; }
/* bslib renders a nested <body class="bslib-page-navbar"> — strip its margin so
   navbar+content sit flush against the outer body's left/right edges */
body.bslib-page-navbar,
.bslib-page-navbar{ margin:0; padding:0; }

/* Buttons --------------------------------------------------------------- */
.btn-gr{
  font-family:var(--font-body);
  font-size:.9rem;
  font-weight:600;
  letter-spacing:.01em;
  padding:12px 20px;
  border-radius:var(--radius);
  border:1px solid transparent;
  cursor:pointer;
  display:inline-flex; align-items:center; gap:.6em;
  transition:background-color .18s var(--ease),
             border-color .18s var(--ease),
             color .18s var(--ease),
             transform .18s var(--ease);
  background:transparent;
  color:var(--ink-0);
  line-height:1;
}
.btn-gr .arrow{
  font-family:var(--font-display);
  font-style:italic;
  font-size:1.25em;
  transition:transform .18s var(--ease);
  margin-bottom:-.05em;
}
.btn-gr:hover .arrow{ transform:translateX(3px); }
.btn-gr-primary{
  background:var(--azure-ink); color:var(--ink-inv); border-color:var(--azure-ink);
}
.btn-gr-primary:hover{
  background:var(--azure-ink-hover); border-color:var(--azure-ink-hover);
}
.btn-gr-ghost{
  background:transparent; color:var(--ink-0); border-color:var(--hair-1);
}
.btn-gr-ghost:hover{
  background:var(--ink-0); color:var(--ink-inv); border-color:var(--ink-0);
}
/* Reference-document button in a page banner (e.g. the priority scoring
   criteria on Orphan Wells). Sized to sit level with the banner title rather
   than compete with it. */
.btn-banner-ref{
  font-family:var(--font-mono);
  font-size:10.5px;
  font-weight:500;
  letter-spacing:.14em;
  text-transform:uppercase;
  padding:9px 14px;
}
.btn-banner-ref .fa,
.btn-banner-ref .fas,
.btn-banner-ref svg{ font-size:12px; }

.btn-reset{
  font-family:var(--font-mono);
  font-size:10.5px;
  font-weight:500;
  letter-spacing:.14em;
  text-transform:uppercase;
  padding:8px 12px;
  background:transparent;
  border:1px solid var(--hair-1);
  color:var(--ink-1);
  border-radius:var(--radius);
  line-height:1;
  cursor:pointer;
  display:inline-flex; align-items:center; gap:7px;
}
.btn-reset:hover{
  background:var(--ink-0); color:var(--ink-inv); border-color:var(--ink-0);
}

/* Register CSV export. Shiny renders downloadButton as an <a.btn>, so the
   anchor defaults (underline, link color) have to be cleared explicitly. */
.btn-download,
a.btn-download{
  font-family:var(--font-mono);
  font-size:10.5px;
  font-weight:500;
  letter-spacing:.14em;
  text-transform:uppercase;
  padding:8px 12px;
  background:var(--ink-0);
  border:1px solid var(--ink-0);
  color:var(--ink-inv);
  border-radius:var(--radius);
  line-height:1;
  cursor:pointer;
  text-decoration:none;
  display:inline-flex;
  align-items:center;
  gap:.5em;
}
.btn-download:hover,
a.btn-download:hover,
a.btn-download:focus{
  background:transparent;
  color:var(--ink-0);
  border-color:var(--ink-0);
  text-decoration:none;
}

/* Badges ---------------------------------------------------------------- */
.live-badge{
  display:inline-flex; align-items:center; gap:8px;
  font-family:var(--font-mono);
  font-size:10.5px; letter-spacing:.16em; text-transform:uppercase;
  color:var(--ink-2);
  font-variant-numeric:tabular-nums;
}
/* Home / landing -------------------------------------------------------- */
.gr-landing{
  position:relative;
  background:var(--paper-0);
}

/* HERO: full-bleed photo with overlaid KPIs ----------------------------- */
.gr-hero{
  position:relative;
  width:100%;
  min-height:clamp(560px, 82vh, 780px);
  overflow:hidden;
  background:var(--hero-backdrop);
  border-bottom:1px solid var(--ink-0);
  isolation:isolate;
}
.gr-hero-bg{
  position:absolute; inset:0;
  width:100%; height:100%;
  object-fit:cover;
  object-position:center 42%;
  filter:saturate(.92) contrast(1.02);
  z-index:0;
}
.gr-hero-scrim{
  position:absolute; inset:0;
  z-index:1;
  pointer-events:none;
  background:
    linear-gradient(180deg,
      rgba(10,27,44,.60) 0%,
      rgba(10,27,44,.30) 22%,
      rgba(10,27,44,.55) 60%,
      rgba(10,27,44,.94) 100%),
    linear-gradient(90deg,
      rgba(10,27,44,.45) 0%,
      rgba(10,27,44,.18) 50%,
      rgba(0,0,0,0) 100%);
}
.gr-hero-inner{
  position:relative;
  z-index:2;
  display:flex; flex-direction:column;
  padding:18px 32px 26px;
  min-height:inherit;
  color:var(--ink-inv);
}

/* Meta strip (top) */
.gr-hero-meta{
  display:flex; justify-content:space-between; align-items:center;
  gap:18px; flex-wrap:wrap;
  padding-bottom:12px;
  border-bottom:1px solid rgba(255,255,255,.22);
}
.gr-hero-meta .left{
  display:flex; align-items:center; gap:12px; flex-wrap:wrap;
}
.gr-hero-meta .live-badge{ color:rgba(255,255,255,.82); }

/* Main body — the headline number + lede + CTAs */
.gr-hero-body{
  flex:1;
  display:flex; flex-direction:column; gap:14px;
  justify-content:center;
  padding:56px 0 32px;
  max-width:980px;
}
.gr-hero-eyebrow{
  display:block;
  font-family:var(--font-mono);
  font-size:.66rem;
  letter-spacing:.2em;
  text-transform:uppercase;
  color:rgba(255,255,255,.88);
  margin-bottom:2px;
}
/* The roster count is this landing page's title, so it takes the display
   weight every other heading in the suite uses rather than the light default,
   and a scale that leaves room for the lede beneath it. */
.gr-hero-number{
  display:block;
  font-family:var(--font-display);
  font-size:clamp(76px, 10.5vw, 158px);
  line-height:.88;
  letter-spacing:-.03em;
  color:#fff;
  font-variant-numeric:tabular-nums;
  font-feature-settings:"tnum","zero";
  font-weight:600;
  text-shadow:0 2px 24px rgba(0,0,0,.28);
}
.gr-hero-number-caption{
  display:block;
  font-family:var(--font-display);
  font-style:italic;
  font-weight:600;
  font-size:clamp(1.15rem, 1.9vw, 1.5rem);
  line-height:1.3;
  color:#fff;
  letter-spacing:-.01em;
  max-width:38ch;
  margin-top:2px;
}
.gr-hero-number-caption .u-mono{
  font-family:var(--font-mono);
  font-style:normal;
  font-size:.88em;
  color:#fff;
}
/* Running copy is set in the body face at body size, as it is on the other
   landing pages in the suite; it was in the display face at 22px here, which
   read as a second heading rather than as a paragraph. */
.gr-hero-lede{
  font-family:var(--font-body);
  font-size:clamp(.95rem, 1.3vw, 1.06rem);
  line-height:1.7;
  color:rgba(255,255,255,.76);
  max-width:60ch;
  margin:10px 0 2px;
}
.gr-hero-lede strong,.gr-hero-lede .u-italic{ color:rgba(255,255,255,.92); }
.gr-hero-cta{ display:flex; gap:10px; flex-wrap:wrap; margin-top:6px; }
.gr-hero-cta .btn-gr-primary{
  background:var(--paper-2); color:var(--ink-0); border-color:var(--paper-2);
}
.gr-hero-cta .btn-gr-primary:hover{
  background:var(--azure-ink); color:var(--paper-2); border-color:var(--azure-ink);
}
.gr-hero-cta .btn-gr-ghost{
  background:transparent; color:var(--paper-2); border-color:rgba(255,255,255,.55);
}
.gr-hero-cta .btn-gr-ghost:hover{
  background:var(--paper-2); color:var(--ink-0); border-color:var(--paper-2);
}

/* KPI strip overlay, pinned to the foot of the hero */
.gr-hero-kpis{
  display:grid;
  /* Four columns: IIJA, USFWS refuge, legacy, parishes. Track count must match
     the number of .kpi children in ui.R or the last one wraps to a new row. */
  grid-template-columns:repeat(4, minmax(0,1fr));
  gap:0;
  margin-top:auto;
  padding-top:16px;
  border-top:1px solid rgba(255,255,255,.25);
}
.gr-hero-kpis .kpi{
  padding:2px 20px;
  border-right:1px solid rgba(255,255,255,.14);
  min-width:0;
}
.gr-hero-kpis .kpi:first-child{ padding-left:0; }
.gr-hero-kpis .kpi:last-child{ border-right:0; padding-right:0; }
/* Four tracks leave less room per cell, so the longest label
   ("USFWS refuge P&A") needs to wrap rather than force the column wider. */
.gr-hero-kpis .k{ overflow-wrap:break-word; }
.gr-hero-kpis .k{
  font-family:var(--font-mono);
  font-size:.62rem;
  letter-spacing:.2em;
  text-transform:uppercase;
  color:rgba(255,255,255,.58);
  margin-bottom:6px;
}
/* A comparable figure, so it is mono like every other number in the suite. */
.gr-hero-kpis .v{
  font-family:var(--font-mono);
  font-weight:600;
  font-size:clamp(1.6rem, 2.5vw, 2.15rem);
  line-height:1;
  color:#fff;
  font-variant-numeric:tabular-nums;
  margin-bottom:4px;
}
.gr-hero-kpis .u{
  font-family:var(--font-mono);
  font-size:.6rem;
  letter-spacing:.13em;
  text-transform:uppercase;
  color:rgba(255,255,255,.44);
}

/* SECTION rhythm -------------------------------------------------------- */
.gr-section{
  padding:56px 32px;
  position:relative;
  border-bottom:1px solid var(--hair-0);
}
.gr-section.alt{ background:var(--paper-1); }
.gr-section-inner{ max-width:1400px; margin:0 auto; }

.gr-section-head{
  display:flex; justify-content:space-between; align-items:flex-end;
  gap:24px; flex-wrap:wrap;
  padding-bottom:16px;
  border-bottom:1px solid var(--ink-0);
  margin-bottom:28px;
}
.gr-section-head .left .eyebrow{ margin-bottom:10px; display:block; }
.gr-section-title{
  font-family:var(--font-display);
  font-size:var(--fs-display-2);
  line-height:1.3;
  letter-spacing:-.015em;
  margin:0;
  font-weight:600;
  color:var(--ink-0);
}
.gr-section-meta{
  font-family:var(--font-mono);
  font-size:11px; letter-spacing:.14em; text-transform:uppercase;
  color:var(--ink-2);
}

/* TRENDS GRID (2-up plates) --------------------------------------------- */
.gr-trends{
  display:grid;
  grid-template-columns:repeat(auto-fit,minmax(420px,1fr));
  border-top:1px solid var(--hair-0);
  border-left:1px solid var(--hair-0);
}
.gr-plate{
  padding:28px 26px 22px;
  border-right:1px solid var(--hair-0);
  border-bottom:1px solid var(--hair-0);
  background:var(--paper-2);
  position:relative;
}
.gr-plate-head{
  display:flex; justify-content:flex-end; align-items:baseline;
  margin-bottom:6px;
}
.gr-plate-title{
  font-family:var(--font-display);
  font-size:24px; line-height:1.4;
  letter-spacing:-.005em;
  color:var(--ink-0);
  margin:0 0 6px;
  font-weight:600;
}
.gr-plate-caption{
  font-size:13px; line-height:1.55;
  color:var(--ink-2);
  max-width:58ch;
  margin:0 0 14px;
}
.gr-plate-source{
  font-family:var(--font-mono);
  font-size:10px;
  letter-spacing:.14em;
  text-transform:uppercase;
  color:var(--ink-2);
  margin-top:12px;
  padding-top:10px;
  border-top:1px dashed var(--hair-0);
}

/* MODULE TOC (publication contents list, not cards) --------------------- */
/* LANDING CARDS (the views, in gulf-energy-explorer's grid) ---------------- */
.gr-cards{ display:flex; flex-direction:column; gap:18px; }
.gr-cards-grid{ display:grid; grid-template-columns:repeat(3, minmax(0,1fr)); gap:18px; }
.gr-card{
  position:relative; display:flex; flex-direction:column;
  min-height:190px; padding:20px 22px 22px; cursor:pointer;
  background:var(--paper-2); border:1px solid var(--hair-0); border-radius:var(--radius);
  color:var(--ink-0); text-align:left;
  transition:transform .2s var(--ease), border-color .2s var(--ease);
}
.gr-card:hover, .gr-card:focus-visible{ transform:translateY(-3px); border-color:var(--azure); outline:none; }
.gr-card:focus-visible{ box-shadow:var(--focus-ring); }
.gr-card-head{ display:flex; align-items:center; justify-content:space-between; gap:10px; margin-bottom:10px; }
.gr-card-eyebrow{
  font-family:var(--font-mono); font-size:10px; letter-spacing:.18em; text-transform:uppercase;
  color:var(--ink-2);
}
.gr-card-open{
  display:inline-flex; align-items:baseline; gap:.5em; white-space:nowrap;
  font-family:var(--font-mono); font-size:11px; letter-spacing:.18em; text-transform:uppercase;
  font-weight:500; color:var(--azure-ink);
}
.gr-card-open .arrow{
  font-family:var(--font-display); font-style:italic; font-size:18px; line-height:1;
  color:var(--signal);
  transition:transform .2s var(--ease);
}
.gr-card:hover .gr-card-open .arrow{ transform:translate(3px,-3px); }
.gr-card-title{
  font-family:var(--font-display); font-size:20px; font-weight:600;
  letter-spacing:-.005em; line-height:1.3; color:var(--ink-0); margin:0 0 6px;
}
.gr-card-desc{
  font-family:var(--font-body); font-size:.9rem; line-height:1.55;
  color:var(--ink-2); margin:0; flex:1; max-width:60ch;
}
.gr-card-stat{
  margin-top:16px;
  font-family:var(--font-mono); font-size:12px; font-weight:600; letter-spacing:.1em; text-transform:uppercase;
  color:var(--azure-ink);
}
.gr-card-statlab{ margin-left:.4em; }
@media (max-width:1100px){ .gr-cards-grid{ grid-template-columns:repeat(2, minmax(0,1fr)); } }
@media (max-width:560px){ .gr-cards-grid{ grid-template-columns:1fr; } }

/* SYNOPSIS (editorial 2-col) -------------------------------------------- */
.gr-synopsis{
  display:grid;
  grid-template-columns:1.25fr 1fr;
  gap:56px;
  align-items:start;
}
.gr-synopsis p{
  font-family:var(--font-body);
  font-size:var(--fs-body); line-height:1.7;
  color:var(--ink-1);
  margin:0 0 1em;
  max-width:60ch;
  font-weight:400;
}
.gr-synopsis aside{
  font-family:var(--font-body);
  font-size:13.5px;
  line-height:1.62;
  color:var(--ink-2);
  border-left:1px solid var(--hair-1);
  padding-left:22px;
}
.gr-synopsis aside h4{
  font-family:var(--font-mono);
  font-size:10.5px;
  letter-spacing:.18em;
  text-transform:uppercase;
  color:var(--ink-0);
  margin:0 0 10px;
  font-weight:600;
}
.gr-synopsis .cta-link{
  display:inline-flex; align-items:baseline; gap:.3em;
  color:var(--azure-ink);
  font-weight:600;
  cursor:pointer;
  border-bottom:1px solid var(--tint-azure);
  padding-bottom:1px;
}
.gr-synopsis .cta-link:hover{ border-color:var(--azure-ink); }

/* Map-page chrome — for all tab layouts with map + analytics ------------ */
.map-page{
  position:relative;
  min-height:calc(100vh - var(--ei-header-h));
  display:flex;
  flex-direction:column;
  background:var(--paper-0);
}

/* Banner strip ---------------------------------------------------------- */
.map-banner{
  display:flex; align-items:flex-end; justify-content:space-between;
  gap:20px;
  padding:28px 32px 18px;
  background:var(--paper-0);
  flex-wrap:wrap;
}
.map-banner .banner-left{
  display:flex; flex-direction:column; gap:2px;
  flex:1 1 auto; min-width:0;
}
.map-banner .b-eyebrow{
  font-family:var(--font-mono);
  font-size:10.5px; letter-spacing:.18em; text-transform:uppercase;
  color:var(--ink-2);
}
.map-banner .b-eyebrow .sep{ color:var(--hair-1); margin:0 10px; }
.map-banner .b-title{
  font-family:var(--font-display);
  font-size:var(--fs-display-3);
  line-height:1.3;
  color:var(--ink-0);
  margin:0;
  font-weight:600;
  letter-spacing:-.012em;
}
.map-banner .b-title em{ font-style:normal; }
.map-banner .banner-right{
  display:flex; align-items:center; gap:10px; flex-wrap:wrap;
  flex:0 0 auto;
}

/* KPI deck (horizontal newspaper columns) ------------------------------- */
.kpi-deck{
  display:grid;
  grid-template-columns:repeat(auto-fit,minmax(180px,1fr));
  border-top:1px solid var(--ink-0);
  border-bottom:1px solid var(--hair-0);
  background:var(--paper-2);
}
.kpi-deck .kpi-cell{
  padding:10px 28px 10px 30px;
  border-right:1px solid var(--hair-0);
  display:flex; flex-direction:column; gap:3px;
  min-height:80px;
  justify-content:flex-start;
  position:relative;
}
.kpi-deck .kpi-cell:last-child{ border-right:0; }
.kpi-deck .kpi-label{
  font-family:var(--font-mono);
  font-size:9.5px; letter-spacing:.18em; text-transform:uppercase;
  color:var(--ink-2);
  margin-bottom:4px;
}
.kpi-deck .kpi-val{
  font-family:var(--font-mono);
  font-weight:500;
  font-size:27px;
  line-height:1.1;
  color:var(--ink-0);
  font-variant-numeric:tabular-nums;
}
.kpi-deck .kpi-val .unit{
  font-family:var(--font-mono);
  font-size:11px; letter-spacing:.14em; text-transform:uppercase;
  color:var(--ink-2);
  margin-left:6px;
}
.kpi-deck .kpi-sub{
  font-family:var(--font-mono);
  font-size:10.5px;
  color:var(--ink-2);
  margin-top:3px;
}
.kpi-deck .kpi-sub.up   { color:var(--teal-ink); }
.kpi-deck .kpi-sub.down { color:var(--rust-ink); }

/* Secondary KPI strip (static outlook: cost + idle) --------------------- */
.kpi-strip-eyebrow{
  display:flex;
  align-items:baseline;
  gap:14px;
  padding:10px 32px 6px;
  border-top:1px solid var(--hair-0);
  background:var(--paper-2);
}
.kpi-strip-eyebrow .eyebrow-label{
  font-family:var(--font-mono);
  font-size:9.5px;
  letter-spacing:.22em;
  text-transform:uppercase;
  color:var(--ink-0);
  font-weight:600;
}
.kpi-strip-eyebrow .eyebrow-note{
  font-family:var(--font-body);
  font-size:11.5px;
  color:var(--ink-2);
  font-style:italic;
}
.kpi-deck.kpi-deck-secondary{
  border-top:0;
  background:var(--paper-1);
}
.kpi-deck.kpi-deck-secondary .kpi-cell{
  min-height:72px;
  padding:10px 28px 10px 30px;
}
.kpi-deck.kpi-deck-secondary .kpi-val{
  font-size:23px;
}

/* Wrapper for a server-rendered KPI that emits its own .kpi-val / .kpi-sub.
   uiOutput's container is a plain block, so without this the value and its
   sub-label run together on one line instead of stacking. */
.kpi-stack{
  display:flex; flex-direction:column; gap:3px;
  min-width:0; align-items:flex-start;
}

/* KPI content rendered by server.R uiOutputs */
.kpi-body{
  display:flex; align-items:center; gap:10px;
}
/* Decorative, so it carries no hue: four crimson glyphs across a KPI deck
   read as four alarms. */
.kpi-icon{
  color:var(--ink-2); font-size:18px; line-height:1;
}
.kpi-text{ display:flex; flex-direction:column; gap:2px; min-width:0; }
.kpi-value{
  font-family:var(--font-mono);
  font-size:27px;
  line-height:1.1;
  color:var(--ink-0);
  font-variant-numeric:tabular-nums;
  margin:0;
  font-weight:500;
}
.kpi-delta{
  font-family:var(--font-mono);
  font-size:10.5px;
  letter-spacing:.08em;
  color:var(--ink-2);
  margin:4px 0 0;
}
.kpi-delta.up   { color:var(--teal-ink); }
.kpi-delta.down { color:var(--rust-ink); }

/* Filter rail — sits in the page flow directly above the table or map it
   filters. Every rail in ui.R also carries .filter-rail--inline, which the
   Show/Hide script keys on. ----------------------------------------------- */
.filter-rail{
  width:100%;
  background:var(--paper-2);
  border:1px solid var(--hair-0);
  border-radius:var(--radius);
  display:flex;
  flex-direction:column;
  align-items:stretch;
  padding:0;
  overflow:visible;
  margin-bottom:18px;
}
.filter-rail-lead{
  display:flex; align-items:center; justify-content:flex-start; gap:10px;
  padding:18px 22px;
  border-right:0;
  border-bottom:1px solid var(--hair-0);
  margin-right:0;
  align-self:stretch;
  flex:0 0 auto;
}
.filter-rail-lead .icon{
  color:var(--ink-0);
  font-size:14px;
  line-height:1;
}
.filter-rail-lead .title{
  font-family:var(--font-mono);
  font-size:10.5px; letter-spacing:.18em; text-transform:uppercase;
  color:var(--ink-0);
  font-weight:600;
}
.filter-rail-cells{
  display:flex;
  flex-direction:column;
  gap:18px;
  padding:18px 22px 22px;
  overflow-y:auto;
  flex:1 1 auto;
  min-height:0;
  min-width:0;
}
.filter-cell{
  display:flex; flex-direction:column; gap:6px;
  min-width:0;
}
.filter-cell > .cell-label{
  font-family:var(--font-display);
  font-size:11.5px; letter-spacing:.08em; text-transform:uppercase;
  color:var(--ink-2);
  margin:0;
  font-weight:600;
  white-space:normal;
  display:flex; align-items:center; gap:6px;
}
.filter-rail--inline .filter-rail-lead{
  padding:10px 24px 8px;
  border-bottom:0;
  flex-wrap:wrap;
}
.filter-rail--inline .filter-rail-lead .btn-reset{
  margin-left:auto;
}
/* The Show/Hide toggle is appended to the lead by JS. On rails with no Reset
   button it is the only trailing control, so it takes the push to the right
   edge itself; where a Reset precedes it, Reset does the pushing and the two
   sit together. */
.filter-rail--inline .filter-rail-lead .inline-rail-toggle{ margin-left:auto; }
.filter-rail--inline .filter-rail-lead .btn-reset ~ .inline-rail-toggle{
  margin-left:0;
}
/* A flex row, not a fixed 12-column grid. On a grid, a cell holding six short
   chips still reserved a whole row and a slider still reserved a quarter of
   one, so every rail carried a band of empty paper and ran two or three rows
   deep. Flexing lets a chip group take the width its chips actually need and
   lets the sliders share whatever is left, which folds most rails onto a
   single row. */
.filter-rail--inline .filter-rail-cells{
  display:flex;
  /* The rail itself is a column, so the direction is restated here rather
     than inherited. */
  flex-direction:row;
  flex-wrap:wrap;
  align-items:flex-end;
  gap:10px 20px;
  padding:2px 24px 14px;
  overflow:visible;
  max-height:1600px;
  opacity:1;
  transition:max-height .28s var(--ease), opacity .2s var(--ease),
             padding .28s var(--ease);
}
/* Collapsed: header row (with Reset + toggle) stays as the handle. max-height
   rather than display:none, so widgets restored collapsed at session start
   still initialize with a real width. */
.filter-rail--inline.is-collapsed .filter-rail-cells{
  max-height:0;
  opacity:0;
  padding-top:0;
  padding-bottom:0;
  overflow:hidden;
}
/* Text, select and date controls stretch but stop short of eating a row on
   their own; sliders take a comfortable share; a cell holding a checkbox or
   radio group is as wide as its chips and no wider, wrapping internally when
   the row runs out. */
.filter-rail--inline .filter-cell{ flex:1 1 190px; min-width:170px; max-width:340px; }
.filter-rail--inline .filter-cell.wide{ flex:1 1 300px; min-width:270px; max-width:480px; }
.filter-rail--inline .filter-cell.x-wide{ flex:0 1 auto; max-width:100%; }
.filter-rail--inline .filter-cell:has(.shiny-options-group){
  flex:0 1 auto;
  min-width:0;
  max-width:100%;
}
.filter-rail--inline .filter-cell .shiny-input-container{ width:100% !important; }
.filter-rail--inline .filter-cell .input-daterange{ width:100%; }
/* ionRangeSlider centers each value bubble on its handle, so at the two ends
   of the track half the bubble sits outside it and runs into the next grid
   cell. Insetting the whole widget (margin, not padding: the bar and handles
   are positioned against this element's padding box) keeps every bubble
   inside its own column. */
.filter-rail--inline .filter-cell .irs--shiny{
  margin-left:22px;
  margin-right:22px;
}
.inline-rail-toggle{
  display:inline-flex; align-items:center; gap:6px;
  font-family:var(--font-mono);
  font-size:10px; letter-spacing:.16em; text-transform:uppercase;
  color:var(--ink-1);
  background:var(--paper-0);
  border:1px solid var(--hair-1);
  border-radius:var(--radius);
  padding:5px 9px;
  cursor:pointer;
  transition:color .18s var(--ease), border-color .18s var(--ease);
}
.inline-rail-toggle:hover{
  color:var(--azure-ink); border-color:var(--azure);
}
.inline-rail-toggle:focus-visible{
  outline:2px solid var(--azure); outline-offset:2px;
}
.inline-rail-toggle .chev{
  font-size:9px; line-height:1;
  transition:transform .2s var(--ease);
}
.inline-rail-toggle[aria-expanded="false"] .chev{ transform:rotate(-90deg); }
@media (max-width:1100px){
  .filter-rail--inline .filter-cell,
  .filter-rail--inline .filter-cell.wide{ flex:1 1 280px; max-width:100%; }
}
@media (max-width:640px){
  .filter-rail--inline .filter-cell,
  .filter-rail--inline .filter-cell.wide,
  .filter-rail--inline .filter-cell.x-wide,
  .filter-rail--inline .filter-cell:has(.shiny-options-group),
  .map-page .filter-rail--inline .filter-cell.x-wide,
  .map-page .filter-rail--inline .filter-cell:has(.shiny-options-group){
    flex:1 1 100%;
    max-width:100%;
  }
  .filter-rail--inline .filter-rail-lead{ padding:10px 16px 8px; }
  .filter-rail--inline .filter-rail-cells{ gap:10px; padding:2px 16px 12px; }
  .filter-rail--inline{ margin-bottom:14px; }
}

/* -- Inline rail on a map page --
   The Register sits in a padded container, so its rail reads as a card. Map
   pages are built from full-bleed bands (banner, KPI deck, map), so the rail
   drops its side borders and radius and picks up the deck's 32px gutter,
   landing as one more band directly above the map it filters. */
.map-page .filter-rail--inline{
  border-left:0;
  border-right:0;
  border-radius:0;
  border-top:0;
  border-bottom:1px solid var(--hair-0);
  margin-bottom:0;
  background:var(--paper-1);
}
.map-page .filter-rail--inline .filter-rail-lead{ padding:10px 32px 6px; }
.map-page .filter-rail--inline .filter-rail-cells{ padding:0 32px 14px; }
/* Map-page rails carry mostly sliders, and ionRangeSlider hangs its value
   bubble past each end of the track, so a slider cell keeps a floor wide
   enough that the two bubbles clear the cells beside it. */
.map-page .filter-rail--inline .filter-cell.wide{ flex:1 1 320px; min-width:290px; }
/* Chip groups on a map page are short enough to share a row rather than
   claim one: they start from a share of the rail and wrap their own chips,
   which folds these rails onto a single line. The Register keeps the
   natural-width behavior above -- its seven status chips need a full row
   however they are packed. */
.map-page .filter-rail--inline .filter-cell.x-wide,
.map-page .filter-rail--inline .filter-cell:has(.shiny-options-group){
  flex:3 1 250px;
  min-width:240px;
  max-width:100%;
}
@media (max-width:1100px){
  .map-page .filter-rail--inline .filter-cell.wide{ flex:1 1 300px; max-width:100%; }
}
@media (max-width:640px){
  .map-page .filter-rail--inline .filter-cell.wide{ flex:1 1 100%; max-width:100%; }
}
@media (max-width:640px){
  .map-page .filter-rail--inline{ margin-bottom:0; }
  .map-page .filter-rail--inline .filter-rail-lead{ padding:12px 18px 10px; }
  .map-page .filter-rail--inline .filter-rail-cells{ padding:2px 18px 14px; }
}

/* Map viewport (full-width) --------------------------------------------- */
.map-viewport{
  width:100%;
  height:60vh;
  min-height:440px;
  background:var(--paper-1);
  border-bottom:1px solid var(--hair-0);
  position:relative;
}
.map-viewport > *,
.map-viewport > .shiny-spinner-output-container,
.map-viewport > .shiny-spinner-output-container > .html-widget{
  width:100% !important; height:100% !important;
}
.map-viewport .maplibregl-map{
  background:var(--map-ground); height:100%; width:100%;
}

/* Analytics section (below map) ----------------------------------------- */
.analytics{
  padding:40px 32px 52px;
  background:var(--paper-0);
}
.analytics-inner{ max-width:1400px; margin:0 auto; }
.analytics-head{
  display:flex; justify-content:space-between; align-items:flex-end;
  gap:18px; flex-wrap:wrap;
  padding-bottom:12px;
  border-bottom:1px solid var(--ink-0);
  margin-bottom:24px;
}
.analytics-head .eyebrow{ display:block; margin-bottom:6px; }
.analytics-head .title{
  font-family:var(--font-display);
  font-size:var(--fs-display-3);
  line-height:1.3;
  color:var(--ink-0);
  margin:0;
  font-weight:600;
  letter-spacing:-.012em;
}
.analytics-head .title em{ font-style:normal; }
.analytics-head .meta{
  font-family:var(--font-mono);
  font-size:11px; letter-spacing:.14em; text-transform:uppercase;
  color:var(--ink-2);
}

.analytics-grid{
  display:grid;
  grid-template-columns:repeat(12,minmax(0,1fr));
  gap:0;
  border-top:1px solid var(--hair-0);
  border-left:1px solid var(--hair-0);
}
.panel{
  border-right:1px solid var(--hair-0);
  border-bottom:1px solid var(--hair-0);
  background:var(--paper-2);
  padding:20px 22px 18px;
  display:flex; flex-direction:column;
  gap:10px;
  min-height:240px;
  grid-column:span 4;
  position:relative;
}
.panel.panel-6{ grid-column:span 6; }
.panel.panel-8{ grid-column:span 8; }
.panel.panel-12{ grid-column:span 12; }
.source-note{
  grid-column:span 12;
  border-right:1px solid var(--hair-0);
  border-bottom:1px solid var(--hair-0);
  background:var(--paper-2);
  padding:14px 22px 16px;
  display:flex;
  gap:18px;
  align-items:baseline;
  flex-wrap:wrap;
}
.source-note-label{
  font-family:var(--font-mono);
  font-size:10.5px;
  letter-spacing:.16em;
  text-transform:uppercase;
  color:var(--ink-2);
  flex-shrink:0;
  padding-top:2px;
}
.source-note-list{
  list-style:none;
  margin:0;
  padding:0;
  flex:1 1 0;
  display:flex;
  flex-direction:column;
  gap:4px;
}
.source-note-list li{
  font-family:var(--font-body);
  font-size:12px;
  line-height:1.55;
  color:var(--ink-2);
}
.source-note-list li em{ font-style:italic; color:var(--ink-1); }
.source-note-list a{
  color:var(--ink-1);
}
.source-note-list a:hover{ color:var(--azure-ink); }
/* The head is a bslib card-header and the body a bslib card-body (the panel
   is a card so full_screen = TRUE carries the §5 expand control); Bootstrap's
   card chrome gives way to the panel's own. */
.panel > .card-header.panel-head{
  background:none;
  min-height:0;
  border-bottom:1px dashed var(--hair-0);
  padding:0 0 10px;
}
.panel > .card-body{
  display:flex; flex-direction:column;
  gap:10px;
  padding:0;
}
.panel-head{
  display:flex; justify-content:space-between; align-items:flex-start;
  gap:10px;
  margin-bottom:6px;
}
.panel-title{
  font-family:var(--font-display);
  font-size:17px;
  line-height:1.4;
  color:var(--ink-0);
  margin:0;
  font-weight:600;
  letter-spacing:-.004em;
  flex:1; min-width:0;
}
.panel-title em{ font-style:normal; }
.panel-tools{ display:flex; align-items:center; gap:6px; flex-wrap:wrap; }

/* Full-screen expansion is the suite standard (§5): the shared stylesheet
   draws the expanded card edge-to-edge and grows the outputs inside. Only
   the compact-grid caps lift here while a panel is expanded. */
.panel[data-full-screen="true"]{ background:var(--paper-2); padding:26px 32px 22px; }
.panel[data-full-screen="true"] .panel-scroll{ max-height:none; }
.panel[data-full-screen="true"] .panel-map{
  flex:1 1 auto; height:auto; min-height:58vh;
  display:flex; flex-direction:column;
}
.panel[data-full-screen="true"] .panel-map .shiny-spinner-output-container,
.panel[data-full-screen="true"] .panel-map .html-widget{
  height:100% !important; min-height:0; flex:1 1 auto;
}
.panel-note{
  font-family:var(--font-body);
  font-size:11.5px;
  line-height:1.55;
  color:var(--ink-2);
  padding-top:8px;
  border-top:1px dashed var(--hair-0);
  margin-top:8px;
}
.panel-note em{ font-style:italic; }

/* Funding-provenance callout. Used where a campaign is funded separately from
   IIJA and the distinction has to survive a screenshot into a board document. */
.funding-note{
  max-width:1400px;
  margin:0 auto 18px;
  padding:14px 18px;
  border-left:3px solid var(--teal);
  background:var(--paper-1);
  font-family:var(--font-body);
  font-size:13px;
  line-height:1.6;
  color:var(--ink-1);
}
.funding-note p{ margin:0; }
.funding-note p + p{ margin-top:8px; }
.funding-note .muted{ font-size:11.5px; color:var(--ink-2); }

.panel-scroll{
  max-height:380px;
  overflow-y:auto;
  scrollbar-width:thin;
  scrollbar-color:var(--hair-1) transparent;
}
.panel-scroll::-webkit-scrollbar{ width:8px; }
.panel-scroll::-webkit-scrollbar-thumb{ background:var(--hair-1); border-radius:4px; }

/* Focused mini-map inside an analytics panel */
.panel-map{
  border:1px solid var(--hair-1);
  border-radius:var(--radius);
  overflow:hidden;
  height:320px;
}
.panel-map > .shiny-spinner-output-container,
.panel-map > .shiny-spinner-output-container > .html-widget{
  width:100% !important; height:100% !important;
}

/* Inline small filter group inside a panel */
.panel-filters{
  display:flex; align-items:flex-end; gap:14px 18px;
  flex-wrap:wrap;
  padding:0 0 6px;
  width:100%;
}
.panel-filters .filter-cell{
  flex:1 1 160px;
  min-width:140px;
  max-width:100%;
}
.panel-filters .filter-cell.wide{
  flex:2 1 240px;
  min-width:200px;
}
.panel-filters .filter-cell .shiny-input-container{
  width:100% !important;
}
.panel-filters .filter-cell .form-control,
.panel-filters .filter-cell .selectize-input,
.panel-filters .filter-cell .irs{
  width:100% !important;
}
.panel-filters .shiny-input-container{ margin:0 !important; }
/* Same inset as the rail: ionRangeSlider centers its value bubble on the
   handle, so at the ends of the track half the bubble sits outside it and
   runs into the control beside it. */
.panel-filters .filter-cell .irs--shiny{
  margin-left:22px;
  margin-right:22px;
}

/* Sub-tabs (Plugging: IIJA / Legacy) ------------------------------------ */
.gr-subtabs{
  background:var(--paper-0);
}
.gr-subtabs > .tabbable{
  display:flex; flex-direction:column;
}
.gr-subtabs .nav.nav-tabs{
  border:0;
  margin:0;
  padding:6px 32px 0;
  border-bottom:1px solid var(--hair-0);
  display:flex;
  background:var(--paper-0);
}
.gr-subtabs .nav.nav-tabs > li{ margin:0; float:none; }
.gr-subtabs .nav.nav-tabs > li > a{
  padding:12px 18px 13px;
  font-family:var(--font-body);
  font-size:13px;
  font-weight:600;
  letter-spacing:.02em;
  color:var(--ink-2);
  border:0;
  border-bottom:2px solid transparent;
  background:transparent;
  margin:0;
  border-radius:0;
  line-height:1.2;
}
.gr-subtabs .nav.nav-tabs > li > a:hover{
  color:var(--ink-0);
  background:transparent;
  border-bottom-color:var(--hair-1);
}
.gr-subtabs .nav.nav-tabs > li.active > a,
.gr-subtabs .nav.nav-tabs > li.active > a:focus,
.gr-subtabs .nav.nav-tabs > li.active > a:hover{
  color:var(--ink-0);
  border-bottom-color:var(--signal);
  background:transparent;
}

/* Register / data page (filter rail + table) ---------------------------- */
.data-page{
  min-height:calc(100vh - var(--ei-header-h));
  background:var(--paper-0);
  display:flex; flex-direction:column;
}
.data-main{
  padding:28px 32px 48px;
  max-width:1500px; width:100%;
  margin:0 auto;
}
.data-frame{
  background:var(--paper-2);
  border:1px solid var(--hair-0);
  padding:22px 24px;
  border-radius:var(--radius);
}
.data-frame-footer{
  margin-top:12px;
  padding-top:10px;
  border-top:1px dashed var(--hair-0);
  font-size:12.5px;
  color:var(--ink-2);
  /* Note on the left, export on the right. The export sits with the table
     rather than in the filter rail so it stays put when the rail collapses. */
  display:flex;
  align-items:flex-start;
  justify-content:space-between;
  gap:24px;
  flex-wrap:wrap;
}
.data-frame-footer .footer-note{ flex:1 1 460px; min-width:0; }
.data-frame-footer .footer-export{
  flex:0 0 auto;
  display:flex;
  flex-direction:column;
  align-items:flex-end;
  gap:6px;
}
.data-frame-footer .export-count{
  font-family:var(--font-mono);
  font-size:10px;
  letter-spacing:.12em;
  text-transform:uppercase;
  color:var(--ink-2);
  white-space:nowrap;
}
@media (max-width:700px){
  .data-frame-footer .footer-export{ align-items:flex-start; width:100%; }
}

/* Shiny inputs — unified compact style ---------------------------------- */
.shiny-input-container .control-label,
.shiny-input-container > label,
.form-group > label{
  font-family:var(--font-display);
  font-size:11.5px;
  font-weight:600;
  letter-spacing:.08em;
  text-transform:uppercase;
  color:var(--ink-2);
  margin-bottom:5px;
  display:block;
}
.shiny-input-container{ margin-bottom:10px; }
.filter-cell .shiny-input-container{ margin-bottom:0; }

.form-control,
.selectize-input,
.shiny-input-container input[type="text"],
.shiny-input-container input[type="number"]{
  background:var(--paper-0);
  border:1px solid var(--hair-1);
  color:var(--ink-0);
  font-family:var(--font-body);
  font-size:13px;
  border-radius:var(--radius);
  box-shadow:none;
  padding:7px 10px;
  min-height:34px;
  transition:border-color .15s var(--ease), box-shadow .15s var(--ease);
}
.form-control:focus,
.selectize-input.focus{
  outline:0;
  border-color:var(--azure);
  box-shadow:var(--focus-ring);
}
.selectize-input{ padding:5px 8px; min-height:34px; }
.selectize-input input{ font-family:var(--font-body); color:var(--ink-0); font-size:13px; }
.selectize-input > .item{
  background:var(--paper-1);
  border:1px solid var(--hair-1);
  color:var(--ink-0);
  border-radius:var(--radius);
  font-size:11.5px;
  font-family:var(--font-mono);
  padding:1px 8px 2px !important;
  margin:1px 3px 1px 0 !important;
}
.selectize-dropdown{
  background:var(--paper-0);
  border:1px solid var(--hair-1);
  font-family:var(--font-body);
  box-shadow:none;
  border-radius:var(--radius);
}
.selectize-dropdown .option{
  padding:8px 12px;
  font-size:13px;
  color:var(--ink-0);
}
.selectize-dropdown .option.active,
.selectize-dropdown .option:hover{
  background:var(--ink-0);
  color:var(--ink-inv);
}

/* Option groups — flex wrap for inline checkbox/radio rows */
.shiny-options-group{
  display:flex;
  flex-wrap:wrap;
  gap:4px 14px;
  margin:2px 0 0;
}

/* Rail-mode: inline checkboxes/radios render as compact pills */
.filter-cell .shiny-options-group{
  gap:4px 6px;
}
.filter-cell .shiny-options-group .radio-inline,
.filter-cell .shiny-options-group .checkbox-inline{
  margin:0 !important;
  padding:0;
}

/* Stacked groups (non-inline) use full rows */
.shiny-options-group .radio,
.shiny-options-group .checkbox{ flex:0 0 100%; }

.radio,.checkbox{
  font-family:var(--font-body);
  font-size:12.5px;
  color:var(--ink-1);
  padding:0;
}
.radio label,.checkbox label,
.radio-inline,.checkbox-inline{
  font-size:12.5px;
  color:var(--ink-1);
  padding:3px 0 3px 22px;
  position:relative;
  cursor:pointer;
  display:inline-flex;
  align-items:center;
  line-height:1.25;
  margin:0;
  min-height:22px;
}
.radio input[type="radio"],
.checkbox input[type="checkbox"],
.radio-inline input[type="radio"],
.checkbox-inline input[type="checkbox"]{
  position:absolute; left:0; top:50%;
  transform:translateY(-50%);
  width:14px; height:14px;
  margin:0;
  accent-color:var(--azure);
}

/* Filter-rail pill treatment for inline groups.
   We render each checkbox/radio label as a pill so dense option lists don't wrap messily. */
.filter-cell .shiny-options-group > .checkbox-inline,
.filter-cell .shiny-options-group > .radio-inline{
  background:var(--paper-2);
  border:1px solid var(--hair-0);
  border-radius:var(--radius);
  padding:4px 10px 4px 26px;
  font-family:var(--font-mono);
  font-size:10.5px;
  letter-spacing:.1em;
  text-transform:uppercase;
  color:var(--ink-1);
  transition:background .15s var(--ease), color .15s var(--ease), border-color .15s var(--ease);
  min-height:28px;
  white-space:nowrap;
}
.filter-cell .shiny-options-group > .checkbox-inline input[type="checkbox"],
.filter-cell .shiny-options-group > .radio-inline input[type="radio"]{
  left:8px;
}
.filter-cell .shiny-options-group > .checkbox-inline:has(input:checked),
.filter-cell .shiny-options-group > .radio-inline:has(input:checked){
  background:var(--ink-0);
  color:var(--ink-inv);
  border-color:var(--ink-0);
}

/* Radio button groups (shinyWidgets radioGroupButtons) */
.btn-group.bootstrap-switch,
.btn-group.radiobtn-group,
.radiobtn-group{
  display:inline-flex;
  border:1px solid var(--hair-1);
  border-radius:var(--radius);
  overflow:hidden;
}
.radiobtn-group .btn,
.btn-group.bootstrap-switch .btn{
  font-family:var(--font-mono);
  font-size:10px;
  letter-spacing:.14em;
  text-transform:uppercase;
  padding:6px 11px;
  background:var(--paper-0);
  color:var(--ink-2);
  border:0;
  border-right:1px solid var(--hair-0);
  border-radius:0;
  box-shadow:none;
  line-height:1.2;
}
.radiobtn-group .btn:last-child{ border-right:0; }
.radiobtn-group .btn.active,
.radiobtn-group .btn:active{
  background:var(--ink-0);
  color:var(--ink-inv);
  box-shadow:none;
}
.radiobtn-group .btn:hover:not(.active){
  background:var(--paper-1);
  color:var(--ink-0);
}

/* Sliders */
.irs{ font-family:var(--font-mono); font-variant-numeric:tabular-nums; }
.irs--shiny .irs-bar{
  background:var(--ink-0);
  border:0;
  height:3px;
  top:27px;
}
.irs--shiny .irs-line{
  background:var(--hair-1);
  height:3px; top:27px;
}
.irs--shiny .irs-handle{
  background:var(--azure);
  border:2px solid var(--paper-0);
  box-shadow:0 0 0 1px var(--azure);
  width:13px; height:13px;
  top:22px;
  cursor:grab;
}
.irs--shiny .irs-handle:hover{ background:var(--azure-ink); }
.irs--shiny .irs-min,
.irs--shiny .irs-max{
  background:transparent;
  color:var(--ink-2);
  font-size:9.5px;
  letter-spacing:.08em;
}
.irs--shiny .irs-from,
.irs--shiny .irs-to,
.irs--shiny .irs-single{
  background:var(--ink-0);
  color:var(--ink-inv);
  border-radius:var(--radius);
  font-size:10.5px;
  padding:2px 6px;
  letter-spacing:.02em;
}
.irs--shiny .irs-from::before,
.irs--shiny .irs-to::before,
.irs--shiny .irs-single::before{ border-top-color:var(--ink-0); }

/* DT tables ------------------------------------------------------------- */
table.dataTable{
  font-family:var(--font-body);
  font-size:12.5px;
  border-collapse:separate;
  border-spacing:0;
  background:var(--paper-0);
  border:1px solid var(--hair-0);
  width:100% !important;
  border-radius:var(--radius);
  overflow:hidden;
}
table.dataTable thead th{
  font-family:var(--font-display);
  font-size:11.5px;
  letter-spacing:.08em;
  text-transform:uppercase;
  color:var(--ink-2);
  background:var(--paper-2);
  border-bottom:2px solid var(--indigo);
  padding:9px 12px;
  text-align:left;
  font-weight:600;
}
table.dataTable tbody td{
  padding:9px 12px;
  color:var(--ink-1);
  border-bottom:1px solid var(--hair-0);
  font-variant-numeric:tabular-nums;
}
table.dataTable tbody tr:nth-child(even) td{ background:var(--paper-sink); }
table.dataTable tbody tr:hover td{ background:var(--paper-1); }
/* Selected row wears the same rust the maps use for a picked feature. */
table.dataTable tbody tr.selected td,
table.dataTable tbody tr.selected:hover td{
  background:var(--select-tint);
  box-shadow:inset 3px 0 0 var(--rust);
}
/* A number can be compared down its column, so it is mono and right-aligned.
   DT tags genuine numeric columns itself; the .is-num class is added by the
   table script in ui.R for columns whose values arrive pre-formatted as
   strings ("$42,105", "1,908 ft"), which DT reads as text. */
table.dataTable td.dt-right,
table.dataTable th.dt-right,
table.dataTable td.is-num{
  font-family:var(--font-mono);
  font-size:11.8px;
  text-align:right;
}
table.dataTable th.dt-right{ font-family:var(--font-display); }
/* A missing value reads as an em dash, never as an empty cell. */
table.dataTable tbody td:empty::after{
  content:"\2014";
  color:var(--ink-2);
  font-family:var(--font-mono);
}
.dataTables_wrapper{
  font-family:var(--font-body);
  font-size:12.5px;
  color:var(--ink-1);
}
.dataTables_wrapper .dataTables_filter input{
  background:var(--paper-0);
  border:1px solid var(--hair-1);
  color:var(--ink-0);
  font-family:var(--font-body);
  font-size:12.5px;
  padding:5px 9px;
  border-radius:var(--radius);
  margin-left:8px;
  min-height:30px;
}
.dataTables_wrapper .dataTables_length select{
  background:var(--paper-0);
  border:1px solid var(--hair-1);
  color:var(--ink-0);
  font-size:12.5px;
  padding:4px 8px;
  border-radius:var(--radius);
}
.dataTables_wrapper .dataTables_info,
.dataTables_wrapper .dataTables_paginate{
  font-size:11.5px;
  color:var(--ink-2);
  padding-top:12px;
  font-family:var(--font-mono);
  letter-spacing:.08em;
}
.dataTables_wrapper .paginate_button{
  padding:4px 10px !important;
  border:1px solid var(--hair-0) !important;
  background:transparent !important;
  color:var(--ink-1) !important;
  font-family:var(--font-mono) !important;
  font-size:10.5px !important;
  border-radius:var(--radius) !important;
  margin:0 2px !important;
  letter-spacing:.06em;
}
.dataTables_wrapper .paginate_button.current,
.dataTables_wrapper .paginate_button.current:hover{
  background:var(--ink-0) !important;
  color:var(--ink-inv) !important;
  border-color:var(--ink-0) !important;
}
.dataTables_wrapper .paginate_button:hover{
  background:var(--paper-1) !important;
  color:var(--ink-0) !important;
}
.dataTables_wrapper .dataTables_filter,
.dataTables_wrapper .dataTables_length{
  padding-bottom:8px;
}

/* MapLibre -------------------------------------------------------------- */
/* Unified control chrome — zoom, geolocate, reset, draw, geocoder.
   IMPORTANT: use background-color (not background shorthand) so the
   SVG icons the controls set as background-image survive. */
.maplibregl-ctrl-group{
  background-color:var(--paper-0) !important;
  border:1px solid var(--hair-1) !important;
  border-radius:var(--radius) !important;
  box-shadow:none !important;
}
.maplibregl-ctrl-group button{
  width:30px !important;
  height:30px !important;
  background-color:var(--paper-0) !important;
  border-radius:var(--radius) !important;
  box-sizing:border-box !important;
}
.maplibregl-ctrl-group button:hover{
  background-color:var(--paper-1) !important;
}
.maplibregl-ctrl-group button + button{
  border-top:1px solid var(--hair-0) !important;
}
/* the draw toolbar's combine / uncombine buttons aren't useful here */
.mapbox-gl-draw_combine,
.mapbox-gl-draw_uncombine{ display:none !important; }

/* Give controls breathing room from the map edge */
.maplibregl-ctrl-top-left{ top:14px; left:14px; }
.maplibregl-ctrl-top-right{ top:14px; right:14px; }
.maplibregl-ctrl-bottom-left{ bottom:14px; left:14px; }
.maplibregl-ctrl-bottom-right{ bottom:14px; right:14px; }

/* mapgl legend — matches paper/ink system. mapgl injects its own
   #maplegend styles, so the id joins the selector to outrank them. */
#maplegend.mapboxgl-legend{
  background:var(--paper-0) !important;
  border:1px solid var(--hair-1) !important;
  border-radius:var(--radius) !important;
  padding:11px 13px 10px !important;
  box-shadow:none !important;
  font-family:var(--font-body) !important;
  font-size:11.5px !important;
  color:var(--ink-1) !important;
  line-height:1.45 !important;
  max-width:220px;
}
#maplegend.mapboxgl-legend h4,
#maplegend.mapboxgl-legend .mapgl-legend-title{
  font-family:var(--font-mono) !important;
  font-size:10px !important;
  letter-spacing:.16em;
  text-transform:uppercase;
  color:var(--ink-0) !important;
  font-weight:600;
  margin:0 0 8px;
  padding-bottom:6px;
  border-bottom:1px solid var(--hair-0);
}
#maplegend.mapboxgl-legend .legend-color{
  border-radius:var(--radius);
  border:1px solid var(--hair-0);
}
.maplibregl-ctrl-attrib{
  background:var(--paper-0) !important;
  color:var(--ink-2) !important;
  font-family:var(--font-mono);
  font-size:10px !important;
}
.maplibregl-popup-content{
  background:var(--paper-0);
  border:1px solid var(--hair-1);
  border-radius:var(--radius);
  box-shadow:none;
  font-family:var(--font-body);
  font-size:12.5px;
  color:var(--ink-1);
  line-height:1.5;
  padding:12px 14px;
}
.maplibregl-popup-anchor-bottom .maplibregl-popup-tip{ border-top-color:var(--paper-0); }
.maplibregl-popup-anchor-top .maplibregl-popup-tip{ border-bottom-color:var(--paper-0); }
.maplibregl-popup-anchor-left .maplibregl-popup-tip{ border-right-color:var(--paper-0); }
.maplibregl-popup-anchor-right .maplibregl-popup-tip{ border-left-color:var(--paper-0); }
.maplibregl-map{ font-family:var(--font-body); }

/* Sparklines (home readout) --------------------------------------------- */
.fa-spark,.home-spark-svg{ width:100%; height:32px; }
.fa-spark-line{ fill:none; stroke:var(--signal); stroke-width:1.4; }
.fa-spark-area{ fill:var(--tint-crimson); }
.fa-spark-end{ fill:var(--signal); }

/* Modals (priority info etc.) ------------------------------------------- */
.modal-content{
  background:var(--paper-0);
  border:1px solid var(--ink-0);
  border-radius:var(--radius);
  box-shadow:none;
  font-family:var(--font-body);
}
.modal-header{ border-bottom:1px solid var(--hair-0); padding:16px 22px; }
.modal-title{
  font-family:var(--font-display);
  font-size:24px;
  color:var(--ink-0);
  font-weight:600;
  letter-spacing:-.008em;
}
.modal-body{ padding:18px 22px; font-size:13.5px; color:var(--ink-1); line-height:1.6; }
.modal-footer{ border-top:1px solid var(--hair-0); padding:12px 22px; }

/* About — editorial long-form ------------------------------------------- */
.about-page{
  min-height:calc(100vh - var(--ei-header-h));
  padding:56px 32px 72px;
  background:var(--paper-0);
}
.about-container{
  max-width:760px;
  margin:0 auto;
  font-family:var(--font-body);
  font-size:15.5px;
  line-height:1.72;
  color:var(--ink-1);
}
.about-container h1,.about-container h2,.about-container h3{
  font-family:var(--font-display);
  color:var(--ink-0);
  font-weight:600;
  letter-spacing:-.012em;
  border-bottom:0 !important;
  padding-bottom:0 !important;
}
.about-container h1{ font-size:44px; margin:0 0 18px; }
.about-container h2{ font-size:30px; margin:40px 0 14px;
  padding-bottom:8px !important; border-bottom:1px solid var(--hair-0) !important; }
.about-container h2 em{ font-style:italic; }
.about-container h3{ font-size:20px; margin:28px 0 10px; color:var(--ink-0); }
.about-container a{
  color:var(--azure-ink);
  border-bottom:1px solid var(--tint-azure);
}
.about-container a:hover{ border-color:var(--azure-ink); }
.about-container code{
  font-family:var(--font-mono);
  background:var(--paper-1);
  padding:1px 6px;
  font-size:.9em;
  border-radius:var(--radius);
  color:var(--ink-0);
}
.about-container ul{ padding-left:20px; }
.about-container li{ margin-bottom:6px; }
.about-container div[style*="grid-template-columns"]{ margin:16px 0 24px !important; }
.about-container div[style*="background: var(--tint-azure)"]{
  background:var(--paper-2) !important;
  border:1px solid var(--hair-0) !important;
  border-radius:var(--radius) !important;
  padding:16px !important;
}
.about-container div[style*="background: var(--tint-azure)"] strong{
  color:var(--ink-0) !important;
  font-family:var(--font-mono);
  font-size:11px !important;
  letter-spacing:.14em;
  text-transform:uppercase;
}
.about-container p[style*="font-size: 14px"]{
  font-size:14.5px !important;
  color:var(--ink-1) !important;
}

/* Utilities ------------------------------------------------------------- */
.u-mono{ font-family:var(--font-mono); }
.u-italic{ font-style:italic; }
/* Headings use a single (non-italic) style for the academic/regulator audience;
   italics are kept only where they carry meaning (defined terms, the Act title). */
.gr-section-title .u-italic{ font-style:normal; }
.shiny-spinner-output-container .load-container{
  background:rgba(255,255,255,.72) !important;
}
.sk-color-1,.sk-color-2,.sk-color-3{ background-color:var(--indigo) !important; }

/* Plotly hover + axis polish (targets our inline styles too).
   plotly writes a font family onto every SVG text node it draws, so without
   the catch-all below the figures arrive in plotly's default sans while the
   rest of the page is in the suite's -- data labels and annotations included,
   not only the ticks and titles named after it. */
.js-plotly-plot .plotly text{ font-family:var(--font-body) !important; }
.js-plotly-plot .plotly .xtick > text,
.js-plotly-plot .plotly .ytick > text{
  fill:var(--ink-2) !important;
  font-family:var(--font-body) !important;
  font-size:11px !important;
  font-variant-numeric:tabular-nums !important;
}
.js-plotly-plot .plotly .legendtext,
.js-plotly-plot .plotly .legend .legendtext,
.js-plotly-plot .plotly .xtitle,
.js-plotly-plot .plotly .ytitle{
  font-family:var(--font-body) !important;
  fill:var(--ink-2) !important;
}
.js-plotly-plot .plotly .gtitle{
  fill:var(--ink-0) !important;
  font-family:var(--font-display) !important;
}
/* Hover tooltips — keep their type in step with the rest of the chart */
.js-plotly-plot .hovertext text,
.js-plotly-plot .plotly .hovertext text{
  font-family:var(--font-body) !important;
}

/* Responsive ------------------------------------------------------------ */

@media (max-width:1280px){
  .panel{ grid-column:span 6; }
  .panel.panel-8,.panel.panel-12{ grid-column:span 12; }
}
@media (max-width:900px){
  .gr-section{ padding:44px 22px; }
  .analytics{ padding-top:32px; padding-bottom:36px; }
  .gr-hero-inner{ padding:18px 22px 24px; }
  .gr-hero{ min-height:clamp(520px, 78vh, 720px); }
  .gr-hero-body{ padding:40px 0 28px; }
  .gr-synopsis{ grid-template-columns:1fr; gap:28px; }
  .gr-synopsis aside{
    border-left:0; padding-left:0;
    border-top:1px solid var(--hair-0); padding-top:22px;
  }
  .kpi-deck{ grid-template-columns:repeat(2,1fr); }
  .kpi-deck .kpi-cell{ border-bottom:1px solid var(--hair-0); }
  .kpi-deck .kpi-cell:nth-child(2n){ border-right:0; }
  /* 2x2. Every row-start cell loses its left padding so both rows align to
     the same left edge, not just the first child. */
  .gr-hero-kpis{ grid-template-columns:repeat(2,1fr); row-gap:14px; }
  .gr-hero-kpis .kpi:nth-child(2n){ border-right:0; padding-right:0; }
  .gr-hero-kpis .kpi:nth-child(2n+1){ padding-left:0; }
  /* Every panel goes full width, including the ones with explicit span
     classes — .panel.panel-6 outweighs a bare .panel on specificity, which
     left half-width panels (and sliver-width charts) on phones. */
  .panel,
  .panel[class*="panel-"],
  .analytics-grid .panel,
  .analytics-grid .panel[class*="panel-"]{ grid-column:span 12 !important; }
  /* Drawer width adapts on narrow viewports — filter-rail rules now defined globally */
  .brand-tagline{ display:none; }
  .brand-accent{ font-size:16px; }
  .analytics-head .title{ font-size:24px; }
  .map-banner .b-title{ font-size:24px; }
}
/* .gr-section drops to 22px of padding at this width; the footer follows it. */
@media (max-width:900px) and (min-width:641px){
  :root{ --ei-footer-min-gutter:22px; }
}
@media (max-width:640px){
  .gr-hero{ min-height:auto; }
  .gr-hero-inner{ padding:16px 18px 22px; }
  .gr-hero-body{ padding:32px 0 24px; }
  .gr-hero-number{ font-size:clamp(72px, 22vw, 120px); letter-spacing:-.03em; }
  .gr-hero-number-caption{ font-size:18px; }
  .gr-hero-lede{ font-size:14.5px; }
  .gr-hero-kpis{ grid-template-columns:1fr 1fr; padding-top:14px; }
  .gr-hero-kpis .kpi{ padding:2px 16px 2px 0; }
  .gr-section{ padding:32px 18px; }
  .gr-section-title{ font-size:28px; }
  .gr-cards-grid{ grid-template-columns:1fr; }
  .map-banner{ flex-direction:column; align-items:flex-start; padding:20px 18px 14px; }
  .map-banner .banner-right{ width:100%; }
  .map-banner .b-title{ font-size:22px; }
  .map-viewport{ height:55vh; min-height:360px; }
  .analytics{ padding:28px 18px 32px; }
  .analytics-head{ flex-direction:column; align-items:flex-start; gap:8px; }
  .analytics-head .title{ font-size:22px; }
  .panel{ padding:16px 16px 14px; min-height:200px; }
  .panel-head{ flex-direction:column; align-items:flex-start; gap:8px; }
  .panel-tools{ width:100%; }

  /* Wide tables scroll sideways instead of breaking the layout */
  .panel-scroll{ overflow-x:auto; }
  .data-frame{ overflow-x:auto; }

  /* Outlook / abatement strip stacks its label above the note */
  .kpi-strip-eyebrow{
    flex-direction:column; align-items:flex-start; gap:4px;
    padding-left:18px; padding-right:18px;
  }

  /* Page-level padding to match the narrow gutters used elsewhere */
  .data-main{ padding:20px 16px 36px; }
  .about-page{ padding:32px 18px 48px; }
  .about-container h1{ font-size:32px; }
  .about-container h2{ font-size:24px; }

  /* Plugging sub-tabs: let the row scroll rather than wrap awkwardly */
  .gr-subtabs .nav.nav-tabs{ padding-left:16px; padding-right:16px; }
}

/* Very small phones — keep the brand on one line */
@media (max-width:420px){
  .brand-accent{ font-size:14px; }
}

/* §6: no modebar — belt over the head script for any chart that skips its own
   config() call. Export belongs on explicit download controls. */
.js-plotly-plot .modebar{ display:none !important; }

/* §5 empty state: a dashed panel on paper, the reason in this tab's own terms,
   and the control that undoes it. A chart with every row filtered out draws
   this instead of blank axes, which say nothing about why they are blank. */
.gr-empty{
  display:flex;
  flex-direction:column;
  align-items:center;
  justify-content:center;
  gap:14px;
  padding:24px;
  border:1px dashed var(--hair-1);
  border-radius:var(--radius);
  background:var(--paper-0);
  text-align:center;
}
.gr-empty__msg{
  margin:0;
  max-width:46ch;
  color:var(--ink-2);
  font-size:.95rem;
  line-height:1.55;
}
