/* Public tracker page ("/") and /Error. Brownstein brand (see the brownstein-brand skill).
   Self-contained: no MudBlazor, no Google Fonts, no CDN. Fonts are self-hosted in wwwroot/fonts.
   Type is Deep Blue or white only; links are underlined. */

/* ---------- Brand fonts (Level 01 = Messina Serif Book Italic, Level 02/03 = Azo Sans) ---------- */
@font-face {
    font-family: 'Azo Sans';
    src: url('/fonts/AzoSans-Light.woff2') format('woff2'), url('/fonts/AzoSans-Light.woff') format('woff');
    font-weight: 300;
    font-style: normal;
    font-display: swap;
}

@font-face {
    font-family: 'Azo Sans';
    src: url('/fonts/AzoSans-Medium.woff2') format('woff2'), url('/fonts/AzoSans-Medium.woff') format('woff');
    font-weight: 500;
    font-style: normal;
    font-display: swap;
}

@font-face {
    font-family: 'Messina Serif';
    src: url('/fonts/MessinaSerifWeb-BookItalic.woff2') format('woff2'), url('/fonts/MessinaSerifWeb-BookItalic.woff') format('woff');
    font-weight: 400;
    font-style: italic;
    font-display: swap;
}

:root {
    /* Brand primaries */
    --deep-blue: #051c2c;
    --electric-blue: #007aff;
    --white: #ffffff;
    /* Brand secondaries: graphics, rules and table striping only (never large backgrounds) */
    --light-gray: #ececec;
    --deep-gray: #d2d5d8;
    --light-gold: #f3c400;

    /* Fallbacks per brand guide: Georgia italic for Messina, Verdana for Azo */
    --font-display: 'Messina Serif', Georgia, serif;
    --font-sans: 'Azo Sans', Verdana, sans-serif;

    /* Contrast (WCAG): Deep Blue on white 17.4:1; white on Deep Blue 17.4:1; Electric Blue vs white 4.0:1 and
       vs Deep Blue 4.3:1 (both >= 3:1, enough for focus rings and large text, not for small body text). */

    /* EXCEPTION to the brand palette: party colors are semantic DATA colors that match the State Government
       team's reference map ("New Governors 2026 Map.jpg", repo root), not brand UI colors. Keep them.
       White bold labels pass WCAG AA: white on D 6.0:1, on R 5.4:1, on I 6.0:1; the same colors as text on
       white (callouts) pass too. */
    --party-r: #C8302C;
    --party-d: #2060C0;
    --party-i: #7B4FA0;
    --party-none: #DDDDDD;
    /* Not yet called: red/blue diagonal stripes (SVG pattern #stripe-pending on the map, CSS gradient on swatches). */
    --stripes-pending: repeating-linear-gradient(45deg, var(--party-r) 0 4px, var(--party-d) 4px 8px);

    /* Logo: 28px tall (189px wide, min 80px); clearspace = 1.5x height on all sides */
    --logo-h: 28px;
    --logo-clear: calc(var(--logo-h) * 1.5);
}

*, *::before, *::after { box-sizing: border-box; }

html { -webkit-text-size-adjust: 100%; }

body.public {
    margin: 0;
    background: var(--white);
    color: var(--deep-blue);
    font-family: var(--font-sans);
    font-weight: 300;
    font-size: 1rem;
    line-height: 1.6;
}

b, strong { font-weight: 500; }

/* Level 01: headlines (always italic). Level 02: labels/eyebrows (always caps). */
h1, h2 { font-family: var(--font-display); font-style: italic; font-weight: 400; line-height: 1.15; color: var(--deep-blue); }
h3 { font-family: var(--font-sans); font-weight: 500; line-height: 1.3; }
.level-02 {
    font-family: var(--font-sans); font-weight: 500; text-transform: uppercase; letter-spacing: 0.1em;
}

/* Links: Deep Blue text, underlined in Electric Blue. Body links are 16px regular, where Electric Blue text
   would fail AA (4.0:1 on white), so the text stays Deep Blue and the brand blue carries the underline. */
