/* ---------------------------------------------------------------------------
 * Design tokens
 *
 * Three tiers, and feature CSS should only ever reach for the third:
 *
 *   Tier 0  channel tokens   raw R G B triples, so a colour can be reused at an
 *                            arbitrary alpha without hardcoding the channels at
 *                            the call site: rgb(var(--primary-rgb) / 0.15)
 *   Tier 1  primitives       the palette itself, named by hue + weight. These are
 *                            the values a theme swaps.
 *   Tier 2  semantics        what a colour *means* (danger, surface, overlay).
 *                            Feature CSS uses these so a palette change is a
 *                            one-line edit here rather than a sitewide sweep.
 *
 * Weights follow the Tailwind 50-900 scale. Intermediate steps (150, 610, 850…)
 * are strays inherited from other palettes — Material, iOS, Chakra, Bootstrap —
 * that arrived by copy-paste and sit a hair off the ramp. They are kept at their
 * exact original values so tokenizing changed nothing on screen; collapsing them
 * onto the nearest 100-step is a deliberate, visible follow-up, not this ticket.
 * --------------------------------------------------------------------------- */
:root {
    /* -- Tier 0: channel tokens ------------------------------------------- */
    /* Composed at the call site as rgb( <channels> / <alpha> ), e.g.
       rgb(var(--primary-rgb) / 0.15). Space-separated on purpose — that is
       the only form the slash-alpha syntax accepts. */
    --primary-rgb: 8 145 178;      /* brand cyan, #0891b2 */
    --navy-rgb: 15 23 42;          /* deep navy, #0f172a — text and scrims */
    --ink-rgb: 28 25 23;           /* warm near-black, #1c1917 — shadow tint */
    --cream-rgb: 255 251 245;      /* page background, #fffbf5 — frosted header */
    --black-rgb: 0 0 0;
    --white-rgb: 255 255 255;

    /* Sticky header height. Anything that offsets against the pinned header
       (e.g. an anchor target's scroll margin) derives from this token so the
       two can't drift. */
    --header-height: 52px;

    /* -- Tier 1: primitives ------------------------------------------------ */

    /* Warm grays (stone). The site's default neutral ramp. */
    --white: #ffffff;
    --gray-50: #fafaf9;
    --gray-100: #f5f5f4;
    --gray-200: #e7e5e4;
    --gray-300: #d6d3d1;
    --gray-350: #a8a29e;
    --gray-400: #78716c;
    /* --gray-400 sits at a 500-weight lightness; both names are in use across the
       tree and resolve to the same value rather than churn every call site. */
    --gray-500: var(--gray-400);
    --gray-550: #888888;
    --gray-600: #57534e;
    --gray-700: #44403c;
    --gray-800: #292524;
    --gray-900: #0f172a;
    --gray-950: #1c1917;

    /* Cool grays (slate). Strays from Tailwind's cool ramp and from iOS. Kept
       distinct from the warm ramp because the hue shift is visible side by side. */
    --slate-100: #f3f4f6;
    --slate-150: #e5e5ea;
    --slate-200: #e5e7eb;
    --slate-210: #e2e8f0;
    --slate-250: #d1d5db;
    --slate-300: #cbd5e1;
    --slate-400: #94a3b8;
    --slate-450: #6b7280;
    --slate-500: #64748b;
    --slate-700: #374151;
    --slate-710: #334155;
    --slate-720: #424245;
    --slate-800: #1e293b;

    /* Reds */
    --red-25: #fff5f5;
    --red-50: #fef2f2;
    --red-55: #ffebee;
    --red-60: #fbe9e7;
    --red-100: #fee2e2;
    --red-110: #fed7d7;
    --red-120: #f8d7da;
    --red-200: #fecaca;
    --red-500: #ff3b30;
    --red-520: #e53e3e;
    --red-600: #dc2626;
    --red-610: #d32f2f;
    --red-620: #d63028;
    --red-650: #c53030;
    --red-660: #c62828;
    --red-700: #b91c1c;
    --red-800: #991b1b;
    --red-900: #7f1d1d;
    --red-910: #721c24;

    /* Oranges */
    --orange-50: #fff7ed;
    --orange-100: #ffe0b2;
    --orange-200: #fed7aa;
    --orange-400: #fb923c;
    --orange-600: #f57f17;
    --orange-620: #d97706;
    --orange-700: #e65100;
    --orange-680: #b45309;
    --orange-750: #b35400;
    --orange-800: #92400e;
    --orange-820: #854d0e;
    --orange-850: #856404;
    --orange-880: #7a4f01;
    --orange-900: #7c2d12;

    /* Ambers */
    --amber-50: #fffbeb;
    --amber-60: #fff8e1;
    --amber-100: #fff3cd;
    --amber-110: #fef3c7;
    --amber-120: #fef9c3;
    --amber-300: #ffe082;
    --amber-320: #fcd34d;

    /* Greens */
    --green-50: #f0fdf4;
    --green-55: #ecfdf5;
    --green-60: #e8f5e9;
    --green-100: #dcfce7;
    --green-110: #d4edda;
    --green-150: #c6f6d5;
    --green-180: #a7f3d0;
    --green-200: #bbf7d0;
    --green-500: #34c759;
    --green-520: #22c55e;
    --green-600: #16a34a;
    --green-650: #2e7d32;
    --green-680: #059669;
    --green-800: #166534;
    --green-820: #065f46;
    --green-850: #22543d;
    --green-900: #155724;

    /* Cyans — the brand hue */
    --cyan-100: #e0f7fa;
    --cyan-200: #b2ebf2;
    --cyan-300: #7dd3fc;
    --cyan-600: #0891b2;
    --cyan-700: #0e7490;
    --cyan-800: #0c5e72;

    /* Blues — links, info states */
    --blue-50: #eff6ff;
    --blue-100: #e0f2fe;
    --blue-150: #bfdbfe;
    --blue-200: #bae6fd;
    --blue-210: #b3d4fc;
    --blue-600: #2563eb;
    --blue-800: #075985;
    --blue-850: #1e3a5f;

    /* -- Tier 2: semantics ------------------------------------------------- */

    /* Brand */
    --primary-color: var(--cyan-600);
    --primary-hover: var(--cyan-700);
    --primary-active: var(--cyan-800);
    --accent-color: var(--orange-400);

    /* Ocean tones — brand-tinted washes */
    --ocean-light: var(--cyan-100);
    --ocean-subtle: rgb(var(--primary-rgb) / 0.08);
    --ocean-wash: rgb(var(--primary-rgb) / 0.05);
    --ocean-tint: rgb(var(--primary-rgb) / 0.1);
    --ocean-tint-strong: rgb(var(--primary-rgb) / 0.15);
    --navy: var(--gray-900);

    /* Surfaces */
    --background: #fffbf5;
    --surface: var(--white);
    --surface-raised: var(--white);   /* cards and popovers above --background */
    --surface-sunken: var(--gray-100); /* wells, inset rows, code blocks */
    --overlay: rgb(var(--black-rgb) / 0.5); /* modal scrim */

    /* Text */
    --text-primary: var(--gray-900);
    --text-secondary: var(--gray-400);
    --text-on-accent: var(--white); /* text sitting on a saturated fill */

    /* Borders */
    --border-color: var(--gray-200);
    --border-strong: var(--gray-300);

    /* Status. Each role carries fg / bg / border so the pill patterns already in
       use across the tree have a token for every part. */
    --danger: var(--red-600);
    --danger-strong: var(--red-700);
    --danger-bg: var(--red-50);
    --danger-border: var(--red-200);

    --success: var(--green-800);
    --success-bg: var(--green-100);
    --success-border: var(--green-200);

    --warning: var(--orange-900);
    --warning-bg: var(--amber-100);
    --warning-border: var(--amber-300);

    --info: var(--blue-600);
    --info-bg: var(--blue-50);
    --info-border: var(--blue-210);

    /* Chrome */
    --header-bg: rgb(var(--cream-rgb) / 0.72); /* frosted sticky header */
    --focus-ring: rgb(var(--primary-rgb) / 0.38);

    /* Warm-tinted shadows */
    --shadow-sm: 0 1px 3px rgb(var(--ink-rgb) / 0.06), 0 1px 2px rgb(var(--ink-rgb) / 0.04);
    --shadow-md: 0 4px 16px rgb(var(--ink-rgb) / 0.08), 0 2px 4px rgb(var(--ink-rgb) / 0.04);
    --shadow-lg: 0 12px 40px rgb(var(--ink-rgb) / 0.12);
    --shadow-ocean: 0 4px 16px rgb(var(--primary-rgb) / 0.2);

    /* -- Legacy aliases ---------------------------------------------------- */
    /* Names that feature CSS already referenced before they existed anywhere.
       Until this block they resolved to their inline fallback, or — where no
       fallback was given — to nothing at all, silently dropping the declaration.
       Defined here so no var() in the tree is undefined. */
    /* --primary has no callers left: the two that existed wanted the link blue,
       not the brand cyan, and now say --color-link. Kept defined because the
       name is an obvious thing to reach for, and undefined is the failure mode
       that hides. */
    --primary: var(--primary-color);
    --danger-color: var(--danger);
    --bg-secondary: var(--gray-100);
    --color-link: var(--blue-600);
    --color-info-bg: var(--info-bg);
    --color-info-border: var(--info-border);
    --font-mono: monospace;

    /* Transitions */
    --transition-fast: 200ms ease-out;
    --transition-medium: 300ms ease-out;
}

* {
    margin: 0;
    padding: 0;
    box-sizing: border-box;
}

/* Hide Alpine x-cloak elements before Alpine initializes */
[x-cloak] {
    display: none !important;
}

body {
    font-family: 'Plus Jakarta Sans', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
    font-size: 17px;
    line-height: 1.47;
    letter-spacing: -0.022em;
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
    background: var(--background);
    color: var(--text-primary);
    display: flex;
    flex-direction: column;
    min-height: 100vh;
    padding-bottom: 0;
}

/* Page shell (CCT-322) - the flex column holding every piece of chrome above
 * the footer: header, site banners, breadcrumbs, <main>, and the sticky
 * disclaimer. Pages whose body region must fill the leftover space claim it
 * with `flex: 1 1 auto; min-height: 0` (see .map-page-layout, .table-page)
 * instead of subtracting a hardcoded chrome sum from 100vh - a sum that was
 * always wrong while a banner was showing, and doubly wrong when banners
 * stacked or wrapped to two lines on mobile.
 *
 * Default: the shell grows to fill the body, so the footer sits on screen at
 * the bottom of short pages exactly as before. */
.page-shell {
    display: flex;
    flex-direction: column;
    flex: 1 1 auto;
    min-height: 0;
}

/* Pages that fill the viewport exactly (the map): the shell is pinned to the
 * viewport height and the footer - which lives outside the shell - falls just
 * below the fold, which is what the old `calc(100vh - 52px - 26px)` bought.
 * The header stays sticky within the shell, and because the shell's bottom
 * edge is only a footer's height above the document bottom, it never scrolls
 * far enough to unstick it. */