a {
    color: var(--deep-blue);
    text-decoration: underline;
    text-decoration-color: var(--electric-blue);
    text-decoration-thickness: 2px;
    text-underline-offset: 3px;
}
a:hover { text-decoration-thickness: 3px; }

/* Focus: Electric Blue ring (>= 3:1 on white and on Deep Blue). Map states keep Light Gold (see Map). */
a:focus-visible, button:focus-visible, select:focus-visible, input:focus-visible {
    outline: 3px solid var(--electric-blue); outline-offset: 2px;
}

.visually-hidden {
    position: absolute !important; width: 1px; height: 1px; padding: 0; margin: -1px;
    overflow: hidden; clip: rect(0, 0, 0, 0); white-space: nowrap; border: 0;
}

.skip-link {
    position: absolute; left: -999px; top: 0; z-index: 10; padding: 8px 12px;
    background: var(--white); color: var(--deep-blue); font-weight: 500;
}
.skip-link:focus { left: 8px; top: 8px; }

.pre { white-space: pre-line; }

/* One right edge for the page: .pub-wrap sets it, and body sections (intro, map, Status at a glance, State by state)
   fill it. Don't cap a section's own width (max-width in ch/px), or its right edge stops short of the map's. */
.pub-wrap { max-width: 1240px; margin: 0 auto; padding: 0 16px; }

/* ---------- Header (logo) + hero: one Deep Blue block ---------- */
.pub-header { background: var(--deep-blue); color: var(--white); }
.pub-header .pub-wrap { padding-top: var(--logo-clear); padding-bottom: var(--logo-clear); }
.pub-logo { display: block; height: var(--logo-h); width: auto; min-width: 80px; }

.pub-hero {
    position: relative; isolation: isolate;
    /* Clip the bands sideways only (no horizontal scroll), so they can run up through the header above.
       overflow: hidden is the fallback for browsers without overflow: clip (bands then stop at the hero top). */
    overflow: hidden; overflow-x: clip; overflow-y: visible;
    background: var(--deep-blue); color: var(--white);
    padding: 0 0 48px;
}
/* The logo stays above the bands where they pass through the header. */
.pub-header .pub-wrap { position: relative; z-index: 1; }
.pub-hero .pub-wrap { position: relative; z-index: 1; }
.pub-hero h1 {
    color: var(--white); font-size: clamp(2.1rem, 5.2vw, 3.5rem); margin: 0 0 14px; max-width: 18ch;
}
.pub-eyebrow {
    margin: 0 0 12px; color: var(--white);
    font-family: var(--font-sans); font-weight: 500; font-size: 0.85rem; text-transform: uppercase; letter-spacing: 0.14em;
}
.pub-updated { margin: 0; color: var(--white); font-weight: 300; font-size: 0.95rem; }

/* Graphic device: one solid Electric Blue band at 72 degrees (skewX(-18deg) => edges 72 degrees from horizontal at
   any height). Anchored at the bottom so the band leans forward and right, away from the text. Decorative only; no
   motion, so prefers-reduced-motion is unaffected. (The thin parallel line beside it was removed at the user's
   request: one stripe, not two.) It starts at the top of the page: top is pulled up by the header's height (logo +
   clearspace above and below), so it runs behind the header (same Deep Blue) as one straight 72-degree line. */
.pub-hero::after {
    content: ''; position: absolute; top: calc(-1 * (var(--logo-h) + 2 * var(--logo-clear))); bottom: 0; z-index: 0;
    background: var(--electric-blue);
    transform: skewX(-18deg); transform-origin: bottom left;
    pointer-events: none;
}
.pub-hero::after { right: 7%; width: clamp(28px, 5vw, 72px); }

@media (max-width: 900px) {
    /* Keep the band at the edge, clear of the headline and the stamp (white small text must not sit on Electric Blue). */
    .pub-hero::after { right: 8px; width: 26px; }
    .pub-hero .pub-wrap { padding-right: 64px; }
}

@media (max-width: 480px) {
    :root { --logo-h: 24px; }
    .pub-hero { padding-bottom: 36px; }
}