body.page-fills-viewport .page-shell {
    height: 100vh;
    flex: none;
}

/* Header - frosted glass effect */
.header {
    background: var(--header-bg);
    backdrop-filter: saturate(120%) blur(16px);
    -webkit-backdrop-filter: saturate(120%) blur(16px);
    border-bottom: none;
    padding: 0 22px;
    height: var(--header-height);
    position: sticky;
    top: 0;
    z-index: 1000;
}

.header-content {
    max-width: 1400px;
    margin: 0 auto;
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 1rem;
    height: 100%;
}

.logo {
    font-size: 21px;
    font-weight: 600;
    color: var(--text-primary);
    text-decoration: none;
    transition: opacity var(--transition-fast);
}

.logo:hover {
    opacity: 0.7;
}

.nav {
    display: flex;
    gap: 0.25rem;
}

.nav-link {
    padding: 6px 12px;
    color: var(--text-primary);
    text-decoration: none;
    border-radius: 980px;
    font-size: 14px;
    font-weight: 400;
    transition: all var(--transition-fast);
}

.nav-link:hover {
    background: var(--gray-100);
}

.nav-link.active {
    background: var(--gray-900);
    color: var(--text-on-accent);
}

/* Leads gets the Lead Mining color scheme (navy band + teal/amber) so it
   stands out from the plain nav links; active flips to the amber CTA look. */
.nav-link-leads {
    /* The banner CTA's amber, as a pill. Active inverts to the navy band. */
    background: var(--accent-color);
    color: var(--warning);
    font-weight: 600;
}

.nav-link-leads:hover {
    background: var(--accent-color);
    color: var(--warning);
    filter: brightness(1.07);
}

.nav-link-leads.active {
    background: linear-gradient(150deg, var(--navy) 0%, var(--slate-800) 100%);
    color: var(--cyan-300);
}

/* User menu */
.user-menu {
    position: relative;
}
.user-menu-btn {
    background: none;
    border: none;
    cursor: pointer;
    padding: 0;
}
.user-avatar {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 32px;
    height: 32px;
    border-radius: 50%;
    background: var(--primary-color);
    color: var(--text-on-accent);
    font-size: 14px;
    font-weight: 600;
}
.user-dropdown {
    position: absolute;
    top: calc(100% + 6px);
    right: 0;
    background: var(--surface-raised);
    border-radius: 12px;
    box-shadow: var(--shadow-lg);
    min-width: 200px;
    padding: 6px 0;
    z-index: 1001;
}
.user-dropdown-email {
    padding: 10px 16px 8px;
    font-size: 13px;
    color: var(--text-secondary);
    border-bottom: 1px solid var(--gray-100);
    margin-bottom: 4px;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
.user-dropdown-item {
    display: block;
    width: 100%;
    padding: 8px 16px;
    font-size: 14px;
    color: var(--text-primary);
    text-decoration: none;
    background: none;
    border: none;
    text-align: left;
    cursor: pointer;
    font-family: inherit;
    transition: background var(--transition-fast);
}
.user-dropdown-item:hover {
    background: var(--gray-100);
}
.user-dropdown-logout {
    color: var(--danger);
}
.user-dropdown-form {
    margin: 0;
}
.signin-btn {
    font-weight: 500;
    color: var(--primary-color) !important;
}

/* Hamburger menu button - hidden on desktop */
.mobile-menu-btn {
    display: none;
    flex-direction: column;
    justify-content: center;
    gap: 5px;
    background: none;
    border: none;
    cursor: pointer;
    padding: 6px;
    border-radius: 6px;
    transition: background var(--transition-fast);
}

.mobile-menu-btn:hover {
    background: var(--gray-100);
}

.hamburger-line {
    display: block;
    width: 18px;
    height: 2px;
    background: var(--text-primary);
    border-radius: 1px;
    transition: all var(--transition-fast);
}

/* Desktop: nav group is just a flex row */
.header-nav-group {
    display: flex;
    align-items: center;
    gap: 0.25rem;
}

/* Mobile header */
@media (max-width: 768px) {
    .header {
        height: auto;
        min-height: 48px;
    }

    .header-content {
        flex-wrap: wrap;
        padding: 0;
        gap: 0;
    }

    .logo {
        font-size: 18px;
        padding: 12px 0;
    }

    .mobile-menu-btn {
        display: flex;
        margin-left: auto;
    }

    .header-nav-group {
        display: none;
        flex-direction: column;
        align-items: stretch;
        width: 100%;
        padding-bottom: 8px;
        border-top: 1px solid var(--gray-200);
    }

    .header-nav-group.is-open {
        display: flex;
    }

    .nav {
        flex-direction: column;
        gap: 2px;
        padding: 8px 0 4px;
    }

    .nav-link {
        padding: 10px 12px;
        font-size: 15px;
        border-radius: 8px;
    }

    .user-menu {
        padding: 4px 0 0;
        border-top: 1px solid var(--gray-100);
    }

    .signin-btn {
        display: block;
        padding: 10px 12px !important;
        font-size: 15px !important;
    }
}

/* App sub-navigation bar */
.app-subnav {
    background: var(--header-bg);
    backdrop-filter: saturate(120%) blur(16px);
    -webkit-backdrop-filter: saturate(120%) blur(16px);
    border-bottom: 1px solid var(--gray-200);
    position: sticky;
    top: 52px;
    z-index: 999;
    overflow-x: auto;
    -ms-overflow-style: none;
    scrollbar-width: none;
}
.app-subnav::-webkit-scrollbar {
    display: none;
}
.app-subnav-inner {
    max-width: 960px;
    margin: 0 auto;
    display: flex;
    align-items: center;
    height: 40px;
    padding: 0 22px;
    gap: 4px;
}
.app-subnav-link {
    padding: 8px 12px;
    font-size: 13px;
    font-weight: 500;
    color: var(--text-secondary);
    text-decoration: none;
    white-space: nowrap;
    border-bottom: 2px solid transparent;
    transition: color var(--transition-fast), border-color var(--transition-fast);
}
.app-subnav-link:hover {
    color: var(--text-primary);
}
.app-subnav-link.active {
    color: var(--primary-color);
    border-bottom-color: var(--primary-color);
}

/* DM child page breadcrumbs */
.dm-breadcrumbs {
    padding: 10px 0 0;
    font-size: 13px;
    color: var(--text-secondary);
}
.dm-breadcrumbs a {
    color: var(--text-secondary);
    text-decoration: none;
    transition: color var(--transition-fast);
}
.dm-breadcrumbs a:hover {
    color: var(--primary-color);
}
.dm-breadcrumbs .sep {
    margin: 0 6px;
}
.dm-breadcrumbs .current {
    color: var(--text-primary);
}

/* Breadcrumbs */
.breadcrumbs {
    max-width: 960px;
    margin: 0 auto;
    padding: 10px 22px 0;
    font-size: 13px;
    color: var(--text-secondary);
}
.breadcrumbs a {
    color: var(--text-secondary);
    text-decoration: none;
    transition: color var(--transition-fast);
}
.breadcrumbs a:hover {
    color: var(--primary-color);
}
.breadcrumbs .sep {
    margin: 0 6px;
}
.breadcrumbs .current {
    color: var(--text-primary);
}

/* Mobile: app sub-nav & breadcrumbs */
@media (max-width: 768px) {
    .app-subnav {
        position: relative;
        top: auto;
    }
    .app-subnav-inner {
        padding: 0 16px;
    }
    .app-subnav-link {
        font-size: 12px;
        padding: 8px 10px;
    }
    .breadcrumbs {
        padding: 8px 16px 0;
    }
}

/* Page content wrapper - grows to fill space. */
.page-content {
    flex: 1;
    display: flex;
    flex-direction: column;
}

/* min-height: 0 lets the wrapper shrink inside a pinned .page-shell so its
 * child can size against the real leftover space (CCT-322) - and a pinned
 * shell (the map) is the only place there is anything to shrink against, so
 * that is the only place the floor is dropped (CCT-345).
 *
 * Everywhere else the wrapper keeps its content-based minimum. `flex: 1` is
 * flex-basis 0, so with the minimum zeroed the wrapper's contribution to the
 * auto-height shell rests entirely on the engine resolving a zero-basis item
 * against its content; an engine that sizes the column from flex base sizes
 * instead ends the shell about one viewport down while the page keeps going.
 * The sticky disclaimer is the shell's last child and is clamped to it, so a
 * short shell is what unsticks the disclaimer mid-page - the /filings/table/
 * report behind CCT-345. Keeping the floor makes the shell's reach a property
 * of the CSS rather than of the engine's intrinsic sizing. */
body.page-fills-viewport .page-content {
    min-height: 0;
}

/* Flash messages */
.messages-container {
    max-width: 900px;
    width: 100%;
    margin: 0 auto;
    padding: 0.75rem 1rem 0;
}

.message {
    padding: 0.75rem 1rem;
    border-radius: 6px;
    font-size: 0.9rem;
    margin-bottom: 0.5rem;
}

.message-success {
    background: var(--green-60);
    color: var(--green-650);
}

.message-error {
    background: var(--red-60);
    color: var(--red-660);
}

.message-warning {
    background: var(--amber-60);
    color: var(--orange-600);
}

.message-info {
    background: var(--ocean-light);
    color: var(--primary-color);
}

/* =============================================
   Site banners (CCT-322)
   =============================================
   Full-width strips rendered between the header and <main>: the terms notice
   period banner, the timezone prompt and the email delivery warning. All three
   had byte-identical inline style blobs on the wrapper and on every control;
   the layout lives here instead so there is one place to change it and one
   place that agrees with the page shell's flex math.
   Behaviour (Alpine state, dismissal endpoints, umami attributes) stays in the
   individual partials - they share nothing but their looks, which is why this
   is a shared class rather than a shared template. Each partial also keeps its
   own identity class (.terms-pending-banner, .tz-prompt,
   .email-delivery-warning); those carry no styles, they name the banner in the
   DOM and one of them is the marker tests/test_middleware.py asserts on.
   Palette is set through custom properties so a variant only overrides colour. */
.site-banner {
    --site-banner-bg: var(--info-bg);
    --site-banner-border: var(--info-border);
    --site-banner-action-bg: var(--primary-color);
    --site-banner-dismiss-color: var(--slate-500);
    background: var(--site-banner-bg);
    border-bottom: 1px solid var(--site-banner-border);
    padding: 10px 16px;
    font-size: 13px;
    display: flex;
    align-items: center;
    gap: 8px;
    flex-wrap: wrap;
    justify-content: center;
}

/* Warning palette - used by the email delivery warning */
.site-banner-danger {
    --site-banner-bg: var(--danger-bg);
    --site-banner-border: var(--danger-border);
    --site-banner-action-bg: var(--danger);
    --site-banner-dismiss-color: var(--red-800);
    color: var(--red-900);
}

/* Inline link inside the banner's message text */
.site-banner-link {
    color: var(--primary-color);
}

/* Primary control - an <a> or a <button> depending on the banner */
.site-banner-action {
    background: var(--site-banner-action-bg);
    color: var(--text-on-accent);
    border: none;
    border-radius: 4px;
    padding: 4px 12px;
    font-size: 13px;
    cursor: pointer;
    text-decoration: none;
}

/* Outlined secondary control */
.site-banner-secondary {
    background: transparent;
    border: 1px solid var(--slate-400);
    border-radius: 4px;
    padding: 4px 12px;
    font-size: 13px;
    cursor: pointer;
    color: var(--slate-710);
}

.site-banner-select {
    font-size: 13px;
    padding: 4px 8px;
    border: 1px solid var(--slate-400);
    border-radius: 4px;
}

.site-banner-dismiss {
    background: transparent;
    border: none;
    color: var(--site-banner-dismiss-color);
    font-size: 13px;
    cursor: pointer;
    text-decoration: underline;
}

/* Notice-period disclosure at the top of /terms/ and /privacy/ (CCT-323).
   Same reasoning as .site-banner above, and the same info palette: the partial
   core/_policy_upcoming.html carried the whole look as six inline style blobs.
   The wrapper, the change summary and the collapsible body already had class
   hooks with nothing behind them - these are those rules. The inner heading,
   lede and <details> parts are addressed as descendants rather than given new
   classes, because tests/test_core_views.py asserts the <details> element's
   markup literally; the partial's markup is unchanged apart from the styles
   moving here. */
.policy-upcoming {
    border: 1px solid var(--info-border);
    background: var(--info-bg);
    border-radius: 12px;
    padding: 16px 20px;
    margin-bottom: 32px;
    /* The consent surfaces link here as /terms/#upcoming-changes; without
       this the sticky .header covers the section heading on the fragment
       jump. */
    scroll-margin-top: calc(var(--header-height) + 16px);
}

/* Child combinators throughout: the pending policy body rendered inside
   .policy-upcoming-content is staff-authored HTML with its own headings and
   paragraphs, which must keep the page's .legal-section styling. */
.policy-upcoming > h2 {
    font-size: 17px;
    font-weight: 600;
    margin-bottom: 8px;
}

.policy-upcoming > p,
.policy-upcoming-summary {
    font-size: 14px;
    margin-bottom: 12px;
}

.policy-upcoming-content > summary {
    font-size: 14px;
    cursor: pointer;
}

.policy-upcoming-content > div {
    margin-top: 12px;
}

/* Main content */
.main {
    width: 100%;
    max-width: 1400px;
    margin: 0 auto;
    padding: 24px 22px;
}

.main.full-width {
    max-width: 100%;
    padding: 0;
}

/* Filter bar */
.filter-bar {
    background: var(--header-bg);
    backdrop-filter: saturate(120%) blur(16px);
    -webkit-backdrop-filter: saturate(120%) blur(16px);
    padding: 12px 22px;
    border-bottom: none;
    display: flex;
    align-items: center;
    gap: 12px;
    flex-wrap: wrap;
}

.filter-label {
    font-size: 13px;
    color: var(--text-secondary);
    font-weight: 500;
}

/* iOS-style segmented control */
.filter-group {
    display: inline-flex;
    background: var(--gray-100);
    border-radius: 8px;
    padding: 2px;
}

.filter-btn {
    padding: 6px 14px;
    background: transparent;
    border: none;
    border-radius: 6px;
    font-size: 13px;
    font-weight: 500;
    color: var(--text-primary);
    cursor: pointer;
    transition: all var(--transition-fast);
}

.filter-btn:hover {
    color: var(--gray-600);
}

.filter-btn.active {
    background: var(--surface);
    box-shadow: 0 1px 3px rgb(var(--black-rgb) / 0.1);
    color: var(--text-primary);
}

/* Map page layout - takes whatever the pinned .page-shell has left after the
 * header, any site banners and the disclaimer (CCT-322). The map template sets
 * body class `page-fills-viewport`, so that leftover is exactly the viewport
 * minus the chrome, however tall the chrome happens to be. */
.map-page-layout {
    display: flex;
    flex-direction: column;
    flex: 1 1 auto;
    min-height: 0;
}

/* Map container */
#map {
    height: 100%;
    width: 100%;
    min-height: 300px;
    background: var(--slate-200);
}