/* ---------- Footer: Deep Blue, white text (logo stays in the header only) ---------- */
.pub-footer { margin-top: 64px; background: var(--deep-blue); color: var(--white); font-size: 0.875rem; }
.pub-footer .pub-wrap { padding-top: 32px; padding-bottom: 36px; }
.pub-footer p { margin: 0 0 8px; max-width: 90ch; }
.pub-copyright { font-weight: 500; }
.pub-footer a { color: var(--white); }

/* ---------- Body sections ---------- */
.pub-memo { margin: 36px 0 8px; font-size: 1.1rem; }
.pub-memo p { margin: 0; }

.pub-empty { padding: 48px 0; text-align: center; }
.pub-empty h1, .pub-empty h2 { font-size: clamp(1.8rem, 4vw, 2.4rem); margin: 0 0 12px; }

.pub-hint { font-size: 0.95rem; margin: 10px 0; }

/* Map heading (Level 01, Deep Blue) + subtitle */
.map-title { font-size: clamp(1.7rem, 3.6vw, 2.4rem); margin: 40px 0 8px; }
.map-subtitle { margin: 0 0 20px; font-size: 1rem; }
/* "States are clickable" hint above the map: Deep Blue Azo Medium text, Electric Blue rule as a graphic accent only.
   Wide text on desktop/tablet, short text on phones (< 700px, no map, picker instead). */
.map-hint { margin: 0 0 16px; padding-left: 12px; border-left: 4px solid var(--electric-blue); color: var(--deep-blue); font-weight: 500; font-size: 1rem; }
.map-hint-narrow { display: none; } /* phone swap is in the headshot phone block below */

/* Map left (~65%), side list right with a thin divider; stacks under 900px */
/* Side list is never taller than the map column: contain: size stops it from adding to the grid row's height,
   so the row is as tall as .map-main (map + legend), align-self: stretch fills that row, and the list scrolls
   inside. padding-right leaves room for the rows' -8px bleed and their focus ring (no sideways scrollbar). */
.map-layout { display: grid; grid-template-columns: minmax(0, 65fr) minmax(0, 35fr); gap: 0 32px; align-items: start; }
.map-main { min-width: 0; }
.map-side {
    border-left: 1px solid var(--deep-gray); padding: 0 14px 0 28px; font-size: 0.95rem;
    contain: size; align-self: stretch; overflow-y: auto; overscroll-behavior: contain;
}
@media (max-width: 900px) {
    /* Stacked: the list takes its natural height again (no inner scroll). */
    .map-layout { grid-template-columns: minmax(0, 1fr); }
    .map-side {
        border-left: 0; border-top: 1px solid var(--deep-gray); padding: 20px 0 0; margin-top: 16px;
        contain: none; overflow: visible;
    }
}

/* Legend (under the map) */
.legend { list-style: none; display: flex; flex-wrap: wrap; gap: 8px 24px; padding: 0; margin: 14px 0 8px; font-size: 0.95rem; }
.legend li { display: flex; align-items: center; gap: 8px; }

.swatch { display: inline-block; width: 16px; height: 16px; border-radius: 2px; flex: 0 0 auto; border: 1px solid rgba(5, 28, 44, 0.15); }
.swatch.p-r { background: var(--party-r); }
.swatch.p-d { background: var(--party-d); }
.swatch.p-i { background: var(--party-i); }
.swatch.p-pending { background: var(--stripes-pending); }
.swatch.p-none { background: var(--party-none); }

/* Side list: groups by party (Level 02 heads); rows are buttons (state Light | governor-elect Medium) */
.side-group { margin: 0 0 24px; }
.side-head {
    display: flex; align-items: center; gap: 10px; margin: 0 0 10px; color: var(--deep-blue);
    font-size: 0.8rem; text-transform: uppercase; letter-spacing: 0.12em;
}
.side-rows { list-style: none; margin: 0; padding: 0; }
.side-row {
    display: grid; grid-template-columns: minmax(7.5em, 40%) minmax(0, 1fr); gap: 0 12px; align-items: baseline;
    width: calc(100% + 16px); padding: 6px 8px; margin: 0 -8px; border: 0; border-radius: 2px; background: transparent;
    color: var(--deep-blue); font: inherit; text-align: left; cursor: pointer; min-height: 36px;
}
.side-row:hover { background: var(--light-gray); }
.side-row.is-selected { background: var(--light-gray); box-shadow: inset 4px 0 0 var(--electric-blue); }
.side-state { font-weight: 300; }
.side-name { font-weight: 500; }
.side-note { font-weight: 300; }
.side-flip { margin-left: 6px; font-weight: 300; font-size: 0.8rem; white-space: nowrap; }
.side-foot { margin: 4px 0 0; font-size: 0.85rem; }