/* Stats card */
.stats-card {
    background: var(--surface);
    border-radius: 12px;
    padding: 24px;
    box-shadow: var(--shadow-md);
    border: none;
    transition: all var(--transition-fast);
}

.stats-card:hover {
    box-shadow: var(--shadow-lg);
    transform: translateY(-1px);
}

.stats-title {
    font-size: 13px;
    color: var(--text-secondary);
    margin-bottom: 4px;
    font-weight: 500;
}

.stats-value {
    font-size: 28px;
    font-weight: 600;
    color: var(--text-primary);
    letter-spacing: -0.03em;
}

/* Word cloud container */
.wordcloud-container {
    background: var(--surface);
    border-radius: 12px;
    padding: 24px;
    box-shadow: var(--shadow-md);
    border: none;
    min-height: 400px;
    transition: all var(--transition-fast);
}

.wordcloud-container:hover {
    box-shadow: var(--shadow-lg);
    transform: translateY(-1px);
}

/* Section headers */
.section-title {
    font-size: 17px;
    font-weight: 600;
    color: var(--text-primary);
    margin-bottom: 16px;
    letter-spacing: -0.022em;
}

.section-subtitle {
    font-size: 13px;
    font-weight: 500;
    color: var(--text-secondary);
    margin-bottom: 12px;
}

/* Loading indicator */
.htmx-indicator {
    display: none;
}

.htmx-request .htmx-indicator {
    display: inline-block;
}

.htmx-request.htmx-indicator {
    display: inline-block;
}

.spinner {
    display: inline-block;
    width: 18px;
    height: 18px;
    border: 2px solid var(--gray-200);
    border-radius: 50%;
    border-top-color: var(--primary-color);
    animation: spin 1s linear infinite;
}

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

/* Footer - normal document flow */
.footer {
    border-top: 1px solid var(--gray-100);
    padding: 12px 22px;
}

.footer-content {
    max-width: 1400px;
    margin: 0 auto;
    display: flex;
    align-items: center;
    justify-content: center;
}

.footer-links {
    display: flex;
    gap: 16px;
    flex-wrap: wrap;
    justify-content: center;
    align-items: center;
}

.footer-links a {
    font-size: 12px;
    color: var(--text-secondary);
    text-decoration: none;
    transition: color var(--transition-fast);
}

.footer-links a:hover {
    color: var(--primary-color);
}

.footer-divider {
    color: var(--gray-200);
    font-size: 12px;
}

/* Sticky disclaimer - sticks to viewport bottom, settles above footer on scroll */
.footer-disclaimer {
    position: sticky;
    bottom: 0;
    background: var(--background);
    border-top: 1px solid var(--gray-100);
    text-align: center;
    font-size: 10px;
    color: var(--gray-400);
    padding: 6px 22px;
    margin: 0;
    line-height: 1.3;
    z-index: 10;
}