/* ---------- Map ---------- */
.us-map { display: block; width: 100%; height: auto; max-width: 960px; margin: 0 auto; }
.us-map .st { fill: var(--party-none); stroke: var(--white); stroke-width: 1.5; stroke-linejoin: round; }
.us-map .st-on { cursor: pointer; transition: opacity 0.15s; }
.us-map .st-on.p-r { fill: var(--party-r); }
.us-map .st-on.p-d { fill: var(--party-d); }
.us-map .st-on.p-i { fill: var(--party-i); }
.us-map .st-on.p-pending { fill: url(#stripe-pending); }
.us-map .st-on:hover { opacity: 0.85; }
.us-map .st-on:focus { outline: none; }
/* Map state focus/selection keeps Light Gold (an allowed secondary graphics color): it is the one palette color
   that stands out against BOTH party fills. An Electric Blue stroke would disappear on the Democrat blue. */
.us-map .st-on:focus-visible, .us-map .st-on.is-selected { stroke: var(--light-gold); stroke-width: 3; }
.us-map .map-sep { stroke: #b0b0b0; stroke-width: 2; }

/* State labels: decorative, never intercept clicks (the state path underneath gets them) */
.us-map .map-labels { pointer-events: none; }
.us-map .map-lbl-in { transform-origin: 0 0; }
.us-map .map-lbl text { fill: var(--white); font-family: var(--font-sans); font-weight: 500; font-size: 14px; }
.us-map .map-lbl.is-boxed rect { fill: var(--white); stroke: rgba(5, 28, 44, 0.25); stroke-width: 0.75; }
.us-map .map-lbl.is-boxed text { fill: var(--deep-blue); font-size: 13px; }
.us-map .map-lbl.is-boxed.p-d text { fill: var(--party-d); }
.us-map .map-lbl.is-boxed.p-r text { fill: var(--party-r); }
.us-map .map-lbl.is-boxed.p-i text { fill: var(--party-i); }
.us-map .map-lbl.is-boxed.p-pending text { fill: var(--deep-blue); }

/* Small Northeast states: outside callout + leader line; the callout is a button for the same state.
   Callouts sit on white, so their focus/selection uses the Electric Blue ring like the rest of the page. */
.us-map .map-leader { stroke: var(--deep-blue); stroke-width: 0.8; pointer-events: none; }
.us-map .map-callout { cursor: pointer; }
.us-map .map-callout text { font-family: var(--font-sans); font-weight: 500; font-size: 13px; pointer-events: none; }
.us-map .map-callout.p-d text { fill: var(--party-d); }
.us-map .map-callout.p-r text { fill: var(--party-r); }
.us-map .map-callout.p-i text { fill: var(--party-i); }
.us-map .map-callout.p-pending text { fill: var(--deep-blue); }
.us-map .map-callout-hit { fill: transparent; stroke: none; pointer-events: all; }
.us-map .map-callout:focus { outline: none; }
.us-map .map-callout:focus-visible .map-callout-hit,
.us-map .map-callout.is-selected .map-callout-hit { stroke: var(--electric-blue); stroke-width: 2; }
.us-map .map-callout.p-pending .map-callout-hit { fill: var(--white); }

/* Small tablets: the SVG scales down, so scale labels up (around each label's own origin) to stay legible.
   Below 700px the map is hidden (state picker instead), so the old 480px/1.7x step is gone. */
@media (max-width: 700px) {
    .us-map .map-lbl-in { transform: scale(1.35); }
}

/* ---------- Phones (< 700px): no map; summary line + native state picker ---------- */
.map-summary, .map-picker { display: none; }
.map-summary { margin: 0 0 16px; font-weight: 500; }
.map-picker-label {
    display: block; margin: 0 0 8px; color: var(--deep-blue);
    font-weight: 500; font-size: 0.8rem; text-transform: uppercase; letter-spacing: 0.12em;
}
.map-picker-field { position: relative; }
.map-picker-field::after {
    /* Chevron (decorative): a rotated Deep Blue corner, so no image or icon font is needed. */
    content: ''; position: absolute; right: 18px; top: 50%; width: 10px; height: 10px; margin-top: -7px;
    border-right: 2px solid var(--deep-blue); border-bottom: 2px solid var(--deep-blue); transform: rotate(45deg);
    pointer-events: none;
}
.map-picker select {
    display: block; width: 100%; min-height: 52px; padding: 12px 48px 12px 14px;
    -webkit-appearance: none; appearance: none;
    background: var(--white); color: var(--deep-blue);
    border: 2px solid var(--deep-blue); border-left: 6px solid var(--electric-blue); border-radius: 2px;
    font-family: var(--font-sans); font-weight: 500; font-size: 1rem; /* 16px: no iOS zoom on focus */
}

@media (max-width: 699.98px) {
    .pub-map-empty { display: none; }
    .map-summary { display: block; }
    /* Visual order on phones: picker, panel, side list. DOM order stays desktop-first (panel after the layout). */
    .map-stage { display: flex; flex-direction: column; }
    .map-picker { display: block; order: 1; }
    .map-layout { display: contents; }
    .map-main { display: none; } /* map, legend and callouts: removed from the accessibility tree too */
    .state-panel { order: 2; width: 100%; margin: 16px 0 0; }
    .map-side { order: 3; margin-top: 28px; }
}

/* ---------- Status at a glance (memo summary table) ----------
   Mobile choice: the table keeps its columns and scrolls horizontally inside .glance-wrap, with the State column
   sticky on the left (cells carry their own opaque background so scrolled text never shows through). */
.pub-glance, .pub-states { margin-top: 48px; }
.pub-glance h2, .pub-states > h2 { font-size: clamp(1.6rem, 3.2vw, 2.1rem); margin: 0 0 16px; }
.glance-wrap { overflow-x: auto; -webkit-overflow-scrolling: touch; border: 1px solid var(--deep-gray); }
.glance-wrap:focus-visible { outline: 3px solid var(--electric-blue); outline-offset: 2px; }
.glance { width: 100%; min-width: 960px; border-collapse: collapse; font-size: 0.9rem; color: var(--deep-blue); }
.glance th, .glance td {
    text-align: left; vertical-align: top; padding: 8px 10px; border: 1px solid var(--deep-gray); overflow-wrap: anywhere;
    background: var(--white);
}
.glance thead th { background: var(--deep-blue); color: var(--white); font-weight: 500; border-color: var(--deep-blue); }
.glance tbody tr:nth-child(even) > * { background: var(--light-gray); }
.glance tbody th { font-weight: 500; white-space: nowrap; }
.glance th:first-child, .glance td:first-child { position: sticky; left: 0; z-index: 1; box-shadow: 1px 0 0 var(--deep-gray); }
.glance thead th:first-child { z-index: 2; }
.glance td:nth-child(2) { min-width: 9em; }
.glance td:nth-child(5), .glance td:nth-child(7) { min-width: 14em; }

/* ---------- State by state: one always-visible section per state (Components/Public/StateSection.razor) ---------- */
.state-section { padding: 24px 0 8px; border-top: 1px solid var(--deep-gray); scroll-margin-top: 16px; }
.state-section-title { margin: 0 0 4px; font-size: 1.3rem; font-weight: 500; color: var(--deep-blue); }
.state-section:target .state-section-title { box-shadow: inset 4px 0 0 var(--electric-blue); padding-left: 10px; }
/* Governor-elect headshot (only when a file exists in images/governors), first thing inside #detail-XX's .state-intro.
   Width/height attributes are 400x500, so aspect-ratio reserves the space before it loads.
   Section: .state-intro-text (Background, meta, facts) is panel-only, so the photo sits directly under the H3.
   Panel under the map: photo left, text right; stacked under 700px (same breakpoint as the phone picker). */
.state-photo { display: block; width: 160px; max-width: 40vw; height: auto; aspect-ratio: 4 / 5; object-fit: cover; object-position: center top; margin: 10px 0 4px; border-radius: 4px; background: var(--light-gray); }
@media (max-width: 480px) { .state-photo { width: 120px; } }
.state-section .state-intro-text { display: none; }
.state-panel .state-intro { display: flex; align-items: flex-start; gap: 24px; }
.state-panel .state-photo { flex: 0 0 auto; width: 140px; margin: 18px 0 0; }
.state-panel .state-intro-text { flex: 1 1 auto; min-width: 0; }
/* Phone rules added with the headshots and the map hint (kept after their base rules so they win the cascade;
   the older phone block above precedes .state-panel's base rule, so these can't move into it). */
@media (max-width: 699.98px) {
    .map-hint-wide { display: none; }
    .map-hint-narrow { display: inline; }
    .state-panel .state-intro { display: block; }
    .state-panel .state-photo { width: 120px; margin: 16px 0 0; }
}

/* Sections show the memo fields in the glance table instead; the panel under the map shows them inline. */
.state-section .state-facts, .state-section .state-jump { display: none; }
/* State by state shows only its own paste (heading, Transition Structure, Other Signals); Background and the
   party/flip line come from the map tab and show only in the panel under the map. */
.state-section .state-background, .state-section .state-meta { display: none; }
.state-section[hidden] { display: none; }

/* Detail block (section and panel) */
.state-detail .state-background { margin: 14px 0 0; }
.state-detail .state-meta { margin: 8px 0 0; font-size: 0.95rem; font-weight: 300; }
.state-detail dl { margin: 0; }
.state-detail dt {
    margin-top: 16px; color: var(--deep-blue);
    font-weight: 500; font-size: 0.78rem; text-transform: uppercase; letter-spacing: 0.1em;
}
.state-detail dd { margin: 4px 0 0; overflow-wrap: anywhere; }
/* "Transition Structure" / "Other Signals": Electric Blue on white is ~4.0:1, so it only passes WCAG AA as
   LARGE text: 24px+ regular/medium (Azo 500 is not "bold", so the 18.66px-bold threshold doesn't apply). */
.state-detail .state-sub { margin: 22px 0 8px; font-family: var(--font-sans); font-weight: 500; font-size: 1.5rem; color: var(--electric-blue); }
.state-detail .state-none { margin: 0; font-weight: 300; font-style: italic; color: var(--deep-blue); }
.state-detail .signals { margin: 0; padding-left: 1.3em; }
.state-detail .signals li { margin: 0 0 6px; }
.state-detail .state-notes { margin: 16px 0 0; }
.state-detail .state-small { margin-top: 16px; font-size: 0.85rem; }
.state-detail .state-small p { margin: 0 0 4px; overflow-wrap: anywhere; }
.state-detail .state-jump { margin: 18px 0 0; font-weight: 500; }

/* Transition Structure: brand table (Deep Blue header, white/Light Gray rows, compact); stacked cards under 600px */
/* Fixed column widths, so one very long cell (Georgia's 16 honorary co-chairs in one Name cell) wraps inside its
   column instead of stretching it and squeezing the others to one letter per line. */
.appointees table { width: 100%; border-collapse: collapse; font-size: 0.9rem; color: var(--deep-blue); table-layout: fixed; }
.appointees thead th:nth-child(1) { width: 22%; }
.appointees thead th:nth-child(2) { width: 26%; }
.appointees thead th:nth-child(4) { width: 9.5em; }
.appointees th, .appointees td { text-align: left; vertical-align: top; padding: 6px 10px; overflow-wrap: anywhere; }
.appointees thead th { background: var(--deep-blue); color: var(--white); font-weight: 500; }
.appointees tbody tr { background: var(--white); }
.appointees tbody tr:nth-child(even) { background: var(--light-gray); }
.appointees tbody th { font-weight: 500; }
.appointees td[data-label="Announced"] { white-space: nowrap; }

@media (max-width: 600px) {
    .appointees thead { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0, 0, 0, 0); }
    .appointees table, .appointees tbody, .appointees tr, .appointees th, .appointees td { display: block; width: 100%; }
    .appointees tr { border: 1px solid var(--deep-gray); border-radius: 2px; padding: 10px 12px; margin-bottom: 8px; }
    .appointees th, .appointees td { padding: 2px 0; white-space: normal; }
    .appointees tbody th { font-size: 1rem; }
    .appointees td[data-label]::before {
        content: attr(data-label) ": "; font-weight: 500; font-size: 0.78rem; text-transform: uppercase; letter-spacing: 0.08em;
    }
    .appointees td[data-label="Background"]::before { content: none; }
    .appointees td[data-label="Announced"] { white-space: normal; }
    .appointees td.pre { white-space: pre-line; }
    .appointees td.ap-empty { display: none; }
}

/* ---------- Selected-state panel: white card, Electric Blue top accent, Deep Blue header bar ---------- */
.state-panel {
    margin: 20px 0 0; border: 1px solid var(--deep-gray); /* full .pub-wrap width: same edges as the map */ border-top: 4px solid var(--electric-blue);
    border-radius: 2px; background: var(--white); color: var(--deep-blue); overflow: hidden; scroll-margin-top: 16px;
    box-shadow: 0 4px 16px rgba(5, 28, 44, 0.12);
}
.state-panel[hidden] { display: none; }
.state-panel-head {
    display: flex; align-items: center; justify-content: space-between; gap: 12px;
    background: var(--deep-blue); color: var(--white); padding: 12px 12px 12px 20px;
}
.state-panel-head h2 { margin: 0; min-width: 0; overflow-wrap: anywhere; font-size: 1.6rem; color: var(--white); }
.state-panel-actions { display: flex; align-items: center; gap: 8px; flex: 0 0 auto; }
/* Copy link: secondary button on the Deep Blue bar (white outline, Level 02 caps), 44px tap target. */
.state-panel-copy {
    min-width: 44px; height: 44px; padding: 0 14px; cursor: pointer;
    background: transparent; color: var(--white); border: 1px solid var(--white); border-radius: 2px;
    font-family: var(--font-sans); font-weight: 500; font-size: 0.75rem; text-transform: uppercase; letter-spacing: 0.1em;
}
.state-panel-copy:hover { background: var(--white); color: var(--deep-blue); }
.state-panel-copy:focus-visible { outline: 3px solid var(--white); outline-offset: 2px; }
.state-panel-status { margin: 0; padding: 10px 20px 0; font-weight: 500; font-size: 0.9rem; }
.state-panel-status:empty { padding: 0; }
.state-panel-link {
    display: block; width: calc(100% - 40px); margin: 8px 20px 0; padding: 10px 12px;
    border: 1px solid var(--deep-blue); border-radius: 2px; color: var(--deep-blue); background: var(--white);
    font-family: var(--font-sans); font-weight: 300; font-size: 1rem;
}
.state-panel-link[hidden] { display: none; }
.state-panel-head h2:focus { outline: none; }
/* Close: Electric Blue button (white x is 24px = large text, 4.0:1 passes). White ring on the Deep Blue bar. */
.state-panel-close {
    background: var(--electric-blue); border: 0; color: var(--white); border-radius: 2px;
    font-family: var(--font-sans); font-size: 1.5rem; line-height: 1; width: 44px; height: 44px; cursor: pointer; flex: 0 0 auto;
}
.state-panel-close:hover { background: var(--white); color: var(--deep-blue); }
.state-panel-close:focus-visible { outline: 3px solid var(--white); outline-offset: 2px; }
#state-panel-body { padding: 4px 20px 24px; }

@media (prefers-reduced-motion: reduce) {
    .us-map .st-on, .us-map .map-lbl-in { transition: none; }
}