/* Keyword rows */
.keyword-row {
    display: flex;
    justify-content: space-between;
    align-items: center;
    padding: 12px 0;
}

.keyword-row:not(:last-child) {
    border-bottom: 1px solid var(--gray-100);
}

.keyword-word {
    font-weight: 500;
    text-transform: capitalize;
    font-size: 15px;
}

.keyword-count {
    color: var(--text-secondary);
    font-size: 15px;
}

/* Filing type rows */
.filing-type-row {
    display: flex;
    justify-content: space-between;
    align-items: center;
    padding: 12px 0;
    font-size: 15px;
}

.filing-type-row:not(:last-child) {
    border-bottom: 1px solid var(--gray-100);
}

.filing-type-name {
    color: var(--text-primary);
}

.filing-type-count {
    font-weight: 600;
    color: var(--text-primary);
}

/* Screen-reader only (visually hidden) */
.sr-only {
    position: absolute;
    width: 1px;
    height: 1px;
    padding: 0;
    margin: -1px;
    overflow: hidden;
    clip: rect(0, 0, 0, 0);
    white-space: nowrap;
    border: 0;
}

.sr-only-focusable:focus {
    position: static;
    width: auto;
    height: auto;
    padding: inherit;
    margin: 0;
    overflow: visible;
    clip: auto;
    white-space: normal;
}

/* Global focus-visible indicator for interactive elements */
:focus-visible {
    outline: 2px solid var(--primary-color);
    outline-offset: 2px;
}

/* Reduced motion preference */
@media (prefers-reduced-motion: reduce) {
    *,
    *::before,
    *::after {
        animation-duration: 0.01ms !important;
        animation-iteration-count: 1 !important;
        transition-duration: 0.01ms !important;
        scroll-behavior: auto !important;
    }
}

/* Reset fieldset styling for semantic grouping without visual chrome */
.fieldset-plain {
    border: 0;
    padding: 0;
    margin: 0;
    min-width: 0;
}

/* Utility classes */
.grid {
    display: grid;
    gap: 1rem;
}

.grid-cols-2 {
    grid-template-columns: repeat(2, 1fr);
}

.grid-cols-3 {
    grid-template-columns: repeat(3, 1fr);
}

.grid-cols-4 {
    grid-template-columns: repeat(4, 1fr);
}

@media (max-width: 768px) {
    .grid-cols-3,
    .grid-cols-4 {
        grid-template-columns: repeat(2, 1fr);
    }
}

@media (max-width: 480px) {
    .grid-cols-2,
    .grid-cols-3,
    .grid-cols-4 {
        grid-template-columns: 1fr;
    }
}

.mb-4 { margin-bottom: 1rem; }
.mt-4 { margin-top: 1rem; }
.p-4 { padding: 1rem; }

/* Leaflet popup customization */
.leaflet-popup-content-wrapper {
    border-radius: 12px;
    box-shadow: var(--shadow-lg);
    border: none;
}

.leaflet-popup-content {
    margin: 14px 16px;
    font-size: 14px;
}

.popup-title {
    font-weight: 600;
    margin-bottom: 4px;
    color: var(--text-primary);
}

.popup-count {
    color: var(--primary-color);
    font-weight: 600;
}

.popup-divider {
    margin: 10px 0;
    border: none;
    border-top: 1px solid var(--gray-100);
}

.popup-filing {
    margin-bottom: 4px;
    font-size: 12px;
    color: var(--text-primary);
}

.popup-more {
    font-size: 12px;
    color: var(--text-secondary);
}

/* =============================================
   Global Modal
   ============================================= */

.modal-overlay {
    position: fixed;
    top: 0;
    left: 0;
    right: 0;
    bottom: 0;
    background: var(--overlay);
    display: flex;
    align-items: center;
    justify-content: center;
    z-index: 3000;
}

.modal {
    background: var(--surface-raised);
    border-radius: 12px;
    padding: 24px;
    max-width: 420px;
    width: 90%;
    max-height: 90vh;
    overflow-y: auto;
    margin: 20px;
    box-shadow: 0 20px 60px rgb(var(--black-rgb) / 0.3);
}

/* Rich-content alerts (showAlert opts.html) carry several paragraphs rather
   than one line, so they get the wider shell the map's help overlay used
   before it moved onto this modal (CCT-82). */
.modal.modal-rich {
    max-width: 520px;
}

.modal-rich-body p:last-child {
    margin-bottom: 0;
}

.modal h4 {
    margin: 0 0 12px 0;
    font-size: 18px;
    font-weight: 600;
    color: var(--text-primary);
}

.modal p {
    margin: 0 0 16px 0;
    font-size: 14px;
    line-height: 1.5;
    color: var(--text-secondary);
}

.modal-actions {
    display: flex;
    gap: 10px;
    justify-content: flex-end;
    margin-top: 20px;
}

.modal-btn {
    padding: 10px 18px;
    font-size: 14px;
    font-weight: 500;
    border: none;
    border-radius: 8px;
    cursor: pointer;
    transition: all var(--transition-fast);
}

.modal-btn.secondary {
    background: var(--gray-100);
    color: var(--text-primary);
}

.modal-btn.secondary:hover {
    background: var(--gray-200);
}

.modal-btn.primary {
    background: var(--primary-color);
    color: white;
}

.modal-btn.primary:hover {
    background: var(--primary-hover);
}

.modal-btn.primary:disabled {
    opacity: 0.5;
    cursor: not-allowed;
}

.modal-btn.danger {
    background: var(--red-500);
    color: white;
}

.modal-btn.danger:hover {
    background: var(--red-620);
}

/* =============================================
   Shared Date Inputs
   ============================================= */

.date-input {
    padding: 6px 10px;
    border: 1px solid var(--border-color);
    border-radius: 6px;
    font-size: 13px;
    font-family: inherit;
    background: var(--surface);
    color: var(--text-primary);
}

.date-input:focus {
    outline: none;
    border-color: var(--primary-color);
    box-shadow: 0 0 0 2px rgb(var(--primary-rgb) / 0.2);
}

.date-separator {
    font-size: 13px;
    color: var(--text-secondary);
}

.apply-btn:disabled {
    opacity: 0.5;
    cursor: not-allowed;
}

/* Beta banner */
.beta-banner {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 0.75rem;
    padding: 0.4rem 1rem;
    background: var(--primary-color);
    color: var(--text-on-accent);
    font-size: 0.85rem;
    font-weight: 500;
    text-align: center;
}
.beta-banner button {
    background: none;
    border: none;
    color: var(--text-on-accent);
    font-size: 1.1rem;
    cursor: pointer;
    padding: 0 0.25rem;
    line-height: 1;
    opacity: 0.7;
}
.beta-banner button:hover {
    opacity: 1;
}

/* Feedback widget */
.feedback-widget {
    display: inline-flex;
    align-items: center;
    gap: 0.5rem;
    font-size: 0.85rem;
    color: var(--text-secondary);
    margin-top: 1rem;
}
.feedback-widget button {
    background: none;
    border: 1px solid var(--border-color);
    border-radius: 4px;
    padding: 0.2rem 0.5rem;
    cursor: pointer;
    font-size: 1rem;
    line-height: 1;
}
.feedback-widget button:hover {
    background: var(--bg-secondary);
}
