/* ============================================
   STORMY EYES - LIVE TORNADO TRACKER
   Branded dark theme with electric blue accents
   ============================================ */

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

:root {
    /* Tornado Emergency */
    --te-color: #ff00cc;
    --te-glow: rgba(255, 0, 204, 0.35);
    --te-fill: rgba(220, 0, 180, 0.4);
    /* PDS Watch */
    --pds-color: #ff6600;
    --pds-glow: rgba(255, 102, 0, 0.3);

    /* Stormy Eyes branded palette */
    --bg-primary: #0b0b16;
    --bg-secondary: rgba(26, 26, 46, 0.95);
    --bg-card: rgba(22, 22, 42, 0.9);
    --bg-card-hover: rgba(30, 30, 55, 0.95);
    --border-color: rgba(74, 158, 255, 0.15);
    --border-glow: rgba(74, 158, 255, 0.3);
    --text-primary: #ffffff;
    --text-secondary: #b0b8c8;
    --text-muted: #666e80;
    /* Stormy Eyes electric blue */
    --accent-blue: #4a9eff;
    --accent-blue-glow: rgba(74, 158, 255, 0.25);
    /* Alert colors */
    --accent-red: #ff6b6b;
    --accent-orange: #f97316;
    --accent-yellow: #eab308;
    --accent-green: #22c55e;
    --accent-cyan: #06b6d4;
    --tornado-color: #ff3333;
    --severe-color: #ff8c00;
    --watch-color: #ffd700;
    --tornado-watch-color: #ffff00;
    --severe-watch-color: #db7093;
    --special-color: #87ceeb;
    --flood-color: #22c55e;
    --flood-emergency-color: #c026d3;
    --cancelled-color: #6b7280;
    --radius: 6px;
    --radius-lg: 10px;
    --shadow: 0 4px 24px rgba(0, 0, 0, 0.5);
    --shadow-blue: 0 0 20px rgba(74, 158, 255, 0.15);
    --transition: 0.3s ease;
}

html, body {
    height: 100%;
    font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
    background: var(--bg-primary);
    color: var(--text-primary);
    overflow-x: hidden;
    overflow-y: auto;
}

/* Global image safety - prevent oversized images */
img {
    max-width: 100%;
    height: auto;
}

/* ============================================
   HEADER
   ============================================ */
.header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 0 20px;
    height: 60px;
    max-height: 60px;
    background: linear-gradient(180deg, rgba(26, 26, 46, 0.98) 0%, rgba(15, 15, 30, 0.95) 100%);
    border-bottom: 1px solid var(--border-color);
    box-shadow: 0 2px 20px rgba(0, 0, 0, 0.3), 0 1px 0 var(--border-glow);
    z-index: 100;
    position: relative;
    overflow: hidden;
}

.header-left {
    display: flex;
    align-items: center;
    gap: 24px;
}

/* Logo + DEV BUILD badge wrapper. In the normal landscape header this is
   a plain row with the same 24px gap .header-left used to supply, so the
   badge still sits beside the logo exactly as before. Vertical/stream
   mode flips it to a column (see VERTICAL STREAM MODE section). */
.header-brand {
    display: flex;
    align-items: center;
    gap: 24px;
}

.logo {
    display: flex;
    align-items: center;
    gap: 12px;
}

.logo-img {
    width: 40px;
    height: 40px;
    min-width: 40px;
    max-width: 40px;
    min-height: 40px;
    max-height: 40px;
    border-radius: 8px;
    object-fit: cover;
    border: 1px solid var(--border-glow);
    box-shadow: 0 0 12px rgba(74, 158, 255, 0.2);
    display: block;
    flex-shrink: 0;
}

.logo-text {
    display: flex;
    flex-direction: column;
}

.logo h1 {
    font-size: 15px;
    font-weight: 700;
    letter-spacing: 1.2px;
    color: var(--text-primary);
    white-space: nowrap;
    line-height: 1.2;
}

.logo .logo-subtitle {
    font-size: 10px;
    font-weight: 600;
    letter-spacing: 2px;
    text-transform: uppercase;
    color: var(--accent-blue);
    line-height: 1.2;
}

.dev-build-badge {
    display: flex;
    align-items: center;
    gap: 5px;
    font-size: 10px;
    font-weight: 700;
    letter-spacing: 1.5px;
    text-transform: uppercase;
    color: #f59e0b;
    background: rgba(245, 158, 11, 0.12);
    border: 1px solid rgba(245, 158, 11, 0.35);
    border-radius: 4px;
    padding: 3px 8px;
    white-space: nowrap;
    line-height: 1;
}

.dev-build-version {
    color: rgba(245, 158, 11, 0.75);
    font-weight: 600;
}

.status-bar {
    display: flex;
    align-items: center;
    gap: 10px;
    font-size: 12px;
    color: var(--text-secondary);
}

.status-dot {
    width: 8px;
    height: 8px;
    border-radius: 50%;
    background: var(--accent-green);
    animation: pulse 2s infinite;
}

.status-dot.error {
    background: var(--accent-red);
    animation: none;
}

@keyframes pulse {
    0%, 100% { opacity: 1; }
    50% { opacity: 0.4; }
}

.separator {
    color: var(--border-color);
}

/* ---- Toast notifications (top-center stack) ---- */
.toast-stack {
    position: fixed;
    top: 72px;
    left: 50%;
    transform: translateX(-50%);
    width: calc(440px * var(--toast-scale, 1));
    max-width: 92vw;
    z-index: 1500;
    display: flex;
    flex-direction: column;
    gap: 8px;
    pointer-events: none;
    /* Cap at the space between the header and the bottom broadcast strip
       (footer bar + ticker + count pills); overflow scrolls */
    max-height: calc(100vh - 130px - var(--ticker-h, 32px) - var(--pillstrip-h, 46px));
    overflow-y: auto;
    overscroll-behavior: contain;
    padding-right: 3px;
    scrollbar-width: thin;
    scrollbar-color: rgba(74, 158, 255, 0.45) transparent;
}
body.scalebar-active .toast-stack {
    max-height: calc(100vh - 164px - var(--ticker-h, 32px) - var(--pillstrip-h, 46px));
}
/* Only intercept mouse events (for wheel-scrolling) when actually overflowing;
   otherwise stay click-through like before. Toggled in _layout(). */
.toast-stack.toast-stack-scroll { pointer-events: auto; }
.toast-stack::-webkit-scrollbar { width: 6px; }
.toast-stack::-webkit-scrollbar-track { background: transparent; }
.toast-stack::-webkit-scrollbar-thumb {
    background: rgba(74, 158, 255, 0.45);
    border-radius: 3px;
}
.toast-stack::-webkit-scrollbar-thumb:hover { background: rgba(74, 158, 255, 0.7); }
.toast {
    pointer-events: auto;
    position: relative;
    display: flex;
    /* Drag/interact UI chrome — same stuck-selection guard as .uni-popup:
       these cards preventDefault mouse interactions, so a native drag-select
       that slipped through could never be cleared by clicking. */
    -webkit-user-select: none;
    user-select: none;
    /* Never compress to fit the stack's max-height — the stack scrolls
       instead. (Flex children shrink by default, which was clipping the
       bottom of cards once the stack got a height cap.) */
    flex-shrink: 0;
    /* fallback for browsers without color-mix() */
    background: var(--bg-card);
    /* glassy top highlight over a tier-color fill blended onto a dark base so
       white text stays readable on every tier (incl. yellow/blue watches) */
    background:
        linear-gradient(180deg, rgba(255, 255, 255, 0.14), rgba(255, 255, 255, 0) 50%),
        linear-gradient(90deg,
            color-mix(in srgb, var(--toast-accent, #4a9eff) 48%, #0b0f1c),
            color-mix(in srgb, var(--toast-accent, #4a9eff) 26%, #0b0f1c));
    border: 1px solid color-mix(in srgb, var(--toast-accent, #4a9eff) 55%, #ffffff);
    border-left: 4px solid var(--toast-accent, #888);
    border-radius: 8px;
    box-shadow: var(--shadow);
    backdrop-filter: blur(10px);
    overflow: hidden;
    animation: toast-in 0.5s cubic-bezier(0.18, 1.3, 0.3, 1);   /* broadcast slide-in: overshoot + flash */
    transition: transform 0.15s ease, box-shadow 0.15s ease;
}
.toast:hover {
    transform: translateY(-1px);
    box-shadow: var(--shadow), 0 6px 22px rgba(0, 0, 0, 0.5);
}
/* Flowing light traveling down the tier-colored accent edge. */
/* Colorful flowing wash that fills the whole card, behind the text. Low alpha
   over the dark base keeps the white text crisp while the hues slowly drift. */
.toast::before {
    content: '';
    position: absolute;
    inset: 0;
    z-index: 0;
    pointer-events: none;
    background: linear-gradient(115deg,
        transparent 24%,
        rgba(255, 120, 200, 0.28) 40%,
        rgba(120, 210, 255, 0.33) 50%,
        rgba(130, 255, 200, 0.28) 60%,
        transparent 76%);
    background-size: 250% 100%;
    background-repeat: no-repeat;
    animation: toast-sweep 6s linear infinite;
}
/* Tier-colored light wave traveling down the accent edge, on top of the fill. */
.toast::after {
    content: '';
    position: absolute;
    left: 0; top: 0; bottom: 0;
    width: 4px;
    z-index: 2;
    pointer-events: none;
    background: linear-gradient(180deg,
        var(--toast-accent, #888) 0%,
        rgba(255, 255, 255, 0.75) 25%,
        var(--toast-accent, #888) 50%,
        rgba(255, 255, 255, 0.75) 75%,
        var(--toast-accent, #888) 100%);
    background-size: 100% 300%;
    animation: toast-edge-wave 7s linear infinite;
}
@keyframes toast-sweep {
    0%   { background-position: -120% 0; }
    100% { background-position: 220% 0; }
}
@keyframes toast-edge-wave {
    0%   { background-position: 0 0; }
    100% { background-position: 0 -300%; }
}
@keyframes toast-in {
    0%   { opacity: 0; transform: translateY(-26px) scale(1.03); filter: blur(3px) brightness(2.2); }
    55%  { opacity: 1; transform: translateY(3px)  scale(1.005); filter: blur(0) brightness(1.35); }
    100% { opacity: 1; transform: translateY(0) scale(1); filter: blur(0) brightness(1); }
}
.toast.toast--leaving {
    animation: toast-out 1.6s ease forwards;   /* slow dissolve — tune this duration */
    pointer-events: none;
    overflow: hidden;
}
@keyframes toast-out {
    0%   { opacity: 1; transform: translateY(0) scale(1); filter: blur(0); }
    80%  { opacity: 0; transform: translateY(-10px) scale(0.96); filter: blur(2px); }
    100% { opacity: 0; transform: translateY(-10px) scale(0.96); filter: blur(2px); height: 0; margin: 0; padding: 0; border-width: 0; }
}
.toast-body { padding: calc(9px * var(--toast-scale, 1)) calc(11px * var(--toast-scale, 1)); flex: 1; min-width: 0; position: relative; z-index: 1; }
.toast-head { display: flex; align-items: center; gap: 7px; }
.toast-icon { font-size: calc(15px * var(--toast-scale, 1)); line-height: 1; }
.toast-title {
    font-size: calc(13px * var(--toast-scale, 1));
    font-weight: 700;
    color: #ffffff;
    text-shadow: 0 1px 3px rgba(0, 0, 0, 0.6);
    flex: 1;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
.toast-verb {
    font-size: calc(9px * var(--toast-scale, 1));
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.5px;
    padding: calc(1px * var(--toast-scale, 1)) calc(6px * var(--toast-scale, 1));
    border-radius: 4px;
    flex-shrink: 0;
}
.toast-close {
    pointer-events: auto;
    background: none;
    border: none;
    color: rgba(255, 255, 255, 0.75);
    font-size: calc(17px * var(--toast-scale, 1));
    line-height: 1;
    cursor: pointer;
    padding: 0 2px;
    flex-shrink: 0;
}
.toast-close:hover { color: #ffffff; }
.toast-pin {
    pointer-events: auto;
    background: none;
    border: none;
    color: rgba(255, 255, 255, 0.5);
    font-size: calc(13px * var(--toast-scale, 1));
    line-height: 1;
    cursor: pointer;
    padding: 0 2px;
    flex-shrink: 0;
    filter: grayscale(1);
    opacity: 0.6;
    transition: opacity 0.2s, filter 0.2s;
}
.toast:hover .toast-pin { opacity: 1; }
.toast.toast-pinned .toast-pin { filter: none; opacity: 1; }
.toast.toast-pinned { box-shadow: var(--shadow), 0 0 0 2px rgba(234, 179, 8, 0.6); }
.toast-sub {
    font-size: calc(11px * var(--toast-scale, 1));
    color: #eaf0f8;
    text-shadow: 0 1px 2px rgba(0, 0, 0, 0.55);
    margin-top: 3px;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
.toast-meta { font-size: calc(10px * var(--toast-scale, 1)); color: rgba(255, 255, 255, 0.72); margin-top: 3px; }
.toast-badges { display: flex; gap: 4px; margin-top: 5px; flex-wrap: wrap; }
.toast-badge {
    font-size: calc(9px * var(--toast-scale, 1));
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.4px;
    padding: 1px 5px;
    border-radius: 3px;
}
.toast--te { animation: toast-in 0.5s cubic-bezier(0.18, 1.3, 0.3, 1), te-toast-pulse 1.1s ease-in-out infinite; }
@keyframes te-toast-pulse {
    0%, 100% { box-shadow: 0 0 8px rgba(255, 0, 204, 0.35); }
    50%      { box-shadow: 0 0 22px rgba(255, 0, 204, 0.7); }
}

/* Tornado Warning: slower, subtler red glow (TE keeps the magenta strobe) */
.toast--tor { animation: toast-in 0.5s cubic-bezier(0.18, 1.3, 0.3, 1), tor-toast-pulse 2.2s ease-in-out infinite; }
@keyframes tor-toast-pulse {
    0%, 100% { box-shadow: 0 0 6px rgba(255, 51, 51, 0.25); }
    50%      { box-shadow: 0 0 16px rgba(255, 51, 51, 0.55); }
}

/* TV-graphics icon chip: accent-tinted rounded square around the emoji */
.toast-icon {
    display: inline-grid;
    place-items: center;
    width: calc(24px * var(--toast-scale, 1));
    height: calc(24px * var(--toast-scale, 1));
    flex-shrink: 0;
    background: color-mix(in srgb, var(--toast-accent, #4a9eff) 28%, rgba(0, 0, 0, 0.35));
    border: 1px solid color-mix(in srgb, var(--toast-accent, #4a9eff) 55%, transparent);
    border-radius: 6px;
    box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.18);
}

/* Expiry countdown — thin "life bar" along the toast's bottom edge.
   JS sets the initial width to the fraction of warning time remaining,
   then transitions it to 0 over the remaining duration. */
.toast-life {
    position: absolute;
    left: 0;
    right: 0;
    bottom: 0;
    height: 3px;
    background: rgba(0, 0, 0, 0.4);
    z-index: 3;
    pointer-events: none;
}
.toast-life i {
    display: block;
    height: 100%;
    background: linear-gradient(90deg,
        color-mix(in srgb, var(--toast-accent, #4a9eff) 80%, #ffffff),
        var(--toast-accent, #4a9eff));
    box-shadow: 0 0 6px color-mix(in srgb, var(--toast-accent, #4a9eff) 70%, transparent);
}

/* Final 5 minutes of a warning: life bar turns red and blinks */
.toast-life-critical i {
    background: linear-gradient(90deg, #ff6655, #ff2222);
    box-shadow: 0 0 8px rgba(255, 40, 40, 0.8);
    animation: life-blink 0.7s steps(2) infinite;
}
@keyframes life-blink {
    50% { opacity: 0.25; }
}

/* ---- Warnings panel hide / edge tab ---- */
.panel-hide-btn {
    position: absolute;
    top: 12px;
    right: 46px;   /* sits beside the float toggle at right:14px */
    width: 26px;
    height: 26px;
    padding: 0;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    background: rgba(255, 255, 255, 0.06);
    border: 1px solid rgba(255, 255, 255, 0.15);
    border-radius: 6px;
    color: rgba(255, 255, 255, 0.7);
    font-size: 14px;
    line-height: 1;
    cursor: pointer;
    transition: background 0.15s ease, color 0.15s ease, border-color 0.15s ease;
}
.panel-hide-btn:hover {
    background: rgba(255, 140, 0, 0.15);
    color: #ffaa44;
    border-color: rgba(255, 140, 0, 0.5);
}

body.warnpanel-hidden #warnings-panel { display: none !important; }

#warnpanel-tab {
    display: none;
    position: fixed;
    left: 0;
    top: 38%;
    z-index: 580;
    writing-mode: vertical-rl;
    transform: rotate(180deg);
    padding: 12px 5px;
    background: rgba(13, 19, 34, 0.95);
    border: 1px solid rgba(255, 140, 0, 0.45);
    border-radius: 6px 0 0 6px;
    font-family: var(--font-display);
    font-size: 11px;
    font-weight: 700;
    letter-spacing: 2px;
    color: rgba(255, 255, 255, 0.85);
    cursor: pointer;
    box-shadow: 0 4px 14px rgba(0, 0, 0, 0.5);
}
#warnpanel-tab:hover { color: #ffaa44; border-color: rgba(255, 140, 0, 0.8); }
body.warnpanel-hidden #warnpanel-tab { display: block; }

/* ---- Broadcast count pills (above the ticker) ---- */
#alert-countstrip {
    position: fixed;
    bottom: 8px;
    left: 50%;
    transform: translateX(-50%);
    display: flex;
    gap: 8px;
    z-index: 599;
    pointer-events: none;
}
body.ticker-active #alert-countstrip { bottom: calc(var(--ticker-h) + 10px); }
body.countstrip-off #alert-countstrip { display: none; }

.count-pill {
    display: flex;
    align-items: center;
    gap: 9px;
    padding: 6px 14px 6px 11px;
    background: linear-gradient(180deg, rgba(26, 32, 52, 0.95), rgba(9, 12, 21, 0.97));
    border: 1px solid rgba(255, 255, 255, 0.14);
    border-radius: 8px;
    backdrop-filter: blur(8px);
    box-shadow: 0 4px 14px rgba(0, 0, 0, 0.5);
    --glow: rgba(255, 255, 255, 0.3);
}
.pill-icon { font-size: calc(17px * var(--ticker-scale, 1)); line-height: 1; }
.pill-num {
    font-family: var(--font-display);
    font-size: calc(26px * var(--ticker-scale, 1));
    font-weight: 700;
    line-height: 1;
    color: #ffffff;
    min-width: calc(18px * var(--ticker-scale, 1));
    text-align: center;
}
.pill-label {
    font-family: var(--font-display);
    font-size: calc(10px * var(--ticker-scale, 1));
    font-weight: 600;
    letter-spacing: 0.8px;
    line-height: 1.15;
    color: rgba(255, 255, 255, 0.75);
    text-align: left;
}
.pill-tor { border-color: rgba(255, 60, 60, 0.55);  --glow: rgba(255, 60, 60, 0.55); }
.pill-tor .pill-num { color: #ff5555; }
.pill-svr { border-color: rgba(255, 140, 0, 0.55);  --glow: rgba(255, 150, 30, 0.5); }
.pill-svr .pill-num { color: #ffaa44; }
.pill-te  { border-color: rgba(255, 0, 204, 0.7);   --glow: rgba(255, 0, 204, 0.75); }
.pill-te .pill-num { color: #ff66dd; }

.pill-zero { opacity: 0.55; border-color: rgba(255, 255, 255, 0.12); }
.pill-zero .pill-num { color: rgba(255, 255, 255, 0.5); }

.pill-hot { animation: pill-glow 1.6s ease-in-out infinite; }
.pill-te.pill-hot { animation-duration: 0.9s; }
@keyframes pill-glow {
    0%, 100% { box-shadow: 0 4px 14px rgba(0, 0, 0, 0.5), 0 0 4px var(--glow); }
    50%      { box-shadow: 0 4px 14px rgba(0, 0, 0, 0.5), 0 0 18px var(--glow); }
}

/* Keep bottom-anchored UI clear of the pills when both are showing */
body.ticker-active.countstrip-on .radar-control-bar { bottom: calc(var(--ticker-h) + var(--pillstrip-h) + 50px); }
body.ticker-active.countstrip-on .map-legend        { bottom: calc(var(--ticker-h) + var(--pillstrip-h) + 54px); }

/* ---- Measure tool (📏 distance & bearing ruler) ---- */
.map-tool-btn {
    position: absolute;
    right: 10px;
    width: 36px;
    height: 36px;
    z-index: 20;
    display: flex;
    align-items: center;
    justify-content: center;
    background: rgba(13, 19, 34, 0.92);
    border: 1px solid rgba(255, 255, 255, 0.18);
    border-radius: 7px;
    font-size: 16px;
    cursor: pointer;
    box-shadow: 0 2px 8px rgba(0, 0, 0, 0.4);
    transition: border-color 0.15s ease, box-shadow 0.15s ease;
}
.map-tool-btn:hover { border-color: rgba(74, 158, 255, 0.6); }
.map-tool-btn.active {
    border-color: rgba(74, 158, 255, 0.8);
    box-shadow: 0 0 10px rgba(74, 158, 255, 0.35);
}
#measure-btn { top: 112px; }   /* below the zoom controls */
#eta-btn     { top: 154px; }
#draw-btn    { top: 196px; }
#impact-btn  { top: 238px; }
#watch-btn   { top: 280px; }   /* 👁 Watch Area — ProbSevere threat watch */
#veltool-btn { top: 322px; }   /* 💨 Velocity probe — peak inbound/outbound MPH */

/* Left-pointing tooltip for right-edge tool buttons */
.map-tool-btn[data-tip] { overflow: visible; }
.map-tool-btn[data-tip]::after {
    content: attr(data-tip);
    position: absolute;
    right: calc(100% + 9px);
    top: 50%;
    transform: translateY(-50%);
    background: rgba(10, 14, 26, 0.96);
    color: #e0e6f0;
    font-size: 11px;
    font-weight: 500;
    white-space: nowrap;
    padding: 4px 9px;
    border-radius: 5px;
    border: 1px solid rgba(255,255,255,0.15);
    box-shadow: 0 2px 8px rgba(0,0,0,0.5);
    pointer-events: none;
    opacity: 0;
    transition: opacity 0.15s ease;
    z-index: 9999;
}
/* Arrow pointing right */
.map-tool-btn[data-tip]::before {
    content: '';
    position: absolute;
    right: calc(100% + 3px);
    top: 50%;
    transform: translateY(-50%);
    border: 5px solid transparent;
    border-left-color: rgba(10, 14, 26, 0.96);
    pointer-events: none;
    opacity: 0;
    transition: opacity 0.15s ease;
    z-index: 9999;
}
.map-tool-btn[data-tip]:hover::after,
.map-tool-btn[data-tip]:hover::before { opacity: 1; }

/* ---- Storm Track Impact card ---- */
#impact-card {
    position: fixed;
    left: 16px;
    top: 25%;
    width: calc(290px * var(--impact-scale, 1));
    max-height: 85vh;
    z-index: 1400;
    display: flex;
    flex-direction: column;
    background: rgba(13, 19, 34, 0.96);
    border: 1px solid rgba(255, 170, 51, 0.45);
    border-radius: 11px;
    box-shadow: 0 12px 40px rgba(0, 0, 0, 0.65);
    backdrop-filter: blur(10px);
    cursor: grab;
    overflow: hidden;
}
.impact-resize {
    position: absolute;
    right: 0;
    bottom: 0;
    width: 16px;
    height: 16px;
    cursor: nwse-resize;
    background:
        linear-gradient(135deg, transparent 50%, rgba(255, 170, 51, 0.55) 50%, rgba(255, 170, 51, 0.55) 60%, transparent 60%,
            transparent 70%, rgba(255, 170, 51, 0.55) 70%, rgba(255, 170, 51, 0.55) 80%, transparent 80%);
}
.impact-head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 9px 12px 7px;
    background: rgba(255, 170, 51, 0.1);
    border-bottom: 1px solid rgba(255, 170, 51, 0.25);
}
.impact-title {
    font-family: var(--font-display);
    font-size: calc(16px * var(--impact-scale, 1));
    font-weight: 700;
    letter-spacing: 0.8px;
    color: #ffffff;
}
.impact-close {
    background: none; border: none;
    color: rgba(255, 255, 255, 0.6);
    font-size: 14px; cursor: pointer; padding: 0 2px;
}
.impact-close:hover { color: #fff; }
/* Expired-warning banner: clicked polygon's warning is no longer live */
.impact-expired {
    padding: 6px 12px;
    background: rgba(255, 71, 87, 0.16);
    border-bottom: 1px solid rgba(255, 71, 87, 0.4);
    color: #ff8591;
    font-family: var(--font-display);
    font-size: calc(12px * var(--impact-scale, 1));
    font-weight: 700;
    letter-spacing: 0.4px;
}
.impact-stats {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 6px 12px;
    padding: 8px 12px 4px;
    font-family: var(--font-display);
    font-size: calc(13px * var(--impact-scale, 1));
    font-weight: 600;
    color: rgba(255, 255, 255, 0.9);
}
.impact-speed { display: inline-flex; align-items: center; gap: 4px; }
#impact-mph {
    width: calc(44px * var(--impact-scale, 1));
    font-size: calc(12px * var(--impact-scale, 1));
    background: rgba(255, 255, 255, 0.07);
    border: 1px solid rgba(255, 255, 255, 0.2);
    border-radius: 4px;
    color: #fff;
    font-size: 12px;
    padding: 1px 4px;
    text-align: center;
}
#impact-apply {
    background: rgba(74, 158, 255, 0.2);
    border: 1px solid rgba(74, 158, 255, 0.5);
    border-radius: 4px;
    color: #4a9eff;
    font-size: 10px;
    font-weight: 700;
    padding: 2px 7px;
    cursor: pointer;
}
#impact-apply:hover { background: rgba(74, 158, 255, 0.32); }
.impact-mode {
    padding: 0 12px 6px;
    font-size: calc(10px * var(--impact-scale, 1));
    color: #22c55e;
}
.impact-list {
    padding: 2px 8px 6px;
    overflow-y: auto;
    flex: 1 1 auto;
    min-height: 0;
    max-height: 46vh;   /* default cap; an explicit card height overrides via flex */
    scrollbar-width: thin;
    scrollbar-color: rgba(255, 170, 51, 0.4) transparent;
}
#impact-card[style*="height"] .impact-list { max-height: none; }
.impact-town {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 8px;
    margin: 4px 0;
    padding: 7px 10px;
    background: rgba(255, 255, 255, 0.05);
    border-left: 3px solid #ffaa33;
    border-radius: 6px;
}
.impact-town-name {
    font-family: var(--font-display);
    font-size: calc(15px * var(--impact-scale, 1));
    font-weight: 700;
    color: #ffffff;
}
.impact-town-dist {
    display: block;
    font-size: calc(11px * var(--impact-scale, 1));
    font-weight: 500;
    color: rgba(255, 255, 255, 0.55);
}
.impact-town-eta {
    font-family: var(--font-display);
    font-size: calc(16px * var(--impact-scale, 1));
    font-weight: 700;
    color: #ffaa33;
    white-space: nowrap;
    text-align: right;
}
.eta-count { display: block; line-height: 1.1; }
.eta-clock {
    display: block;
    font-size: calc(10px * var(--impact-scale, 1));
    font-weight: 600;
    color: rgba(255, 255, 255, 0.55);
}
.eta-now {
    color: #ff4444;
    animation: flash 0.8s infinite;
}
.eta-passed { color: rgba(255, 255, 255, 0.35); }
.impact-loading {
    padding: 12px;
    font-size: 12px;
    color: rgba(255, 255, 255, 0.6);
    text-align: center;
}
.impact-foot {
    padding: 5px 12px 8px;
    font-size: 9px;
    color: rgba(255, 255, 255, 0.4);
    border-top: 1px solid rgba(255, 255, 255, 0.08);
}
#impact-hint {
    position: fixed;
    top: 70px;
    left: 50%;
    transform: translateX(-50%);
    z-index: 1400;
    padding: 6px 14px;
    background: rgba(13, 19, 34, 0.95);
    border: 1px solid rgba(255, 170, 51, 0.5);
    border-radius: 7px;
    font-family: var(--font-display);
    font-size: 13px;
    font-weight: 600;
    color: #ffffff;
}

/* ---- Draw palette (telestrator) ---- */
#draw-palette {
    display: none;
    position: absolute;
    top: 196px;
    right: 52px;
    z-index: 20;
    flex-direction: column;
    gap: 5px;
    padding: 8px;
    background: rgba(13, 19, 34, 0.95);
    border: 1px solid rgba(255, 255, 255, 0.18);
    border-radius: 9px;
    box-shadow: 0 6px 22px rgba(0, 0, 0, 0.55);
    backdrop-filter: blur(10px);
}
#draw-palette.open { display: flex; }

.draw-tool, .draw-action {
    width: 32px;
    height: 30px;
    display: flex;
    align-items: center;
    justify-content: center;
    background: rgba(255, 255, 255, 0.06);
    border: 1px solid rgba(255, 255, 255, 0.14);
    border-radius: 6px;
    color: rgba(255, 255, 255, 0.85);
    font-size: 14px;
    cursor: pointer;
}
.draw-tool:hover, .draw-action:hover { border-color: rgba(74, 158, 255, 0.6); }
.draw-tool.sel {
    background: rgba(74, 158, 255, 0.22);
    border-color: rgba(74, 158, 255, 0.8);
    color: #4a9eff;
}

.draw-sep { height: 1px; background: rgba(255, 255, 255, 0.12); margin: 2px 0; }

.draw-colors {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    gap: 4px;
}
.draw-color {
    width: 100%;
    height: 14px;
    border: 1px solid rgba(0, 0, 0, 0.5);
    border-radius: 3px;
    cursor: pointer;
    padding: 0;
}
.draw-color.sel { outline: 2px solid #ffffff; outline-offset: 1px; }

.draw-widths { display: flex; gap: 4px; }
.draw-width {
    flex: 1;
    height: 18px;
    display: flex;
    align-items: center;
    background: rgba(255, 255, 255, 0.06);
    border: 1px solid rgba(255, 255, 255, 0.14);
    border-radius: 4px;
    cursor: pointer;
    padding: 0 4px;
}
.draw-width i { display: block; width: 100%; background: #ffffff; border-radius: 2px; }
.draw-width.sel { border-color: rgba(74, 158, 255, 0.8); }

.draw-text-input {
    background: rgba(13, 19, 34, 0.95);
    border: 1px solid rgba(74, 158, 255, 0.6);
    border-radius: 5px;
    padding: 3px 8px;
    font-family: var(--font-display);
    font-size: 15px;
    font-weight: 600;
    outline: none;
    width: 130px;
}
.draw-text-label {
    font-family: var(--font-display);
    font-size: 17px;
    font-weight: 700;
    letter-spacing: 0.5px;
    white-space: nowrap;
    pointer-events: none;
}
#eta-btn.active {
    border-color: rgba(255, 140, 0, 0.8);
    box-shadow: 0 0 10px rgba(255, 140, 0, 0.35);
}

.measure-label {
    font-family: var(--font-display);
    font-size: 12px;
    font-weight: 700;
    letter-spacing: 0.5px;
    line-height: 1.25;
    color: #ffffff;
    background: rgba(13, 19, 34, 0.92);
    border: 1px solid rgba(74, 158, 255, 0.5);
    border-radius: 5px;
    padding: 2px 8px;
    white-space: nowrap;
    text-align: center;
    pointer-events: none;
    box-shadow: 0 2px 8px rgba(0, 0, 0, 0.5);
}
.measure-label-cursor {
    border-color: rgba(74, 158, 255, 0.9);
    background: rgba(20, 30, 54, 0.96);
}
.measure-label-vertex { font-size: 11px; opacity: 0.95; }
.measure-label-eta {
    border-color: rgba(255, 140, 0, 0.8);
    background: rgba(34, 22, 8, 0.95);
    font-size: 12px;
    line-height: 1.35;
}
.measure-label-eta b { color: #ffaa44; }

/* Autopilot header toggle: pulses while directing.
   Red = AUTO TOR (tornado only), orange = AUTO ALL (severe joins). */
#btn-autopilot.active {
    border-color: rgba(255, 60, 60, 0.7);
    color: #ff7777;
    box-shadow: 0 0 10px rgba(255, 60, 60, 0.3);
    animation: chip-pulse 2s infinite;
}
#btn-autopilot.active.mode-all {
    border-color: rgba(255, 140, 0, 0.75);
    color: #ffaa44;
    box-shadow: 0 0 10px rgba(255, 140, 0, 0.35);
}

/* ---- Map right-click context menu ---- */
#map-ctx-menu {
    position: fixed;
    z-index: 4000;
    min-width: 190px;
    padding: 5px;
    background: rgba(13, 19, 34, 0.97);
    border: 1px solid rgba(255, 255, 255, 0.18);
    border-radius: 10px;
    box-shadow: 0 14px 44px rgba(0, 0, 0, 0.7);
    backdrop-filter: blur(12px);
    display: flex;
    flex-direction: column;
    gap: 1px;
}
.ctx-coords {
    background: rgba(74, 158, 255, 0.1);
    border: 1px solid rgba(74, 158, 255, 0.3);
    border-radius: 6px;
    color: #9ec9ff;
    font-family: monospace;
    font-size: 12px;
    padding: 6px 10px;
    cursor: copy;
    text-align: left;
}
.ctx-coords:hover { background: rgba(74, 158, 255, 0.2); }
.ctx-item {
    display: flex;
    align-items: center;
    gap: 8px;
    background: none;
    border: none;
    border-radius: 6px;
    color: rgba(255, 255, 255, 0.88);
    font-family: var(--font-display);
    font-size: 14px;
    font-weight: 600;
    letter-spacing: 0.4px;
    padding: 7px 10px;
    cursor: pointer;
    text-align: left;
}
.ctx-item:hover { background: rgba(74, 158, 255, 0.15); color: #ffffff; }
.ctx-sep { height: 1px; background: rgba(255, 255, 255, 0.1); margin: 3px 4px; }

/* Saved locations (⭐ markers) */
.saved-loc {
    display: flex;
    align-items: center;
    gap: 4px;
    cursor: pointer;
    filter: drop-shadow(0 2px 4px rgba(0, 0, 0, 0.7));
}
.sloc-pin { font-size: 16px; }
.sloc-name {
    font-family: var(--font-display);
    font-size: 13px;
    font-weight: 700;
    letter-spacing: 0.4px;
    color: #ffd75e;
    text-shadow: 0 1px 3px rgba(0, 0, 0, 0.9);
    white-space: nowrap;
}
.sloc-del {
    display: none;
    background: rgba(255, 60, 60, 0.85);
    border: none;
    border-radius: 4px;
    color: #fff;
    font-size: 10px;
    width: 16px;
    height: 16px;
    line-height: 1;
    cursor: pointer;
    padding: 0;
}
.saved-loc.sloc-armed .sloc-del { display: inline-flex; align-items: center; justify-content: center; }

.sloc-input {
    background: rgba(13, 19, 34, 0.96);
    border: 1px solid rgba(255, 215, 94, 0.6);
    border-radius: 5px;
    padding: 3px 8px;
    font-family: var(--font-display);
    font-size: 14px;
    color: #ffd75e;
    outline: none;
    width: 140px;
}

/* NWS point-forecast popup */
.wx-popup { font-size: 12px; color: #eef2f8; min-width: 200px; }
.wx-place {
    font-family: var(--font-display);
    font-size: 16px;
    font-weight: 700;
    letter-spacing: 0.5px;
    margin-bottom: 4px;
}
.wx-now { display: flex; align-items: baseline; gap: 8px; }
.wx-temp { font-family: var(--font-display); font-size: 26px; font-weight: 700; color: #ffd75e; }
.wx-short { font-weight: 600; }
.wx-meta { color: rgba(255, 255, 255, 0.7); margin: 3px 0; }
.wx-detail { font-size: 11px; line-height: 1.45; color: rgba(255, 255, 255, 0.8); margin: 5px 0; }
.wx-next { font-size: 11px; color: rgba(255, 255, 255, 0.75); border-top: 1px solid rgba(255,255,255,0.1); padding-top: 5px; }
/* Multi-day outlook list under the current conditions — click a row to expand */
.wx-days { margin-top: 6px; border-top: 1px solid rgba(255,255,255,0.12); max-height: 240px; overflow-y: auto; }
.wx-day { border-bottom: 1px solid rgba(255,255,255,0.06); }
.wx-day:last-child { border-bottom: none; }
.wx-day-row { display: flex; align-items: baseline; gap: 8px; padding: 4px 2px; font-size: 11px; cursor: pointer; }
.wx-day-row:hover { background: rgba(255,255,255,0.06); }
.wx-day.wx-day-open .wx-day-row { background: rgba(120,170,255,0.12); }
.wx-day-name { flex: 0 0 auto; min-width: 52px; white-space: nowrap; font-weight: 700; color: #cfe0ff; }
.wx-day.wx-night .wx-day-name { color: #9fb0d0; font-weight: 600; }
.wx-day-short { flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; color: rgba(255,255,255,0.82); }
.wx-day-temp { flex: 0 0 auto; font-family: var(--font-display); font-weight: 700; color: #ffd75e; }
.wx-day.wx-night .wx-day-temp { color: #8fc9ff; }
.wx-day-full { display: none; font-size: 11px; line-height: 1.45; color: rgba(255,255,255,0.85); padding: 1px 4px 7px; }
.wx-day.wx-day-open .wx-day-full { display: block; }
.wx-src { font-size: 9px; color: rgba(255, 255, 255, 0.4); margin-top: 5px; }
.wx-loading { padding: 8px 4px; color: rgba(255, 255, 255, 0.7); }

/* Weather Here window opacity — slider in the popup footer drives --wx-op
   (set inline on the popup root by contextmenu.js, persisted). Only the
   background fades; the text stays crisp. */
.maplibregl-popup-content:has(.wx-popup) {
    background: rgba(16, 16, 32, var(--wx-op, 0.96)) !important;
}
.wx-op-row { display: flex; align-items: center; gap: 8px; margin-top: 5px; }
.wx-op-row .wx-src { margin-top: 0; white-space: nowrap; }
.wx-op {
    flex: 1;
    min-width: 60px;
    height: 3px;
    accent-color: var(--accent-blue);
    cursor: pointer;
}

/* Watch popup probability grid (SPC WWP data, 2x3) */
.watch-prob-grid {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    gap: 4px;
    margin: 4px 0 6px;
}
.watch-prob-cell {
    background: rgba(255, 255, 255, 0.05);
    border: 1px solid rgba(255, 255, 255, 0.1);
    border-radius: 4px;
    padding: 4px 2px;
    text-align: center;
}
.watch-prob-label {
    font-size: 8px;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.3px;
    color: rgba(255, 255, 255, 0.55);
    white-space: nowrap;
}
.watch-prob-val {
    font-family: var(--font-display);
    font-size: 15px;
    font-weight: 700;
    color: #ffffff;
    line-height: 1.1;
}

/* SPC panel close button */
.spc-panel-close {
    margin-left: auto;
    background: rgba(255, 255, 255, 0.06);
    border: 1px solid rgba(255, 255, 255, 0.15);
    border-radius: 5px;
    color: rgba(255, 255, 255, 0.65);
    font-size: 11px;
    width: 22px;
    height: 22px;
    line-height: 1;
    cursor: pointer;
    padding: 0;
}
.spc-panel-close:hover { color: #fff; border-color: rgba(255, 140, 0, 0.6); }

/* History panel ✕ — mirrors .spc-panel-close, blue accent to match the panel */
.history-panel-close {
    margin-left: auto;
    background: rgba(255, 255, 255, 0.06);
    border: 1px solid rgba(255, 255, 255, 0.15);
    border-radius: 5px;
    color: rgba(255, 255, 255, 0.65);
    font-size: 11px;
    width: 22px;
    height: 22px;
    line-height: 1;
    cursor: pointer;
    padding: 0;
    flex: none;
}
.history-panel-close:hover { color: #fff; border-color: var(--accent-blue); }

/* ===== Unified click popup (consolidates overlapping layers) ===== */
.uni-popup-shell .maplibregl-popup-content {
    background: #0d1420;
    border: 1px solid rgba(120, 160, 210, 0.28);
    border-radius: 10px;
    padding: 9px 11px;
    box-shadow: 0 10px 30px rgba(0, 0, 0, 0.6);
}
.uni-popup-shell .maplibregl-popup-tip { border-top-color: #0d1420; border-bottom-color: #0d1420; }
.uni-popup {
    font-size: 12px; color: #e6edf6;
    box-sizing: border-box;
    width: 330px;          /* default; user can drag-resize from the corner */
    min-width: 240px;
    max-width: 92vw;
    max-height: 86vh;      /* grows to fit content up to here, then scrolls */
    overflow: auto;
    resize: both;          /* drag the bottom-right grip to resize */
    /* The card is drag-to-move UI chrome, not copy-text. Native drag-select
       could start from the link/resize-corner exemptions and then never be
       cleared (both this card's mousedown and the map canvas preventDefault,
       which is what normally clears a selection) — the "stuck highlighted
       text" bug. No selection possible = nothing to get stuck. */
    -webkit-user-select: none;
    user-select: none;
}
.uni-head {
    font-weight: 700; font-size: 10px; text-transform: uppercase; letter-spacing: 0.7px;
    color: #9fb2c8; padding: 0 2px 7px; border-bottom: 1px solid rgba(255, 255, 255, 0.08); margin-bottom: 4px;
}
.uni-section { border-left: 3px solid #4a9eff; padding: 5px 0 5px 9px; margin: 5px 0; }
.uni-section + .uni-section { border-top: 1px solid rgba(255, 255, 255, 0.07); padding-top: 8px; }
.uni-sec-label {
    font-weight: 700; font-size: 10.5px; text-transform: uppercase; letter-spacing: 0.5px; margin-bottom: 3px;
}
.uni-sec-body { font-size: 11.5px; line-height: 1.45; color: #d4deea; }
.uni-row { display: flex; justify-content: space-between; gap: 12px; line-height: 1.5; }
.uni-k { color: #8da2b8; }
.uni-v { color: #e6edf6; font-weight: 600; text-align: right; }
.uni-item + .uni-item, .uni-item-div + .uni-item { margin-top: 4px; }
.uni-item-div { height: 1px; background: rgba(255, 255, 255, 0.07); margin: 5px 0; }
.uni-item-top { display: flex; align-items: center; gap: 4px; font-size: 12px; margin-bottom: 2px; }
.uni-line { padding: 2px 0; line-height: 1.4; }
.uni-sub { color: #8da2b8; font-size: 10.5px; }
.uni-tropical { overflow-wrap: anywhere; }
.uni-tropical .uni-k, .uni-tropical .uni-v { min-width: 0; }
.uni-tropical .uni-sub { margin-top: 4px; }
.uni-tropical-caution { color: #ffd37f; }
.uni-more { color: #8da2b8; font-size: 10px; }
.uni-status { font-size: 9px; font-weight: 800; padding: 1px 6px; border-radius: 3px; margin-left: 6px; letter-spacing: 0.4px; }
.uni-chip { display: inline-block; font-size: 9.5px; font-weight: 700; padding: 1px 5px; border: 1px solid; border-radius: 3px; letter-spacing: 0.3px; }
.uni-chiprow { display: flex; flex-wrap: wrap; gap: 4px; margin: 1px 0 4px; }
.uni-left { color: #7fd0ff; font-weight: 700; font-size: 10px; margin-left: 5px; white-space: nowrap; }
.uni-left-low { color: #ff6b6b; }
.uni-linkrow { margin-top: 4px; }
.uni-link { color: #6db3ff; text-decoration: none; font-size: 10.5px; }
.uni-link:hover { text-decoration: underline; }

/* Popup "time left" tag on the Expires row */
.popup-remaining {
    font-size: 10px;
    font-weight: 700;
    color: #22c55e;
    margin-left: 4px;
    white-space: nowrap;
}
.popup-remaining-low {
    color: #ff5c5c;
    animation: flash 1.2s infinite;
}

/* ---- NEXRAD color scale bar (below header, radar-product aware) ---- */
.radar-scalebar {
    position: fixed;
    top: 66px;
    left: 50%;
    transform: translateX(-50%);
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 5px 14px;
    background: rgba(10, 14, 23, 0.9);
    border: 1px solid rgba(255, 255, 255, 0.14);
    border-radius: 7px;
    backdrop-filter: blur(10px);
    box-shadow: 0 4px 16px rgba(0, 0, 0, 0.45);
    z-index: 90;
}

.scalebar-name {
    font-family: var(--font-display);
    font-size: 12px;
    font-weight: 700;
    letter-spacing: 1.2px;
    color: rgba(255, 255, 255, 0.85);
    white-space: nowrap;
}

.scalebar-body { display: flex; flex-direction: column; gap: 2px; }

.scalebar-ramp {
    width: min(420px, 52vw);
    height: 9px;
    border-radius: 3px;
    border: 1px solid rgba(255, 255, 255, 0.25);
}

.scalebar-ticks {
    display: flex;
    justify-content: space-between;
    width: min(420px, 52vw);
    font-family: var(--font-display);
    font-size: 10px;
    font-weight: 600;
    letter-spacing: 0.5px;
    color: rgba(255, 255, 255, 0.7);
    line-height: 1;
}

/* Push the toast stack down while the scale bar is up so they never overlap */
body.scalebar-active .toast-stack { top: 104px; }

/* ---- HRRR REFP precip-type key ----------------------------------------
   Sits in the same top-center slot the scale bar would occupy (REFP has no
   single dBZ axis, so it never shows the bar). Dark panel matches the scale
   bar; the legend image rides a white chip so any PNG background stays
   readable on the dark map. Non-interactive / click-through (OBS-friendly). */
.hrrr-refp-legend {
    position: fixed;
    top: 66px;
    left: 50%;
    transform: translateX(-50%);
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 4px 12px;
    background: rgba(10, 14, 23, 0.9);
    border: 1px solid rgba(255, 255, 255, 0.14);
    border-radius: 7px;
    backdrop-filter: blur(10px);
    box-shadow: 0 4px 16px rgba(0, 0, 0, 0.45);
    z-index: 90;
    pointer-events: none;
}
.hrrr-refp-legend-name {
    font-family: var(--font-display);
    font-size: 11px;
    font-weight: 700;
    letter-spacing: 1px;
    line-height: 1.05;
    text-align: center;
    color: rgba(255, 255, 255, 0.85);
    white-space: nowrap;
}
.hrrr-refp-legend-chip {
    background: #fff;
    border: 1px solid rgba(255, 255, 255, 0.25);
    border-radius: 4px;
    padding: 3px 5px;
    display: flex;
    align-items: center;
}
.hrrr-refp-legend-chip img {
    display: block;
    width: auto;
    height: auto;
    max-width: min(60vw, 600px);
    max-height: 60px;
}
/* Keep the toast stack clear of the key, same as the scale bar does */
body.hrrr-refp-legend-active .toast-stack { top: 104px; }
body.vertical-mode .hrrr-refp-legend { top: calc(var(--se-header-h, 73px) + 7px); }

/* Radar site-lock button (shown only in single-site product modes) */
#radar-site-lock {
    font-size: 10px;
    white-space: nowrap;
    flex-shrink: 0;
}
#radar-site-lock.active {
    border-color: rgba(255, 200, 60, 0.7);
    color: #ffd11a;
    box-shadow: 0 0 8px rgba(255, 200, 60, 0.25);
}
/* Detached (dragged-out) toasts: float free of the stack */
.toast-floating {
    box-shadow: 0 12px 38px rgba(0, 0, 0, 0.65), 0 0 0 1px rgba(74, 158, 255, 0.25);
}
.toast-dragging {
    opacity: 0.93;
    cursor: grabbing !important;
    transition: none !important;
}

/* Dragged map popups: content follows the mouse, anchor tip hides */
.popup-dragged .maplibregl-popup-tip { opacity: 0; }
.maplibregl-popup-content { transition: none; }

/* Report-type filter chips in the toast footer (🌪 🧊 💨) */
.toast-rfilters { display: inline-flex; gap: 3px; margin-left: 5px; vertical-align: middle; }
.toast-rfilter {
    width: 22px;
    height: 20px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    padding: 0;
    background: rgba(255, 255, 255, 0.04);
    border: 1px solid rgba(255, 255, 255, 0.1);
    border-radius: 4px;
    font-size: 11px;
    cursor: pointer;
    filter: grayscale(1);
    opacity: 0.4;
    transition: opacity 0.15s ease, filter 0.15s ease, border-color 0.15s ease;
}
.toast-rfilter.on {
    filter: none;
    opacity: 1;
    border-color: rgba(74, 158, 255, 0.45);
    background: rgba(74, 158, 255, 0.1);
}
.toast-rfilter:hover { opacity: 1; }

/* Flash-flood toast toggle chip — always present on the bar. Reuses the
   .toast-rfilter look; this wrapper just gives it the same breathing room as
   the report-filter group. Tinted aqua (not blue) when on so it reads as flood. */
.toast-floodwrap { display: inline-flex; margin-left: 5px; vertical-align: middle; }
.toast-floodtoggle.on {
    border-color: rgba(34, 211, 238, 0.5);
    background: rgba(34, 211, 238, 0.12);
}

.toast-footer {
    position: fixed;
    left: 50%;
    transform: translateX(-50%);
    width: calc(440px * var(--toast-scale, 1));
    max-width: 92vw;
    z-index: 1500;
    cursor: grab;
    display: flex;
    justify-content: space-between;
    align-items: center;
    gap: 8px;
    background: var(--bg-card);
    border: 1px solid var(--border-color);
    border-radius: 8px;
    padding: 5px 11px;
    backdrop-filter: blur(10px);
}
.toast-footer button {
    background: none;
    border: none;
    color: var(--accent-blue);
    cursor: pointer;
    font-size: 11px;
    font-weight: 600;
    padding: 2px 4px;
}
.toast-footer button:hover { text-decoration: underline; }
.toast-foot-right { display: flex; gap: 12px; align-items: center; }
.toast-replay { font-weight: 700 !important; }
.toast-noalerts { color: var(--text-muted); font-style: italic; }

/* ---- Floating brand logo panel (StormyEyes TorTrak2) ---- */
.brand-panel {
    position: fixed;
    left: 16px;
    top: 72px;
    width: 360px;
    z-index: 1400;
    cursor: grab;
    user-select: none;
    touch-action: none;
}
.brand-panel.dragging { cursor: grabbing; }
.brand-panel[hidden] { display: none; }
.brand-img {
    width: 100%;
    height: auto;
    display: block;
    pointer-events: none;
    -webkit-user-drag: none;
    filter: drop-shadow(0 6px 16px rgba(0, 0, 0, 0.55));
}
.brand-close {
    position: absolute;
    top: -9px; right: -9px;
    width: 22px; height: 22px;
    border-radius: 50%;
    background: rgba(20, 28, 48, 0.92);
    border: 1px solid var(--border-color);
    color: #fff;
    font-size: 14px;
    line-height: 1;
    cursor: pointer;
    opacity: 0;
    transition: opacity 0.2s;
}
.brand-panel:hover .brand-close { opacity: 1; }
.brand-close:hover { border-color: var(--accent-blue); }
.brand-resize {
    position: absolute;
    right: -3px; bottom: -3px;
    width: 18px; height: 18px;
    cursor: nwse-resize;
    opacity: 0;
    transition: opacity 0.2s;
    background: linear-gradient(135deg, transparent 45%, var(--accent-blue) 45%, var(--accent-blue) 70%, transparent 70%);
    border-radius: 0 0 4px 0;
}
.brand-panel:hover .brand-resize { opacity: 0.75; }
/* Bottom-edge grip: drags the logo's HEIGHT independent of width (deliberate
   aspect-ratio stretch). Right-click resets to the natural aspect ratio. */
.brand-resize-v {
    position: absolute;
    left: 50%; bottom: -3px;
    width: 28px; height: 10px;
    transform: translateX(-50%);
    cursor: ns-resize;
    opacity: 0;
    transition: opacity 0.2s;
    background: linear-gradient(to bottom, transparent 30%, var(--accent-blue) 30%, var(--accent-blue) 70%, transparent 70%);
    border-radius: 4px;
}
.brand-panel:hover .brand-resize-v { opacity: 0.75; }
/* Only once a custom height is set (brandpanel.js toggles the class): the image
   fills the stretched panel. Without the class, height:auto still governs. */
.brand-panel.brand-stretched .brand-img { height: 100%; }
.control-btn .brand-btn-icon { font-size: 14px; line-height: 1; }

/* ---- Detailed (rich) toast cards ---- */
/* Base .toast is a flex row (slim layout). Rich cards are block so their
   content fills the full card width instead of hugging the left. */
.toast.toast-rich { display: block; }
.rtoast {
    position: relative;
    z-index: 1;
    padding: calc(12px * var(--toast-scale, 1)) calc(14px * var(--toast-scale, 1));
    display: flex;
    flex-direction: column;
    gap: calc(8px * var(--toast-scale, 1));
}
.rtoast-head { display: flex; align-items: center; gap: calc(8px * var(--toast-scale, 1)); }
.rtoast-icon { font-size: calc(22px * var(--toast-scale, 1)); line-height: 1; }
.rtoast-title {
    flex: 1;
    min-width: 0;
    font-size: calc(18px * var(--toast-scale, 1));
    font-weight: 800;
    letter-spacing: 0.5px;
    color: #fff;
    text-shadow: 0 1px 4px rgba(0, 0, 0, 0.6);
    text-transform: uppercase;
    white-space: normal;
    line-height: 1.12;
}
.rtoast-sub {
    font-size: calc(11px * var(--toast-scale, 1));
    font-weight: 700;
    letter-spacing: 0.6px;
    color: #fff;
    opacity: 0.82;
    text-transform: uppercase;
    text-shadow: 0 1px 2px rgba(0, 0, 0, 0.5);
    margin-top: calc(-4px * var(--toast-scale, 1));
}
.rtoast-panel, .rtoast-cell {
    background: rgba(0, 0, 0, 0.26);
    border-radius: calc(8px * var(--toast-scale, 1));
    padding: calc(7px * var(--toast-scale, 1)) calc(11px * var(--toast-scale, 1));
    text-align: center;
    min-width: 0;
}
.rtoast-plabel, .rtoast-clabel {
    font-size: calc(9px * var(--toast-scale, 1));
    font-weight: 700;
    letter-spacing: 1px;
    text-transform: uppercase;
    color: rgba(255, 255, 255, 0.66);
    overflow-wrap: break-word;
}
.rtoast-pval, .rtoast-cval { overflow-wrap: break-word; }
.rtoast-pval, .rtoast-cval {
    font-size: calc(14px * var(--toast-scale, 1));
    font-weight: 700;
    color: #fff;
    margin-top: 2px;
    text-shadow: 0 1px 2px rgba(0, 0, 0, 0.5);
}
.rtoast-cval { font-size: calc(15px * var(--toast-scale, 1)); }
.rtoast-details { font-weight: 600; font-size: calc(13px * var(--toast-scale, 1)); line-height: 1.3; white-space: normal; }
/* Counties + states stacked and centered so nothing runs off the right edge. */
.rtoast-prow { display: flex; flex-direction: column; align-items: center; gap: 1px; margin-top: 2px; text-align: center; }
.rtoast-prow > span { font-weight: 700; color: #fff; max-width: 100%; white-space: normal; overflow-wrap: break-word; }
.rtoast-prow > span:first-child { font-size: calc(13px * var(--toast-scale, 1)); }
.rtoast-pright { color: rgba(255, 255, 255, 0.8); font-size: calc(11px * var(--toast-scale, 1)); }
.rtoast-upper { text-transform: uppercase; }
.rtoast-grid { display: grid; grid-template-columns: 1fr 1fr; gap: calc(8px * var(--toast-scale, 1)); }
.rtoast-grid .rtoast-cell:only-child { grid-column: 1 / -1; }
.rtoast-probgrid { display: grid; grid-template-columns: 1fr 1fr 1fr; gap: calc(7px * var(--toast-scale, 1)); }
.rtoast .toast-close { line-height: 1; align-self: flex-start; }

/* Display popover toggle row */
.display-toggle-row {
    display: flex;
    align-items: center;
    justify-content: space-between;
    font-size: 12px;
    color: var(--text-secondary);
}
.display-toggle-row input[type="checkbox"] { width: 16px; height: 16px; accent-color: var(--accent-blue); cursor: pointer; }
.control-btn .toast-toggle-icon { font-size: 14px; line-height: 1; }
.control-btn .display-btn-icon { font-size: 14px; line-height: 1; }
.control-btn.toast-muted { opacity: 0.55; }

/* ============================================
   HEADER DROPDOWN MENUS (Layers / More)
   ============================================ */
.header-menu {
    position: fixed;
    z-index: 1600;   /* above the toast stack + Replay/Reports footer (1500) —
                        an open menu is direct user interaction and wins */
    min-width: 220px;
    background: rgba(10, 15, 28, 0.97);
    border: 1px solid var(--border-glow);
    border-radius: 10px;
    padding: 6px;
    display: none;
    flex-direction: column;
    gap: 2px;
    backdrop-filter: blur(12px);
    box-shadow: 0 8px 32px rgba(0,0,0,0.6), 0 0 12px rgba(74,158,255,0.08);
    /* Never taller than the viewport — scroll on short screens (laptops).
       JS sets the exact max-height at open time; this is the fallback. */
    max-height: calc(100vh - 70px);
    overflow-y: auto;
    overscroll-behavior: contain;
}
.header-menu.visible { display: flex; }

.header-menu::-webkit-scrollbar { width: 6px; }
.header-menu::-webkit-scrollbar-track { background: transparent; }
.header-menu::-webkit-scrollbar-thumb {
    background: rgba(74, 158, 255, 0.45);
    border-radius: 3px;
}
.header-menu::-webkit-scrollbar-thumb:hover { background: rgba(74, 158, 255, 0.7); }

.header-menu-title {
    font-size: 10px;
    font-weight: 700;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    color: var(--text-secondary);
    opacity: 0.7;
    padding: 6px 10px 4px;
}

/* Menu rows reuse .control-btn so existing active states & badges work,
   restyled as full-width list items. */
.header-menu .control-btn {
    width: 100%;
    justify-content: flex-start;
    background: transparent;
    border: 1px solid transparent;
    border-radius: 7px;
    padding: 8px 10px;
    position: relative;
}
.header-menu .control-btn:hover {
    background: var(--bg-card-hover);
}
.header-menu .control-btn.active {
    background: var(--accent-blue-glow);
    border-color: var(--accent-blue);
    box-shadow: none;
}
.header-menu .menu-item-sub {
    margin-left: auto;
    font-size: 10px;
    opacity: 0.5;
}

/* Layers trigger button */
.menu-caret { font-size: 9px; opacity: 0.6; }
#btn-layers.menu-open .menu-caret,
#btn-more.menu-open { color: var(--text-primary); }
#btn-layers.has-layers {
    border-color: var(--accent-blue);
    color: var(--accent-blue);
}
.layers-count {
    background: var(--accent-blue);
    color: #fff;
    font-size: 10px;
    font-weight: 700;
    line-height: 1;
    padding: 2px 5px;
    border-radius: 8px;
    min-width: 10px;
    text-align: center;
}

/* More button: icon-only, keep it compact */
.more-btn { padding: 6px 8px; }

/* ============================================
   THREAT-REACTIVE AMBIENCE
   data-threat on <body> is set by js/ambience.js from the worst
   active warning: watch → svr → tor → emergency.
   ============================================ */
#ambience-vignette {
    position: fixed;
    inset: 0;
    pointer-events: none;
    z-index: 1100;             /* above map & panels, below menus/toasts */
    opacity: 0;
    transition: opacity 1.5s ease, box-shadow 1.5s ease;
}
body[data-threat] #ambience-vignette { opacity: 1; }

body[data-threat="watch"]     #ambience-vignette { box-shadow: inset 0 0 110px rgba(255, 200, 60, 0.10); }
body[data-threat="svr"]       #ambience-vignette { box-shadow: inset 0 0 140px rgba(255, 140, 0, 0.16); }
body[data-threat="tor"]       #ambience-vignette {
    box-shadow: inset 0 0 170px rgba(255, 45, 45, 0.22);
    animation: ambient-pulse 2.6s ease-in-out infinite;
}
body[data-threat="emergency"] #ambience-vignette {
    box-shadow: inset 0 0 210px rgba(255, 0, 140, 0.30);
    animation: ambient-pulse 1.5s ease-in-out infinite;
}

@keyframes ambient-pulse {
    0%, 100% { opacity: 0.55; }
    50%      { opacity: 1; }
}

/* Header accent follows the threat level */
.header { transition: border-color 1.2s ease, box-shadow 1.2s ease; }

body[data-threat="watch"] .header {
    border-bottom-color: rgba(255, 200, 60, 0.45);
    box-shadow: 0 2px 20px rgba(0,0,0,0.3), 0 1px 0 rgba(255, 200, 60, 0.35);
}
body[data-threat="svr"] .header {
    border-bottom-color: rgba(255, 140, 0, 0.55);
    box-shadow: 0 2px 24px rgba(255, 140, 0, 0.12), 0 1px 0 rgba(255, 140, 0, 0.45);
}
body[data-threat="tor"] .header {
    border-bottom-color: rgba(255, 45, 45, 0.65);
    box-shadow: 0 2px 28px rgba(255, 45, 45, 0.18), 0 1px 0 rgba(255, 45, 45, 0.55);
}
body[data-threat="emergency"] .header {
    border-bottom-color: rgba(255, 0, 140, 0.7);
    box-shadow: 0 2px 32px rgba(255, 0, 140, 0.22), 0 1px 0 rgba(255, 0, 140, 0.6);
}

/* Active-warning count in the status bar takes the threat color */
#warning-count { transition: color 1.2s ease; }
body[data-threat="svr"]       #warning-count { color: #ffaa44; font-weight: 700; }
body[data-threat="tor"]       #warning-count { color: #ff5555; font-weight: 700; }
body[data-threat="emergency"] #warning-count { color: #ff4dac; font-weight: 700; }

/* One-shot edge flash for newly-arrived tornado warnings */
#ambience-flash {
    position: fixed;
    inset: 0;
    pointer-events: none;
    z-index: 1101;
    opacity: 0;
}
#ambience-flash[data-level="tor"] {
    box-shadow: inset 0 0 240px rgba(255, 45, 45, 0.5);
}
#ambience-flash[data-level="emergency"] {
    box-shadow: inset 0 0 280px rgba(255, 0, 140, 0.55);
}
#ambience-flash.flashing {
    animation: ambient-flash 1.8s ease-out;
}

/* Three quick beats, then fade — punchy but over fast */
@keyframes ambient-flash {
    0%   { opacity: 0; }
    8%   { opacity: 1; }
    22%  { opacity: 0.25; }
    34%  { opacity: 1; }
    48%  { opacity: 0.2; }
    62%  { opacity: 0.85; }
    100% { opacity: 0; }
}

/* Respect users who opt out of motion */
@media (prefers-reduced-motion: reduce) {
    body[data-threat] #ambience-vignette { animation: none !important; }
    #ambience-flash.flashing { animation: none !important; }
}

/* ---- Display settings popover (toast + particle sliders) ---- */
.display-popover {
    position: fixed;
    top: 0; left: 0;
    z-index: 4000;
    width: 280px;
    max-width: 92vw;
    background: var(--bg-card);
    border: 1px solid var(--border-color);
    border-radius: var(--radius-lg);
    box-shadow: var(--shadow);
    backdrop-filter: blur(10px);
    padding: 14px 16px;
    /* Small-screen fix (2026-07-04): the popover had no height bound, so on
       short laptop displays the bottom rows — demo-kit buttons + Reset —
       ran off-screen unreachably. display.js sets max-height to the space
       below the settings button; this makes the overflow scroll inside. */
    overflow-y: auto;
    overscroll-behavior: contain;
    scrollbar-width: thin;
}
.display-popover[hidden] { display: none; }
.display-pop-close {
    position: absolute; top: 8px; right: 8px;
    width: 22px; height: 22px; padding: 0;
    display: flex; align-items: center; justify-content: center;
    background: rgba(255, 255, 255, 0.06); border: 1px solid rgba(255, 255, 255, 0.18);
    border-radius: 5px; color: #cdd6e4; font-size: 13px; line-height: 1; cursor: pointer;
}
.display-pop-close:hover { background: rgba(255, 90, 90, 0.30); border-color: #ff6b6b; color: #fff; }
.display-pop-title {
    font-size: 11px;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 1px;
    color: var(--text-muted);
    margin: 0 0 4px;
}
.display-row { margin-top: 12px; }
.display-row-head {
    display: flex;
    justify-content: space-between;
    align-items: baseline;
    font-size: 12px;
    color: var(--text-secondary);
    margin-bottom: 5px;
}
.display-row-val { color: var(--accent-cyan); font-weight: 600; font-variant-numeric: tabular-nums; }
.display-row input[type="range"] { width: 100%; accent-color: var(--accent-blue); cursor: pointer; }
.display-pop-reset {
    margin-top: 14px;
    width: 100%;
    background: none;
    border: 1px solid var(--border-color);
    border-radius: var(--radius);
    color: var(--text-secondary);
    font-size: 12px;
    font-weight: 600;
    padding: 6px;
    cursor: pointer;
}
.display-pop-reset:hover { color: var(--text-primary); border-color: var(--border-glow); }
.display-pop-test {
    margin-top: 14px;
    width: 100%;
    background: var(--accent-blue-glow);
    border: 1px solid var(--accent-blue);
    border-radius: var(--radius);
    color: var(--text-primary);
    font-size: 12px;
    font-weight: 700;
    padding: 7px;
    cursor: pointer;
}
.display-pop-test:hover { background: rgba(74, 158, 255, 0.35); }

/* ---- Header multi-timezone clock ---- */
.header-clock {
    position: relative;
    display: inline-flex;
    align-items: center;
    flex-wrap: nowrap;
    flex-shrink: 0;
    white-space: nowrap;
    gap: 5px;
    cursor: pointer;
    user-select: none;
    font-variant-numeric: tabular-nums;
}
.header-clock .clk-time,
.header-clock .clk-label { white-space: nowrap; }
.header-clock .clk-label { color: var(--text-muted); font-weight: 600; }
.header-clock .clk-time  { color: var(--text-primary); font-weight: 600; }
.header-clock .clk-utc   { color: var(--text-secondary); }
.header-clock .clock-sep { color: var(--text-muted); }
.header-clock .clk-caret {
    color: var(--text-muted);
    font-size: 9px;
    transition: transform 0.2s ease;
}
.header-clock[aria-expanded="true"] .clk-caret { transform: rotate(180deg); }
.header-clock:hover .clk-time { color: var(--accent-cyan); }

.clock-dropdown {
    position: fixed;          /* lifted to <body> by clock.js; coords set there */
    top: 0;
    left: 0;
    background: var(--bg-card);
    border: 1px solid var(--border-color);
    border-radius: var(--radius-lg);
    padding: 6px;
    min-width: 175px;
    z-index: 4000;            /* above the map and panels */
    box-shadow: var(--shadow);
    backdrop-filter: blur(8px);
}
.clock-dropdown[hidden] { display: none; }
.clock-row {
    display: flex;
    justify-content: space-between;
    gap: 18px;
    padding: 5px 9px;
    font-size: 12px;
    border-radius: 4px;
}
.clock-row .clock-z   { color: var(--text-muted); }
.clock-row .clk-time  { color: var(--text-primary); font-weight: 600; }
.clock-row-utc {
    border-top: 1px solid var(--border-color);
    margin-top: 3px;
    padding-top: 7px;
}
.clock-row-utc .clk-time { color: var(--accent-cyan); }

.header-right {
    display: flex;
    align-items: center;
    gap: 8px;
}

.control-btn {
    display: flex;
    align-items: center;
    gap: 6px;
    padding: 6px 12px;
    background: var(--bg-card);
    border: 1px solid var(--border-color);
    border-radius: var(--radius);
    color: var(--text-secondary);
    font-size: 12px;
    cursor: pointer;
    transition: all var(--transition);
    white-space: nowrap;
}

.control-btn:hover {
    background: var(--bg-card-hover);
    color: var(--text-primary);
}

.control-btn.active {
    background: var(--accent-blue-glow);
    border-color: var(--accent-blue);
    color: var(--accent-blue);
    box-shadow: 0 0 10px rgba(74, 158, 255, 0.15);
}

/* ============================================
   MAIN LAYOUT
   ============================================ */
.main-content {
    display: flex;
    height: calc(100vh - 60px);
    /* Use a pixel floor instead of locking to the viewport so that on short
       browser windows (laptops, tabs/bookmarks bar, taskbar) the body can
       overflow and the page scrolls. On tall windows height wins and it still
       fits the screen exactly, same as before. */
    min-height: 640px;
}

.map-container {
    flex: 1;
    position: relative;
}

#map {
    width: 100%;
    height: 100%;
}

/* ============================================
   MAP LEGEND
   ============================================ */
.map-legend {
    position: absolute;
    bottom: 40px;
    left: 16px;
    padding: 10px 14px;
    background: rgba(17, 24, 39, 0.92);
    backdrop-filter: blur(12px);
    border: 1px solid var(--border-color);
    border-radius: var(--radius);
    z-index: 10;
}

.legend-title {
    font-size: 11px;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 1px;
    color: var(--text-muted);
    margin-bottom: 8px;
}

.legend-item {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 3px 0;
    font-size: 12px;
    color: var(--text-secondary);
}

.legend-color {
    width: 14px;
    height: 14px;
    border-radius: 3px;
    border: 1px solid rgba(255, 255, 255, 0.1);
}

/* ============================================
   WARNINGS PANEL
   ============================================ */
.warnings-panel {
    width: 420px;
    background: linear-gradient(180deg, rgba(26, 26, 46, 0.95) 0%, rgba(17, 17, 34, 0.98) 100%);
    border-left: 1px solid var(--border-color);
    display: flex;
    flex-direction: column;
    overflow: hidden;
    position: relative; /* Anchor for absolute children (toggle button, resize grip) */
    container: warning-panel / size;
}

/* Keep the filters and floating-panel controls outside the content scroller.
   The list retains a useful minimum when hail or summary content grows. */
.warnings-panel > .panel-header { flex-shrink: 0; }
.warnings-panel .panel-tabs { flex-wrap: wrap; }
.warnings-panel-body {
    display: flex;
    flex-direction: column;
    flex: 1;
    min-height: 0;
    overflow-y: auto;
    scrollbar-width: thin;
    scrollbar-color: var(--border-color) transparent;
}
.warnings-panel-body > .panel-summary,
.warnings-panel-body > .se-brand-bar { flex-shrink: 0; }
.warnings-panel-body > .panel-content { min-height: 144px; }

/* A short docked sheet or resized floating panel uses one content scroller.
   Cards and hail remain reachable instead of competing for a zero-height
   nested warning list. Larger panels keep the independent warning list. */
@container warning-panel (max-height: 420px) {
    .warnings-panel-body { display: block; }
    .warnings-panel-body > .panel-content {
        min-height: 0;
        overflow: visible;
    }
    .warnings-panel-body .hail-report-list {
        max-height: none;
        overflow: visible;
    }
}

/* Compact the chrome before it can consume a short sheet's content area. */
@container warning-panel (max-height: 240px) {
    .warnings-panel > .panel-header { padding: 6px 46px 6px 10px; }
    .warnings-panel > .panel-header h2 {
        font-size: 14px;
        margin-bottom: 6px;
        padding-bottom: 0;
    }
    .warnings-panel > .panel-header h2::after { display: none; }
    .warnings-panel .tab-btn { padding: 4px 6px; font-size: 11px; }
    .warnings-panel .panel-float-toggle { top: 6px; right: 10px; }
}
@container warning-panel (max-height: 160px) {
    /* Keep the heading available to assistive technology while the filter
       row becomes the visible header in the smallest bottom sheets. */
    .warnings-panel > .panel-header h2 {
        position: absolute;
        width: 1px;
        height: 1px;
        margin: 0;
        padding: 0;
        overflow: hidden;
        clip-path: inset(50%);
        white-space: nowrap;
    }
}

/* ----- Floating mode ----- */
.warnings-panel.floating {
    position: fixed !important;
    z-index: 150;
    border: 1px solid var(--border-color);
    border-left: 1px solid var(--border-color);
    border-radius: var(--radius-lg);
    box-shadow:
        0 16px 50px rgba(0, 0, 0, 0.65),
        0 0 0 1px rgba(74, 158, 255, 0.18),
        0 0 22px rgba(74, 158, 255, 0.12);
    backdrop-filter: blur(10px);
    min-width: 260px;
    min-height: 200px;
    /* Narrow-screen bottom-sheet limits belong to the docked panel only. */
    max-height: none;
    /* width / height / left / top are set inline by PanelFloatManager */
}

.warnings-panel.floating .panel-header {
    cursor: move;
    user-select: none;
}
/* Buttons inside the header should still get the pointer cursor — they're
   click targets, not drag handles. */
.warnings-panel.floating .panel-header button {
    cursor: pointer;
}

/* Dragging / resizing — give the whole document a consistent cursor and
   block accidental text selection while the user is moving the panel. */
body.panel-dragging  { cursor: move        !important; user-select: none; }
body.panel-resizing  { cursor: nwse-resize !important; user-select: none; }
body.panel-dragging *, body.panel-resizing * { user-select: none !important; }

/* ----- Float toggle button (lives in panel-header, top-right) ----- */
.panel-float-toggle {
    position: absolute;
    top: 12px;
    right: 14px;
    width: 26px;
    height: 26px;
    padding: 0;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    background: transparent;
    border: 1px solid var(--border-color);
    border-radius: 5px;
    color: var(--text-secondary);
    cursor: pointer;
    transition: all 0.18s ease;
    z-index: 2;
}
.panel-float-toggle:hover {
    background: rgba(74, 158, 255, 0.15);
    color: #4a9eff;
    border-color: rgba(74, 158, 255, 0.5);
}
.panel-float-toggle.is-floating {
    background: rgba(74, 158, 255, 0.22);
    color: #4a9eff;
    border-color: rgba(74, 158, 255, 0.55);
}

/* ----- Corner resize grip (only visible when floating) ----- */
.panel-resize-grip {
    display: none;
    position: absolute;
    right: 2px;
    bottom: 2px;
    width: 18px;
    height: 18px;
    cursor: nwse-resize;
    color: var(--text-muted);
    opacity: 0.55;
    align-items: flex-end;
    justify-content: flex-end;
    z-index: 2;
    pointer-events: auto;
}
.warnings-panel.floating .panel-resize-grip {
    display: flex;
}
.panel-resize-grip:hover {
    opacity: 1;
    color: #4a9eff;
}

.panel-header {
    padding: 16px 20px;
    border-bottom: 1px solid var(--border-color);
    padding-right: 50px; /* leave room for the float-toggle button */
}

.panel-tabs {
    display: flex;
    gap: 4px;
}

/* ---- At-a-glance summary bar ---- */
.panel-summary {
    display: flex;
    flex-wrap: wrap;
    gap: 6px;
    padding: 8px 20px;
    border-bottom: 1px solid var(--border-color);
}

.psum-chip {
    display: inline-flex;
    align-items: center;
    gap: 5px;
    background: var(--bg-card);
    border: 1px solid var(--border-color);
    border-radius: 6px;
    padding: 3px 8px;
    font-size: 11px;
    color: var(--text-secondary);
    white-space: nowrap;
}

.psum-ico { font-size: 11px; line-height: 1; }
.psum-num { font-weight: 700; font-size: 13px; }
.psum-label { color: var(--text-muted); }

.psum-tornado      .psum-num { color: #ff5252; }
.psum-severe       .psum-num { color: #ff8c00; }
.psum-considerable .psum-num { color: #ffd11a; }
.psum-destructive  .psum-num { color: #ff2d2d; }
.psum-flashflood   .psum-num { color: #22c55e; }
.psum-flashflood-considerable .psum-num { color: #ffb020; }  /* considerable flood — amber */
.psum-flashflood-emergency    .psum-num { color: #ff4de0; }  /* flash flood emergency — magenta */
.psum-pds          .psum-num { color: #d77dff; }

/* Tornado Emergency chip — highest tier, only shown when active. Pulses
   magenta to demand attention on stream. */
.psum-te {
    background: rgba(255, 0, 204, 0.18);
    border-color: rgba(255, 0, 204, 0.85);
    color: #ffd6f4;
    padding: 4px 11px;   /* a touch larger than the other chips */
    font-size: 12px;
    animation: psum-te-pulse 1s ease-in-out infinite;
}
.psum-te .psum-num { color: #ff5ccc; font-size: 15px; }
.psum-te .psum-ico { font-size: 13px; animation: te-icon-pulse 0.8s ease-in-out infinite alternate; }
.psum-te .psum-label {
    color: #ffd6f4;
    font-weight: 700;
    letter-spacing: 0.5px;
}

@keyframes psum-te-pulse {
    0%, 100% { box-shadow: 0 0 6px rgba(255, 0, 204, 0.4);  border-color: rgba(255, 0, 204, 0.7); }
    50%      { box-shadow: 0 0 16px rgba(255, 0, 204, 0.9); border-color: rgba(255, 0, 204, 1); }
}

/* When a Tornado Emergency is active, the whole panel header glows magenta. */
.warnings-panel.te-active .panel-header {
    animation: te-header-pulse 1.1s ease-in-out infinite;
}
@keyframes te-header-pulse {
    0%, 100% { box-shadow: inset 0 0 0 rgba(255, 0, 204, 0);    border-bottom-color: var(--border-color); }
    50%      { box-shadow: inset 0 2px 22px rgba(255, 0, 204, 0.38); border-bottom-color: rgba(255, 0, 204, 0.85); }
}

/* PDS chip — watch-level "big one" flag, only shown when active */
.psum-pds {
    background: rgba(186, 85, 255, 0.14);
    border-color: rgba(186, 85, 255, 0.7);
    color: #e3c3ff;
    box-shadow: 0 0 8px rgba(186, 85, 255, 0.35);
}
.psum-pds .psum-label { color: #e3c3ff; font-weight: 600; }

/* Non-zero damage tiers get a subtle accent border so they pop */
.psum-considerable:not(.psum-zero) { border-color: rgba(255,209,26,0.5); }
.psum-destructive:not(.psum-zero)  { border-color: rgba(255,45,45,0.6); }
.psum-flashflood:not(.psum-zero)              { border-color: rgba(34,197,94,0.5); }
.psum-flashflood-considerable:not(.psum-zero) { border-color: rgba(255,176,32,0.6); }
.psum-flashflood-emergency:not(.psum-zero)    { border-color: rgba(255,77,224,0.75); box-shadow: 0 0 10px rgba(255,77,224,0.35); }

.psum-zero { opacity: 0.38; }

/* "N alerts unreadable" — audit C9. Deliberately NOT one of the hazard colors:
   this is not a weather severity, it is a statement that the numbers next to it
   are incomplete. Slate/amber so it reads as an instrument fault, and it is
   exempt from .psum-zero because it is only ever rendered when non-zero. */
.psum-unreadable {
    background: rgba(255, 176, 32, 0.12);
    border-color: rgba(255, 176, 32, 0.65);
    color: #ffdca8;
}
.psum-unreadable .psum-num   { color: #ffb020; }
.psum-unreadable .psum-label { color: #ffdca8; font-weight: 600; }

.tab-btn {
    padding: 6px 14px;
    background: transparent;
    border: 1px solid var(--border-color);
    border-radius: var(--radius);
    color: var(--text-secondary);
    font-size: 12px;
    cursor: pointer;
    transition: all var(--transition);
}

.tab-btn:hover {
    background: var(--bg-card);
}

.tab-btn.active {
    background: var(--accent-blue);
    border-color: var(--accent-blue);
    color: white;
}

.panel-content {
    flex: 1;
    overflow-y: auto;
    padding: 12px;
}

.panel-content::-webkit-scrollbar {
    width: 6px;
}

.panel-content::-webkit-scrollbar-track {
    background: transparent;
}

.panel-content::-webkit-scrollbar-thumb {
    background: var(--border-color);
    border-radius: 3px;
}

/* ============================================
   WARNING CARDS
   ============================================ */
.warning-card {
    padding: 14px 16px;
    background: var(--bg-card);
    border: 1px solid var(--border-color);
    border-radius: var(--radius);
    margin-bottom: 8px;
    cursor: pointer;
    transition: all var(--transition);
    position: relative;
    overflow: hidden;
}

.warning-card::before {
    content: '';
    position: absolute;
    left: 0;
    top: 0;
    bottom: 0;
    width: 4px;
}

.warning-card.tornado::before { background: var(--tornado-color); }
.warning-card.severe::before { background: var(--severe-color); }
.warning-card.watch::before { background: var(--watch-color); }
.warning-card.tornado-watch::before { background: var(--tornado-watch-color); }
.warning-card.severe-watch::before { background: var(--severe-watch-color); }
.warning-card.flash-flood::before { background: var(--flood-color); }
.warning-card.flash-flood-emergency::before { background: var(--flood-emergency-color); }
.warning-card.special::before { background: var(--special-color); }
.warning-card.cancelled::before { background: var(--cancelled-color); }

.warning-card:hover {
    background: var(--bg-card-hover);
    border-color: var(--border-glow);
    transform: translateY(-1px);
    box-shadow: 0 4px 16px rgba(0, 0, 0, 0.3);
}

.warning-card.cancelled {
    opacity: 0.6;
}

/* ============================================
   WARNING PANEL SECTIONS (categorized groups)
   ============================================ */
.warning-section {
    margin-bottom: 18px;
}

.warning-section-header {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 6px 2px 8px;
    margin-bottom: 8px;
    border-bottom: 1px solid var(--border-color);
    position: sticky;
    top: 0;
    background: var(--bg-secondary);
    z-index: 4;
    cursor: pointer;
    user-select: none;
    transition: background var(--transition);
}

.warning-section-header:hover {
    background: var(--bg-card-hover);
}

.warning-section-header:focus-visible {
    outline: 2px solid var(--border-glow);
    outline-offset: -2px;
}

/* Chevron rotates to point right when collapsed */
.warning-section-chevron {
    font-size: 10px;
    line-height: 1;
    color: var(--text-muted);
    transition: transform var(--transition);
    transform: rotate(0deg);
}

.warning-section.collapsed .warning-section-chevron {
    transform: rotate(-90deg);
}

/* Push the count chip to the far right (header is now flex-start) */
.warning-section-count {
    margin-left: auto;
}

/* Collapsed: hide the cards. Card margins collapse cleanly with display:none. */
.warning-section.collapsed .warning-section-cards {
    display: none;
}

.warning-section.collapsed {
    margin-bottom: 8px;
}

.warning-section-title {
    font-size: 12px;
    font-weight: 700;
    letter-spacing: 0.6px;
    text-transform: uppercase;
    color: var(--text-secondary);
}

.warning-section-count {
    min-width: 20px;
    padding: 1px 8px;
    font-size: 11px;
    font-weight: 700;
    text-align: center;
    border-radius: 10px;
    color: var(--text-secondary);
    background: var(--bg-card);
    border: 1px solid var(--border-color);
}

/* Per-section accent — title + count tinted to match the warning color bar */
.warning-section--tornado-warning .warning-section-title { color: var(--tornado-color); }
.warning-section--severe-warning  .warning-section-title { color: var(--severe-color); }
.warning-section--tornado-watch   .warning-section-title { color: var(--tornado-watch-color); }
.warning-section--severe-watch    .warning-section-title { color: var(--severe-watch-color); }
.warning-section--special         .warning-section-title { color: var(--special-color); }

.warning-section--tornado-warning .warning-section-count { color: var(--tornado-color); border-color: var(--tornado-color); }
.warning-section--severe-warning  .warning-section-count { color: var(--severe-color);  border-color: var(--severe-color); }
.warning-section--tornado-watch   .warning-section-count { color: var(--tornado-watch-color);   border-color: var(--tornado-watch-color); }
.warning-section--severe-watch    .warning-section-count { color: var(--severe-watch-color);   border-color: var(--severe-watch-color); }
.warning-section--special         .warning-section-count { color: var(--special-color); border-color: var(--special-color); }

.card-top {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    margin-bottom: 8px;
}

.card-type {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    font-size: 12px;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.5px;
}

.card-type.tornado { color: var(--tornado-color); }
.card-type.severe { color: var(--severe-color); }
.card-type.watch { color: var(--watch-color); }
.card-type.tornado-watch { color: var(--tornado-watch-color); }
.card-type.severe-watch { color: var(--severe-watch-color); }
.card-type.flash-flood { color: var(--flood-color); }
.card-type.flash-flood-emergency { color: var(--flood-emergency-color); }
.card-type.special { color: var(--special-color); }

.card-status {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    padding: 2px 8px;
    border-radius: 20px;
    font-size: 10px;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.5px;
}

.card-status.active {
    background: rgba(239, 68, 68, 0.15);
    color: var(--accent-red);
    border: 1px solid rgba(239, 68, 68, 0.3);
}

.card-status.cancelled {
    background: rgba(107, 114, 128, 0.15);
    color: var(--cancelled-color);
    border: 1px solid rgba(107, 114, 128, 0.3);
}

.card-status.expired {
    background: rgba(107, 114, 128, 0.15);
    color: var(--cancelled-color);
    border: 1px solid rgba(107, 114, 128, 0.3);
}

.card-location {
    font-size: 14px;
    font-weight: 600;
    color: var(--text-primary);
    margin-bottom: 6px;
    line-height: 1.3;
}

.card-details {
    display: flex;
    flex-wrap: wrap;
    gap: 12px;
    font-size: 11px;
    color: var(--text-secondary);
}

.card-detail {
    display: flex;
    align-items: center;
    gap: 4px;
}

.card-detail svg {
    width: 12px;
    height: 12px;
    opacity: 0.7;
}

.card-meta {
    display: flex;
    align-items: center;
    justify-content: space-between;
    margin-top: 10px;
    padding-top: 10px;
    border-top: 1px solid var(--border-color);
    font-size: 11px;
    color: var(--text-muted);
}

/* Red "Issued June 5 at 5:42PM CDT" on warning cards */
.card-issued {
    color: var(--accent-red);
    font-weight: 600;
}

/* Muted live "· 3 min ago" after the issued time */
.card-age {
    color: var(--text-muted);
    font-weight: 400;
}

/* Live countdown chip — updated every second by _tickCountdowns.
   Three urgency states (normal / warn / urgent) plus expired. */
.warning-countdown {
    display: inline-block;
    margin-left: 6px;
    padding: 1px 6px;
    border-radius: 4px;
    font-size: 10px;
    font-weight: 700;
    letter-spacing: 0.2px;
    /* Tabular numerals keep digit width fixed so the chip doesn't jitter */
    font-variant-numeric: tabular-nums;
    background: rgba(34, 197, 94, 0.15);
    border: 1px solid rgba(34, 197, 94, 0.35);
    color: #4ade80;
    vertical-align: 1px;
}
.warning-countdown.countdown-warn {
    background: rgba(255, 204, 0, 0.15);
    border-color: rgba(255, 204, 0, 0.45);
    color: #ffcc00;
}
.warning-countdown.countdown-urgent {
    background: rgba(255, 51, 51, 0.18);
    border-color: rgba(255, 51, 51, 0.55);
    color: #ff6b6b;
    animation: countdownUrgentPulse 1.4s ease-in-out infinite;
}
.warning-countdown.countdown-expired {
    background: rgba(107, 114, 128, 0.18);
    border-color: rgba(107, 114, 128, 0.4);
    color: #9ca3af;
}
@keyframes countdownUrgentPulse {
    0%, 100% { box-shadow: 0 0 0 0   rgba(255, 51, 51, 0.45); }
    50%      { box-shadow: 0 0 0 4px rgba(255, 51, 51, 0);    }
}

.card-storm-motion {
    display: flex;
    align-items: center;
    gap: 6px;
}

.motion-arrow {
    display: inline-block;
    transition: transform 0.3s;
}

/* ============================================
   TORNADO CONFIRMED BADGE
   ============================================ */
.tornado-radar-tag {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    padding: 2px 8px;
    background: rgba(74, 158, 255, 0.12);
    border: 1px solid rgba(74, 158, 255, 0.3);
    border-radius: 4px;
    font-size: 10px;
    font-weight: 700;
    color: var(--accent-blue);
    text-transform: uppercase;
    letter-spacing: 0.5px;
}

.tornado-possible-tag {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    padding: 2px 8px;
    background: rgba(255, 51, 51, 0.15);
    border: 1px solid rgba(255, 51, 51, 0.5);
    border-radius: 4px;
    font-size: 10px;
    font-weight: 800;
    color: #ff5555;
    text-transform: uppercase;
    letter-spacing: 0.3px;
    margin-left: 4px;
}

.tornado-confirmed {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    padding: 2px 8px;
    background: rgba(239, 68, 68, 0.2);
    border: 1px solid rgba(239, 68, 68, 0.4);
    border-radius: 4px;
    font-size: 10px;
    font-weight: 700;
    color: var(--accent-red);
    text-transform: uppercase;
    letter-spacing: 0.5px;
    animation: flash 1.5s infinite;
}

@keyframes flash {
    0%, 100% { opacity: 1; }
    50% { opacity: 0.6; }
}

/* ============================================
   LOADING / EMPTY STATES
   ============================================ */
.loading-state {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    padding: 60px 20px;
    color: var(--text-muted);
}

.spinner {
    width: 32px;
    height: 32px;
    border: 3px solid var(--border-color);
    border-top-color: var(--accent-blue);
    border-radius: 50%;
    animation: spin 0.8s linear infinite;
    margin-bottom: 12px;
}

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

.empty-state {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    padding: 60px 20px;
    text-align: center;
}

.empty-state svg {
    width: 48px;
    height: 48px;
    color: var(--text-muted);
    margin-bottom: 16px;
    opacity: 0.5;
}

.empty-state h3 {
    font-size: 15px;
    font-weight: 600;
    color: var(--text-secondary);
    margin-bottom: 6px;
}

.empty-state p {
    font-size: 13px;
    color: var(--text-muted);
}

/* ============================================
   MODAL
   ============================================ */
.modal-overlay {
    display: none;
    position: fixed;
    inset: 0;
    background: rgba(0, 0, 0, 0.7);
    backdrop-filter: blur(4px);
    z-index: 1000;
    align-items: center;
    justify-content: center;
}

.modal-overlay.active {
    display: flex;
}

.modal {
    width: 90%;
    max-width: 600px;
    max-height: 80vh;
    background: var(--bg-secondary);
    border: 1px solid var(--border-color);
    border-radius: var(--radius-lg);
    overflow-y: auto;
    position: relative;
    box-shadow: var(--shadow);
}

.modal-close {
    position: absolute;
    top: 12px;
    right: 12px;
    width: 32px;
    height: 32px;
    display: flex;
    align-items: center;
    justify-content: center;
    background: var(--bg-card);
    border: 1px solid var(--border-color);
    border-radius: 50%;
    color: var(--text-secondary);
    font-size: 18px;
    cursor: pointer;
    z-index: 1;
    transition: all var(--transition);
}

.modal-close:hover {
    background: var(--accent-red);
    color: white;
    border-color: var(--accent-red);
}

.modal-body {
    padding: 24px;
}

.modal-body h2 {
    font-size: 18px;
    margin-bottom: 4px;
}

.modal-body .modal-subtitle {
    font-size: 13px;
    color: var(--text-secondary);
    margin-bottom: 20px;
}

.modal-section {
    margin-bottom: 16px;
}

.modal-section h3 {
    font-size: 12px;
    text-transform: uppercase;
    letter-spacing: 1px;
    color: var(--text-muted);
    margin-bottom: 8px;
}

.modal-section p {
    font-size: 13px;
    line-height: 1.6;
    color: var(--text-secondary);
}

/* Impacted-towns count + overflow hint */
.towns-count {
    color: var(--text-muted);
    font-weight: 600;
    font-size: 0.85em;
}
.towns-more {
    color: var(--text-muted);
    font-style: italic;
    font-size: 0.92em;
}

.modal-grid {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 12px;
}

.modal-stat {
    padding: 12px;
    background: var(--bg-card);
    border-radius: var(--radius);
    border: 1px solid var(--border-color);
}

.modal-stat label {
    display: block;
    font-size: 10px;
    text-transform: uppercase;
    letter-spacing: 0.5px;
    color: var(--text-muted);
    margin-bottom: 4px;
}

.modal-stat span {
    font-size: 14px;
    font-weight: 600;
    color: var(--text-primary);
}

/* ============================================
   RESPONSIVE
   ============================================ */
@media (max-width: 1024px) {
    .warnings-panel {
        width: 340px;
    }
}

@media (max-width: 768px) {
    html, body {
        height: 100%;
        overflow: hidden;
    }
    body {
        display: flex;
        flex-direction: column;
    }

    .header {
        flex-direction: column;
        height: auto;
        max-height: none;
        overflow: visible;
        flex-shrink: 0;
        padding: 10px 16px;
        gap: 8px;
    }

    .header-left {
        flex-direction: column;
        gap: 6px;
    }

    /* Flex-fill the region below the header (see ≤680px block for the
       body flex setup; this keeps 681–768px consistent). */
    .main-content {
        flex-direction: column;
        flex: 1;
        min-height: 0;
    }

    .map-container {
        flex: 1;
        min-height: 0;
    }

    .warnings-panel {
        width: 100%;
        height: 45%;
        flex-shrink: 0;
        border-left: none;
        border-top: 1px solid var(--border-color);
    }

}

/* ============================================
   MAPLIBRE OVERRIDES
   ============================================ */
.maplibregl-popup-content {
    background: rgba(16, 16, 32, 0.96) !important;
    color: var(--text-primary) !important;
    border: 1px solid var(--border-glow) !important;
    border-radius: var(--radius-lg) !important;
    padding: 0 !important;
    font-family: inherit !important;
    box-shadow: 0 8px 32px rgba(0, 0, 0, 0.6), 0 0 12px rgba(74, 158, 255, 0.1) !important;
    overflow: hidden;
    min-width: 260px;
}

.maplibregl-popup-tip {
    border-top-color: rgba(16, 16, 32, 0.96) !important;
}

.maplibregl-popup-close-button {
    color: var(--text-secondary) !important;
    font-size: 20px !important;
    right: 6px !important;
    top: 4px !important;
    z-index: 2;
}

.maplibregl-popup-close-button:hover {
    color: var(--text-primary) !important;
}

.maplibregl-ctrl-group {
    background: var(--bg-card) !important;
    border: 1px solid var(--border-color) !important;
}

.maplibregl-ctrl-group button {
    background-color: transparent !important;
}

.maplibregl-ctrl-group button + button {
    border-top-color: var(--border-color) !important;
}

.maplibregl-ctrl-group button span {
    filter: invert(0.8);
}

/* Enhanced popup card styles */
.popup-card-header {
    padding: 10px 14px;
    display: flex;
    align-items: center;
    gap: 8px;
    border-bottom: 1px solid rgba(255,255,255,0.08);
}

.popup-card-header .popup-type-icon {
    width: 28px;
    height: 28px;
    border-radius: 6px;
    display: flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
    font-size: 14px;
}

.popup-card-header .popup-event-name {
    font-size: 13px;
    font-weight: 700;
    line-height: 1.2;
}

.popup-card-header .popup-status {
    font-size: 10px;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.5px;
    padding: 2px 6px;
    border-radius: 3px;
    margin-left: auto;
    flex-shrink: 0;
}

.popup-card-body {
    padding: 10px 14px;
}

.popup-card-row {
    display: flex;
    justify-content: space-between;
    align-items: baseline;
    padding: 3px 0;
    font-size: 11px;
    color: var(--text-secondary);
}

.popup-card-row .popup-label {
    color: var(--text-muted);
    flex-shrink: 0;
    margin-right: 8px;
}

.popup-card-row .popup-value {
    text-align: right;
    color: var(--text-primary);
    font-weight: 500;
}

.popup-card-footer {
    padding: 6px 14px 10px;
    font-size: 10px;
    color: var(--text-muted);
    border-top: 1px solid rgba(255,255,255,0.05);
}

/* Stacked warnings popup — shown when multiple polygons overlap at the click point */
.popup-stack-badge {
    padding: 7px 14px;
    font-size: 10px;
    font-weight: 700;
    color: #ffcc00;
    background: linear-gradient(90deg, rgba(255, 204, 0, 0.18), rgba(255, 204, 0, 0.06));
    border-bottom: 1px solid rgba(255, 204, 0, 0.35);
    text-align: center;
    letter-spacing: 0.5px;
    text-transform: uppercase;
}

.popup-stack-scroll {
    max-height: 440px;
    overflow-y: auto;
    /* Slim scrollbar so it doesn't overwhelm the small popup */
    scrollbar-width: thin;
    scrollbar-color: rgba(255,255,255,0.2) transparent;
}
.popup-stack-scroll::-webkit-scrollbar {
    width: 6px;
}
.popup-stack-scroll::-webkit-scrollbar-thumb {
    background: rgba(255,255,255,0.18);
    border-radius: 3px;
}
.popup-stack-scroll::-webkit-scrollbar-thumb:hover {
    background: rgba(255,255,255,0.3);
}

.popup-stack-divider {
    height: 1px;
    background: linear-gradient(90deg, transparent, rgba(255,255,255,0.18), transparent);
    margin: 0;
}

/* Legacy popup classes (fallback) */
.popup-title {
    font-size: 13px;
    font-weight: 700;
    margin-bottom: 6px;
    padding: 10px 14px 0;
}

.popup-detail {
    font-size: 12px;
    color: var(--text-secondary);
    line-height: 1.5;
    padding: 6px 14px 10px;
}

/* ============================================
   STORMY EYES BRANDING EXTRAS
   ============================================ */
.se-brand-bar {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 8px;
    padding: 8px 16px;
    background: linear-gradient(90deg, rgba(74, 158, 255, 0.08) 0%, rgba(26, 26, 46, 0.5) 50%, rgba(74, 158, 255, 0.08) 100%);
    border-top: 1px solid var(--border-color);
    font-size: 10px;
    color: var(--text-muted);
    letter-spacing: 0.5px;
    overflow: hidden;
    flex-shrink: 0;
}

.se-brand-bar a {
    color: var(--accent-blue);
    text-decoration: none;
    font-weight: 600;
}

.se-brand-bar a:hover {
    text-decoration: underline;
}

.se-brand-bar img {
    width: 16px;
    height: 16px;
    min-width: 16px;
    max-width: 16px;
    min-height: 16px;
    max-height: 16px;
    border-radius: 3px;
    object-fit: cover;
    display: block;
    flex-shrink: 0;
}

/* Header glow accent line */
.header::after {
    content: '';
    position: absolute;
    bottom: -1px;
    left: 0;
    right: 0;
    height: 1px;
    background: linear-gradient(90deg, transparent 0%, var(--accent-blue) 50%, transparent 100%);
    opacity: 0.4;
}

/* Panel header branded underline */
.panel-header h2 {
    font-size: 15px;
    font-weight: 600;
    margin-bottom: 12px;
    position: relative;
    padding-bottom: 8px;
}

.panel-header h2::after {
    content: '';
    position: absolute;
    bottom: 0;
    left: 0;
    width: 40px;
    height: 2px;
    background: var(--accent-blue);
    border-radius: 1px;
}

/* ============================================
   HISTORY PANEL
   ============================================ */
.history-panel {
    position: fixed;
    top: 120px;
    right: 60px;
    width: 280px;
    padding: 14px 16px;
    background: rgba(17, 17, 34, 0.94);
    backdrop-filter: blur(14px);
    border: 1px solid var(--border-color);
    border-radius: var(--radius-lg);
    z-index: 1100;
    box-shadow: var(--shadow);
    cursor: grab;
    user-select: none;
}
.history-panel.dragging { cursor: grabbing; }

.history-panel-title {
    display: flex;
    align-items: center;
    gap: 6px;
    font-size: 12px;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.8px;
    color: var(--accent-blue);
    margin-bottom: 10px;
    padding-bottom: 8px;
    border-bottom: 1px solid var(--border-color);
}

/* Mode tabs (Recent / Archive) */
.history-mode-tabs {
    display: flex;
    gap: 4px;
    margin-bottom: 10px;
}

.history-mode-btn {
    flex: 1;
    padding: 6px 10px;
    background: transparent;
    border: 1px solid var(--border-color);
    border-radius: var(--radius);
    color: var(--text-secondary);
    font-size: 11px;
    font-weight: 600;
    cursor: pointer;
    transition: all var(--transition);
    text-align: center;
}

.history-mode-btn:hover {
    background: var(--bg-card);
}

.history-mode-btn.active {
    background: var(--accent-blue);
    border-color: var(--accent-blue);
    color: white;
}

/* Quick time buttons */
.history-field-label {
    font-size: 10px;
    text-transform: uppercase;
    letter-spacing: 0.5px;
    color: var(--text-muted);
    font-weight: 600;
    margin-bottom: 4px;
}

.time-quick-btns {
    display: flex;
    gap: 4px;
    flex-wrap: wrap;
}

.time-btn {
    padding: 5px 10px;
    background: rgba(15, 15, 30, 0.8);
    border: 1px solid var(--border-color);
    border-radius: var(--radius);
    color: var(--text-secondary);
    font-size: 11px;
    font-weight: 600;
    cursor: pointer;
    transition: all var(--transition);
    flex: 1;
    text-align: center;
    min-width: 36px;
}

.time-btn:hover {
    background: var(--bg-card-hover);
    border-color: var(--border-glow);
}

.time-btn.active {
    background: var(--accent-blue-glow);
    border-color: var(--accent-blue);
    color: var(--accent-blue);
    box-shadow: 0 0 8px rgba(74, 158, 255, 0.15);
}

/* Checkbox labels */
.check-label {
    display: flex;
    align-items: center;
    gap: 6px;
    font-size: 11px;
    color: var(--text-secondary);
    cursor: pointer;
    padding: 2px 0;
}

.check-label input[type="checkbox"] {
    accent-color: var(--accent-blue);
    width: 14px;
    height: 14px;
    cursor: pointer;
}

.history-mode-content {
    /* content area for each mode */
}

.spinner-sm {
    width: 14px;
    height: 14px;
    border: 2px solid var(--border-color);
    border-top-color: var(--accent-blue);
    border-radius: 50%;
    animation: spin 0.8s linear infinite;
    margin-left: auto;
}

.history-row {
    display: flex;
    gap: 8px;
    margin-bottom: 8px;
}

.history-field {
    flex: 1;
    display: flex;
    flex-direction: column;
    gap: 3px;
}

.history-field label {
    font-size: 10px;
    text-transform: uppercase;
    letter-spacing: 0.5px;
    color: var(--text-muted);
    font-weight: 600;
}

.history-field input,
.history-field select {
    width: 100%;
    padding: 6px 8px;
    background: rgba(15, 15, 30, 0.8);
    border: 1px solid var(--border-color);
    border-radius: var(--radius);
    color: var(--text-primary);
    font-size: 12px;
    font-family: inherit;
    outline: none;
    transition: border-color var(--transition);
}

.history-field input:focus,
.history-field select:focus {
    border-color: var(--accent-blue);
    box-shadow: 0 0 8px rgba(74, 158, 255, 0.15);
}

.history-field select option {
    background: #111122;
    color: var(--text-primary);
}

.history-apply-btn {
    width: 100%;
    padding: 8px;
    margin-top: 4px;
    background: var(--accent-blue);
    border: none;
    border-radius: var(--radius);
    color: white;
    font-size: 12px;
    font-weight: 600;
    letter-spacing: 0.5px;
    cursor: pointer;
    transition: all var(--transition);
}

.history-apply-btn:hover {
    background: #5aadff;
    box-shadow: 0 0 16px rgba(74, 158, 255, 0.3);
}

.history-apply-btn:disabled {
    background: var(--text-muted);
    cursor: not-allowed;
    box-shadow: none;
}

.history-stats {
    margin-top: 10px;
    padding-top: 8px;
    border-top: 1px solid var(--border-color);
    font-size: 11px;
    color: var(--text-secondary);
    line-height: 1.5;
}

/* ============================================
   RECENT WARNINGS LIST (history panel)
   ============================================ */
.recent-warnings-list-wrap {
    margin-top: 10px;
    padding-top: 8px;
    border-top: 1px solid var(--border-color);
}

.recent-list-title {
    font-size: 10px;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.6px;
    color: var(--text-muted);
    margin-bottom: 6px;
}

.recent-warnings-list {
    max-height: 260px;
    overflow-y: auto;
    display: flex;
    flex-direction: column;
    gap: 6px;
    padding-right: 2px;
}

.recent-warnings-list::-webkit-scrollbar {
    width: 6px;
}
.recent-warnings-list::-webkit-scrollbar-thumb {
    background: var(--border-color);
    border-radius: 3px;
}

.recent-list-empty {
    font-size: 11px;
    color: var(--text-muted);
    padding: 8px 4px;
    text-align: center;
}

.recent-row {
    padding: 7px 9px;
    background: rgba(255, 255, 255, 0.03);
    border: 1px solid var(--border-color);
    border-left-width: 3px;
    border-radius: 6px;
    cursor: pointer;
    transition: background var(--transition), border-color var(--transition), transform var(--transition);
}

.recent-row:hover {
    background: rgba(255, 255, 255, 0.06);
    transform: translateX(1px);
}

.recent-row.tornado {
    border-left-color: #ff3333;
}

.recent-row.severe {
    border-left-color: #ff8c00;
}

.recent-row.cancelled,
.recent-row.expired {
    opacity: 0.65;
}

/* Rows for warnings whose polygon isn't loaded (e.g. cancel-only in window). */
.recent-row.no-geom {
    cursor: default;
    opacity: 0.5;
}

.recent-row.no-geom:hover {
    background: rgba(255, 255, 255, 0.03);
    transform: none;
}

.recent-row-nopoly {
    display: inline-block;
    padding: 0 4px;
    margin-left: 4px;
    background: rgba(107, 114, 128, 0.22);
    color: #9ca3af;
    border-radius: 3px;
    font-size: 9px;
    font-weight: 700;
    letter-spacing: 0.3px;
    text-transform: uppercase;
}

/* ============================================
   STACKED-WARNING POPUP (multiple overlapping)
   ============================================ */
.stack-popup-header {
    padding: 10px 14px;
    font-size: 11px;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.6px;
    color: var(--accent-blue);
    border-bottom: 1px solid var(--border-color);
    background: rgba(74, 158, 255, 0.08);
}

.stack-popup-list {
    max-height: 340px;
    overflow-y: auto;
}

.stack-popup-list::-webkit-scrollbar {
    width: 6px;
}
.stack-popup-list::-webkit-scrollbar-thumb {
    background: var(--border-color);
    border-radius: 3px;
}

.stack-popup-card {
    padding: 8px 12px;
    border-left: 3px solid transparent;
    border-bottom: 1px solid rgba(255, 255, 255, 0.05);
    cursor: pointer;
    transition: background var(--transition);
}

.stack-popup-card:last-child {
    border-bottom: none;
}

.stack-popup-card:hover {
    background: rgba(255, 255, 255, 0.04);
}

.stack-popup-top {
    display: flex;
    align-items: center;
    gap: 6px;
    margin-bottom: 3px;
}

.stack-popup-icon {
    font-size: 12px;
    line-height: 1;
}

.stack-popup-event {
    flex: 1;
    font-size: 12px;
    font-weight: 700;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.stack-popup-status {
    font-size: 9px;
    font-weight: 700;
    padding: 1px 5px;
    border-radius: 3px;
    letter-spacing: 0.4px;
}

.stack-popup-area {
    font-size: 11px;
    color: var(--text-secondary);
    margin-bottom: 3px;
    line-height: 1.3;
}

.stack-popup-times {
    display: flex;
    justify-content: space-between;
    gap: 6px;
    font-size: 10px;
    color: var(--text-muted);
    font-variant-numeric: tabular-nums;
}

.recent-row-top {
    display: flex;
    align-items: center;
    gap: 6px;
    margin-bottom: 3px;
}

.recent-row-icon {
    font-size: 12px;
    line-height: 1;
}

.recent-row-event {
    flex: 1;
    font-size: 11px;
    font-weight: 700;
    color: var(--text-primary);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.recent-row-status {
    font-size: 9px;
    font-weight: 700;
    padding: 1px 5px;
    border-radius: 3px;
    letter-spacing: 0.4px;
}

.recent-row-status.active {
    background: rgba(34, 197, 94, 0.18);
    color: #4ade80;
}

.recent-row-status.cancelled {
    background: rgba(107, 114, 128, 0.22);
    color: #9ca3af;
}

.recent-row-status.expired {
    background: rgba(249, 115, 22, 0.18);
    color: #fb923c;
}

.recent-row-area {
    font-size: 11px;
    color: var(--text-secondary);
    line-height: 1.3;
    margin-bottom: 3px;
}

.recent-row-more {
    display: inline-block;
    padding: 0 4px;
    margin-left: 2px;
    background: var(--border-color);
    border-radius: 3px;
    font-size: 9px;
    color: var(--text-muted);
}

.recent-row-times {
    display: flex;
    justify-content: space-between;
    gap: 6px;
    font-size: 10px;
    color: var(--text-muted);
    font-variant-numeric: tabular-nums;
}

.history-ef-legend {
    display: flex;
    gap: 4px;
    margin-top: 8px;
    flex-wrap: wrap;
}

.ef-chip {
    padding: 2px 6px;
    border-radius: 3px;
    font-size: 9px;
    font-weight: 700;
    color: #fff;
    letter-spacing: 0.3px;
}

/* ============================================
   STATE STATS TABLE
   ============================================ */
.history-summary {
    margin-bottom: 6px;
}

.state-stats-toggle {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 5px 0;
    font-size: 11px;
    font-weight: 600;
    color: var(--accent-blue);
    cursor: pointer;
    user-select: none;
    transition: color var(--transition);
}

.state-stats-toggle:hover {
    color: #5aadff;
}

.toggle-arrow {
    font-size: 9px;
}

.state-stats-table {
    margin-top: 4px;
    max-height: 200px;
    overflow-y: auto;
}

.state-stats-table::-webkit-scrollbar {
    width: 4px;
}

.state-stats-table::-webkit-scrollbar-thumb {
    background: var(--border-color);
    border-radius: 2px;
}

.state-row {
    display: flex;
    align-items: center;
    padding: 3px 0;
    font-size: 11px;
    color: var(--text-secondary);
    border-bottom: 1px solid rgba(74, 158, 255, 0.06);
}

.state-row.state-header {
    font-size: 9px;
    text-transform: uppercase;
    letter-spacing: 0.5px;
    color: var(--text-muted);
    font-weight: 600;
    border-bottom: 1px solid var(--border-color);
    padding-bottom: 4px;
    margin-bottom: 2px;
}

.state-row.top-state {
    color: var(--accent-blue);
    font-weight: 600;
}

.state-name {
    flex: 1;
}

.state-val {
    width: 48px;
    text-align: right;
    font-variant-numeric: tabular-nums;
}

.state-val.has-ef4 {
    color: var(--accent-red);
    font-weight: 600;
}

.state-val.has-fat {
    color: var(--accent-orange);
    font-weight: 600;
}

.state-row-more {
    padding: 4px 0;
    font-size: 10px;
    color: var(--text-muted);
    font-style: italic;
}

/* ============================================
   DETAIL SECTION (BELOW MAP)
   ============================================ */
.detail-section {
    background: linear-gradient(180deg, var(--bg-primary) 0%, rgba(12, 12, 24, 1) 100%);
    border-top: 1px solid var(--border-color);
    padding: 0 24px 32px;
    min-height: 200px;
}

.detail-section-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 20px 0 16px;
    border-bottom: 1px solid var(--border-color);
    margin-bottom: 20px;
    position: sticky;
    top: 0;
    background: var(--bg-primary);
    z-index: 5;
}

.detail-section-title {
    display: flex;
    align-items: center;
    gap: 10px;
}

.detail-tornado-icon {
    font-size: 20px;
}

.detail-section-title h2 {
    font-size: 17px;
    font-weight: 700;
    letter-spacing: 0.3px;
    color: var(--tornado-color);
}

.detail-count {
    font-size: 12px;
    font-weight: 500;
    color: var(--text-muted);
    padding: 3px 10px;
    background: var(--bg-card);
    border: 1px solid var(--border-color);
    border-radius: 20px;
}

.detail-section-tabs {
    display: flex;
    gap: 4px;
}

.detail-tab {
    padding: 6px 14px;
    background: transparent;
    border: 1px solid var(--border-color);
    border-radius: var(--radius);
    color: var(--text-secondary);
    font-size: 12px;
    cursor: pointer;
    transition: all var(--transition);
}

.detail-tab:hover {
    background: var(--bg-card);
}

.detail-tab.active {
    background: var(--accent-blue);
    border-color: var(--accent-blue);
    color: white;
}

.detail-cards-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(420px, 1fr));
    gap: 16px;
}

.detail-loading {
    grid-column: 1 / -1;
    display: flex;
    flex-direction: column;
    align-items: center;
    padding: 40px;
    color: var(--text-muted);
}

.detail-empty {
    grid-column: 1 / -1;
    text-align: center;
    padding: 40px;
    color: var(--text-muted);
}

.detail-empty svg {
    width: 40px;
    height: 40px;
    margin-bottom: 12px;
    opacity: 0.4;
}

.detail-empty h3 {
    font-size: 15px;
    color: var(--text-secondary);
    margin-bottom: 4px;
}

.detail-empty p {
    font-size: 12px;
}

/* Individual detail tile */
.detail-tile {
    background: var(--bg-card);
    border: 1px solid var(--border-color);
    border-radius: var(--radius-lg);
    overflow: hidden;
    transition: all var(--transition);
    position: relative;
}

.detail-tile:hover {
    border-color: var(--border-glow);
    box-shadow: 0 4px 20px rgba(0, 0, 0, 0.3), var(--shadow-blue);
    transform: translateY(-2px);
}

.detail-tile.cancelled {
    opacity: 0.65;
}

/* Tile header */
.detail-tile-header {
    padding: 12px 16px 10px;
    position: relative;
}

.detail-tile-header.tornado {
    background: linear-gradient(135deg, rgba(255, 51, 51, 0.12) 0%, rgba(255, 51, 51, 0.03) 100%);
    border-bottom: 2px solid var(--tornado-color);
}

.detail-tile-top-row {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 10px;
}

.detail-tile-location {
    font-size: 15px;
    font-weight: 700;
    color: var(--text-primary);
    line-height: 1.2;
}

.detail-tile-source {
    display: flex;
    align-items: center;
    gap: 10px;
    margin-top: 6px;
    flex-wrap: wrap;
}

.detail-confirmed-tag {
    display: inline-flex;
    align-items: center;
    padding: 2px 8px;
    background: rgba(239, 68, 68, 0.2);
    border: 1px solid rgba(239, 68, 68, 0.4);
    border-radius: 4px;
    font-size: 10px;
    font-weight: 700;
    color: var(--accent-red);
    text-transform: uppercase;
    letter-spacing: 0.5px;
    animation: flash 1.5s infinite;
}

.detail-radar-tag {
    display: inline-flex;
    align-items: center;
    padding: 2px 8px;
    background: rgba(74, 158, 255, 0.12);
    border: 1px solid rgba(74, 158, 255, 0.3);
    border-radius: 4px;
    font-size: 10px;
    font-weight: 600;
    color: var(--accent-blue);
    text-transform: uppercase;
    letter-spacing: 0.3px;
}

.detail-motion {
    font-size: 11px;
    color: var(--text-secondary);
}

.detail-tile-status {
    display: inline-flex;
    align-items: center;
    gap: 5px;
    padding: 4px 10px;
    border-radius: 20px;
    font-size: 11px;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.5px;
    flex-shrink: 0;
}

.detail-tile-status.active {
    background: rgba(239, 68, 68, 0.15);
    color: var(--accent-red);
    border: 1px solid rgba(239, 68, 68, 0.3);
}

.detail-tile-status.cancelled {
    background: rgba(107, 114, 128, 0.15);
    color: var(--cancelled-color);
    border: 1px solid rgba(107, 114, 128, 0.3);
}

.detail-tile-status .status-dot-sm {
    width: 6px;
    height: 6px;
    border-radius: 50%;
    animation: pulse 2s infinite;
}

.detail-tile-status.active .status-dot-sm {
    background: var(--accent-red);
}

.detail-tile-status.cancelled .status-dot-sm {
    background: var(--cancelled-color);
    animation: none;
}

/* Tile body */
.detail-tile-body {
    padding: 12px 16px;
}

.detail-tile-times {
    display: flex;
    align-items: center;
    gap: 0;
}

.detail-time-block {
    flex: 1;
    text-align: center;
}

.detail-time-label {
    display: block;
    font-size: 10px;
    text-transform: uppercase;
    letter-spacing: 0.5px;
    color: var(--text-muted);
    margin-bottom: 2px;
}

.detail-time-value {
    font-size: 13px;
    font-weight: 600;
    color: var(--text-primary);
}

.detail-time-divider {
    width: 1px;
    height: 28px;
    background: var(--border-color);
    margin: 0 8px;
    flex-shrink: 0;
}

.detail-tile-counties {
    margin-top: 10px;
    font-size: 12px;
    color: var(--text-secondary);
    line-height: 1.5;
}

.detail-tile-cities {
    margin-top: 6px;
    font-size: 12px;
    color: var(--text-primary);
    line-height: 1.5;
}

.detail-tile-cities-label {
    font-weight: 700;
    color: var(--text-secondary);
    margin-right: 4px;
}

/* "+N more" town toggle on Active Warnings cards */
.cities-more-btn {
    background: none;
    border: none;
    padding: 0 0 0 4px;
    margin: 0;
    font: inherit;
    font-size: 11px;
    font-weight: 700;
    color: var(--accent-blue, #4ea1ff);
    cursor: pointer;
    text-decoration: underline;
}

.cities-more-btn:hover {
    opacity: 0.8;
}

.detail-tile-threats {
    display: flex;
    gap: 6px;
    flex-wrap: wrap;
    margin-top: 10px;
}

.detail-threat-tag {
    padding: 3px 8px;
    background: rgba(255, 107, 107, 0.1);
    border: 1px solid rgba(255, 107, 107, 0.2);
    border-radius: 4px;
    font-size: 11px;
    font-weight: 600;
    color: var(--accent-red);
}

.detail-tile-footer {
    padding: 8px 16px;
    font-size: 11px;
    color: var(--text-muted);
    border-top: 1px solid rgba(255, 255, 255, 0.04);
}

/* Cancelled overlay banner */
.detail-tile-cancelled-banner {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 8px;
    padding: 8px 16px;
    background: rgba(107, 114, 128, 0.12);
    border-top: 1px solid rgba(107, 114, 128, 0.2);
    font-size: 12px;
    font-weight: 600;
    color: var(--cancelled-color);
}

.detail-tile-cancelled-banner svg {
    width: 14px;
    height: 14px;
}

/* Responsive for detail section */
@media (max-width: 768px) {
    .detail-section {
        padding: 0 12px 24px;
    }

    .detail-section-header {
        flex-direction: column;
        gap: 10px;
        align-items: flex-start;
    }

    .detail-cards-grid {
        grid-template-columns: 1fr;
    }
}

/* ============================================
   TORNADO EMERGENCY BANNER
   ============================================ */
#te-banner {
    display: none;
    width: 100%;
    padding: 0;
    overflow: hidden;
    max-height: 0;
    transition: max-height 0.4s ease, padding 0.4s ease;
    z-index: 99;
    position: relative;
}

#te-banner.active {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 10px;
    max-height: 48px;
    padding: 10px 20px;
    background: linear-gradient(90deg,
        rgba(100, 0, 80, 0.95) 0%,
        rgba(180, 0, 140, 0.98) 20%,
        rgba(220, 0, 180, 1) 50%,
        rgba(180, 0, 140, 0.98) 80%,
        rgba(100, 0, 80, 0.95) 100%);
    border-bottom: 2px solid var(--te-color);
    box-shadow: 0 4px 30px var(--te-glow), 0 0 60px rgba(255, 0, 204, 0.2);
    animation: te-banner-flash 1.2s ease-in-out infinite;
}

@keyframes te-banner-flash {
    0%, 100% { box-shadow: 0 4px 30px var(--te-glow), 0 0 60px rgba(255, 0, 204, 0.2); }
    50%       { box-shadow: 0 4px 50px rgba(255, 0, 204, 0.7), 0 0 100px rgba(255, 0, 204, 0.4); }
}

.te-banner-icon {
    font-size: 18px;
    animation: te-icon-pulse 0.8s ease-in-out infinite alternate;
}

@keyframes te-icon-pulse {
    from { transform: scale(1); }
    to   { transform: scale(1.3); }
}

.te-banner-text {
    font-size: 14px;
    font-weight: 900;
    letter-spacing: 2px;
    text-transform: uppercase;
    color: #fff;
    text-shadow: 0 0 12px rgba(255, 255, 255, 0.6);
}

.te-banner-sep {
    color: rgba(255, 255, 255, 0.4);
    font-size: 14px;
}

.te-banner-location {
    font-size: 13px;
    font-weight: 600;
    color: rgba(255, 255, 255, 0.9);
    letter-spacing: 0.5px;
}

.te-banner-count {
    font-size: 11px;
    font-weight: 700;
    padding: 2px 8px;
    background: rgba(255, 255, 255, 0.2);
    border-radius: 12px;
    color: #fff;
    letter-spacing: 0.5px;
}

/* Header warning count flashes when TE is active */
#warning-count.has-tornado-emergency {
    color: var(--te-color);
    animation: flash 1s infinite;
    font-weight: 700;
}

/* ============================================
   TORNADO EMERGENCY BADGES
   ============================================ */
.tornado-emergency-badge {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    padding: 3px 10px;
    background: rgba(220, 0, 180, 0.2);
    border: 1px solid rgba(255, 0, 204, 0.6);
    border-radius: 4px;
    font-size: 10px;
    font-weight: 900;
    color: var(--te-color);
    text-transform: uppercase;
    letter-spacing: 0.8px;
    animation: flash 0.9s infinite;
    text-shadow: 0 0 8px rgba(255, 0, 204, 0.5);
}

.pds-badge {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    padding: 2px 8px;
    background: rgba(255, 102, 0, 0.18);
    border: 1px solid rgba(255, 102, 0, 0.5);
    border-radius: 4px;
    font-size: 10px;
    font-weight: 800;
    color: var(--pds-color);
    text-transform: uppercase;
    letter-spacing: 0.6px;
    animation: flash 1.8s infinite;
}

/* Detail tile tags */
.detail-emergency-tag {
    display: inline-flex;
    align-items: center;
    padding: 3px 10px;
    background: rgba(220, 0, 180, 0.2);
    border: 1px solid rgba(255, 0, 204, 0.5);
    border-radius: 4px;
    font-size: 11px;
    font-weight: 900;
    color: var(--te-color);
    text-transform: uppercase;
    letter-spacing: 0.8px;
    animation: flash 0.9s infinite;
}

.detail-pds-tag {
    display: inline-flex;
    align-items: center;
    padding: 3px 10px;
    background: rgba(255, 102, 0, 0.15);
    border: 1px solid rgba(255, 102, 0, 0.4);
    border-radius: 4px;
    font-size: 11px;
    font-weight: 800;
    color: var(--pds-color);
    text-transform: uppercase;
    letter-spacing: 0.5px;
}

/* Warning card TE / PDS treatment */
.warning-card.is-tornado-emergency {
    border-color: rgba(255, 0, 204, 0.5);
    background: linear-gradient(135deg, rgba(80, 0, 60, 0.6) 0%, var(--bg-card) 100%);
    box-shadow: 0 0 16px rgba(255, 0, 204, 0.15), inset 0 0 20px rgba(220, 0, 180, 0.05);
}

.warning-card.is-tornado-emergency::before {
    background: var(--te-color);
    box-shadow: 0 0 8px var(--te-color);
}

.warning-card.is-tornado-emergency:hover {
    border-color: var(--te-color);
    box-shadow: 0 0 24px rgba(255, 0, 204, 0.3);
}

.warning-card.is-pds {
    border-color: rgba(255, 102, 0, 0.4);
    background: linear-gradient(135deg, rgba(60, 25, 0, 0.6) 0%, var(--bg-card) 100%);
}

.warning-card.is-pds::before {
    background: var(--pds-color);
}

/* Detail tile TE / PDS header styles */
.detail-tile-header.tornado-emergency {
    background: linear-gradient(135deg, rgba(180, 0, 140, 0.2) 0%, rgba(220, 0, 180, 0.05) 100%);
    border-bottom: 2px solid var(--te-color);
}

.detail-tile-header.pds {
    background: linear-gradient(135deg, rgba(160, 60, 0, 0.18) 0%, rgba(255, 102, 0, 0.03) 100%);
    border-bottom: 2px solid var(--pds-color);
}

.detail-tile.is-tornado-emergency {
    border-color: rgba(255, 0, 204, 0.4);
    box-shadow: 0 0 20px rgba(255, 0, 204, 0.1);
}

.detail-tile.is-pds {
    border-color: rgba(255, 102, 0, 0.3);
}

/* ============================================
   DAMAGE THREAT BADGES (IBW "DESTRUCTIVE" tag)
   ============================================ */
.damage-catastrophic-badge,
.damage-destructive-badge,
.damage-considerable-badge {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    padding: 2px 8px;
    border-radius: 4px;
    font-size: 10px;
    font-weight: 900;
    text-transform: uppercase;
    letter-spacing: 0.7px;
    margin-left: 4px;
}

.damage-catastrophic-badge {
    background: rgba(220, 0, 180, 0.22);
    border: 1px solid rgba(255, 0, 204, 0.6);
    color: var(--te-color);
    text-shadow: 0 0 8px rgba(255, 0, 204, 0.5);
    animation: flash 0.8s infinite;
}

.damage-destructive-badge {
    background: rgba(255, 30, 30, 0.22);
    border: 1px solid rgba(255, 60, 60, 0.6);
    color: #ff5050;
    text-shadow: 0 0 8px rgba(255, 60, 60, 0.45);
    animation: flash 1s infinite;
}

.damage-considerable-badge {
    background: rgba(255, 170, 0, 0.18);
    border: 1px solid rgba(255, 170, 0, 0.5);
    color: #ffb733;
    letter-spacing: 0.5px;
}

/* Detail tile damage tags (slightly larger to match other detail tags) */
.detail-damage-catastrophic-tag,
.detail-damage-destructive-tag,
.detail-damage-considerable-tag {
    display: inline-flex;
    align-items: center;
    padding: 3px 10px;
    border-radius: 4px;
    font-size: 11px;
    font-weight: 900;
    text-transform: uppercase;
    letter-spacing: 0.6px;
    margin-left: 6px;
}

.detail-damage-catastrophic-tag {
    background: rgba(220, 0, 180, 0.2);
    border: 1px solid rgba(255, 0, 204, 0.5);
    color: var(--te-color);
    animation: flash 0.8s infinite;
}

.detail-damage-destructive-tag {
    background: rgba(255, 30, 30, 0.2);
    border: 1px solid rgba(255, 60, 60, 0.5);
    color: #ff5050;
    animation: flash 1s infinite;
}

.detail-damage-considerable-tag {
    background: rgba(255, 170, 0, 0.15);
    border: 1px solid rgba(255, 170, 0, 0.4);
    color: #ffb733;
}

/* Warning-card outer treatment for destructive / considerable */
.warning-card.is-destructive {
    border-color: rgba(255, 60, 60, 0.45);
    background: linear-gradient(135deg, rgba(70, 0, 0, 0.5) 0%, var(--bg-card) 100%);
    box-shadow: 0 0 14px rgba(255, 60, 60, 0.12);
}

.warning-card.is-destructive::before {
    background: #ff3030;
    box-shadow: 0 0 8px rgba(255, 60, 60, 0.6);
}

.warning-card.is-considerable {
    border-color: rgba(255, 170, 0, 0.35);
}

.warning-card.is-considerable::before {
    background: #ffaa00;
}

/* Map legend TE color chip */
.legend-color.te {
    background: #ff00cc;
    box-shadow: 0 0 6px rgba(255, 0, 204, 0.5);
}

/* ============================================
   VOICE BUTTON GROUP (header)
   ============================================ */
.voice-btn-group {
    display: flex;
    align-items: stretch;
    gap: 0;
    border: 1px solid var(--border-color);
    border-radius: var(--radius);
    overflow: hidden;
}

.voice-btn-group .control-btn {
    border: none;
    border-radius: 0;
    padding: 6px 12px;
    gap: 6px;
    position: relative;
}

.voice-settings-btn {
    padding: 6px 9px !important;
    border-left: 1px solid var(--border-color) !important;
}

.voice-settings-btn:hover {
    border-left-color: var(--border-glow) !important;
}

/* Voice on / speaking states */
.voice-btn.active {
    background: rgba(34, 197, 94, 0.1);
    color: #22c55e;
}

.voice-btn.active:hover {
    background: rgba(34, 197, 94, 0.15);
    color: #4ade80;
}

.voice-btn.speaking {
    background: rgba(34, 197, 94, 0.18) !important;
    color: #4ade80 !important;
}

/* Pulsing green dot when speaking */
.voice-speaking-dot {
    display: none;
    width: 6px;
    height: 6px;
    border-radius: 50%;
    background: #22c55e;
    margin-left: 2px;
    flex-shrink: 0;
}

.voice-btn.speaking .voice-speaking-dot {
    display: inline-block;
    animation: pulse 0.8s ease-in-out infinite;
}

/* Skip button — stops the current voice burst without turning voice off.
   Hidden until voice is enabled. Pulses orange while speech is queued. */
.voice-skip-btn {
    display: none;
    padding: 5px 8px;
    background: transparent;
    border: 1px solid var(--border-color);
    color: var(--text-secondary);
    cursor: pointer;
    transition: all 0.18s ease;
    align-items: center;
    justify-content: center;
}
.voice-skip-btn.visible {
    display: inline-flex;
}
.voice-skip-btn:hover {
    background: rgba(255, 255, 255, 0.06);
    color: var(--text-primary);
    border-color: rgba(255, 140, 0, 0.5);
}
.voice-skip-btn.active {
    color: #ff8c00;
    border-color: rgba(255, 140, 0, 0.55);
    animation: voiceSkipPulse 1.4s ease-in-out infinite;
}
@keyframes voiceSkipPulse {
    0%, 100% { box-shadow: 0 0 0 0   rgba(255, 140, 0, 0.45); }
    50%      { box-shadow: 0 0 0 5px rgba(255, 140, 0, 0);    }
}

/* ============================================
   VOICE SETTINGS PANEL
   ============================================ */
.voice-panel {
    display: none;
    position: fixed;
    top: 68px;
    right: 16px;
    width: 300px;
    background: rgba(17, 17, 34, 0.97);
    backdrop-filter: blur(16px);
    border: 1px solid var(--border-color);
    border-radius: var(--radius-lg);
    box-shadow: var(--shadow), 0 0 20px rgba(34, 197, 94, 0.08);
    z-index: 200;
    padding: 14px 16px 16px;
}

.voice-panel.visible {
    display: block;
    animation: panel-drop 0.18s ease;
}

@keyframes panel-drop {
    from { opacity: 0; transform: translateY(-6px); }
    to   { opacity: 1; transform: translateY(0); }
}

.voice-panel-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding-bottom: 10px;
    margin-bottom: 12px;
    border-bottom: 1px solid var(--border-color);
}

.voice-panel-title {
    display: flex;
    align-items: center;
    gap: 6px;
    font-size: 12px;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.8px;
    color: var(--accent-blue);
}

.voice-now-speaking {
    font-size: 11px;
    font-weight: 600;
    color: var(--text-muted);
    padding: 2px 8px;
    background: var(--bg-card);
    border: 1px solid var(--border-color);
    border-radius: 20px;
    letter-spacing: 0.3px;
    transition: all 0.3s;
}

.voice-now-speaking.is-speaking {
    color: #4ade80;
    background: rgba(34, 197, 94, 0.12);
    border-color: rgba(34, 197, 94, 0.3);
    animation: flash 1s infinite;
}

.voice-panel-row {
    display: flex;
    align-items: center;
    gap: 10px;
    margin-bottom: 10px;
}

.voice-panel-label {
    font-size: 11px;
    font-weight: 600;
    color: var(--text-muted);
    text-transform: uppercase;
    letter-spacing: 0.4px;
    width: 44px;
    flex-shrink: 0;
}

.voice-slider-wrap {
    flex: 1;
    display: flex;
    align-items: center;
    gap: 8px;
}

.voice-slider {
    flex: 1;
    height: 4px;
    -webkit-appearance: none;
    appearance: none;
    background: var(--border-color);
    border-radius: 2px;
    outline: none;
    cursor: pointer;
}

.voice-slider::-webkit-slider-thumb {
    -webkit-appearance: none;
    width: 14px;
    height: 14px;
    border-radius: 50%;
    background: var(--accent-blue);
    cursor: pointer;
    box-shadow: 0 0 4px rgba(74, 158, 255, 0.4);
    transition: background 0.2s;
}

.voice-slider::-webkit-slider-thumb:hover {
    background: #5aadff;
}

.voice-slider-val {
    font-size: 11px;
    font-weight: 600;
    color: var(--text-secondary);
    width: 52px;
    text-align: right;
    flex-shrink: 0;
}

.voice-select {
    flex: 1;
    padding: 5px 8px;
    background: rgba(15, 15, 30, 0.8);
    border: 1px solid var(--border-color);
    border-radius: var(--radius);
    color: var(--text-primary);
    font-size: 11px;
    font-family: inherit;
    outline: none;
    cursor: pointer;
    max-width: 100%;
}

.voice-select:focus {
    border-color: var(--accent-blue);
}

.voice-select option {
    background: #111122;
    color: var(--text-primary);
    font-size: 12px;
}

/* Alert priority legend */
.voice-panel-alerts-title {
    font-size: 10px;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.6px;
    color: var(--text-muted);
    margin: 10px 0 6px;
}

.voice-alert-legend {
    background: rgba(0, 0, 0, 0.2);
    border: 1px solid rgba(255, 255, 255, 0.05);
    border-radius: var(--radius);
    padding: 6px 8px;
    margin-bottom: 12px;
}

.val-row {
    font-size: 10px;
    color: var(--text-secondary);
    padding: 3px 0;
    border-bottom: 1px solid rgba(255, 255, 255, 0.03);
    line-height: 1.4;
}

.val-row:last-child { border-bottom: none; }

.val-te        { color: #ff77ee; }
.val-pds       { color: #ff9944; }
.val-confirmed { color: #ff6b6b; }
.val-radar     { color: #4a9eff; }
.val-watch     { color: #ffff00; }
.val-sts       { color: #ff8c00; }
.val-cancel    { color: #22c55e; }

/* Test button */
.voice-test-btn {
    width: 100%;
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 6px;
    padding: 8px;
    background: rgba(74, 158, 255, 0.12);
    border: 1px solid rgba(74, 158, 255, 0.3);
    border-radius: var(--radius);
    color: var(--accent-blue);
    font-size: 12px;
    font-weight: 600;
    cursor: pointer;
    transition: all var(--transition);
    font-family: inherit;
}

.voice-test-btn:hover {
    background: rgba(74, 158, 255, 0.2);
    border-color: var(--accent-blue);
    box-shadow: 0 0 12px rgba(74, 158, 255, 0.2);
}

/* ============================================
   VOICE BUTTON GROUP
   ============================================ */
.voice-btn-group {
    display: flex;
    align-items: stretch;
    gap: 0;
    border: 1px solid var(--border-color);
    border-radius: var(--radius);
    overflow: hidden;
}

.voice-btn-group .control-btn {
    border: none;
    border-radius: 0;
    padding: 6px 12px;
    gap: 6px;
    position: relative;
}

/* Separator between the two buttons */
.voice-settings-btn {
    padding: 6px 9px !important;
    border-left: 1px solid var(--border-color) !important;
}

.voice-settings-btn:hover {
    border-left-color: var(--border-glow) !important;
}

/* Voice button states */
.voice-btn.active {
    background: rgba(34, 197, 94, 0.1);
    border-color: rgba(34, 197, 94, 0.4);
    color: #22c55e;
}

.voice-btn.active:hover {
    background: rgba(34, 197, 94, 0.15);
    color: #4ade80;
}

.voice-btn.speaking {
    background: rgba(34, 197, 94, 0.18) !important;
    color: #4ade80 !important;
}

/* Pulsing dot when speaking */
.voice-speaking-dot {
    display: none;
    width: 6px;
    height: 6px;
    border-radius: 50%;
    background: #22c55e;
    margin-left: 2px;
}

.voice-btn.speaking .voice-speaking-dot {
    display: inline-block;
    animation: pulse 0.8s ease-in-out infinite;
}

/* ============================================
   VOICE SETTINGS PANEL
   ============================================ */
.voice-panel {
    display: none;
    position: fixed;
    top: 68px;
    right: 16px;
    width: 300px;
    background: rgba(17, 17, 34, 0.97);
    backdrop-filter: blur(16px);
    border: 1px solid var(--border-color);
    border-radius: var(--radius-lg);
    box-shadow: var(--shadow), 0 0 20px rgba(34, 197, 94, 0.08);
    z-index: 200;
    padding: 14px 16px 16px;
}

.voice-panel.visible {
    display: block;
    animation: panel-drop 0.18s ease;
}

@keyframes panel-drop {
    from { opacity: 0; transform: translateY(-6px); }
    to   { opacity: 1; transform: translateY(0); }
}

.voice-panel-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding-bottom: 10px;
    margin-bottom: 12px;
    border-bottom: 1px solid var(--border-color);
}

.voice-panel-title {
    display: flex;
    align-items: center;
    gap: 6px;
    font-size: 12px;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.8px;
    color: var(--accent-blue);
}

.voice-now-speaking {
    font-size: 11px;
    font-weight: 600;
    color: var(--text-muted);
    padding: 2px 8px;
    background: var(--bg-card);
    border: 1px solid var(--border-color);
    border-radius: 20px;
    letter-spacing: 0.3px;
    transition: all 0.3s;
}

.voice-now-speaking.is-speaking {
    color: #4ade80;
    background: rgba(34, 197, 94, 0.12);
    border-color: rgba(34, 197, 94, 0.3);
    animation: flash 1s infinite;
}

.voice-panel-row {
    display: flex;
    align-items: center;
    gap: 10px;
    margin-bottom: 10px;
}

.voice-panel-label {
    font-size: 11px;
    font-weight: 600;
    color: var(--text-muted);
    text-transform: uppercase;
    letter-spacing: 0.4px;
    width: 44px;
    flex-shrink: 0;
}

.voice-slider-wrap {
    flex: 1;
    display: flex;
    align-items: center;
    gap: 8px;
}

.voice-slider {
    flex: 1;
    height: 4px;
    -webkit-appearance: none;
    appearance: none;
    background: var(--border-color);
    border-radius: 2px;
    outline: none;
    cursor: pointer;
}

.voice-slider::-webkit-slider-thumb {
    -webkit-appearance: none;
    width: 14px;
    height: 14px;
    border-radius: 50%;
    background: var(--accent-blue);
    cursor: pointer;
    box-shadow: 0 0 4px rgba(74, 158, 255, 0.4);
    transition: background 0.2s;
}

.voice-slider::-webkit-slider-thumb:hover {
    background: #5aadff;
}

.voice-slider-val {
    font-size: 11px;
    font-weight: 600;
    color: var(--text-secondary);
    width: 48px;
    text-align: right;
    flex-shrink: 0;
}

.voice-select {
    flex: 1;
    padding: 5px 8px;
    background: rgba(15, 15, 30, 0.8);
    border: 1px solid var(--border-color);
    border-radius: var(--radius);
    color: var(--text-primary);
    font-size: 11px;
    font-family: inherit;
    outline: none;
    cursor: pointer;
    max-width: 100%;
}

.voice-select:focus {
    border-color: var(--accent-blue);
}

.voice-select option {
    background: #111122;
    color: var(--text-primary);
    font-size: 12px;
}

/* Alert legend inside voice panel */
.voice-panel-alerts-title {
    font-size: 10px;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.6px;
    color: var(--text-muted);
    margin: 10px 0 6px;
}

.voice-alert-legend {
    background: rgba(0, 0, 0, 0.2);
    border: 1px solid rgba(255,255,255,0.05);
    border-radius: var(--radius);
    padding: 6px 8px;
    margin-bottom: 12px;
}

.val-row {
    font-size: 10px;
    color: var(--text-secondary);
    padding: 3px 0;
    border-bottom: 1px solid rgba(255,255,255,0.03);
    line-height: 1.4;
}
.val-row:last-child { border-bottom: none; }

.val-te       { color: #ff77ee; }
.val-pds      { color: #ff9944; }
.val-confirmed { color: #ff6b6b; }
.val-radar    { color: #4a9eff; }
.val-watch    { color: #ffff00; }
.val-sts      { color: #ff8c00; }
.val-cancel   { color: #22c55e; }

/* Test button */
.voice-test-btn {
    width: 100%;
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 6px;
    padding: 8px;
    background: rgba(74, 158, 255, 0.12);
    border: 1px solid rgba(74, 158, 255, 0.3);
    border-radius: var(--radius);
    color: var(--accent-blue);
    font-size: 12px;
    font-weight: 600;
    cursor: pointer;
    transition: all var(--transition);
    font-family: inherit;
}

.voice-test-btn:hover {
    background: rgba(74, 158, 255, 0.2);
    border-color: var(--accent-blue);
    box-shadow: 0 0 12px rgba(74, 158, 255, 0.2);
}

/* ============================================
   VOICE BUTTON GROUP (header)
   ============================================ */
.voice-btn-group {
    display: flex;
    align-items: stretch;
    gap: 0;
    border: 1px solid var(--border-color);
    border-radius: var(--radius);
    overflow: hidden;
}

.voice-btn-group .control-btn {
    border: none;
    border-radius: 0;
    padding: 6px 12px;
    gap: 6px;
    position: relative;
}

.voice-settings-btn {
    padding: 6px 9px !important;
    border-left: 1px solid var(--border-color) !important;
}

.voice-settings-btn:hover {
    border-left-color: var(--border-glow) !important;
}

.voice-btn.active {
    background: rgba(34, 197, 94, 0.1);
    color: #22c55e;
}

.voice-btn.active:hover {
    background: rgba(34, 197, 94, 0.15);
    color: #4ade80;
}

.voice-btn.speaking {
    background: rgba(34, 197, 94, 0.18) !important;
    color: #4ade80 !important;
}

.voice-speaking-dot {
    display: none;
    width: 6px;
    height: 6px;
    border-radius: 50%;
    background: #22c55e;
    margin-left: 2px;
    flex-shrink: 0;
}

.voice-btn.speaking .voice-speaking-dot {
    display: inline-block;
    animation: pulse 0.8s ease-in-out infinite;
}

/* ============================================
   VOICE SETTINGS PANEL
   ============================================ */
.voice-panel {
    display: none;
    position: fixed;
    top: 68px;
    right: 16px;
    width: 300px;
    background: rgba(17, 17, 34, 0.97);
    backdrop-filter: blur(16px);
    border: 1px solid var(--border-color);
    border-radius: var(--radius-lg);
    box-shadow: var(--shadow), 0 0 20px rgba(34, 197, 94, 0.08);
    z-index: 200;
    padding: 14px 16px 16px;
}

.voice-panel.visible {
    display: block;
    animation: panel-drop 0.18s ease;
}

@keyframes panel-drop {
    from { opacity: 0; transform: translateY(-6px); }
    to   { opacity: 1; transform: translateY(0); }
}

.voice-panel-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding-bottom: 10px;
    margin-bottom: 12px;
    border-bottom: 1px solid var(--border-color);
}

.voice-panel-title {
    display: flex;
    align-items: center;
    gap: 6px;
    font-size: 12px;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.8px;
    color: var(--accent-blue);
}

.voice-now-speaking {
    font-size: 11px;
    font-weight: 600;
    color: var(--text-muted);
    padding: 2px 8px;
    background: var(--bg-card);
    border: 1px solid var(--border-color);
    border-radius: 20px;
    letter-spacing: 0.3px;
    transition: all 0.3s;
}

.voice-now-speaking.is-speaking {
    color: #4ade80;
    background: rgba(34, 197, 94, 0.12);
    border-color: rgba(34, 197, 94, 0.3);
    animation: flash 1s infinite;
}

.voice-panel-row {
    display: flex;
    align-items: center;
    gap: 10px;
    margin-bottom: 10px;
}

.voice-panel-label {
    font-size: 11px;
    font-weight: 600;
    color: var(--text-muted);
    text-transform: uppercase;
    letter-spacing: 0.4px;
    width: 44px;
    flex-shrink: 0;
}

.voice-slider-wrap {
    flex: 1;
    display: flex;
    align-items: center;
    gap: 8px;
}

.voice-slider {
    flex: 1;
    height: 4px;
    -webkit-appearance: none;
    appearance: none;
    background: var(--border-color);
    border-radius: 2px;
    outline: none;
    cursor: pointer;
}

.voice-slider::-webkit-slider-thumb {
    -webkit-appearance: none;
    width: 14px;
    height: 14px;
    border-radius: 50%;
    background: var(--accent-blue);
    cursor: pointer;
    box-shadow: 0 0 4px rgba(74, 158, 255, 0.4);
    transition: background 0.2s;
}

.voice-slider::-webkit-slider-thumb:hover {
    background: #5aadff;
}

.voice-slider-val {
    font-size: 11px;
    font-weight: 600;
    color: var(--text-secondary);
    width: 52px;
    text-align: right;
    flex-shrink: 0;
}

.voice-select {
    flex: 1;
    padding: 5px 8px;
    background: rgba(15, 15, 30, 0.8);
    border: 1px solid var(--border-color);
    border-radius: var(--radius);
    color: var(--text-primary);
    font-size: 11px;
    font-family: inherit;
    outline: none;
    cursor: pointer;
    max-width: 100%;
}

.voice-select:focus { border-color: var(--accent-blue); }

.voice-select option {
    background: #111122;
    color: var(--text-primary);
    font-size: 12px;
}

.voice-panel-alerts-title {
    font-size: 10px;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.6px;
    color: var(--text-muted);
    margin: 10px 0 6px;
}

.voice-alert-legend {
    background: rgba(0, 0, 0, 0.2);
    border: 1px solid rgba(255, 255, 255, 0.05);
    border-radius: var(--radius);
    padding: 6px 8px;
    margin-bottom: 12px;
}

.val-row {
    font-size: 10px;
    color: var(--text-secondary);
    padding: 3px 0;
    border-bottom: 1px solid rgba(255, 255, 255, 0.03);
    line-height: 1.4;
}

.val-row:last-child { border-bottom: none; }
.val-te        { color: #ff77ee; }
.val-pds       { color: #ff9944; }
.val-confirmed { color: #ff6b6b; }
.val-radar     { color: #4a9eff; }
.val-watch     { color: #ffff00; }
.val-sts       { color: #ff8c00; }
.val-cancel    { color: #22c55e; }

.voice-test-btn {
    width: 100%;
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 6px;
    padding: 8px;
    background: rgba(74, 158, 255, 0.12);
    border: 1px solid rgba(74, 158, 255, 0.3);
    border-radius: var(--radius);
    color: var(--accent-blue);
    font-size: 12px;
    font-weight: 600;
    cursor: pointer;
    transition: all var(--transition);
    font-family: inherit;
}

.voice-test-btn:hover {
    background: rgba(74, 158, 255, 0.2);
    border-color: var(--accent-blue);
    box-shadow: 0 0 12px rgba(74, 158, 255, 0.2);
}

/* ============================================
   RADAR CONTROL BAR
   ============================================ */

/* Container — fixed to bottom of map */
.radar-control-bar {
    display: none;    /* shown via .visible class */
    position: absolute;
    bottom: 36px;
    left: 50%;
    /* --rbf-scale: whole-bar zoom, set by the corner grip (radarbarfloat.js,
       2026-08-02). Docked scales from the bottom-center so it stays seated
       on its bottom offset; floating scales from the top-left so the
       dragged left/top anchor stays valid. Still a transformed element, so
       the storm-sig local-sweep rationale (see MOTIF section) is unchanged. */
    transform: translateX(-50%) scale(var(--rbf-scale, 1));
    transform-origin: 50% 100%;
    width: calc(100% - 24px);
    max-width: 780px;
    background: rgba(10, 14, 23, 0.92);
    backdrop-filter: blur(10px);
    border: 1px solid rgba(74, 158, 255, 0.25);
    border-radius: 10px;
    padding: 7px 10px;
    z-index: 200;
    display: none;
    flex-wrap: wrap;
    gap: 8px;
    align-items: center;
    box-shadow: 0 4px 24px rgba(0,0,0,0.6);
    animation: radar-bar-drop 0.2s ease;
}

@keyframes radar-bar-drop {
    from { opacity: 0; transform: translateX(-50%) translateY(8px) scale(var(--rbf-scale, 1)); }
    to   { opacity: 1; transform: translateX(-50%) translateY(0) scale(var(--rbf-scale, 1)); }
}

.radar-control-bar.visible {
    display: flex;
}

/* Playback buttons */
.radar-playback {
    display: flex;
    align-items: center;
    gap: 4px;
}

.radar-btn {
    background: rgba(255,255,255,0.06);
    border: 1px solid rgba(255,255,255,0.12);
    border-radius: 6px;
    color: var(--text-primary);
    font-size: 15px;
    width: 32px;
    height: 32px;
    display: flex;
    align-items: center;
    justify-content: center;
    cursor: pointer;
    transition: all var(--transition);
    padding: 0;
    font-family: inherit;
}

.radar-btn:disabled, .radar-select:disabled, .radar-scrubber:disabled {
    opacity: 0.4;
    cursor: default;
}

.radar-btn:hover:not(:disabled) {
    background: rgba(74, 158, 255, 0.15);
    border-color: rgba(74, 158, 255, 0.4);
    color: var(--accent-blue);
}

.radar-btn-play {
    width: 36px;
    height: 36px;
    font-size: 16px;
    background: rgba(74, 158, 255, 0.12);
    border-color: rgba(74, 158, 255, 0.3);
    color: var(--accent-blue);
}

.radar-btn-live {
    width: 44px;
    font-size: 11px;
    font-weight: 600;
}

.radar-btn-play:hover:not(:disabled) {
    background: rgba(74, 158, 255, 0.25);
    border-color: var(--accent-blue);
    box-shadow: 0 0 10px rgba(74, 158, 255, 0.3);
}

/* Scrubber + timestamp */
.radar-scrub-wrap {
    flex: 1;
    min-width: 140px;
    display: flex;
    flex-direction: column;
    gap: 4px;
}

.radar-scrubber {
    width: 100%;
    height: 4px;
    -webkit-appearance: none;
    appearance: none;
    background: rgba(255,255,255,0.12);
    border-radius: 2px;
    outline: none;
    cursor: pointer;
}

.radar-scrubber::-webkit-slider-thumb {
    -webkit-appearance: none;
    width: 14px;
    height: 14px;
    border-radius: 50%;
    background: var(--accent-blue);
    cursor: pointer;
    box-shadow: 0 0 6px rgba(74, 158, 255, 0.5);
}

.radar-scrubber::-moz-range-thumb {
    width: 14px;
    height: 14px;
    border-radius: 50%;
    background: var(--accent-blue);
    border: none;
    cursor: pointer;
}

.radar-time-row {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 8px;
}

.radar-timestamp {
    font-size: 11px;
    color: var(--text-secondary);
    font-variant-numeric: tabular-nums;
}

/* Frame badges */
.radar-badge {
    font-size: 10px;
    font-weight: 700;
    padding: 1px 6px;
    border-radius: 4px;
    background: rgba(255,255,255,0.08);
    color: var(--text-secondary);
    letter-spacing: 0.5px;
    text-transform: uppercase;
}

.radar-badge-live {
    background: rgba(34, 197, 94, 0.18);
    color: #22c55e;
    border: 1px solid rgba(34, 197, 94, 0.35);
    animation: radar-live-pulse 2s ease-in-out infinite;
}

@keyframes radar-live-pulse {
    0%, 100% { opacity: 1; }
    50%       { opacity: 0.6; }
}

.radar-badge-fcst {
    background: rgba(255, 200, 60, 0.15);
    color: #ffc83c;
    border: 1px solid rgba(255, 200, 60, 0.3);
}

/* Station-health indicator in the control bar (radar.js _setSiteStatus).
   Mirrors the operator pill's DOWN/STALE semantics, but lives in the always-on
   bar so it stays visible even when the pill is moved/hidden. order:-1 pins it
   to the far-left of the flex bar so a DOWN can't be missed. */
.radar-status-indicator {
    order: -1;
    font-size: 10px;
    font-weight: 800;
    padding: 3px 9px;
    border-radius: 5px;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    white-space: nowrap;
    font-variant-numeric: tabular-nums;
}
.radar-status-indicator.is-down {
    background: rgba(255, 42, 42, 0.18);
    color: #ff5a5a;
    border: 1px solid rgba(255, 42, 42, 0.55);
    box-shadow: 0 0 10px rgba(255, 42, 42, 0.35);
    animation: radar-down-blink 1s steps(2, jump-none) infinite;
}
@keyframes radar-down-blink { 50% { opacity: 0.4; } }
.radar-status-indicator.is-stale {
    background: rgba(255, 179, 0, 0.16);
    color: #ffd98a;
    border: 1px solid rgba(255, 179, 0, 0.45);
}

/* Settings section */
/* Settings live behind the ⚙ flyout — hidden by default for a slim bar */
.radar-settings {
    display: none;
    width: 100%;
    grid-template-columns: repeat(auto-fit, minmax(min(100%, 260px), 1fr));
    align-content: start;
    gap: 5px 16px;
    padding-top: 7px;
    border-top: 1px solid rgba(255, 255, 255, 0.08);
    max-height: var(--rbf-settings-height, 45vh);
    overflow-y: auto;
    overflow-x: hidden;
    overscroll-behavior: contain;
    scrollbar-gutter: stable;
    scrollbar-width: thin;
    scrollbar-color: rgba(74, 158, 255, 0.45) transparent;
    min-height: 0;
    flex-shrink: 0;
}
.radar-control-bar.settings-open .radar-settings { display: grid; }
.radar-settings .radar-setting-row { min-width: 0; }
.radar-settings .radar-label { width: 62px; overflow-wrap: anywhere; }
.radar-settings .radar-select,
.radar-settings .radar-mini-slider { min-width: 0; }
.radar-settings .radar-btn,
.radar-settings .radar-mini-val { flex-shrink: 0; }
.radar-settings #radar-site-auto { width: auto; padding: 0 6px; font-size: 11px; }
.radar-settings .mrms-row,
.radar-settings .mrms-legend { grid-column: 1 / -1; }
.radar-settings .mrms-btns { min-width: 0; }

.radar-bar-actions {
    display: flex;
    gap: 4px;
    flex-shrink: 0;
}
#radar-settings-toggle.active {
    background: rgba(74, 158, 255, 0.2);
    border-color: rgba(74, 158, 255, 0.55);
    color: #4a9eff;
}

/* Minimized state: hide the bar, show a small reopen tab */
body.radarbar-min .radar-control-bar { display: none !important; }
#radar-bar-tab {
    display: none;
    position: absolute;
    bottom: 116px;
    right: 12px;
    /* Above #radar-pill (870). That HUD is draggable with a persisted
       position and gets repositioned by the resize clamp, so it could park
       itself over this tab — same dark rounded shape, same corner — and
       swallow the click, which reads as "the pill is gone / does nothing".
       Also breaks the z-index tie with .hurr-tab, which sits ~8px above. */
    z-index: 880;
    padding: 4px 12px;
    background: rgba(10, 14, 23, 0.94);
    border: 1px solid rgba(74, 158, 255, 0.45);
    border-radius: 6px;
    font-family: var(--font-display);
    font-size: 11px;
    font-weight: 700;
    letter-spacing: 1.5px;
    color: rgba(255, 255, 255, 0.85);
    cursor: pointer;
    box-shadow: 0 4px 14px rgba(0, 0, 0, 0.5);
}
#radar-bar-tab:hover { color: #4a9eff; border-color: rgba(74, 158, 255, 0.8); }
body.radarbar-min #radar-bar-tab.radar-on { display: block; }
body.ticker-active.countstrip-on #radar-bar-tab { bottom: calc(var(--ticker-h) + var(--pillstrip-h) + 92px); }
/* Lift the RADAR reopen tab above the alert ticker/alerts cluster so it's never buried */
body.ticker-active #radar-bar-tab { bottom: calc(var(--ticker-h) + 120px); }

/* Replay / active-alerts / Reports bar toggle — persistent tab stacked above
   the RADAR tab on the right edge (amber to match the bar it controls) */
#alerts-bar-toggle {
    position: absolute;
    bottom: 76px;
    right: 12px;
    z-index: 200;
    padding: 4px 12px;
    background: rgba(10, 14, 23, 0.94);
    border: 1px solid rgba(255, 170, 0, 0.45);
    border-radius: 6px;
    font-family: var(--font-display);
    font-size: 11px;
    font-weight: 700;
    letter-spacing: 1.5px;
    color: rgba(255, 255, 255, 0.85);
    cursor: pointer;
    box-shadow: 0 4px 14px rgba(0, 0, 0, 0.5);
}
#alerts-bar-toggle:hover { color: #ffaa00; border-color: rgba(255, 170, 0, 0.8); }
#alerts-bar-toggle.off { opacity: 0.5; }
body.ticker-active.countstrip-on #alerts-bar-toggle { bottom: calc(var(--ticker-h) + var(--pillstrip-h) + 48px); }
body.obs-clean #alerts-bar-toggle { display: none; }

.radar-setting-row {
    display: flex;
    align-items: center;
    gap: 6px;
}

/* A setting that doesn't apply to the current product (e.g. Smooth+/Filter on a
   Level II product) — dimmed and non-interactive instead of a dead control. */
.radar-setting-row.radar-row-disabled {
    opacity: 0.4;
    pointer-events: none;
}

.radar-label {
    font-size: 10px;
    color: var(--text-secondary);
    width: 44px;
    flex-shrink: 0;
    text-transform: uppercase;
    letter-spacing: 0.5px;
}

.radar-mini-slider {
    flex: 1;
    height: 3px;
    -webkit-appearance: none;
    appearance: none;
    background: rgba(255,255,255,0.12);
    border-radius: 2px;
    outline: none;
    cursor: pointer;
}

.radar-mini-slider::-webkit-slider-thumb {
    -webkit-appearance: none;
    width: 11px;
    height: 11px;
    border-radius: 50%;
    background: var(--accent-blue);
    cursor: pointer;
}

.radar-mini-val {
    font-size: 10px;
    color: var(--text-secondary);
    width: 28px;
    text-align: right;
    font-variant-numeric: tabular-nums;
}

.radar-select {
    flex: 1;
    /* Solid dark background — Chrome paints the native dropdown popup
       with the select's background-color, so a transparent value here
       makes options render white-on-white and look invisible */
    background: #1c2230;
    border: 1px solid rgba(255,255,255,0.1);
    border-radius: 4px;
    color: var(--text-primary);
    font-size: 10px;
    padding: 2px 4px;
    cursor: pointer;
    font-family: inherit;
    /* Hint the browser to use dark-mode native widgets for the popup */
    color-scheme: dark;
}

.radar-select:focus {
    outline: none;
    border-color: rgba(74, 158, 255, 0.4);
}

/* Explicitly style the popup options (Firefox + Chromium honor these) */
.radar-select option {
    background: #1c2230;
    color: #e8eaf0;
}

.radar-select optgroup {
    background: #141a26;
    color: #7ea6d8;
    font-weight: 700;
    font-style: normal;
}

.voice-select option {
    background: #111122;
    color: var(--text-primary);
}

/* Loading spinner */
.radar-loading {
    font-size: 16px;
    color: var(--accent-blue);
    animation: spin 1s linear infinite;
    line-height: 1;
}

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

/* Active state for radar toggle button */
#btn-radar-toggle.active {
    background: rgba(74, 158, 255, 0.15);
    border-color: rgba(74, 158, 255, 0.5);
    color: var(--accent-blue);
    box-shadow: 0 0 10px rgba(74, 158, 255, 0.2);
}

/* ============================================
   MOTION / ZOOM HINT STYLES (card additions)
   ============================================ */
.card-meta {
    display: flex;
    align-items: center;
    justify-content: space-between;
    flex-wrap: wrap;
    gap: 4px;
}

.card-meta-right {
    display: flex;
    align-items: center;
    gap: 8px;
    flex-shrink: 0;
}

.card-storm-motion {
    display: flex;
    align-items: center;
    gap: 3px;
    font-size: 11px;
    color: var(--text-secondary);
    background: rgba(255,255,255,0.04);
    padding: 2px 6px;
    border-radius: 4px;
}

.motion-arrow {
    display: inline-block;
    font-size: 12px;
    line-height: 1;
    color: var(--accent-blue);
    transition: transform 0.1s;
}

.motion-arrow-text {
    color: var(--accent-blue);
    font-size: 12px;
}

.card-zoom-hint {
    font-size: 10px;
    color: var(--text-muted, #555);
    opacity: 0.6;
    cursor: pointer;
    padding: 1px 5px;
    border-radius: 3px;
    border: 1px solid rgba(255,255,255,0.07);
    transition: opacity 0.2s, color 0.2s;
    white-space: nowrap;
}

.warning-card:hover .card-zoom-hint {
    opacity: 1;
    color: var(--accent-blue);
    border-color: rgba(74,158,255,0.3);
}

/* Read-aloud button on warning cards */
.card-speak-btn, .card-toast-btn, .card-pin-btn, .card-details-btn {
    font: inherit;
    font-size: 10px;
    line-height: 1;
    color: var(--text-muted, #888);
    background: none;
    opacity: 0.7;
    cursor: pointer;
    padding: 2px 6px;
    border-radius: 3px;
    border: 1px solid rgba(255,255,255,0.07);
    transition: opacity 0.2s, color 0.2s, border-color 0.2s, background 0.2s;
    white-space: nowrap;
}

.warning-card:hover .card-speak-btn,
.warning-card:hover .card-toast-btn,
.warning-card:hover .card-pin-btn,
.warning-card:hover .card-details-btn {
    opacity: 1;
}

.card-speak-btn:hover,
.card-toast-btn:hover,
.card-pin-btn:hover,
.card-details-btn:hover {
    color: var(--accent-blue, #4ea1ff);
    border-color: rgba(74,158,255,0.4);
}

.card-speak-btn.speaking,
.card-toast-btn.toasted {
    color: var(--accent-blue, #4ea1ff);
    border-color: rgba(74,158,255,0.6);
    background: rgba(74,158,255,0.12);
}

/* Pinned (sticky) state — stays lit while the toast is pinned on screen. */
.card-pin-btn.pinned {
    opacity: 1;
    color: var(--accent-yellow, #eab308);
    border-color: rgba(234,179,8,0.6);
    background: rgba(234,179,8,0.14);
}

/* Popup motion row */
.popup-motion-row .popup-motion-val {
    display: flex;
    align-items: center;
    gap: 2px;
}

.popup-motion-arrow {
    color: var(--accent-blue);
    display: inline-block;
    line-height: 1;
}

/* ============================================
   LSR POPUP STYLES
   ============================================ */
.lsr-popup .maplibregl-popup-content {
    min-width: 240px;
}

.lsr-popup-header {
    padding: 10px 14px;
    display: flex;
    align-items: center;
    gap: 8px;
    border-bottom: 1px solid rgba(255,255,255,0.08);
}

.lsr-popup-icon { font-size: 18px; }

.lsr-popup-type {
    font-size: 13px;
    font-weight: 700;
}

.lsr-popup-time {
    font-size: 10px;
    color: var(--text-secondary);
    margin-left: auto;
    white-space: nowrap;
}

.lsr-popup-body {
    padding: 10px 14px;
}

.lsr-popup-row {
    display: flex;
    gap: 8px;
    font-size: 12px;
    margin-bottom: 6px;
    align-items: flex-start;
}

.lsr-popup-label {
    color: var(--text-secondary);
    font-size: 10px;
    text-transform: uppercase;
    letter-spacing: 0.5px;
    padding-top: 1px;
    flex-shrink: 0;
    width: 52px;
}

.lsr-popup-val {
    color: var(--text-primary);
    font-size: 12px;
    line-height: 1.3;
}

.lsr-popup-comment {
    font-size: 11px;
    color: var(--text-secondary);
    border-top: 1px solid rgba(255,255,255,0.06);
    padding-top: 8px;
    margin-top: 6px;
    line-height: 1.4;
    max-height: 80px;
    overflow-y: auto;
}

.lsr-popup-footer {
    font-size: 10px;
    color: var(--text-secondary);
    opacity: 0.5;
    margin-top: 8px;
    text-align: right;
}

/* ============================================
   MOBILE-RESPONSIVE OVERHAUL
   ============================================ */

/* ---- Tablet (≤900px) ---- */
@media (max-width: 900px) {
    .header {
        padding: 8px 12px;
        gap: 6px;
    }

    .header-right {
        gap: 4px;
        flex-wrap: wrap;
    }

    .control-btn {
        padding: 5px 10px;
        font-size: 11px;
    }

    .control-btn svg {
        width: 15px;
        height: 15px;
    }

    .radar-control-bar {
        bottom: 28px;
        padding: 8px 10px;
        gap: 8px;
    }

    .radar-settings {
        min-width: 130px;
    }
}

/* ---- Laptop / tablet (681–1024px) — collapse control buttons to
   icon-only so the top row stays on one line and the map keeps full
   width. With the layer buttons now living in the Layers dropdown,
   only ~6 buttons remain top-level, so labels survive down to 1024px
   (previously 1600px). Text labels are hidden via font-size:0; SVG
   and emoji icons are restored explicitly. Tooltips (title=) still
   name each button on hover. The dropdown menus themselves are
   outside .header-right, so their rows always keep full labels. ---- */
@media (min-width: 681px) and (max-width: 1024px) {
    .header-right {
        gap: 6px;
        flex-wrap: nowrap;
    }

    .header-right .control-btn {
        font-size: 0;          /* collapse bare-text labels + label spans */
        gap: 0;
        padding: 7px;
        justify-content: center;
    }

    /* Restore glyph icons that depend on font-size (voice uses an emoji) */
    .header-right .control-btn .voice-btn-icon {
        font-size: 15px;
    }

    /* Keep the Layers active-count badge readable in icon-only mode */
    .header-right .control-btn .layers-count {
        font-size: 10px;
        margin-left: 3px;
    }

    /* Keep SVG icons at a consistent, comfortably tappable size */
    .header-right .control-btn svg {
        width: 18px;
        height: 18px;
    }
}

/* ---- Mobile (≤680px) — primary phone breakpoint ---- */
@media (max-width: 680px) {
    /* Flex-column page so header takes its natural height and the
       map/panel region fills whatever is left — no magic-number math. */
    html, body {
        height: 100%;
        overflow: hidden;
    }
    body {
        display: flex;
        flex-direction: column;
    }

    /* Header collapses to two rows. CRITICAL: reset the base 60px
       max-height + overflow:hidden, otherwise the button row is clipped. */
    .header {
        flex-direction: column;
        height: auto;
        max-height: none;
        overflow: visible;
        flex-shrink: 0;
        padding: 8px 12px;
        gap: 6px;
        position: relative;
    }

    .header-left {
        flex-direction: row;
        align-items: center;
        gap: 8px;
        width: 100%;
    }

    /* Match the tightened .header-left gap so branding stays compact */
    .header-brand { gap: 8px; }

    .logo-text h1 { font-size: 14px; }
    .logo-subtitle { display: none; }

    .status-bar {
        font-size: 10px;
        gap: 4px;
        flex-wrap: nowrap;
        overflow: hidden;
        text-overflow: ellipsis;
        white-space: nowrap;
    }

    #warning-count { display: none; }

    .header-right {
        width: 100%;
        gap: 4px;
        flex-wrap: nowrap;
        overflow-x: auto;
        scrollbar-width: none;
        padding-bottom: 2px;
    }

    .header-right::-webkit-scrollbar { display: none; }

    .control-btn {
        padding: 5px 8px;
        font-size: 10px;
        white-space: nowrap;
        flex-shrink: 0;
    }

    .control-btn svg { width: 14px; height: 14px; }

    /* Voice button group */
    .voice-btn-group { flex-shrink: 0; }
    .voice-btn-label { display: none; }
    .voice-btn { padding: 5px 8px !important; }

    /* Main layout — vertical stack that fills the space below the header.
       flex:1 + min-height:0 lets it shrink/grow regardless of header height. */
    .main-content {
        flex-direction: column;
        flex: 1;
        min-height: 0;
        height: auto;
        overflow: hidden;
    }

    .map-container {
        flex: 1;
        height: 0;
        min-height: 280px;
        position: relative;
    }

    /* Warnings panel becomes a bottom sheet */
    .warnings-panel {
        width: 100%;
        height: 42%;
        max-height: 42%;
        flex-shrink: 0;
        border-left: none;
        border-top: 1px solid var(--border-color);
        overflow-y: auto;
    }

    /* Panel header more compact */
    .panel-header {
        padding: 8px 12px;
        position: sticky;
        top: 0;
        z-index: 10;
        background: var(--bg-secondary);
    }

    .panel-header h2 { font-size: 13px; }

    .tab-btn {
        padding: 4px 10px;
        font-size: 11px;
    }

    /* Warning cards more compact */
    .warning-card {
        padding: 10px 12px;
        margin: 0 8px 6px;
    }

    .card-location { font-size: 11px; }

    .card-detail {
        font-size: 10px;
    }

    .card-meta {
        font-size: 10px;
        flex-wrap: wrap;
    }

    .card-zoom-hint { display: none; }  /* hide on mobile — touch is the interaction */

    /* Map legend — compact on mobile */
    .map-legend {
        padding: 6px 8px;
        font-size: 10px;
        bottom: 32px;
        left: 8px;
    }

    .legend-title { font-size: 9px; margin-bottom: 4px; }

    .legend-item { gap: 4px; margin-bottom: 3px; }

    .legend-color {
        width: 10px;
        height: 10px;
        border-radius: 2px;
    }

    /* History panel */
    .history-panel {
        top: 8px;
        left: 8px;
        max-width: calc(100vw - 16px);
        font-size: 11px;
    }

    /* Radar control bar — stacks on mobile */
    .radar-control-bar {
        flex-direction: column;
        align-items: stretch;
        width: calc(100% - 16px);
        bottom: 32px;
        padding: 8px 10px;
        gap: 6px;
    }

    .radar-playback { justify-content: center; }

    .radar-settings {
        flex-direction: row;
        flex-wrap: wrap;
        gap: 6px;
        min-width: unset;
    }

    .radar-setting-row { flex: 1; min-width: 120px; }

    /* Voice panel */
    .voice-panel {
        right: 8px;
        left: 8px;
        width: auto;
        top: auto;
        bottom: 60px;
    }

    /* Detail section — hidden on mobile by default, scrollable */
    .detail-section {
        display: none;
    }

    /* TE banner */
    #te-banner {
        font-size: 12px;
        padding: 6px 12px;
    }

    /* Popups more narrow on small screens */
    .maplibregl-popup-content {
        max-width: 260px !important;
    }

    /* MapLibre nav controls — move away from radar bar and scale down
       so the zoom pill stops dominating the map on small screens. */
    .maplibregl-ctrl-top-right {
        top: 8px;
        right: 8px;
        transform: scale(0.82);
        transform-origin: top right;
    }

    .maplibregl-ctrl-group button {
        width: 30px;
        height: 30px;
    }
}

/* ---- Small phones (≤400px) ---- */
@media (max-width: 400px) {
    .logo-img { width: 28px; height: 28px; }
    .logo-text h1 { font-size: 12px; }

    .header-right {
        gap: 3px;
    }

    .control-btn {
        padding: 4px 6px;
        font-size: 9px;
        gap: 3px;
    }

    .control-btn svg { width: 13px; height: 13px; }

    .map-container {
        min-height: 240px;
    }

    .warnings-panel {
        height: 45%;
        max-height: 45%;
    }
}

/* ---- Touch devices — larger hit areas ---- */
@media (hover: none) and (pointer: coarse) {
    .control-btn {
        min-height: 36px;
    }

    .radar-btn {
        min-width: 38px;
        min-height: 38px;
    }

    .tab-btn {
        min-height: 32px;
        padding: 6px 12px;
    }

    /* Slightly larger markers for fat-finger tapping. Scale the inner element,
       never the root — MapLibre uses the root's transform to position it. */
    .lsr-marker .lsr-marker-inner {
        transform: scale(1.2);
    }
}

/* ============================================
   LSR & LIGHTNING BUTTON STYLES
   ============================================ */

/* LSR tornado count badge */
.lsr-count-badge {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    background: #ff3333;
    color: #fff;
    font-size: 9px;
    font-weight: 700;
    min-width: 16px;
    height: 16px;
    border-radius: 8px;
    padding: 0 4px;
    margin-left: 3px;
    line-height: 1;
    vertical-align: middle;
    box-shadow: 0 0 6px rgba(255,51,51,0.5);
}

/* Active states for new buttons */
#btn-lsr-toggle.active {
    background: rgba(255, 51, 51, 0.12);
    border-color: rgba(255, 51, 51, 0.45);
    color: #ff6b6b;
    box-shadow: 0 0 8px rgba(255,51,51,0.2);
}

#btn-lightning-toggle.active {
    background: rgba(255, 229, 0, 0.1);
    border-color: rgba(255, 229, 0, 0.45);
    color: #ffe500;
    box-shadow: 0 0 8px rgba(255,229,0,0.2);
}

#btn-watches-toggle.active {
    background: rgba(255, 215, 0, 0.1);
    border-color: rgba(255, 215, 0, 0.45);
    color: #ffd700;
    box-shadow: 0 0 8px rgba(255,215,0,0.2);
}

/* Lightning strike layer — ensure markers appear above radar */
.maplibregl-marker { z-index: auto; }

/* ============================================
   STORM TRACKER BUTTON
   ============================================ */
#btn-stormtracker-toggle.active {
    color: #ff3333;
    border-color: rgba(255,51,51,0.5);
    box-shadow: 0 0 8px rgba(255,51,51,0.4);
}

/* ============================================
   SOUND ALERTS BUTTON
   ============================================ */
#btn-sound-toggle.active {
    color: #22c55e;
    border-color: rgba(34,197,94,0.5);
    box-shadow: 0 0 8px rgba(34,197,94,0.35);
}

/* ============================================
   HAIL CHART PANEL (sidebar)
   ============================================ */
.hail-chart-panel {
    border-top: 1px solid rgba(255,255,255,0.07);
    background: rgba(255,255,255,0.02);
    padding: 0;
    flex-shrink: 0;
}

.hail-chart-header {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 9px 12px;
    cursor: pointer;
    user-select: none;
    transition: background 0.15s;
}
.hail-chart-header:hover { background: rgba(255,255,255,0.04); }

.hail-chart-title {
    font-size: 12px;
    font-weight: 600;
    color: rgba(255,255,255,0.75);
    flex: 1;
}
.hail-chart-badge {
    background: #22c55e;
    color: #fff;
    font-size: 10px;
    font-weight: 700;
    padding: 1px 6px;
    border-radius: 8px;
    min-width: 18px;
    text-align: center;
}
.hail-chart-toggle {
    font-size: 10px;
    color: rgba(255,255,255,0.35);
}

.hail-chart-body {
    padding: 4px 10px 10px;
}
.hail-max-size {
    font-size: 11px;
    color: rgba(255,255,255,0.45);
    margin-bottom: 6px;
    text-align: center;
}
.hail-chart-canvas {
    width: 100%;
    height: 120px;
    display: block;
    border-radius: 6px;
    background: rgba(0,0,0,0.2);
}
.hail-chart-legend {
    display: flex;
    justify-content: center;
    gap: 8px;
    flex-wrap: wrap;
    margin-top: 6px;
}
.hail-legend-item {
    font-size: 9px;
    color: rgba(255,255,255,0.5);
}

/* ============================================================
   SPC OUTLOOK — Panel, layer toggles, legend, popups
   ============================================================ */

/* ---- Header button active state ---- */
#btn-spc-panel.active {
    background: rgba(255, 140, 0, 0.25);
    border-color: #ff8c00;
    color: #ffaa44;
    box-shadow: 0 0 8px rgba(255, 140, 0, 0.4);
}

/* ---- Floating panel ---- */
.spc-panel {
    position: fixed;
    top: calc(var(--header-height, 56px) + 8px);
    right: 12px;
    z-index: 1600;
    width: 270px;
    background: rgba(10, 15, 28, 0.97);
    border: 1px solid rgba(255, 140, 0, 0.4);
    border-radius: 10px;
    padding: 14px 14px 10px;
    display: none;
    flex-direction: column;
    gap: 10px;
    backdrop-filter: blur(12px);
    box-shadow: 0 4px 24px rgba(0,0,0,0.6);
}

.spc-panel.visible {
    display: flex;
}

.spc-panel-header {
    display: flex;
    align-items: center;
    gap: 7px;
    font-size: 12px;
    font-weight: 700;
    letter-spacing: 0.08em;
    color: #ffaa44;
    text-transform: uppercase;
    padding-bottom: 8px;
    border-bottom: 1px solid rgba(255,140,0,0.2);
}

/* ---- Layer toggle buttons ---- */
.spc-layer-toggles {
    display: flex;
    flex-direction: column;
    gap: 5px;
}

.spc-toggle-btn {
    display: flex;
    align-items: center;
    gap: 9px;
    background: rgba(255,255,255,0.05);
    border: 1px solid rgba(255,255,255,0.12);
    border-radius: 6px;
    color: rgba(255,255,255,0.75);
    font-size: 12px;
    font-weight: 500;
    padding: 7px 10px;
    cursor: pointer;
    transition: all 0.18s ease;
    text-align: left;
}

.spc-toggle-btn:hover {
    background: rgba(255,255,255,0.1);
    color: #fff;
}

.spc-toggle-btn.active {
    background: rgba(255, 140, 0, 0.2);
    border-color: rgba(255, 140, 0, 0.7);
    color: #ffcc66;
    font-weight: 600;
}

.spc-toggle-swatch {
    display: inline-block;
    width: 16px;
    height: 16px;
    border-radius: 3px;
    border: 2px solid rgba(255,255,255,0.3);
    flex-shrink: 0;
}

/* ---- Day 1/2/3 tabs ---- */
.spc-day-tabs {
    display: flex;
    gap: 4px;
    margin: 8px 0 2px;
}

.spc-day-tab {
    flex: 1;
    background: rgba(255,255,255,0.05);
    border: 1px solid rgba(255,255,255,0.12);
    border-radius: 6px;
    color: rgba(255,255,255,0.7);
    font-size: 11px;
    font-weight: 600;
    letter-spacing: 0.03em;
    padding: 5px 0;
    cursor: pointer;
    transition: all 0.16s ease;
}

.spc-day-tab:hover {
    background: rgba(255,255,255,0.1);
    color: #fff;
}

.spc-day-tab.active {
    background: rgba(255, 140, 0, 0.22);
    border-color: rgba(255, 140, 0, 0.7);
    color: #ffcc66;
}

/* ---- SPC hover tooltip ---- */
.spc-hover-tip {
    position: absolute;
    z-index: 60;
    pointer-events: none;
    background: rgba(15, 18, 26, 0.94);
    border: 1px solid rgba(255, 140, 0, 0.55);
    border-radius: 5px;
    padding: 4px 8px;
    font-size: 12px;
    color: #fff;
    white-space: nowrap;
    box-shadow: 0 2px 10px rgba(0,0,0,0.5);
}

.spc-hover-tip b { color: #ffcc66; }

/* ---- Hail bar hover tooltip ---- */
.hail-bar-tip {
    position: fixed;
    z-index: 9999;
    pointer-events: none;
    background: rgba(15, 18, 26, 0.96);
    border: 1px solid rgba(34, 197, 94, 0.55);
    border-radius: 5px;
    padding: 5px 9px;
    font-size: 12px;
    line-height: 1.35;
    color: #fff;
    white-space: nowrap;
    box-shadow: 0 2px 10px rgba(0,0,0,0.55);
}

.hail-bar-tip .hail-tip-size { font-weight: 700; color: #7CFFB0; }
.hail-bar-tip .hail-tip-loc  { color: rgba(255,255,255,0.92); }
.hail-bar-tip .hail-tip-time { color: rgba(255,255,255,0.55); font-size: 11px; }

/* ---- Hail report list (under the chart) ---- */
.hail-report-list {
    margin-top: 8px;
    max-height: 150px;
    overflow-y: auto;
    border-top: 1px solid rgba(255,255,255,0.08);
    padding-top: 6px;
}

.hail-list-row {
    display: flex;
    align-items: center;
    gap: 7px;
    padding: 3px 2px;
    font-size: 11px;
    border-bottom: 1px solid rgba(255,255,255,0.04);
}

.hail-list-row:last-child { border-bottom: none; }

.hail-list-dot {
    width: 9px;
    height: 9px;
    border-radius: 50%;
    flex-shrink: 0;
    box-shadow: 0 0 3px rgba(0,0,0,0.4);
}

.hail-list-size {
    color: #fff;
    font-weight: 700;
    min-width: 34px;
    flex-shrink: 0;
}

.hail-list-loc {
    color: rgba(255,255,255,0.78);
    flex: 1;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.hail-list-time {
    color: rgba(255,255,255,0.5);
    flex-shrink: 0;
    font-size: 10px;
}
.hail-list-pin {
    flex-shrink: 0;
    background: none;
    border: none;
    cursor: pointer;
    font-size: 11px;
    line-height: 1;
    padding: 1px 2px;
    filter: grayscale(1);
    opacity: 0.45;
    transition: opacity 0.15s, filter 0.15s;
}
.hail-list-row:hover .hail-list-pin { opacity: 0.9; }
.hail-list-pin:hover { opacity: 1; filter: none; }

/* Slim scrollbar for the list */
.hail-report-list::-webkit-scrollbar { width: 6px; }
.hail-report-list::-webkit-scrollbar-thumb {
    background: rgba(255,255,255,0.15);
    border-radius: 3px;
}

/* ---- Categorical legend ---- */
.spc-legend {
    border-top: 1px solid rgba(255,255,255,0.08);
    padding-top: 8px;
}

.spc-legend-title {
    font-size: 10px;
    font-weight: 700;
    letter-spacing: 0.08em;
    color: rgba(255,255,255,0.4);
    text-transform: uppercase;
    margin-bottom: 6px;
}

.spc-legend-row {
    display: flex;
    align-items: center;
    gap: 7px;
    font-size: 11px;
    color: rgba(255,255,255,0.7);
    padding: 2px 0;
}

.spc-leg-swatch {
    display: inline-block;
    width: 14px;
    height: 14px;
    border-radius: 2px;
    border: 1.5px solid transparent;
    flex-shrink: 0;
}

/* Hatched swatch for SIGN legend */
.spc-leg-hatch {
    background-image: repeating-linear-gradient(
        -45deg,
        rgba(0,0,0,0) 0px,
        rgba(0,0,0,0) 2px,
        rgba(255,255,255,0.8) 2px,
        rgba(255,255,255,0.8) 3.5px
    );
    background-color: rgba(180,180,180,0.2);
    border-color: rgba(255,255,255,0.4);
}

/* Group-specific SVG swatches; categorical coverage uses neutral dots. */
.spc-leg-cig {
    background-color: rgba(180,180,180,0.2);
    border-color: rgba(255,255,255,0.4);
}
.spc-leg-cig-area {
    background-image: radial-gradient(circle, rgba(255,255,255,0.92) 1px, transparent 1.5px);
    background-size: 6px 6px;
    background-color: rgba(180,180,180,0.2);
    border-color: rgba(255,255,255,0.4);
}
.spc-cig-note {
    font-size: 10px;
    color: var(--text-secondary);
    margin-top: 4px;
}

/* ---- Probability scale legend (chips) ---- */
.spc-prob-row {
    display: flex;
    flex-wrap: wrap;
    gap: 4px;
    margin-bottom: 6px;
}

.spc-prob-chip {
    display: inline-block;
    min-width: 28px;
    text-align: center;
    padding: 2px 5px;
    border-radius: 3px;
    font-size: 10px;
    font-weight: 700;
    color: #fff;
    text-shadow: 0 1px 2px rgba(0,0,0,0.7);
    border: 1px solid rgba(255,255,255,0.25);
}

/* ---- Location search box ---- */
.geo-search {
    position: relative;
    display: flex;
    align-items: center;
}

.geo-search-form {
    width: 0;
    overflow: hidden;
    opacity: 0;
    transition: width 0.22s ease, opacity 0.22s ease, margin-left 0.22s ease;
}

.geo-search.open .geo-search-form {
    width: 190px;
    opacity: 1;
    margin-left: 5px;
}

.geo-search-field {
    position: relative;
    display: flex;
    align-items: center;
}

.geo-search-input {
    width: 100%;
    box-sizing: border-box;
    background: rgba(255,255,255,0.07);
    border: 1px solid rgba(255,255,255,0.18);
    border-radius: 6px;
    color: #fff;
    font-size: 13px;
    padding: 7px 28px 7px 10px;
    outline: none;
}

.geo-search-clear {
    position: absolute;
    right: 4px;
    top: 50%;
    transform: translateY(-50%);
    width: 20px;
    height: 20px;
    display: flex;
    align-items: center;
    justify-content: center;
    background: rgba(255,255,255,0.12);
    border: none;
    border-radius: 50%;
    color: rgba(255,255,255,0.7);
    font-size: 16px;
    line-height: 1;
    cursor: pointer;
    padding: 0;
    transition: background 0.15s ease, color 0.15s ease;
}

.geo-search-clear:hover {
    background: rgba(255,140,0,0.35);
    color: #fff;
}

.geo-search-input:focus {
    border-color: rgba(255,140,0,0.7);
    background: rgba(255,255,255,0.1);
}

.geo-search-input::placeholder { color: rgba(255,255,255,0.4); }

/* ---- Place-search typeahead dropdown (fixed; anchored under the input) ---- */
.geo-suggest {
    list-style: none; margin: 0; padding: 4px;
    position: fixed; z-index: 3000;
    max-height: 300px; overflow-y: auto;
    background: rgba(10, 14, 24, 0.97);
    border: 1px solid rgba(255, 255, 255, 0.16);
    border-radius: 8px;
    box-shadow: 0 10px 26px rgba(0, 0, 0, 0.55);
    backdrop-filter: blur(4px);
    display: none;
}
.geo-suggest.open { display: block; }
.geo-suggest-item {
    display: flex; align-items: baseline; justify-content: space-between; gap: 10px;
    padding: 6px 9px; border-radius: 6px; cursor: pointer; color: #e6eef8; font-size: 13px;
}
.geo-suggest-item:hover, .geo-suggest-item.active { background: rgba(255, 140, 0, 0.22); }
.geo-suggest-name { font-weight: 600; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.geo-suggest-st { color: #9fb3c8; font-size: 11px; font-weight: 700; letter-spacing: 0.05em; flex: 0 0 auto; }

.geo-search-status {
    position: absolute;
    top: 100%;
    left: 0;
    right: 0;
    margin-top: 4px;
    background: rgba(15,18,26,0.96);
    border: 1px solid rgba(255,255,255,0.15);
    border-radius: 5px;
    padding: 5px 9px;
    font-size: 11px;
    color: rgba(255,255,255,0.8);
    z-index: 50;
    box-shadow: 0 2px 10px rgba(0,0,0,0.5);
}

.geo-search-status.error {
    color: #ff8080;
    border-color: rgba(255,80,80,0.5);
}

.geo-search-marker {
    cursor: pointer;
    filter: drop-shadow(0 2px 3px rgba(0,0,0,0.5));
}

.geo-marker-popup {
    font-size: 12px;
    color: #222;
    font-family: var(--font-main, 'Inter', sans-serif);
    line-height: 1.35;
}

/* ---- Map popups for SPC data ---- */
.spc-popup {
    font-family: var(--font-main, 'Inter', sans-serif);
    font-size: 12px;
    line-height: 1.45;
    color: #f0f0f0;
}

.spc-popup-title {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 8px;
    margin-bottom: 6px;
}

.spc-md-badge {
    background: rgba(255, 140, 0, 0.25);
    border: 1px solid #ff8c00;
    border-radius: 4px;
    color: #ffaa44;
    font-weight: 700;
    font-size: 13px;
    padding: 2px 7px;
}

.spc-popup-fc {
    font-size: 11px;
    color: rgba(255,255,255,0.5);
}

.spc-popup-body {
    font-size: 12px;
    color: rgba(255,255,255,0.85);
    margin-bottom: 5px;
    line-height: 1.4;
}

.spc-popup-meta {
    font-size: 11px;
    color: rgba(255,255,255,0.5);
    margin-bottom: 2px;
}

.spc-popup-link {
    display: inline-block;
    margin-top: 8px;
    font-size: 11px;
    color: #4a9eff;
    text-decoration: none;
    border-bottom: 1px solid rgba(74,158,255,0.35);
}

.spc-popup-link:hover {
    color: #77bbff;
    border-bottom-color: #77bbff;
}

.spc-risk-label {
    font-size: 13px;
    font-weight: 700;
    border: 1px solid;
    border-radius: 4px;
    padding: 2px 8px;
}

/* ============================================
   BROADCAST KIT — ticker crawl, slam banners,
   condensed display typography
   ============================================ */

:root {
    --font-display: 'Barlow Condensed', 'Arial Narrow', Arial, sans-serif;
    /* Broadcast strip scale (ticker + count pills) — adjustable in Display
       settings so the bottom strip stays readable on small stream views */
    --ticker-scale: 1;
    --ticker-h: calc(32px * var(--ticker-scale, 1));
    --pillstrip-h: calc(46px * var(--ticker-scale, 1));
    /* Storm Track Impact card scale (Display settings slider) */
    --impact-scale: 1;
}

/* ---- Typography pass: condensed broadcast type on alert elements ---- */
.toast-title {
    font-family: var(--font-display);
    font-size: calc(16px * var(--toast-scale, 1));
    font-weight: 600;
    letter-spacing: 0.6px;
    text-transform: uppercase;
}

.legend-title {
    font-family: var(--font-display);
    font-size: 13px;
    letter-spacing: 1.5px;
}

/* ---- Warning ticker (bottom crawl) ---- */
#alert-ticker {
    position: fixed;
    left: 0;
    right: 0;
    bottom: 0;
    height: var(--ticker-h);
    display: flex;
    align-items: stretch;
    background: linear-gradient(180deg, rgba(10, 13, 22, 0.96), rgba(6, 8, 14, 0.98));
    border-top: 1px solid rgba(255, 255, 255, 0.12);
    backdrop-filter: blur(10px);
    z-index: 600;
    overflow: hidden;
}

#alert-ticker.ticker-collapsed { display: none; }

.ticker-cap {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 0 12px;
    background: linear-gradient(135deg, #16203a, #0d1322);
    border-right: 2px solid rgba(74, 158, 255, 0.5);
    flex-shrink: 0;
    z-index: 2;
    box-shadow: 6px 0 12px rgba(0, 0, 0, 0.55);
}

.ticker-brand {
    font-family: var(--font-display);
    font-size: calc(14px * var(--ticker-scale, 1));
    font-weight: 700;
    letter-spacing: 1.5px;
    color: #ffffff;
    white-space: nowrap;
}

.ticker-chips { display: flex; gap: 5px; }

.ticker-chip {
    font-family: var(--font-display);
    font-size: calc(12px * var(--ticker-scale, 1));
    font-weight: 700;
    letter-spacing: 0.8px;
    padding: 1px 7px;
    border-radius: 3px;
    border: 1px solid;
    white-space: nowrap;
}

.chip-tor   { color: #ff5555; border-color: rgba(255, 60, 60, 0.7);  background: rgba(255, 40, 40, 0.16); animation: chip-pulse 1.6s infinite; }
.chip-svr   { color: #ffaa44; border-color: rgba(255, 140, 0, 0.6);  background: rgba(255, 140, 0, 0.12); }
.chip-watch { color: #ffee66; border-color: rgba(255, 230, 60, 0.5); background: rgba(255, 230, 60, 0.10); }

@keyframes chip-pulse {
    0%, 100% { box-shadow: 0 0 0 0 rgba(255, 60, 60, 0.5); }
    50%      { box-shadow: 0 0 8px 2px rgba(255, 60, 60, 0.25); }
}

.ticker-viewport {
    flex: 1;
    overflow: hidden;
    display: flex;
    align-items: center;
    /* soft fade at both ends of the crawl */
    mask-image: linear-gradient(90deg, transparent 0, #000 24px, #000 calc(100% - 24px), transparent 100%);
    -webkit-mask-image: linear-gradient(90deg, transparent 0, #000 24px, #000 calc(100% - 24px), transparent 100%);
}

.ticker-track {
    display: inline-flex;
    align-items: center;
    white-space: nowrap;
    will-change: transform;
}

.ticker-viewport:hover .ticker-track { animation-play-state: paused !important; }

@keyframes ticker-scroll {
    from { transform: translateX(0); }
    to   { transform: translateX(-50%); }
}

.ticker-item {
    display: inline-flex;
    align-items: baseline;
    gap: 8px;
    padding: 0 10px;
    font-family: var(--font-display);
    font-size: calc(15px * var(--ticker-scale, 1));
    text-shadow: 0 1px 3px rgba(0, 0, 0, 0.8);
}

.tk-event { font-weight: 700; letter-spacing: 0.8px; }

.tk-tag {
    font-size: 11px;
    font-weight: 700;
    letter-spacing: 0.6px;
    padding: 0 5px;
    border-radius: 3px;
    border: 1px solid;
}
.tk-pds  { color: #ff8833; border-color: rgba(255, 102, 0, 0.6); }
.tk-conf { color: #ff5555; border-color: rgba(255, 60, 60, 0.6); }

.tk-area  { color: rgba(255, 255, 255, 0.92); font-weight: 500; letter-spacing: 0.3px; }
.tk-until { color: rgba(255, 255, 255, 0.6); font-size: calc(13px * var(--ticker-scale, 1)); letter-spacing: 0.4px; }

.ticker-sep { color: rgba(255, 255, 255, 0.25); font-size: 9px; padding: 0 4px; }

.ticker-item-idle {
    color: rgba(255, 255, 255, 0.45);
    font-weight: 600;
    letter-spacing: 2px;
    animation: idle-breathe 4s ease-in-out infinite;
}
@keyframes idle-breathe {
    0%, 100% { opacity: 0.55; }
    50%      { opacity: 0.95; }
}

.ticker-hide {
    flex-shrink: 0;
    width: 26px;
    background: transparent;
    border: none;
    border-left: 1px solid rgba(255, 255, 255, 0.08);
    color: rgba(255, 255, 255, 0.35);
    font-size: 12px;
    cursor: pointer;
    transition: color 0.15s ease;
}
.ticker-hide:hover { color: #fff; }

#ticker-tab {
    display: none;
    position: fixed;
    right: 12px;
    bottom: 0;
    padding: 3px 12px;
    background: rgba(13, 19, 34, 0.95);
    border: 1px solid rgba(74, 158, 255, 0.4);
    border-bottom: none;
    border-radius: 6px 6px 0 0;
    font-family: var(--font-display);
    font-size: 12px;
    font-weight: 700;
    letter-spacing: 1.2px;
    color: rgba(255, 255, 255, 0.8);
    cursor: pointer;
    z-index: 600;
}
#ticker-tab.ticker-tab-visible { display: block; }
#ticker-tab.tab-hot {
    border-color: rgba(255, 60, 60, 0.7);
    color: #ff7777;
    animation: chip-pulse 1.6s infinite;
}
#ticker-tab b { color: #fff; }

/* Lift bottom-anchored UI above the ticker when it's visible */
body.ticker-active .map-legend        { bottom: calc(var(--ticker-h) + 44px); }
body.ticker-active .radar-control-bar { bottom: calc(var(--ticker-h) + 40px); }

/* ---- Slam banner (broadcast alert entrance) ---- */
.slam-banner {
    position: fixed;
    top: 11%;
    left: 50%;
    width: min(92vw, 920px);
    z-index: 3000;
    transform: translateX(-50%);
    border-radius: 10px;
    overflow: hidden;
    border: 1px solid color-mix(in srgb, var(--slam-accent, #ff3333) 70%, #ffffff);
    background:
        linear-gradient(110deg,
            color-mix(in srgb, var(--slam-accent, #ff3333) 58%, #0a0d16) 0%,
            color-mix(in srgb, var(--slam-accent, #ff3333) 34%, #0a0d16) 55%,
            #0a0d16 100%);
    box-shadow:
        0 12px 48px rgba(0, 0, 0, 0.7),
        0 0 36px color-mix(in srgb, var(--slam-accent, #ff3333) 45%, transparent);
    animation: slam-in 0.55s cubic-bezier(0.18, 1.4, 0.3, 1);
}

@keyframes slam-in {
    0%   { transform: translateX(-50%) translateY(-130%) scale(1.04); }
    60%  { transform: translateX(-50%) translateY(6%)    scale(1.01); }
    100% { transform: translateX(-50%) translateY(0)     scale(1); }
}

.slam-banner.slam-leaving {
    animation: slam-out 0.6s ease forwards;
}
@keyframes slam-out {
    to { opacity: 0; transform: translateX(-50%) translateY(-18px) scale(0.94); filter: blur(3px); }
}

.slam-flash {
    position: absolute;
    inset: 0;
    background: #ffffff;
    opacity: 0;
    pointer-events: none;
    animation: slam-flash 0.7s ease 0.45s;
}
@keyframes slam-flash {
    0%   { opacity: 0.85; }
    100% { opacity: 0; }
}

.slam-inner {
    position: relative;
    padding: 14px 22px 13px;
    text-align: center;
}

.slam-event {
    font-family: var(--font-display);
    font-size: clamp(30px, 5vw, 48px);
    font-weight: 700;
    letter-spacing: 3px;
    line-height: 1.05;
    color: #ffffff;
    text-shadow: 0 2px 14px rgba(0, 0, 0, 0.6);
}

.slam-banner.slam-te .slam-event {
    animation: slam-te-flash 0.8s steps(2) infinite;
}
@keyframes slam-te-flash {
    0%, 100% { color: #ffffff; }
    50%      { color: #ffb3ee; }
}

.slam-meta {
    display: flex;
    align-items: center;
    justify-content: center;
    flex-wrap: wrap;
    gap: 10px;
    margin-top: 5px;
    font-family: var(--font-display);
}

.slam-area  { font-size: 17px; font-weight: 500; color: rgba(255, 255, 255, 0.92); letter-spacing: 0.5px; }
.slam-until { font-size: 15px; font-weight: 700; color: rgba(255, 255, 255, 0.75); letter-spacing: 1px; }

.slam-badge {
    font-size: 12px;
    font-weight: 700;
    letter-spacing: 1px;
    padding: 1px 8px;
    border: 1px solid;
    border-radius: 3px;
    background: rgba(0, 0, 0, 0.28);
}

/* While a slam banner is on screen, the toast stack (and its footer bar)
   steps back so the two layers never visually collide. Restored when the
   slam queue empties. */
.toast-stack, .toast-footer {
    transition: opacity 0.35s ease, filter 0.35s ease;
}
body.slam-active .toast-stack,
body.slam-active .toast-footer {
    opacity: 0.08;
    filter: blur(2px);
    pointer-events: none;
}

/* Tornado Emergency screen-edge vignette pulse */
.slam-vignette {
    position: fixed;
    inset: 0;
    pointer-events: none;
    z-index: 2990;
    box-shadow: inset 0 0 120px 28px rgba(255, 0, 204, 0.4);
    animation: vignette-pulse 0.9s ease-in-out infinite;
}
@keyframes vignette-pulse {
    0%, 100% { opacity: 0.35; }
    50%      { opacity: 1; }
}
.slam-vignette.slam-vignette-leaving {
    transition: opacity 0.6s ease;
    opacity: 0 !important;
    animation: none;
}

/* MapLibre popup dark override for SPC */
.maplibregl-popup-content:has(.spc-popup) {
    background: rgba(12, 18, 32, 0.97);
    border: 1px solid rgba(255,140,0,0.3);
    border-radius: 8px;
    padding: 12px 14px;
}

/* ============ MRMS OVERLAYS (rotation tracks + MESH) ============ */
.mrms-row { flex: 1 1 100% !important; }
.mrms-btns {
    display: flex;
    gap: 6px;
    flex-wrap: wrap;
}
.mrms-btn {
    background: rgba(255, 255, 255, 0.06);
    border: 1px solid rgba(255, 255, 255, 0.16);
    color: #cfd6e4;
    font: inherit;
    font-size: 12px;
    padding: 4px 9px;
    border-radius: 12px;
    cursor: pointer;
    transition: background 0.15s, border-color 0.15s, color 0.15s;
    white-space: nowrap;
}
.mrms-btn:hover { background: rgba(255, 255, 255, 0.12); }
.mrms-btn.active {
    background: rgba(255, 60, 90, 0.22);
    border-color: rgba(255, 90, 120, 0.65);
    color: #ffffff;
}
.mrms-btn.loading { opacity: 0.55; cursor: progress; }

.mrms-legend {
    flex: 1 1 100%;
    margin-top: 6px;
    padding: 6px 8px;
    background: rgba(0, 0, 0, 0.25);
    border-radius: 6px;
    font-size: 11px;
}
.mrms-legend-row {
    display: flex;
    align-items: center;
    gap: 4px;
    flex-wrap: wrap;
    margin: 2px 0;
}
.mrms-legend-title {
    color: #9aa6ba;
    margin-right: 6px;
    font-size: 10.5px;
    text-transform: uppercase;
    letter-spacing: 0.04em;
}
.mrms-chip {
    color: #000;
    font-weight: 700;
    font-size: 10px;
    padding: 1px 6px;
    border-radius: 3px;
    text-shadow: 0 0 2px rgba(255,255,255,0.35);
}

/* ============ PROBSEVERE ============ */
.ps-legend {
    position: fixed;
    left: 12px;
    bottom: 86px;
    z-index: 640;
    background: rgba(10, 14, 24, 0.92);
    border: 1px solid rgba(255, 255, 255, 0.14);
    border-radius: 8px;
    padding: 8px 10px;
    font-size: 11px;
    color: #cfd6e4;
    backdrop-filter: blur(4px);
}
.ps-legend-head { font-weight: 700; letter-spacing: 0.06em; font-size: 10.5px; color: #9aa6ba; margin-bottom: 5px; cursor: move; display: flex; align-items: center; justify-content: space-between; gap: 8px; }
.ps-legend-ttl { pointer-events: none; }
.ps-legend-hide { background: none; border: none; color: #9aa6ba; font-size: 15px; line-height: 1; cursor: pointer; padding: 0 1px; }
.ps-legend-hide:hover { color: #fff; }
#probsevere-restore {
    position: fixed; left: 12px; bottom: 86px; z-index: 640;
    background: rgba(10, 14, 24, 0.92); border: 1px solid rgba(255, 200, 60, 0.5);
    color: #ffd45e; font-family: var(--font-display); font-weight: 700;
    font-size: 11px; letter-spacing: 0.06em; padding: 5px 9px; border-radius: 8px;
    cursor: pointer; box-shadow: 0 4px 14px rgba(0, 0, 0, 0.5);
}
#probsevere-restore:hover { border-color: rgba(255, 200, 60, 0.9); color: #fff; }
.ps-mode-row { display: flex; gap: 4px; margin-bottom: 6px; }
.ps-mode-chip {
    background: rgba(255,255,255,0.07);
    border: 1px solid rgba(255,255,255,0.18);
    color: #cfd6e4; font: inherit; font-size: 11px;
    padding: 2px 8px; border-radius: 10px; cursor: pointer;
}
.ps-mode-chip.on { background: rgba(255,60,90,0.25); border-color: rgba(255,90,120,0.7); color: #fff; }
.ps-scale-row { display: flex; gap: 3px; }
.ps-scale-chip { color: #000; font-weight: 700; font-size: 10px; padding: 1px 6px; border-radius: 3px; }
.ps-popup { font-size: 12px; color: #dfe5f1; max-height: 320px; overflow-y: auto; }
.ps-popup-title { font-weight: 700; margin-bottom: 6px; }
.ps-valid { color: #8b96ab; font-weight: 400; margin-left: 6px; font-size: 11px; }
.ps-prob-row { display: flex; flex-wrap: wrap; gap: 6px; margin-bottom: 7px; }
.ps-prob { background: rgba(255,255,255,0.05); padding: 2px 7px; border-radius: 4px; border: 1px solid transparent; font-size: 11px; }
.ps-prob-active { font-weight: 700; }
.ps-lines div { color: #aeb8c9; line-height: 1.45; }
.maplibregl-popup-content:has(.ps-popup) {
    background: rgba(12, 18, 32, 0.97);
    border: 1px solid rgba(255,80,110,0.35);
    border-radius: 8px;
    padding: 12px 14px;
}

/* ============ MESOANALYSIS PANEL ============ */
.meso-panel {
    position: fixed;
    top: 70px; right: 16px;
    z-index: 720;
    width: min(560px, 92vw);
    display: none;
    flex-direction: column;
    background: rgba(10, 14, 24, 0.96);
    border: 1px solid rgba(255, 255, 255, 0.16);
    border-radius: 10px;
    box-shadow: 0 10px 40px rgba(0,0,0,0.55);
    overflow: hidden;
}
.meso-head { display: flex; align-items: center; gap: 8px; padding: 8px 10px; cursor: move; background: rgba(255,255,255,0.05); }
.meso-title { font-weight: 700; font-size: 12px; letter-spacing: 0.06em; color: #e8edf6; white-space: nowrap; }
.meso-select { flex: 1; background: #141a28; color: #dfe5f1; border: 1px solid rgba(255,255,255,0.2); border-radius: 5px; font-size: 12px; padding: 3px 6px; min-width: 0; }
.meso-updated { font-size: 10.5px; color: #8b96ab; white-space: nowrap; }
.meso-close { background: none; border: none; color: #9aa6ba; font-size: 14px; cursor: pointer; padding: 2px 6px; }
.meso-close:hover { color: #fff; }
.meso-sectors { display: flex; flex-wrap: wrap; gap: 4px; padding: 6px 10px; background: rgba(255,255,255,0.03); }
.meso-sec-chip {
    background: rgba(255,255,255,0.06);
    border: 1px solid rgba(255,255,255,0.16);
    color: #cfd6e4; font-size: 11px; padding: 2px 8px;
    border-radius: 10px; cursor: pointer;
}
.meso-sec-chip.on { background: rgba(80,160,255,0.25); border-color: rgba(120,180,255,0.7); color: #fff; }
.meso-imgwrap { position: relative; background: #fff; min-height: 200px; }
.meso-img { display: block; width: 100%; height: auto; }
.meso-img-top { position: absolute; inset: 0; }
.meso-error {
    position: absolute; inset: 0;
    display: flex; align-items: center; justify-content: center;
    background: rgba(20,26,40,0.9); color: #aeb8c9; font-size: 13px;
}

/* ============ REPLAY ============ */
.replay-bar {
    position: fixed;
    left: 50%; transform: translateX(-50%);
    bottom: 14px;
    z-index: 760;
    display: none;
    align-items: center;
    gap: 7px;
    padding: 9px 12px;
    background: rgba(10, 14, 24, 0.96);
    border: 1px solid rgba(255, 170, 0, 0.45);
    border-radius: 10px;
    box-shadow: 0 8px 32px rgba(0,0,0,0.6);
    flex-wrap: wrap;
    max-width: 94vw;
}
.replay-badge {
    background: #ffaa00; color: #000;
    font-weight: 800; font-size: 11px; letter-spacing: 0.08em;
    padding: 3px 9px; border-radius: 5px;
    animation: replayPulse 1.6s ease-in-out infinite;
}
@keyframes replayPulse { 0%,100% { opacity: 1; } 50% { opacity: 0.55; } }
.replay-input {
    background: #141a28; color: #dfe5f1;
    border: 1px solid rgba(255,255,255,0.2);
    border-radius: 5px; font-size: 12px; padding: 3px 6px;
    color-scheme: dark;
}
.replay-btn {
    background: rgba(255,255,255,0.08);
    border: 1px solid rgba(255,255,255,0.2);
    color: #e8edf6; font-size: 12px; padding: 4px 10px;
    border-radius: 6px; cursor: pointer;
}
.replay-btn:hover { background: rgba(255,255,255,0.16); }
.replay-load { background: rgba(80,160,255,0.22); border-color: rgba(120,180,255,0.6); }
.replay-exit { background: rgba(255,60,60,0.22); border-color: rgba(255,90,90,0.6); font-weight: 700; }
.replay-scrub { width: 180px; accent-color: #ffaa00; }
.replay-clock { font-size: 12px; font-weight: 700; color: #ffd27f; min-width: 128px; text-align: center; }
.replay-sep { width: 1px; height: 20px; background: rgba(255,255,255,0.18); }
.replay-status { font-size: 11px; color: #8b96ab; }
body.replay-active .radar-control-bar,
body.replay-active #radar-bar-tab { display: none !important; }

/* ============ QUAD VIEW ============ */
#quad-grid {
    position: absolute;
    inset: 0;
    z-index: 540;
    display: grid;
    grid-template-columns: 1fr 1fr;
    grid-template-rows: 1fr 1fr;
    gap: 2px;
    background: #000;
}
.quad-cell { position: relative; min-height: 0; }
.quad-label {
    position: absolute;
    top: 6px; left: 8px;
    z-index: 5;
    background: rgba(8, 12, 20, 0.82);
    color: #e8edf6;
    font-size: 11px;
    font-weight: 700;
    letter-spacing: 0.05em;
    padding: 3px 8px;
    border-radius: 5px;
    border: 1px solid rgba(255,255,255,0.16);
    pointer-events: none;
}

/* ============ HOTKEYS + OBS CLEAN MODE ============ */
#hotkey-flash {
    position: fixed;
    left: 50%; top: 76px; transform: translateX(-50%);
    z-index: 900;
    background: rgba(10, 14, 24, 0.94);
    border: 1px solid rgba(255,255,255,0.22);
    color: #fff; font-size: 13px; font-weight: 600;
    padding: 7px 16px; border-radius: 8px;
    opacity: 0; pointer-events: none;
    transition: opacity 0.18s ease;
}
#hotkey-flash.show { opacity: 1; }
#hotkey-help {
    position: fixed;
    left: 50%; top: 50%; transform: translate(-50%, -50%);
    z-index: 950;
    background: rgba(10, 14, 24, 0.97);
    border: 1px solid rgba(255,255,255,0.2);
    border-radius: 10px;
    padding: 16px 20px;
    width: min(440px, 92vw);
    box-shadow: 0 14px 50px rgba(0,0,0,0.7);
}
#hotkey-help .hk-title { display: flex; justify-content: space-between; font-weight: 800; font-size: 13px; letter-spacing: 0.06em; color: #fff; margin-bottom: 10px; }
#hotkey-help #hk-close { background: none; border: none; color: #9aa6ba; cursor: pointer; font-size: 14px; }
#hotkey-help .hk-grid { display: grid; grid-template-columns: auto 1fr; gap: 5px 14px; font-size: 12.5px; }
#hotkey-help .hk-key { color: #ffd27f; font-weight: 700; font-family: monospace; }
#hotkey-help .hk-desc { color: #cfd6e4; }
body.obs-clean .header,
body.obs-clean .warnings-panel,
body.obs-clean .radar-control-bar,
body.obs-clean #radar-bar-tab,
body.obs-clean .map-legend,
body.obs-clean .panel-summary { display: none !important; }
body.obs-clean .map-container { width: 100vw !important; }
/* Engineering diagnostics must never reach an OBS clean scene. These two are
   the only overlays that were still surviving ?ui=clean (Silent-Failure audit,
   2026-07-31). !important is load-bearing on both: #tortrak-debug-overlay sets
   display inline from debugoverlay.js, and #l2diag-panel's display comes from
   the stylesheet l2diag.js injects into <head>, which would otherwise win on
   source order. Belt-and-suspenders with the state guard in l2diag.js — this
   rule holds even if the panel is somehow enabled. */
body.obs-clean #l2diag-panel,
body.obs-clean #tortrak-debug-overlay { display: none !important; }

/* ============ AUTOPILOT BROADCAST PILL ============ */
#autopilot-pill {
    position: fixed;
    /* Default spot sits BELOW the top-center broadcast band (toast stack
       start + always-on Replay/Reports bar, both z1500 > this z880) —
       at the old 70px the pill was permanently buried under that bar. */
    top: 132px;
    left: 50%;
    transform: translateX(-50%);
    z-index: 880;
    display: flex;
    align-items: center;
    /* All internal sizing is in em — JS scales the whole pill by setting
       font-size (scroll-wheel resize). */
    gap: 0.56em;
    padding: 0.48em 1.12em 0.48em 0.8em;
    border-radius: 999px;
    cursor: grab;
    user-select: none;
    touch-action: none;   /* pointer-event dragging on touch screens */
    color: #fff;
    font-size: 12.5px;
    font-weight: 800;
    letter-spacing: 0.12em;
    background:
        linear-gradient(rgba(10, 14, 24, 0.93), rgba(10, 14, 24, 0.93)) padding-box,
        linear-gradient(90deg, #ff3333, #ff8c00, #ff3333) border-box;
    background-size: auto, 250% 100%;
    border: 1.5px solid transparent;
    box-shadow: 0 2px 18px rgba(255, 60, 60, 0.35);
    overflow: hidden;
    animation: apBorderSweep 3.2s linear infinite;
}
#autopilot-pill.ap-all {
    background:
        linear-gradient(rgba(10, 14, 24, 0.93), rgba(10, 14, 24, 0.93)) padding-box,
        linear-gradient(90deg, #ff8c00, #ffd400, #ff8c00) border-box;
    background-size: auto, 250% 100%;
    box-shadow: 0 2px 18px rgba(255, 150, 0, 0.35);
}
@keyframes apBorderSweep {
    from { background-position: 0 0, 0% 50%; }
    to   { background-position: 0 0, 250% 50%; }
}
/* shimmer sweep across the text */
#autopilot-pill::after {
    content: '';
    position: absolute;
    top: 0; bottom: 0;
    width: 3.7em;
    left: -4.8em;
    background: linear-gradient(105deg, transparent, rgba(255,255,255,0.22), transparent);
    animation: apShimmer 2.8s ease-in-out infinite;
    pointer-events: none;
}
@keyframes apShimmer {
    0%   { left: -4.8em; }
    55%  { left: calc(100% + 1.6em); }
    100% { left: calc(100% + 1.6em); }
}
.ap-pill-dot {
    width: 0.64em; height: 0.64em;
    border-radius: 50%;
    background: #ff3b3b;
    box-shadow: 0 0 0.64em #ff3b3b;
    animation: apDot 1.1s ease-in-out infinite;
}
#autopilot-pill.ap-all .ap-pill-dot { background: #ffaa00; box-shadow: 0 0 0.64em #ffaa00; }
@keyframes apDot { 0%, 100% { opacity: 1; } 50% { opacity: 0.25; } }
.ap-pill-cam { font-size: 1.04em; }
.ap-pill-mode {
    background: rgba(255, 255, 255, 0.14);
    border-radius: 0.32em;
    padding: 0.08em 0.56em;
    font-size: 0.84em;
    letter-spacing: 0.08em;
    color: #ffd9c2;
}
#autopilot-pill.ap-dragging {
    cursor: grabbing;
    opacity: 0.88;
    box-shadow: 0 6px 28px rgba(0, 0, 0, 0.6);
}

/* ============ RADAR MODE PILL (operator HUD) ============ */
#radar-pill {
    position: fixed;
    /* Default: centered over the alerts area. left:50% + translateX(-50%) keeps
       it centered through window resizes and label-width changes for free. A
       drag overrides this with absolute left/top (radarpill.js); the dragged
       position persists (seRadarPillPos) and is restored on launch — right-click
       clears it and returns the pill to this CSS-centered default. */
    bottom: 104px;
    left: 50%;
    transform: translateX(-50%);
    z-index: 870;
    display: flex;
    align-items: center;
    gap: 0.5em;
    padding: 0.42em 1em 0.42em 0.75em;
    border-radius: 999px;
    cursor: grab;
    user-select: none;
    touch-action: none;
    color: #d9f3ff;
    font-size: 11.5px;
    font-weight: 700;
    letter-spacing: 0.1em;
    background: rgba(10, 16, 26, 0.92);
    border: 1.5px solid rgba(54, 198, 255, 0.55);
    box-shadow: 0 2px 14px rgba(54, 198, 255, 0.22);
}
/* Dock the radar mode pill just above the warning count strip so it never
   overlaps the pills. Mirrors #alert-countstrip's own bottom offsets (the pill
   used to sit at a fixed bottom:104px and collide when the ticker / count strip
   raised the pills). A dragged pill still overrides these via inline style. */
body.countstrip-on #radar-pill { bottom: calc(var(--pillstrip-h, 46px) + 20px); }
body.ticker-active.countstrip-on #radar-pill { bottom: calc(var(--ticker-h, 32px) + var(--pillstrip-h, 46px) + 22px); }
body.ticker-active.countstrip-off #radar-pill { bottom: calc(var(--ticker-h, 32px) + 20px); }
/* When the SignalCast on-air bug is up, raise the pill above it so the on-air
   stack reads: radar pill > SignalCast > warning count strip. */
body.signalcast-bug-on.countstrip-on #radar-pill { bottom: calc(var(--pillstrip-h, 46px) + 56px); }
body.signalcast-bug-on.ticker-active.countstrip-on #radar-pill { bottom: calc(var(--ticker-h, 32px) + var(--pillstrip-h, 46px) + 58px); }
body.signalcast-bug-on.countstrip-off #radar-pill { bottom: 56px; }
body.signalcast-bug-on.ticker-active.countstrip-off #radar-pill { bottom: calc(var(--ticker-h, 32px) + 56px); }

/* ============ MOSAIC STATUS PILL (js/mosaic.js) ============ */
/* Positioning lives here, NOT in ensurePill()'s inline cssText (which now only
   carries the pill's visual styling). Bottom offsets ride above the alert
   ticker / warning count strip via --ticker-h / --pillstrip-h, same convention
   as #radar-pill, #hurricane-tab, #detail-restore-tab and .map-legend above.
   Constants are chosen so the pill stays at its historical bottom:64px spot at
   the default --ticker-scale and only rises when the ticker/strip actually
   need the room (offsets scale with --ticker-scale automatically).
   z-index 610 beats #alert-ticker (600) and #alert-countstrip (599) — the pill
   is a child of .map-container, which creates no stacking context, so this
   competes directly with the ticker's z-index and guarantees the pill can
   never paint underneath it even if the ticker's height changes. */
#mosaic-pill {
    position: absolute;
    left: 12px;
    bottom: 64px;
    z-index: 610;
}
body.countstrip-on #mosaic-pill { bottom: calc(var(--pillstrip-h, 46px) + 18px); }
body.ticker-active #mosaic-pill { bottom: calc(var(--ticker-h, 32px) + 32px); }
body.ticker-active.countstrip-on #mosaic-pill { bottom: calc(var(--ticker-h, 32px) + var(--pillstrip-h, 46px) + 18px); }

/* ============ LIVESWEEP STATUS PILL (js/livesweep-glue.js) ============ */
/* Same deal as #mosaic-pill above: positioning lives here, ensurePill()'s inline
   cssText carries visuals only. It previously hardcoded bottom:34px / z-index:45,
   which put it UNDER the alert ticker (600) both in space and in stacking order —
   on a ticker-active broadcast layout the pill was simply invisible.
   Offsets sit one slot (42px) above the mosaic pill's, so if both status pills are
   ever up at once they stack instead of overlapping in the same bottom-left spot. */
#livesweep-pill {
    position: absolute;
    left: 12px;
    bottom: 106px;
    z-index: 610;
}
body.countstrip-on #livesweep-pill { bottom: calc(var(--pillstrip-h, 46px) + 60px); }
body.ticker-active #livesweep-pill { bottom: calc(var(--ticker-h, 32px) + 74px); }
body.ticker-active.countstrip-on #livesweep-pill { bottom: calc(var(--ticker-h, 32px) + var(--pillstrip-h, 46px) + 60px); }

#radar-pill.rp-dim {
    border-color: rgba(255, 255, 255, 0.18);
    box-shadow: none;
    color: #8b96ab;
    opacity: 0.75;
}
#radar-pill.rp-dragging {
    cursor: grabbing;
    opacity: 0.88;
    box-shadow: 0 6px 28px rgba(0, 0, 0, 0.6);
}
.rp-dot {
    width: 0.6em; height: 0.6em;
    border-radius: 50%;
    flex: none;
}
.rp-dot-live  { background: #2eff7e; box-shadow: 0 0 0.55em #2eff7e; }
.rp-dot-amber { background: #ffb300; box-shadow: 0 0 0.55em #ffb300; }
.rp-dot-off   { background: #5a6477; }
.rp-dot-down  { background: #ff2a2a; box-shadow: 0 0 0.6em #ff2a2a; animation: rp-down-blink 1s steps(2) infinite; }
@keyframes rp-down-blink { 50% { opacity: 0.25; } }
.rp-down-tag  { color: #ff5a5a; font-weight: 700; letter-spacing: 0.02em; }
.rp-icon { font-size: 1.05em; }
.rp-badge {
    border-radius: 0.3em;
    padding: 0.06em 0.5em;
    font-size: 0.8em;
    letter-spacing: 0.08em;
}
.rp-auto { background: rgba(46, 255, 126, 0.16); color: #8fffc0; border: 1px solid rgba(46,255,126,0.4); }
.rp-lock { background: rgba(255, 179, 0, 0.16);  color: #ffd98a; border: 1px solid rgba(255,179,0,0.4); }
.rp-mode-clear  { background: rgba(90, 180, 255, 0.14); color: #a8d6ff; border: 1px solid rgba(90,180,255,0.4); }
.rp-mode-precip { background: rgba(120, 220, 120, 0.14); color: #b2f0b2; border: 1px solid rgba(120,220,120,0.4); }
.rp-range { background: rgba(245, 166, 35, 0.18); color: #ffce82; border: 1px solid rgba(245,166,35,0.5); }
.rp-range-far { background: rgba(255, 75, 75, 0.20); color: #ff9b9b; border: 1px solid rgba(255,75,75,0.55); }
/* audit 2026-07-27 #1: live edge lost — timeline on completed volumes only.
   Amber, NOT red: the station is still healthy, the data is just older. Kept
   visually distinct from .rp-range (also amber) by the heavier weight. */
.rp-edge-lost { background: rgba(255, 140, 0, 0.22); color: #ffc46b; border: 1px solid rgba(255,140,0,0.6); font-weight: 700; }
/* operator-only: never visible in OBS clean scenes */
body.obs-clean #radar-pill { display: none !important; }
/* keep the transient hotkey toast clear of the pill */
#hotkey-flash { top: 118px; }

/* ============================================
   FLOATING MAP LEGEND (legendfloat.js)
   Pop-out twin of the Active Warnings panel float —
   same button look, same blue glow when detached.
   ============================================ */
/* Make room for the float + hide buttons beside the "Warnings" title */
.map-legend .legend-title { padding-right: 56px; }

/* Hidden legend (× button / Map Layers toggle) — display:none beats the
   ticker/countstrip offset rules and the floating overrides alike. */
.map-legend.legend-hidden { display: none !important; }

/* "×" hide button — sits left of the pop-out button, red tint on hover */
.legend-hide-btn { right: 36px; }
.legend-hide-btn:hover {
    background: rgba(255, 95, 95, 0.15);
    color: #ff5f5f;
    border-color: rgba(255, 95, 95, 0.5);
}

.legend-float-btn {
    position: absolute;
    top: 8px;
    right: 9px;
    width: 22px;
    height: 22px;
    padding: 0;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    background: transparent;
    border: 1px solid var(--border-color);
    border-radius: 5px;
    color: var(--text-muted);
    cursor: pointer;
    transition: all 0.15s ease;
}
.legend-float-btn:hover {
    background: rgba(74, 158, 255, 0.15);
    color: #4a9eff;
    border-color: rgba(74, 158, 255, 0.5);
}
.legend-float-btn.is-floating {
    background: rgba(74, 158, 255, 0.22);
    color: #4a9eff;
    border-color: rgba(74, 158, 255, 0.55);
}

/* Detached mode — fixed overlay, draggable anywhere. The !importants
   beat the ticker/countstrip bottom-offset rules that reposition the
   docked legend (body.ticker-active .map-legend …), which would
   otherwise outrank this class and yank the floating legend around
   whenever the ticker toggles. */
.map-legend.floating {
    position: fixed !important;
    bottom: auto !important;
    right: auto !important;
    z-index: 150;
    cursor: move;
    user-select: none;
    touch-action: none;   /* pointer-event dragging on touch screens */
    box-shadow:
        0 16px 50px rgba(0, 0, 0, 0.65),
        0 0 0 1px rgba(74, 158, 255, 0.18),
        0 0 22px rgba(74, 158, 255, 0.12);
}
.map-legend.floating .legend-float-btn { cursor: pointer; }
.map-legend.legend-dragging {
    opacity: 0.92;
    box-shadow: 0 6px 28px rgba(0, 0, 0, 0.6);
}

/* ============================================
   VOICE PANEL — announce-category checkboxes
   (explicit voice filter, replaces panel-tab coupling)
   ============================================ */
.voice-announce-group {
    display: flex;
    flex-direction: column;
    gap: 5px;
    margin: 2px 0 12px;
}
.voice-ann-row {
    display: flex;
    align-items: center;
    gap: 8px;
    font-size: 12px;
    color: var(--text-secondary);
    cursor: pointer;
    user-select: none;
}
.voice-ann-row input[type="checkbox"] {
    accent-color: #4a9eff;
    cursor: pointer;
    margin: 0;
}
.voice-ann-locked {
    font-size: 10.5px;
    color: var(--text-muted);
    margin-top: 3px;
}

/* ============================================
   WARNING POPUP — SPC outlook context line
   (shown when a warning is clicked over an SPC risk area;
   replaces the old second popup that fought for the spot)
   ============================================ */
.popup-spc-context {
    margin-top: 7px;
    padding: 5px 10px;
    font-size: 10.5px;
    font-weight: 600;
    letter-spacing: 0.3px;
    color: #ffb74a;
    background: rgba(255, 140, 0, 0.08);
    border: 1px solid rgba(255, 140, 0, 0.25);
    border-radius: 5px;
}

/* ============================================
   PANEL TABS — five-up since the Confirmed tab
   (wrap instead of overflowing the 420px panel)
   ============================================ */
.panel-tabs { flex-wrap: wrap; }
.panel-tabs .tab-btn { padding: 6px 11px; }
.tab-btn.tab-btn-confirmed.active {
    background: var(--accent-red, #ff3333);
    border-color: var(--accent-red, #ff3333);
}

/* ============================================
   FLOATING RADAR CONTROL BAR (radarbarfloat.js)
   Pop-out twin of the legend/panel floats — the whole bar
   (playback + scrubber + settings flyout) detaches into a
   fixed draggable overlay. Hide/show rules from minimize,
   replay mode, and obs-clean still apply unchanged.
   ============================================ */
.radar-control-bar.floating {
    position: fixed !important;
    bottom: auto !important;
    /* Zoom survives in floating mode; top-left origin keeps the dragged
       left/top anchor exact while the bar grows down-right. */
    transform: scale(var(--rbf-scale, 1)) !important;
    transform-origin: 0 0 !important;
    animation: none !important;
    width: min(680px, calc(100vw - 20px));
    max-width: none;
    z-index: 860;             /* above panels/legend, below the radar pill */
    user-select: none;
    touch-action: none;       /* pointer-event dragging on touch screens */
    box-shadow:
        0 16px 50px rgba(0, 0, 0, 0.65),
        0 0 0 1px rgba(74, 158, 255, 0.18),
        0 0 22px rgba(74, 158, 255, 0.12);
}
.radar-control-bar.radarbar-dragging {
    opacity: 0.88;
    cursor: grabbing;
}
/* Corner zoom grip (radarbarfloat.js 2026-08-02) — drag to scale the whole
   bar, right-click the grip to snap back to 100%. Present docked AND
   floating. The `.radar-control-bar > *` rule forces children to
   position:relative/z-index:1; this more-specific rule wins it back. */
.radar-control-bar .radarbar-zoom-grip {
    position: absolute;
    right: 1px;
    bottom: 1px;
    width: 16px;
    height: 16px;
    z-index: 3;
    display: flex;
    align-items: flex-end;
    justify-content: flex-end;
    cursor: nwse-resize;
    color: rgba(140, 190, 255, 0.45);
    touch-action: none;
    user-select: none;
}
.radar-control-bar .radarbar-zoom-grip:hover,
.radar-control-bar.radarbar-zooming .radarbar-zoom-grip {
    color: rgba(140, 190, 255, 0.95);
}
#radar-bar-float.active {
    background: rgba(74, 158, 255, 0.2);
    border-color: rgba(74, 158, 255, 0.55);
    color: #4a9eff;
}

/* ============================================
   VERTICAL STREAM MODE — TTLS / portrait 9:16 captures
   body.vertical-mode is applied by js/verticalmode.js when:
     (a) Auto (default) — the window is taller than it is wide,
     (b) the Tools-menu "Vertical" toggle is forced ON, or
     (c) the page is loaded with ?vertical=1.
   Header becomes two rows — branding + live status on top, a
   full-width evenly-spaced icon-only button row below. The
   clock and last-update are hidden to make room (tooltips on
   hover still name every button).
   Declared LAST in the file so it wins ties against the
   width-based responsive blocks above.
   ============================================ */
body.vertical-mode {
    display: flex;
    flex-direction: column;
    height: 100vh;
    overflow: hidden;
}

body.vertical-mode .header {
    flex-direction: row;
    align-items: center;
    height: auto;
    max-height: none;
    overflow: visible;
    flex-shrink: 0;
    padding: 4px 12px;
    gap: 10px;
}

/* Single line: branding | buttons | status. .header-left dissolves
   (display:contents) so .header-brand and .status-bar become direct
   flex items of .header and the button cluster can sit between them.
   Sizing for these three lives in the "balanced sidebands" rule below. */
body.vertical-mode .header-left   { display: contents; }
body.vertical-mode .header-brand  { order: 1; }
body.vertical-mode .header-right  { order: 2; }
body.vertical-mode .status-bar    { order: 3; }
body.vertical-mode .logo          { flex-shrink: 0; }

/* Stack the build badge UNDER the logo instead of beside it. Side by
   side the badge ran ~200-240px wide (10px type + 1.5px tracking across
   "DEV BUILD L2CC V31 / RADAR V53") — wider than the logo itself — which
   made the left side of the header roughly 370px against a ~230px status
   block on the right. Stacking + compacting drops the whole branding
   column to the logo's own width, so the two sides are close to balanced
   and the button row has room to sit centered on one line. */
body.vertical-mode .header-brand {
    flex-direction: column;
    align-items: flex-start;
    gap: 1px;
}

/* Compact branding so row 1 stays short (base locks the img at 40px) */
body.vertical-mode .logo { gap: 8px; }
body.vertical-mode .logo-img {
    width: 30px;
    height: 30px;
    min-width: 30px;
    max-width: 30px;
    min-height: 30px;
    max-height: 30px;
}
body.vertical-mode .logo h1 { font-size: 13px; letter-spacing: 1px; }
body.vertical-mode .logo .logo-subtitle { font-size: 9px; letter-spacing: 1.5px; }

/* Compact build badge — thin chip so the stacked row costs as little
   header height as possible. font-size:0 swallows the literal
   "DEV BUILD " text node (it's a bare text node, not selectable), and
   ::before puts a short "DEV" back; the version span keeps its own size.
   Net label: "DEV L2CC V31 / RADAR V53" at ~137px, narrower than the
   logo above it, so the badge no longer drives the column width. */
body.vertical-mode .dev-build-badge {
    font-size: 0;
    letter-spacing: 0;
    gap: 4px;
    padding: 1px 5px;
    border-radius: 3px;
    align-self: flex-start;
}
body.vertical-mode .dev-build-badge::before {
    content: "DEV";
    font-size: 8px;
    font-weight: 700;
    letter-spacing: 0.8px;
    line-height: 1.2;
}
body.vertical-mode .dev-build-version {
    font-size: 8px;
    letter-spacing: 0.4px;
    line-height: 1.2;
}

/* Hide the clock, last-update and their separators */
body.vertical-mode .header-clock,
body.vertical-mode #last-update,
body.vertical-mode .status-bar .separator { display: none; }

body.vertical-mode .status-bar {
    gap: 8px;
    overflow: hidden;
    white-space: nowrap;
}

/* Keep the warning count visible & prominent — it matters on stream.
   (Also overrides the ≤680px rule that hides it; ID selector there.) */
body.vertical-mode #warning-count {
    display: inline;
    font-weight: 700;
}

/* Buttons — one tight cluster sized to its contents. It is NOT the
   flexible element any more; the two side blocks are (see the balanced
   sidebands rule below), which is what actually centers it. flex-shrink
   stays enabled so a genuinely cramped window still wraps the cluster
   rather than overflowing the header. */
body.vertical-mode .header-right {
    flex: 0 1 auto;
    min-width: 0;
    width: auto;
    justify-content: center;
    align-items: center;
    gap: 5px;
    flex-wrap: wrap;
    overflow: visible;
}

/* Icon-only buttons: collapse text labels, keep glyphs (same
   font-size:0 trick as the 681–1024px block above) */
body.vertical-mode .header-right .control-btn {
    font-size: 0;
    gap: 0;
    padding: 5px 8px;
    min-height: 28px;
    justify-content: center;
    flex-shrink: 0;
}

/* Restore emoji glyphs that inherit font-size */
body.vertical-mode .header-right .control-btn .voice-btn-icon,
body.vertical-mode .header-right .control-btn .toast-toggle-icon {
    font-size: 14px;
}

/* Keep the Layers active-count badge readable */
body.vertical-mode .header-right .control-btn .layers-count {
    font-size: 10px;
    margin-left: 3px;
}

body.vertical-mode .header-right .control-btn svg {
    width: 16px;
    height: 16px;
}

/* Search input stays modest so it doesn't shove the row around */
body.vertical-mode .geo-search.open .geo-search-form { width: 150px; }
body.vertical-mode .geo-search-input { font-size: 12px; }

/* ---- Balanced sidebands = a truly centered button cluster ----------
   The old layout made the BUTTON row the flexible element, so it was
   only centered within the leftover space between branding and status.
   Because those two blocks are different widths, the cluster sat
   off-centre and the offset moved on every resize.

   Invert it: the cluster sizes to its content, and the two side blocks
   each take `flex: 1 1 0`. Equal flex weight + equal (zero) basis means
   they always resolve to the SAME width, which puts the cluster exactly
   on the header's midpoint — at any window size, with no media query,
   no absolute positioning, and no chance of the blocks overlapping the
   way absolute positioning would risk.

   min-width:max-content is the graceful-degradation valve: when the
   window really is too narrow to give both sides an equal share, the
   status text refuses to clip and the cluster drifts slightly instead
   of losing "N Active Warnings" off the edge. ---- */
body.vertical-mode .header-brand,
body.vertical-mode .status-bar {
    flex: 1 1 0;
    min-width: max-content;
}

body.vertical-mode .status-bar {
    justify-content: flex-end;
}

/* Narrow portrait (true phone-shaped windows) — the single line
   can't fit, so wrap: logo + status on top, buttons below. */
@media (max-width: 799px) {
    body.vertical-mode .header { flex-wrap: wrap; row-gap: 3px; padding: 4px 10px 5px; }
    body.vertical-mode .status-bar { order: 2; margin-left: auto; }
    body.vertical-mode .header-right { order: 3; flex-basis: 100%; }
}

/* Fixed overlays were positioned for the 60px single-row header —
   track the real header height (--se-header-h, measured by
   verticalmode.js on resize) so they always sit just below it. */
body.vertical-mode .radar-scalebar { top: calc(var(--se-header-h, 73px) + 7px); }
body.vertical-mode .toast-stack {
    top: calc(var(--se-header-h, 73px) + 13px);
    max-height: calc(100vh - var(--se-header-h, 73px) - 71px - var(--ticker-h, 32px) - var(--pillstrip-h, 46px));
}
body.vertical-mode.scalebar-active .toast-stack {
    top: calc(var(--se-header-h, 73px) + 47px);
    max-height: calc(100vh - var(--se-header-h, 73px) - 105px - var(--ticker-h, 32px) - var(--pillstrip-h, 46px));
}

/* ---- Detail section (below the map) ----
   The vertical layout pulls it into the viewport, where the fixed
   bottom broadcast strip (TOR/SVR count pills + ticker) painted on
   top of its text. Give it a fixed, internally-scrollable slot and
   reserve the strip's space below it with margin, so the pills sit
   in their own clear zone and the text reads correctly. */
body.vertical-mode .detail-section {
    flex-shrink: 0;
    height: 220px;
    min-height: 0;
    overflow-y: auto;
    padding: 0 16px 16px;
    scrollbar-width: thin;
}

body.vertical-mode .detail-section-header { padding: 10px 0 8px; margin-bottom: 12px; }

/* Reserve room for whichever bottom overlays are active */
body.vertical-mode.countstrip-on .detail-section {
    margin-bottom: calc(var(--pillstrip-h, 46px) + 14px);
}
body.vertical-mode.ticker-active .detail-section {
    margin-bottom: calc(var(--ticker-h, 32px) + 8px);
}
body.vertical-mode.ticker-active.countstrip-on .detail-section {
    margin-bottom: calc(var(--ticker-h, 32px) + var(--pillstrip-h, 46px) + 18px);
}

/* Main area flexes to fill whatever is left below the header
   (the base rule hardcodes calc(100vh - 60px) for a 60px header) */
body.vertical-mode .main-content {
    flex: 1;
    min-height: 0;
    height: auto;
}

/* ============================================
   DETAIL SECTION COLLAPSE — Tornado Warnings panel
   body.detail-collapsed is toggled by js/detailcollapse.js via the
   chevron in the section header (state persists). Collapsed, only
   the title bar remains; in vertical mode the freed space goes
   straight to the map (flex), with the pill/ticker zone preserved.
   ============================================ */
.detail-collapse-btn {
    padding: 6px 10px;
    background: transparent;
    border: 1px solid var(--border-color);
    border-radius: var(--radius);
    color: var(--text-secondary);
    font-size: 12px;
    cursor: pointer;
    line-height: 1;
}

.detail-collapse-btn:hover {
    color: var(--text-primary);
    border-color: var(--accent-blue);
}

.detail-collapse-caret {
    display: inline-block;
    transition: transform 0.2s ease;
}

body.detail-collapsed .detail-collapse-caret { transform: rotate(-90deg); }

/* Hide everything but the title bar */
body.detail-collapsed .detail-section > *:not(.detail-section-header) { display: none; }

body.detail-collapsed .detail-section {
    min-height: 0;
    padding-bottom: 6px;
}

body.detail-collapsed .detail-section-header {
    margin-bottom: 0;
    border-bottom: none;
}

/* Vertical mode: the fixed 220px slot shrinks to the title bar */
body.vertical-mode.detail-collapsed .detail-section {
    height: auto;
    overflow: hidden;
}

/* ---- Fully hidden: the map takes the space; the count pills,
   radar pill and other fixed overlays float straight on the map.
   A small tab at the bottom-right brings the panel back. ---- */
body.detail-hidden .detail-section { display: none; }

#detail-restore-tab {
    display: none;
    position: fixed;
    right: 12px;
    bottom: 34px;
    padding: 4px 12px;
    background: rgba(13, 19, 34, 0.92);
    border: 1px solid rgba(74, 158, 255, 0.4);
    border-radius: 6px;
    font-family: var(--font-display);
    font-size: 11px;
    font-weight: 700;
    letter-spacing: 1.2px;
    color: rgba(255, 255, 255, 0.8);
    cursor: pointer;
    z-index: 600;
    backdrop-filter: blur(8px);
}

#detail-restore-tab:hover {
    color: #fff;
    border-color: rgba(74, 158, 255, 0.8);
}

body.detail-hidden #detail-restore-tab { display: block; }

/* Ride above the ticker when it's on */
body.ticker-active #detail-restore-tab {
    bottom: calc(var(--ticker-h, 32px) + 10px);
}
body.countstrip-on #detail-restore-tab {
    bottom: calc(var(--pillstrip-h, 46px) + 20px);
}
body.ticker-active.countstrip-on #detail-restore-tab {
    bottom: calc(var(--ticker-h, 32px) + var(--pillstrip-h, 46px) + 20px);
}

/* Compact hiding is a layout default, not a veto on an explicit restore.
   Keep a way back even when no saved hide preference exists. */
@media (max-width: 680px) {
    body:not(.detail-shown) #detail-restore-tab { display: block; }
    body.detail-shown:not(.detail-hidden) .detail-section {
        display: block;
        flex-shrink: 0;
        height: min(220px, 30vh);
        min-height: 0;
        padding: 0 12px 12px;
        overflow-y: auto;
        scrollbar-width: thin;
    }
    body.detail-shown .detail-section-header { padding: 8px 0; margin-bottom: 10px; }
    body.detail-shown .map-container { min-height: 0; }
    body.detail-shown.detail-collapsed .detail-section {
        height: auto;
        padding-bottom: 6px;
        overflow: hidden;
    }
    body.detail-shown.detail-collapsed .detail-section-header { margin-bottom: 0; }
    body.detail-shown.countstrip-on .detail-section {
        margin-bottom: calc(var(--pillstrip-h, 46px) + 14px);
    }
    body.detail-shown.ticker-active .detail-section {
        margin-bottom: calc(var(--ticker-h, 32px) + 8px);
    }
    body.detail-shown.ticker-active.countstrip-on .detail-section {
        margin-bottom: calc(var(--ticker-h, 32px) + var(--pillstrip-h, 46px) + 18px);
    }
}

/* Autopilot pill default — track the real header height in vertical mode
   and clear the scale bar + Replay/Reports band below it */
body.vertical-mode #autopilot-pill {
    top: calc(var(--se-header-h, 73px) + 96px);
}

/* ============================================
   WIND FLOW LAYER — particle canvas (js/windparticles.js)
   ============================================ */
#wind-canvas {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    pointer-events: none;
    z-index: 1;          /* over the map canvas, under HTML overlays */
}

/* Keep in-map HTML overlays above the wind canvas */
.map-legend { z-index: 5; }

/* Map popups (Weather Here, storm reports, SPC, etc.) must also sit
   above the wind canvas — otherwise particles streak across them and
   the popup looks transparent no matter what its background says. */
.maplibregl-popup { z-index: 6; }

/* Wind button shows amber while data is failing/rate-limited */
#btn-wind-toggle.wind-degraded {
    border-color: rgba(255, 170, 0, 0.6);
    color: #ffaa00;
}

/* Wind opacity row inside the Layers menu */
.wind-opacity-row {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 2px 10px 6px 26px;
}

.wind-opacity-label {
    font-size: 10px;
    color: var(--text-muted);
    white-space: nowrap;
}

.wind-opacity-row input[type="range"] {
    flex: 1;
    min-width: 70px;
    accent-color: var(--accent-blue);
    height: 3px;
}

.wind-opacity-val {
    font-size: 10px;
    color: var(--text-secondary);
    min-width: 30px;
    text-align: right;
}

/* ============================================
   MESO PANEL — wheel zoom, drag pan, corner resize (js/meso.js)
   ============================================ */
.meso-imgwrap {
    overflow: hidden;          /* clip the zoomed image */
}

.meso-zoom {
    position: relative;
    transform-origin: 0 0;
    will-change: transform;
}

.meso-imgwrap.meso-zoomed  { cursor: grab; }
.meso-imgwrap.meso-panning { cursor: grabbing; }

.meso-zoom-badge {
    position: absolute;
    top: 8px;
    right: 8px;
    padding: 3px 8px;
    background: rgba(10, 14, 24, 0.85);
    border: 1px solid rgba(255, 255, 255, 0.25);
    border-radius: 999px;
    color: #dfe5f1;
    font-size: 11px;
    font-weight: 700;
    letter-spacing: 0.04em;
    pointer-events: none;
    z-index: 3;
}

.meso-resize {
    position: absolute;
    right: 0;
    bottom: 0;
    width: 18px;
    height: 18px;
    cursor: nwse-resize;
    z-index: 5;
    /* diagonal grip lines */
    background:
        linear-gradient(135deg, transparent 0 57%, rgba(255,255,255,0.45) 57% 63%,
                        transparent 63% 72%, rgba(255,255,255,0.45) 72% 78%,
                        transparent 78% 87%, rgba(255,255,255,0.45) 87% 93%, transparent 93%);
}

.meso-resize:hover {
    background:
        linear-gradient(135deg, transparent 0 57%, rgba(116,200,255,0.9) 57% 63%,
                        transparent 63% 72%, rgba(116,200,255,0.9) 72% 78%,
                        transparent 78% 87%, rgba(116,200,255,0.9) 87% 93%, transparent 93%);
}

/* ============================================================
   V2 FEATURE PACK — satellite, ghosts, sounding, director,
   cross-section slicer, recap reel
   ============================================================ */

/* ---- Satellite legend (bottom-left, stacks above PS legend) ---- */
.sat-legend {
    position: fixed; left: 12px; bottom: 196px; z-index: 640;
    width: 236px; max-width: calc(100vw - 8px);
    background: rgba(10, 14, 24, 0.92);
    border: 1px solid rgba(255, 255, 255, 0.14);
    border-radius: 8px; padding: 7px 9px;
    font-size: 11px; color: #cfd6e4;
    backdrop-filter: blur(4px); display: none;
}
.sat-legend-head { font-weight: 700; letter-spacing: 0.06em; font-size: 10.5px; color: #9aa6ba; margin-bottom: 5px; }
.sat-mode-row { display: flex; gap: 4px; }
.sat-mode-chip {
    background: rgba(255,255,255,0.07);
    border: 1px solid rgba(255,255,255,0.18);
    color: #cfd6e4; font: inherit; font-size: 11px;
    padding: 2px 8px; border-radius: 999px; cursor: pointer;
}
.sat-mode-chip.on { background: rgba(126,240,255,0.18); border-color: #7ef0ff; color: #d8f8ff; }
.sat-warn { margin-top: 5px; color: #ffb74d; font-size: 10.5px; }
.sat-status { margin-top: 4px; color: #9aa6ba; font-size: 10.5px; }

/* ---- Hurricanes / tropical legend (draggable; mirrors .sat-legend) ---- */
.hurr-legend {
    position: fixed; left: 12px; bottom: 330px; z-index: 641;
    width: 234px; max-height: 72vh; overflow-y: auto;
    background: rgba(10, 14, 24, 0.92);
    border: 1px solid rgba(255, 255, 255, 0.14);
    border-radius: 8px; padding: 7px 9px;
    font-size: 11px; color: #cfd6e4;
    backdrop-filter: blur(4px); display: none;
}
.hurr-legend-head { display: flex; align-items: center; justify-content: space-between; gap: 6px; margin-bottom: 6px; cursor: move; }
.hurr-legend-title { font-weight: 700; letter-spacing: 0.06em; font-size: 10.5px; color: #9aa6ba; }
.hurr-legend-x {
    flex: 0 0 auto; background: rgba(255, 255, 255, 0.06); border: 1px solid rgba(255, 255, 255, 0.18);
    color: #cdd6e4; font: inherit; font-size: 11px; line-height: 1; width: 20px; height: 18px;
    border-radius: 5px; cursor: pointer; padding: 0;
}
.hurr-legend-x:hover { background: rgba(255, 90, 90, 0.30); border-color: #ff6b6b; color: #fff; }
.hurr-legend-actions { display: flex; gap: 4px; align-items: center; flex: 0 0 auto; }
.hurr-legend-hide {
    flex: 0 0 auto; background: rgba(255, 255, 255, 0.06); border: 1px solid rgba(255, 255, 255, 0.18);
    color: #cdd6e4; font: inherit; font-size: 11px; line-height: 1; width: 20px; height: 18px;
    border-radius: 5px; cursor: pointer; padding: 0;
}
.hurr-legend-hide:hover { background: rgba(0, 140, 255, 0.28); border-color: #4aa3ff; color: #fff; }

/* Right-edge restore tab — tropical panel hidden but overlay still live */
.hurr-tab {
    display: none;
    position: fixed; right: 12px; bottom: 160px; z-index: 650;
    padding: 4px 12px;
    background: rgba(10, 14, 23, 0.94);
    border: 1px solid rgba(0, 140, 255, 0.45);
    border-radius: 6px;
    font-family: var(--font-display);
    font-size: 11px; font-weight: 700; letter-spacing: 1.5px;
    color: rgba(255, 255, 255, 0.85);
    cursor: pointer;
    box-shadow: 0 4px 14px rgba(0, 0, 0, 0.5);
}
.hurr-tab:hover { color: #4aa3ff; border-color: rgba(0, 140, 255, 0.8); }
body.ticker-active #hurricane-tab { bottom: calc(var(--ticker-h) + 164px); }
body.ticker-active.countstrip-on #hurricane-tab { bottom: calc(var(--ticker-h) + var(--pillstrip-h) + 136px); }
body.obs-clean #hurricane-tab { display: none !important; }
.hurr-storms { display: flex; flex-direction: column; gap: 3px; margin-bottom: 6px; }
.hurr-storm-row {
    display: flex; align-items: flex-start; gap: 7px; width: 100%; text-align: left;
    background: rgba(255, 255, 255, 0.05); border: 1px solid rgba(255, 255, 255, 0.10);
    color: #e6eef8; font: inherit; font-size: 11px; padding: 4px 6px; border-radius: 6px; cursor: pointer;
}
.hurr-storm-row:hover { background: rgba(255, 255, 255, 0.10); }
.hurr-dot { width: 9px; height: 9px; border-radius: 50%; flex: 0 0 auto; margin-top: 3px; box-shadow: 0 0 0 1px rgba(255, 255, 255, 0.4); }
.hurr-storm-col { display: flex; flex-direction: column; gap: 1px; min-width: 0; flex: 1 1 auto; }
.hurr-storm-line1 { display: flex; align-items: baseline; gap: 6px; }
.hurr-storm-name { font-weight: 700; }
.hurr-storm-tier { margin-left: auto; color: #9fb3c8; font-size: 10px; white-space: nowrap; }
.hurr-reason { font-size: 10px; font-weight: 600; }
.hurr-approach { font-size: 10px; color: #9fb3c8; }
.hurr-empty { color: #cfd6e4; font-style: italic; margin-bottom: 2px; }
.hurr-empty-sub { color: #6b7a8d; font-size: 10px; margin-bottom: 6px; }
.hurr-sec { font-weight: 700; letter-spacing: 0.05em; font-size: 9.5px; color: #8a97ab; text-transform: uppercase; margin: 4px 0 3px; }
.hurr-area-row {
    display: flex; align-items: center; gap: 7px; width: 100%; text-align: left; margin-bottom: 3px;
    background: rgba(255, 211, 127, 0.07); border: 1px solid rgba(255, 211, 127, 0.20);
    color: #e6eef8; font: inherit; font-size: 10.5px; padding: 3px 6px; border-radius: 6px; cursor: pointer;
}
.hurr-area-row:hover { background: rgba(255, 211, 127, 0.14); }
.hurr-area-pct { font-weight: 700; flex: 0 0 auto; min-width: 34px; }
.hurr-area-region { flex: 1 1 auto; min-width: 0; }
.hurr-area-dist { margin-left: auto; color: #9fb3c8; font-size: 10px; white-space: nowrap; }
.hurr-chips { display: flex; flex-wrap: wrap; gap: 4px; }
.hurr-chip {
    background: rgba(255, 255, 255, 0.07); border: 1px solid rgba(255, 255, 255, 0.18);
    color: #cfd6e4; font: inherit; font-size: 10.5px; padding: 2px 8px; border-radius: 999px; cursor: pointer;
}
.hurr-chip.on { background: rgba(126, 240, 255, 0.18); border-color: #7ef0ff; color: #d8f8ff; }
.hurr-legend-foot { display: flex; flex-wrap: wrap; gap: 4px; margin-top: 6px; }
.hurr-basin { color: #bccddd; font-size: 10px; margin-top: 7px; padding-top: 6px; border-top: 1px solid rgba(255,255,255,0.12); }
.hurr-basin [data-basin-status] { white-space: pre-line; overflow-wrap: anywhere; line-height: 1.5; }
.hurr-basin button:disabled { opacity: 0.45; cursor: default; }
.hurr-feed-status { color: #9fb3c8; font-size: 10px; margin: 6px 0; overflow-wrap: anywhere; }
.hurr-feed-status summary { cursor: pointer; padding: 3px 0; }
.hurr-feed-attention summary { color: #ffd37f; }
.hurr-feed-row { display: flex; flex-direction: column; gap: 2px; padding: 4px 0; border-top: 1px solid rgba(255,255,255,0.08); }
.hurr-feed-row strong { font-weight: 600; }

/* ---- Radar station markers — hover tooltip ---- */
.rstn-popup .maplibregl-popup-content {
    background: rgba(10, 14, 24, 0.95);
    border: 1px solid rgba(255, 255, 255, 0.16);
    border-radius: 7px; padding: 6px 9px;
    box-shadow: 0 6px 18px rgba(0, 0, 0, 0.5);
}
.rstn-popup .maplibregl-popup-tip { display: none; }
.rstn-tip { font-size: 11px; color: #e6eef8; line-height: 1.5; white-space: nowrap; }
.rstn-tip b { color: #fff; font-weight: 700; letter-spacing: 0.4px; }
.rstn-tip-st { display: block; font-weight: 600; }
.rstn-tip-go { display: block; font-size: 10px; color: #8aa0b6; }

/* ---- Tornado ghost popup ---- */
.ghost-popup { font-size: 12px; color: #e8edf6; min-width: 170px; }
.ghost-title { font-weight: 700; font-size: 13px; margin-bottom: 3px; }
.ghost-fat { color: #ff6b6b; font-weight: 700; margin-left: 6px; }
.ghost-row { color: #b9c2d4; margin: 1px 0; }
.ghost-src { margin-top: 5px; font-size: 10px; color: #7d8798; letter-spacing: 0.04em; }

/* ---- Sounding popup ---- */
.snd-popup { font-size: 12px; color: #e8edf6; }
.snd-loading { padding: 14px 8px; color: #b9c2d4; }
.snd-title { font-weight: 700; font-size: 13px; margin-bottom: 5px; }
.snd-when { color: #9aa6ba; font-weight: 400; font-size: 11px; margin-left: 6px; }
.snd-chips { display: flex; gap: 4px; margin-bottom: 6px; }
.snd-chip {
    background: rgba(255,255,255,0.07);
    border: 1px solid rgba(255,255,255,0.18);
    color: #cfd6e4; font-size: 11px;
    padding: 1px 9px; border-radius: 999px; cursor: pointer;
}
.snd-chip.on { background: rgba(255,90,90,0.18); border-color: #ff5a5a; color: #ffd9d9; }
.snd-canvas-row { display: flex; align-items: flex-start; gap: 4px; overflow: visible; }
.snd-canvas-row canvas { background: rgba(8,11,20,0.85); border-radius: 6px; flex-shrink: 0; }
#snd-hodo { flex: none; }
.snd-ix {
    display: flex; flex-wrap: wrap; gap: 3px 10px;
    margin-top: 6px; font-size: 11px; color: #b9c2d4;
}
.snd-ix b { color: #fff; font-weight: 700; }
.snd-src { margin-top: 5px; font-size: 10px; color: #7d8798; letter-spacing: 0.03em; }

/* ---- Director chip (top-center, below autopilot's default spot) ---- */
#director-chip {
    position: fixed; top: calc(var(--se-header-h, 60px) + 10px);
    left: 50%; transform: translateX(-50%);
    z-index: 880; display: flex; align-items: center; gap: 7px;
    background: rgba(10, 14, 24, 0.92);
    border: 1px solid rgba(126, 240, 255, 0.45);
    border-radius: 999px; padding: 5px 13px;
    font-size: 12px; color: #d8f8ff; cursor: grab;
    backdrop-filter: blur(4px);
    box-shadow: 0 2px 14px rgba(0,0,0,0.45);
    user-select: none; touch-action: none;
}
#director-chip:active { cursor: grabbing; }
.dir-dot {
    width: 8px; height: 8px; border-radius: 50%;
    background: #36e07c; box-shadow: 0 0 8px #36e07c;
    animation: dirPulse 1.6s ease-in-out infinite;
}
.dir-dot.held { background: #ffaa00; box-shadow: 0 0 8px #ffaa00; animation: none; }
@keyframes dirPulse { 0%,100% { opacity: 1; } 50% { opacity: 0.35; } }
.dir-label { font-weight: 800; letter-spacing: 0.1em; font-size: 11px; }
.dir-body { color: #9fdbe8; }

/* ---- Cross-section slicer ---- */
#slicer-panel {
    position: fixed; left: 50%; transform: translateX(-50%);
    bottom: 84px; z-index: 900;
    background: rgba(10, 14, 24, 0.94);
    border: 1px solid rgba(126, 240, 255, 0.35);
    border-radius: 10px; padding: 8px 10px 10px;
    backdrop-filter: blur(5px);
    box-shadow: 0 4px 24px rgba(0,0,0,0.5);
}
.slicer-head { display: flex; align-items: center; gap: 8px; margin-bottom: 4px; }
.slicer-title { font-weight: 800; letter-spacing: 0.08em; font-size: 11.5px; color: #7ef0ff; }
.slicer-meta { font-size: 11px; color: #9aa6ba; }
.slicer-spacer { flex: 1; }
.slicer-btn {
    background: rgba(255,255,255,0.07);
    border: 1px solid rgba(255,255,255,0.18);
    color: #cfd6e4; font-size: 11px;
    padding: 2px 9px; border-radius: 6px; cursor: pointer;
}
.slicer-btn:hover { background: rgba(126,240,255,0.14); }
.slicer-close { font-weight: 700; }
.slicer-status { font-size: 11.5px; color: #9fdbe8; padding: 4px 2px; display: none; }
#slicer-canvas { display: block; border-radius: 6px; background: rgba(8,11,20,0.9); }
#slicer-hint {
    position: fixed; top: calc(var(--se-header-h, 60px) + 14px);
    left: 50%; transform: translateX(-50%) translateY(-8px);
    z-index: 1600; background: rgba(10, 14, 24, 0.95);
    border: 1px solid rgba(126, 240, 255, 0.5);
    border-radius: 8px; padding: 7px 14px;
    font-size: 12.5px; color: #d8f8ff;
    opacity: 0; transition: opacity 0.25s, transform 0.25s;
    pointer-events: none;
}
#slicer-hint.show { opacity: 1; transform: translateX(-50%) translateY(0); }

/* ---- Recap reel card ---- */
#reel-card {
    position: fixed; top: 50%; left: 50%; transform: translate(-50%, -50%);
    z-index: 1700; width: 330px;
    background: rgba(12, 16, 27, 0.97);
    border: 1px solid rgba(255, 90, 90, 0.4);
    border-radius: 12px; padding: 12px 14px 14px;
    color: #e8edf6; font-size: 12.5px;
    box-shadow: 0 8px 40px rgba(0,0,0,0.6);
}
.reel-head {
    display: flex; align-items: center; justify-content: space-between;
    font-weight: 800; letter-spacing: 0.07em; font-size: 13px; color: #ff8a8a;
    margin-bottom: 6px;
}
.reel-x {
    background: none; border: none; color: #9aa6ba;
    font-size: 14px; cursor: pointer; padding: 2px 4px;
}
.reel-x:hover { color: #fff; }
.reel-tip { color: #9aa6ba; font-size: 11.5px; margin-bottom: 9px; line-height: 1.35; }
.reel-row { display: flex; gap: 6px; margin-bottom: 7px; }
.reel-input {
    flex: 1; min-width: 0;
    background: rgba(255,255,255,0.06);
    border: 1px solid rgba(255,255,255,0.16);
    color: #e8edf6; font-size: 12px;
    padding: 4px 6px; border-radius: 6px;
}
.reel-go {
    flex: 1; background: rgba(255,60,60,0.16);
    border: 1px solid #ff5a5a; color: #ffd9d9;
    font-weight: 700; font-size: 13px; letter-spacing: 0.04em;
    padding: 7px 0; border-radius: 8px; cursor: pointer;
}
.reel-go:hover { background: rgba(255,60,60,0.3); }
.reel-status { font-size: 12px; color: #9fdbe8; min-height: 16px; }
.reel-dot {
    display: inline-block; width: 8px; height: 8px; border-radius: 50%;
    background: #ff4444; box-shadow: 0 0 8px #ff4444;
    margin-right: 5px; animation: dirPulse 1.1s ease-in-out infinite;
}

/* reel card drag handle */
.reel-head { cursor: grab; user-select: none; touch-action: none; }
#reel-card.reel-dragging { opacity: 0.92; }

/* ---- SPC Floating Outlook Window ---- */
.spc-float-win {
    position: fixed;
    top: 90px;
    right: 320px;
    width: 360px;
    max-width: 92vw;
    max-height: 72vh;
    display: flex;
    flex-direction: column;
    background: rgba(10, 14, 26, 0.97);
    border: 1px solid rgba(255, 140, 0, 0.45);
    border-radius: 10px;
    box-shadow: 0 6px 28px rgba(0,0,0,0.65);
    backdrop-filter: blur(14px);
    z-index: 1800;
    font-size: 12px;
    color: #cfd6e4;
    overflow: hidden;
}
.spc-float-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 8px;
    padding: 10px 12px 8px;
    border-bottom: 1px solid rgba(255,255,255,0.1);
    cursor: grab;
    user-select: none;
    background: rgba(255,140,0,0.08);
}
.spc-float-header:active { cursor: grabbing; }
.spc-float-title {
    font-weight: 700;
    font-size: 12px;
    letter-spacing: 0.04em;
    display: flex;
    align-items: center;
    gap: 8px;
}
.spc-float-badge {
    font-size: 12px;
    font-weight: 800;
    border: 1px solid;
    border-radius: 4px;
    padding: 1px 7px;
    letter-spacing: 0.05em;
}
.spc-float-close {
    background: none;
    border: none;
    color: #8b96ab;
    cursor: pointer;
    font-size: 14px;
    padding: 0 2px;
    line-height: 1;
}
.spc-float-close:hover { color: #fff; }
.spc-float-meta {
    display: flex;
    flex-wrap: wrap;
    gap: 6px 14px;
    padding: 7px 12px 5px;
    font-size: 11px;
    color: #8b96ab;
    border-bottom: 1px solid rgba(255,255,255,0.07);
}
.spc-float-desc {
    padding: 7px 12px;
    font-size: 11px;
    color: #ffd27f;
    border-bottom: 1px solid rgba(255,255,255,0.07);
    font-style: italic;
}
.spc-float-text {
    flex: 1;
    overflow-y: auto;
    padding: 8px 12px;
    scrollbar-width: thin;
    scrollbar-color: rgba(255,140,0,0.3) transparent;
}
.spc-float-pre {
    margin: 0;
    white-space: pre-wrap;
    word-break: break-word;
    font-family: 'Courier New', monospace;
    font-size: 11px;
    line-height: 1.5;
    color: #c8d0df;
}
.spc-float-loading, .spc-float-na {
    color: #8b96ab;
    font-style: italic;
    font-size: 11px;
}
.spc-float-footer {
    padding: 7px 12px;
    border-top: 1px solid rgba(255,255,255,0.08);
    background: rgba(0,0,0,0.2);
}
.spc-float-link {
    color: #4a9eff;
    font-size: 11px;
    font-weight: 600;
    text-decoration: none;
}
.spc-float-link:hover { text-decoration: underline; }
/* MD Viewer list items */
.spc-md-item {
    padding: 8px 0;
}
.spc-md-item-head {
    display: flex;
    justify-content: space-between;
    align-items: center;
    margin-bottom: 3px;
}
.spc-md-item-num {
    font-weight: 700;
    font-size: 12px;
    color: #ffd27f;
}
.spc-md-it {}
/* ============================================================
   AUTO-TOAST — persistent Autopilot "now showing" warning card
   (js/autotoast.js). AtmosphericX-style alert card. Lives in its
   own free region (default: on the map, below the legend) so it never collides with
   the top-center toast stack where live alerts fire. Draggable +
   scroll-to-resize; em-based so one font-size knob scales it all.
   ============================================================ */
.se-autotoast {
    position: fixed;
    top: 264px; left: 22px; right: auto;   /* floats on the map, below the warnings legend — drag anywhere */
    z-index: 1450;                 /* above map/panels, below top toast stack + footer (1500) */
    font-size: 13px;               /* the single scale knob (JS sets px when resized) */
    width: 15em; max-width: 62vw;  /* compact, roughly square card — not a wide strip */
    box-sizing: border-box;
    padding: 0.95em 1.05em 0.9em;
    border-radius: 0.85em;
    color: #eef4ff;
    font-family: var(--global-font, inherit);
    background: linear-gradient(135deg, rgba(19,25,40,0.97) 0%, rgba(11,15,27,0.97) 100%);
    border: 1px solid rgba(255,255,255,0.10);
    border-left: 0.23em solid var(--at-accent, #4a9eff);
    box-shadow: 0 0.6em 1.7em rgba(0,0,0,0.5),
                0 0 0 1px rgba(255,255,255,0.05) inset,
                0 0 1.6em -0.4em var(--at-glow, rgba(74,158,255,0.4));
    overflow: hidden;
    cursor: grab;
    user-select: none;
    -webkit-user-select: none;
    opacity: 0;
    transition: opacity 0.22s ease, transform 0.22s cubic-bezier(0.34,1.56,0.64,1),
                box-shadow 0.2s ease, border-color 0.2s ease;
    will-change: transform, opacity;
}
/* entrance: fade + slight rise; position-independent so it works at the default
   spot or anywhere it's been dragged */
.se-autotoast { transform: translateY(8px) scale(0.98); }
.se-autotoast.se-at-in { opacity: 1; transform: none; }
.se-autotoast.se-at-leaving { opacity: 0 !important; transform: scale(0.94) !important; }
.se-autotoast.se-at-dragging { cursor: grabbing; box-shadow: 0 0.9em 2.2em rgba(0,0,0,0.6), 0 0 2em -0.3em var(--at-glow, rgba(74,158,255,0.5)); }
.se-autotoast:hover { border-color: rgba(255,255,255,0.18); }

/* faint accent wash at the top of the card */
.se-autotoast .se-at-band {
    position: absolute; left: 0; top: 0; right: 0; height: 0.28em;
    background: var(--at-accent, #4a9eff);
    opacity: 0.95;
}
.se-autotoast::before {
    content: ''; position: absolute; left: 0; top: 0; right: 0; height: 4.2em;
    background: linear-gradient(180deg, var(--at-glow, rgba(74,158,255,0.4)) -40%, transparent 100%);
    opacity: 0.28; pointer-events: none;
}

/* "🎬 AUTOPILOT" chip */
.se-autotoast .se-at-auto {
    position: relative;
    display: inline-flex; align-items: center; gap: 0.3em;
    font-size: 0.62em; font-weight: 800; letter-spacing: 0.16em;
    text-transform: uppercase;
    color: var(--at-accent, #4a9eff);
    opacity: 0.92; margin-bottom: 0.5em;
}
.se-autotoast .se-at-cam { font-size: 1.15em; }

.se-autotoast .se-at-close {
    position: absolute; top: 0.5em; right: 0.5em;
    width: 1.6em; height: 1.6em; line-height: 1;
    display: flex; align-items: center; justify-content: center;
    background: rgba(255,255,255,0.10); color: #fff;
    border: none; border-radius: 0.35em;
    font-size: 1.05em; cursor: pointer; opacity: 0;
    transition: opacity 0.18s ease, background 0.18s ease, transform 0.18s ease;
}
.se-autotoast:hover .se-at-close { opacity: 0.9; }
.se-autotoast .se-at-close:hover { background: rgba(255,255,255,0.22); transform: scale(1.08); }

.se-autotoast .se-at-head {
    position: relative;
    display: flex; align-items: flex-start; gap: 0.4em;
    line-height: 1.12;
}
.se-autotoast .se-at-icon { font-size: 1.3em; flex: none; }
.se-autotoast .se-at-title {
    font-size: 1.06em; font-weight: 800; letter-spacing: 0.02em;
    text-transform: uppercase;
    color: var(--at-accent, #eef4ff);
    text-shadow: 0 1px 2px rgba(0,0,0,0.5);
    white-space: normal;            /* wrap long event names — keeps the card square */
}
.se-autotoast .se-at-loc {
    position: relative;
    margin-top: 0.3em; font-size: 0.94em; font-weight: 600;
    color: #dfe8f7; opacity: 0.95;
}

.se-autotoast .se-at-hazards {
    position: relative;
    display: flex; flex-wrap: wrap; gap: 0.4em;
    margin-top: 0.6em;
}
.se-autotoast .se-at-row {
    display: inline-flex; align-items: baseline; gap: 0.35em;
    background: rgba(255,255,255,0.07);
    border-radius: 0.4em; padding: 0.18em 0.5em;
    font-size: 0.86em;
}
.se-autotoast .se-at-k { opacity: 0.62; font-weight: 600; }
.se-autotoast .se-at-v { font-weight: 700; color: #fff; font-variant-numeric: tabular-nums; }
.se-autotoast .se-at-badge {
    display: inline-flex; align-items: center;
    font-size: 0.74em; font-weight: 800; letter-spacing: 0.06em;
    text-transform: uppercase;
    padding: 0.22em 0.55em; border-radius: 0.4em;
    color: var(--at-accent, #4a9eff);
    background: color-mix(in srgb, var(--at-accent, #4a9eff) 16%, transparent);
    border: 1px solid var(--at-accent, #4a9eff);
}
/* color-mix fallback for older engines */
@supports not (background: color-mix(in srgb, red, blue)) {
    .se-autotoast .se-at-badge { background: rgba(255,255,255,0.08); }
}

.se-autotoast .se-at-foot {
    position: relative;
    margin-top: 0.65em;
    display: flex; align-items: center; justify-content: space-between;
}
.se-autotoast .se-at-expire {
    font-size: 0.82em; font-weight: 600; opacity: 0.82;
    font-variant-numeric: tabular-nums;
}
.se-autotoast .se-at-expire.se-at-expired { color: #ff6b6b; opacity: 1; }

/* Tornado Emergency: gently pulse the accent band so it reads "live" */
.se-autotoast.sev-te .se-at-band { animation: se-at-bandpulse 1.4s ease-in-out infinite; }
@keyframes se-at-bandpulse { 0%,100% { opacity: 0.55; } 50% { opacity: 1; } }

/* ============================================================================
   ============================================================================
   STORM SIGNATURE THEME LAYER                          added 2026-08-02
   ----------------------------------------------------------------------------
   ADDITIVE. Nothing above this line was edited. Delete from this banner to
   the end of the file to revert completely (and drop the js/stormsig.js tag
   in index.html).

   The whole skin hangs off ONE variable, --live, which js/stormsig.js drives
   from the worst warning currently IN THE MAP VIEW via <html data-vthreat>:

       clear → blue    watch → amber    severe → orange
       tornado → red   confirmed → crimson    te → magenta

   NOT touched, on purpose:
     - body[data-threat]  (js/ambience.js edge vignette) — separate system,
       still works; stormsig.js only narrows what it is fed.
     - --accent-blue and friends keep their literal values; --live defaults
       to them, so a "clear" screen looks exactly like the build you know.

   THINGS THAT ARE DELIBERATELY NOT DONE HERE, and why:
     - no clip-path on .header — lines 2793 / 5845 / 7731 reset its
       overflow:hidden to visible on purpose (wrapped button row at ≤768px,
       ≤680px and in vertical-mode). clip-path ignores that reset and would
       re-clip the row. The header gets its identity from the underbar and
       the charge sweep instead.
     - no clip-path on .map-tool-btn — its data-tip tooltip is a ::after
       that renders outside the button (see line 607).
     - no clip-path on .brand-panel — close/resize grips sit at negative
       offsets outside the box.
     - chamfers on .warnings-panel / .map-legend are LEFT-side only, so the
       float toggle, hide button and resize grip (all right-side) survive.
     - .warning-card is chamfered bottom-RIGHT only; its left edge is the
       4px hazard-colour spine.
     - every moving part is a background-position animation on the element
       or on a pseudo-element, never a translated overlay, so nothing can
       escape a container in vertical/mobile layouts.
   ============================================================================
   ============================================================================ */

:root {
    /* Threat-reactive primaries. Default = today's electric blue. */
    --live:      #4a9eff;
    --live-2:    #7b5cff;
    --live-rgb:  74, 158, 255;
    --sig-pulse: 9s;            /* ambient cadence; shortens as threat rises */
    --sig-sweep: 1;             /* charge-sweep intensity. 0 = off, 1 = default,
                                   1.8 = unmissable. StormSig.sweep(n) at runtime. */
    --sig-cut:   11px;          /* chamfer depth */

    /* Re-point the two derived border variables at --live. This alone
       carries the threat colour into ~90 existing rules with no rewrites.
       Values match the originals exactly when --live is the default blue. */
    --border-color: rgba(var(--live-rgb), 0.15);
    --border-glow:  rgba(var(--live-rgb), 0.30);
    --accent-blue-glow: rgba(var(--live-rgb), 0.25);
    --shadow-blue: 0 0 20px rgba(var(--live-rgb), 0.15);
}

/* ---- THREAT STATES ------------------------------------------------------ */
html[data-vthreat="watch"]     { --live:#ffc21f; --live-2:#ff8a00; --live-rgb:255,194,31;  --sig-pulse:7s; }
html[data-vthreat="severe"]    { --live:#ff8c1a; --live-2:#ff4d1f; --live-rgb:255,140,26;  --sig-pulse:5.5s; }
html[data-vthreat="tornado"]   { --live:#ff3b3b; --live-2:#ff0a5e; --live-rgb:255,59,59;   --sig-pulse:4s; }
html[data-vthreat="confirmed"] { --live:#ff1f5a; --live-2:#ff00cc; --live-rgb:255,31,90;   --sig-pulse:3s; }
html[data-vthreat="te"]        { --live:#ff00cc; --live-2:#9b30ff; --live-rgb:255,0,204;   --sig-pulse:2.1s; }

/* Colour moves slowly so a state change reads as a mood shift on camera,
   not a flashbulb. */
.header, .warnings-panel, .radar-control-bar, .map-legend,
.control-btn, .radar-btn, .tab-btn, .detail-tab, .mrms-btn,
.warning-card, .ticker-cap, .radar-select {
    transition: border-color 1.2s ease, box-shadow 1.2s ease,
                background-color 1.2s ease, color 1.2s ease;
}

/* ---- MOTIF: the charge sweep -------------------------------------------- */
/* A slow sheen crossing the chrome — distant lightning behind a cloud deck,
   not a bolt graphic. Implemented as an animated background-position so it
   physically cannot overflow its box in any layout mode. */
/* ONE WAVE, NOT FOUR SHIMMERS.
   The sweep layer is background-attachment:fixed, so its coordinate system is
   the VIEWPORT, not the element. Every surface therefore shows its own slice
   of a single light band travelling across the screen — the header lights up,
   then the alerts panel, then the legend, in the order the band reaches them.

   Travel is in vw so it is identical on every element regardless of width.
   The band sits at the centre of a 200vw-wide image, so band centre =
   background-position + 100vw:  -55vw (off left) -> 125vw (off right).
   LEFT TO RIGHT, everywhere — same direction as the radar bar's local
   sweep. The last 22% of the cycle parks it off-screen, which is the
   "distant lightning" beat: a pass, then a rest, not a metronome.

   NOT applied to .radar-control-bar: it carries transform:translateX(-50%),
   and a transformed ancestor makes background-attachment:fixed resolve
   against the element instead of the viewport. That bar keeps a local sweep,
   shaped to the same 78%-travel + 22%-rest cycle and phase-locked to the
   global wave by stormsig.js alignSweeps(). */
@keyframes sig-charge {
    0%     { background-position: -155vw 0, 0 0, 0 0, 0 0; }
    78%    { background-position: 25vw 0, 0 0, 0 0, 0 0; }
    100%   { background-position: 25vw 0, 0 0, 0 0, 0 0; }
}
@keyframes sig-charge-3 {
    0%     { background-position: -155vw 0, 0 0, 0 0; }
    78%    { background-position: 25vw 0, 0 0, 0 0; }
    100%   { background-position: 25vw 0, 0 0, 0 0; }
}
/* Local (element-relative) version for the radar bar. With a 260%-wide
   image, band centre in bar-widths = 1.3 - 1.6 × position%. These stops map
   the band across the bar over the SAME 0–78% window as the global wave,
   so with a shared startTime the two read as one front. */
@keyframes sig-charge-pseudo {
    0%     { background-position: 115.6% 0, 0 0; }
    78%    { background-position: 3.1% 0, 0 0; }
    100%   { background-position: 3.1% 0, 0 0; }
}

/* ---- HEADER ------------------------------------------------------------- */
.header {
    background:
        /* 1 charge sweep */
        linear-gradient(100deg,
            transparent 43%,
            rgba(var(--live-rgb), calc(0.17 * var(--sig-sweep))) 47%,
            rgba(255, 255, 255,   calc(0.09 * var(--sig-sweep))) 50%,
            rgba(var(--live-rgb), calc(0.17 * var(--sig-sweep))) 53%,
            transparent 57%),
        /* 2 scan texture */
        repeating-linear-gradient(0deg,
            transparent 0 3px, rgba(160, 200, 255, 0.022) 3px 4px),
        /* 3 threat wash from the brand corner */
        radial-gradient(90% 240% at 12% 0%, rgba(var(--live-rgb), 0.14), transparent 60%),
        /* 4 original header gradient, untouched */
        linear-gradient(180deg, rgba(26, 26, 46, 0.98) 0%, rgba(15, 15, 30, 0.95) 100%);
    background-size: 200vw 100vh, auto, auto, auto;
    background-attachment: fixed, scroll, scroll, scroll;
    background-repeat: no-repeat, repeat, no-repeat, no-repeat;
    animation: sig-charge var(--sig-pulse) linear infinite;
}

/* The single most useful pixel row on the screen: threat colour, full width,
   directly under the brand. Reuses the existing accent-line pseudo-element. */
.header::after {
    bottom: 0;
    height: 2px;
    background: linear-gradient(90deg,
        transparent 0%,
        rgba(var(--live-rgb), 0.55) 12%,
        var(--live) 38%,
        var(--live-2) 62%,
        rgba(var(--live-rgb), 0.55) 88%,
        transparent 100%);
    box-shadow: 0 0 14px rgba(var(--live-rgb), 0.55);
    opacity: 1;
}

.logo-text h1 {
    background: linear-gradient(92deg, #fff 25%, rgba(var(--live-rgb), 0.95) 78%);
    -webkit-background-clip: text;
            background-clip: text;
    color: transparent;
    filter: drop-shadow(0 0 10px rgba(var(--live-rgb), 0.26));
}
.logo-subtitle { color: rgba(var(--live-rgb), 0.72); letter-spacing: 1.6px; }
.logo-img { box-shadow: 0 0 0 1px rgba(var(--live-rgb), 0.20),
                        0 0 20px rgba(var(--live-rgb), 0.28); }

.dev-build-badge {
    color: var(--live);
    border-color: rgba(var(--live-rgb), 0.35);
    background: rgba(var(--live-rgb), 0.07);
}

/* ---- MOTIF: chamfer ------------------------------------------------------ */
/* Cut corners read as instrumentation. Applied only where nothing needs to
   escape the box — see the header note at the top of this block. */
.tab-btn, .detail-tab, .radar-btn, .mrms-btn, .radar-select,
.dev-build-badge, .count-pill {
    border-radius: 0;
    clip-path: polygon(7px 0, 100% 0, 100% calc(100% - 7px),
                       calc(100% - 7px) 100%, 0 100%, 0 7px);
}
/* .voice-btn-group owns its own radius and clips its children; leave it. */
.control-btn:not(.voice-btn-group .control-btn):not(.map-tool-btn) {
    border-radius: 0;
    clip-path: polygon(7px 0, 100% 0, 100% calc(100% - 7px),
                       calc(100% - 7px) 100%, 0 100%, 0 7px);
}

/* ---- WARNINGS PANEL ------------------------------------------------------ */
.warnings-panel {
    background:
        linear-gradient(100deg,
            transparent 43%,
            rgba(var(--live-rgb), calc(0.15 * var(--sig-sweep))) 47%,
            rgba(255, 255, 255,   calc(0.08 * var(--sig-sweep))) 50%,
            rgba(var(--live-rgb), calc(0.15 * var(--sig-sweep))) 53%,
            transparent 57%),
        repeating-linear-gradient(0deg,
            transparent 0 3px, rgba(160, 200, 255, 0.022) 3px 4px),
        /* the spine — 2px threat edge, the motif that repeats everywhere */
        linear-gradient(180deg,
            transparent 0%, var(--live) 18%, var(--live-2) 55%, transparent 100%),
        linear-gradient(180deg, rgba(26, 26, 46, 0.95) 0%, rgba(17, 17, 34, 0.98) 100%);
    background-size: 200vw 100vh, auto, 2px 100%, auto;
    background-attachment: fixed, scroll, scroll, scroll;
    background-repeat: no-repeat, repeat, no-repeat, no-repeat;
    animation: sig-charge var(--sig-pulse) linear infinite;
    border-left-color: rgba(var(--live-rgb), 0.22);
}
/* Left corners only: the float toggle, hide button and resize grip all live
   on the right edge and a chamfer there would eat them. */
.warnings-panel.floating {
    border-radius: 0;
    clip-path: polygon(var(--sig-cut) 0, 100% 0, 100% 100%,
                       var(--sig-cut) 100%, 0 calc(100% - var(--sig-cut)),
                       0 var(--sig-cut));
    box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.06),
                0 12px 40px rgba(0, 0, 0, 0.55),
                0 0 30px rgba(var(--live-rgb), 0.10);
}
/* Corner ticks — the machined detail. */
.warnings-panel::before,
.warnings-panel::after {
    content: '';
    position: absolute;
    left: 7px;
    width: 9px; height: 9px;
    pointer-events: none;
    z-index: 3;
    opacity: 0.8;
    border-color: var(--live);
}
.warnings-panel::before { top: 7px;    border-top: 1.5px solid; border-left: 1.5px solid; }
.warnings-panel::after  { bottom: 7px; border-bottom: 1.5px solid; border-left: 1.5px solid; }

.panel-header h2 {
    font-family: var(--font-display, 'Barlow Condensed'), sans-serif;
    font-size: 19px;
    letter-spacing: 1.6px;
    text-transform: uppercase;
    text-shadow: 0 0 18px rgba(var(--live-rgb), 0.30);
}
.panel-header h2::after { background: linear-gradient(90deg, var(--live), transparent); }

/* Warning rows: lit top edge + a bloom in the row's own hazard colour.
   Chamfer bottom-right only — the left edge is the 4px severity spine. */
.warning-card {
    border-radius: 0;
    clip-path: polygon(0 0, 100% 0, 100% calc(100% - 9px),
                       calc(100% - 9px) 100%, 0 100%);
    box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.045);
}

/* ---- RADAR CONSOLE ------------------------------------------------------- */
.radar-control-bar {
    border-color: rgba(var(--live-rgb), 0.28);
    border-radius: 0;
    clip-path: polygon(var(--sig-cut) 0, 100% 0, 100% calc(100% - var(--sig-cut)),
                       calc(100% - var(--sig-cut)) 100%, 0 100%, 0 var(--sig-cut));
    box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.06),
                0 4px 24px rgba(0, 0, 0, 0.6),
                0 0 28px rgba(var(--live-rgb), 0.08);
}
/* The sweep lives on a pseudo-element here: .radar-control-bar.floating
   carries `animation: none !important`, which would kill an animation set
   on the element itself but cannot reach its pseudo-element. */
.radar-control-bar::before {
    content: '';
    position: absolute;
    inset: 0;
    pointer-events: none;
    z-index: 0;
    background:
        linear-gradient(100deg,
            transparent 43%,
            rgba(var(--live-rgb), calc(0.16 * var(--sig-sweep))) 47%,
            rgba(255, 255, 255,   calc(0.08 * var(--sig-sweep))) 50%,
            rgba(var(--live-rgb), calc(0.16 * var(--sig-sweep))) 53%,
            transparent 57%),
        repeating-linear-gradient(0deg,
            transparent 0 3px, rgba(160, 200, 255, 0.020) 3px 4px);
    background-size: 260% 100%, auto;
    background-repeat: no-repeat, repeat;
    animation: sig-charge-pseudo var(--sig-pulse) linear infinite;
}
.radar-control-bar > * { position: relative; z-index: 1; }

.radar-label {
    font-family: var(--font-display, 'Barlow Condensed'), sans-serif;
    font-size: 11px;
    font-weight: 600;
    letter-spacing: 1.5px;
    text-transform: uppercase;
    color: rgba(var(--live-rgb), 0.62);
}
.radar-btn:hover  { border-color: rgba(var(--live-rgb), 0.45); }
.radar-btn-play   { background: rgba(var(--live-rgb), 0.14);
                    border-color: rgba(var(--live-rgb), 0.35);
                    box-shadow: 0 0 16px rgba(var(--live-rgb), 0.22); }
.radar-select:focus { border-color: rgba(var(--live-rgb), 0.55); outline: none; }
.mrms-btn:hover   { border-color: rgba(var(--live-rgb), 0.42); }

/* Numbers read as instrumentation, not body copy. */
.radar-mini-val, .radar-time, .clk-time, #warning-count,
.count-pill, .hail-max-size {
    font-variant-numeric: tabular-nums;
    font-feature-settings: 'tnum' 1;
}

/* ---- ACTIVE STATES: one glow, everywhere -------------------------------- */
.control-btn.active {
    background: rgba(var(--live-rgb), 0.14);
    border-color: rgba(var(--live-rgb), 0.55);
    color: var(--live);
    box-shadow: 0 0 16px rgba(var(--live-rgb), 0.25),
                inset 0 0 12px rgba(var(--live-rgb), 0.08);
}
.tab-btn.active, .detail-tab.active {
    background: rgba(var(--live-rgb), 0.16);
    border-color: rgba(var(--live-rgb), 0.55);
    color: #fff;
    box-shadow: 0 0 14px rgba(var(--live-rgb), 0.22);
}
/* The Confirmed tab keeps its own red identity — it means something specific. */
.tab-btn.tab-btn-confirmed.active {
    background: var(--accent-red, #ff3333);
    border-color: var(--accent-red, #ff3333);
    box-shadow: 0 0 14px rgba(255, 51, 51, 0.35);
}

/* ---- FLOATING CHROME GLOWS ---------------------------------------------- */
.map-legend.floating,
.radar-control-bar.floating {
    box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.06),
                0 12px 40px rgba(0, 0, 0, 0.55),
                0 0 26px rgba(var(--live-rgb), 0.12);
}
.map-legend {
    background:
        linear-gradient(100deg,
            transparent 44%,
            rgba(var(--live-rgb), calc(0.15 * var(--sig-sweep))) 47%,
            rgba(255, 255, 255,   calc(0.08 * var(--sig-sweep))) 50%,
            rgba(var(--live-rgb), calc(0.15 * var(--sig-sweep))) 53%,
            transparent 56%),
        repeating-linear-gradient(0deg,
            transparent 0 3px, rgba(160, 200, 255, 0.020) 3px 4px),
        rgba(17, 24, 39, 0.92);
    background-size: 200vw 100vh, auto, auto;
    background-attachment: fixed, scroll, scroll;
    background-repeat: no-repeat, repeat, repeat;
    animation: sig-charge-3 var(--sig-pulse) linear infinite;
    border-color: rgba(var(--live-rgb), 0.20);
    border-radius: 0;
    clip-path: polygon(var(--sig-cut) 0, 100% 0, 100% 100%,
                       var(--sig-cut) 100%, 0 calc(100% - var(--sig-cut)),
                       0 var(--sig-cut));
}
.legend-title {
    font-family: var(--font-display, 'Barlow Condensed'), sans-serif;
    letter-spacing: 1.4px;
    text-transform: uppercase;
    color: rgba(var(--live-rgb), 0.75);
}

/* ---- LOWER THIRD --------------------------------------------------------- */
#alert-ticker { border-top-color: rgba(var(--live-rgb), 0.22); }
.ticker-cap {
    border-right: 2px solid rgba(var(--live-rgb), 0.55);
    background:
        linear-gradient(100deg,
            transparent 44%,
            rgba(var(--live-rgb), calc(0.20 * var(--sig-sweep))) 47%,
            rgba(255, 255, 255,   calc(0.10 * var(--sig-sweep))) 50%,
            rgba(var(--live-rgb), calc(0.20 * var(--sig-sweep))) 53%,
            transparent 56%),
        repeating-linear-gradient(0deg,
            transparent 0 3px, rgba(160, 200, 255, 0.020) 3px 4px),
        linear-gradient(135deg, rgba(var(--live-rgb), 0.16), rgba(13, 19, 34, 0.95));
    background-size: 200vw 100vh, auto, auto;
    background-attachment: fixed, scroll, scroll;
    background-repeat: no-repeat, repeat, no-repeat;
    animation: sig-charge-3 var(--sig-pulse) linear infinite;
    box-shadow: 6px 0 22px -8px rgba(var(--live-rgb), 0.45);
}
.ticker-brand { letter-spacing: 2.4px; }

/* ---- MAP POPUPS (warning polygon cards, unified click popup) ------------- */
/* MapLibre positions popups inside a transformed container, so — exactly
   like the radar bar — the viewport-fixed wave can't reach them. They get
   the LOCAL sweep instead, shaped to the same 78%-travel + 22%-rest cycle
   and phase-locked to the global wave by stormsig.js alignSweeps()
   (any animation named sig-charge-* is clocked together).

   The Weather Here popup is untouched on purpose:
   .maplibregl-popup-content:has(.wx-popup) is more specific, so its
   opacity-slider background wins and it takes no sweep — right for a
   plain data readout. */
.maplibregl-popup-content {
    position: relative;
    border-color: rgba(var(--live-rgb), 0.30) !important;
    box-shadow: 0 8px 32px rgba(0, 0, 0, 0.6),
                0 0 14px rgba(var(--live-rgb), 0.12) !important;
    transition: border-color 1.2s ease, box-shadow 1.2s ease;
}
/* The sweep must live on a pseudo-element: the popup's base style sets
   `background: ... !important`, and an !important declaration outranks
   animation keyframes — animating background-position on the element
   itself silently does nothing. (Same class of trap as the radar bar's
   `animation: none !important`, same escape hatch.) The card's own
   overflow:hidden clips this overlay to its rounded corners. */
.maplibregl-popup-content::after {
    content: '';
    position: absolute;
    inset: 0;
    pointer-events: none;
    z-index: 1;
    border-radius: inherit;
    background:
        /* 1 charge sweep — a notch gentler than the chrome; these cards
           are text-dense and sit over the radar */
        linear-gradient(100deg,
            transparent 43%,
            rgba(var(--live-rgb), calc(0.13 * var(--sig-sweep))) 47%,
            rgba(255, 255, 255,   calc(0.07 * var(--sig-sweep))) 50%,
            rgba(var(--live-rgb), calc(0.13 * var(--sig-sweep))) 53%,
            transparent 57%),
        /* 2 scan texture */
        repeating-linear-gradient(0deg,
            transparent 0 3px, rgba(160, 200, 255, 0.020) 3px 4px);
    background-size: 260% 100%, auto;
    background-repeat: no-repeat, repeat;
    animation: sig-charge-pseudo var(--sig-pulse) linear infinite;
}

/* ---- MOTION DISCIPLINE --------------------------------------------------- */
/* Guard the PRE-EXISTING infinite loops that were never covered by the
   stylesheet's reduced-motion block. The signature sweep is deliberately
   NOT in this list — see below. */
@media (prefers-reduced-motion: reduce) {
    .warnings-panel.te-active .panel-header,
    #alert-countstrip .count-pill,
    .radar-live-dot, .ap-chip, .replay-bar {
        animation: none !important;
    }
}

/* THE SWEEP RUNS EVERYWHERE, ALWAYS.
   It is the brand signature of the stream, so it runs in every layout —
   landscape, body.vertical-mode (TTLS portrait capture), narrow windows —
   and it does NOT follow the OS reduced-motion flag: streaming PCs often
   have Windows "animation effects" turned off for performance, and that
   setting silently reporting prefers-reduced-motion is exactly how this
   sweep vanished on air twice. (OBS clean mode still hides all of this
   chrome outright via display:none — unaffected.)

   The ONLY off switch is explicit and operator-owned:
       StormSig.sweep(0)   → sets <html data-sig-motion="off">, persisted
       StormSig.sweep(1)   → back on (1.8 = unmissable)                    */
html[data-sig-motion="off"] .header,
html[data-sig-motion="off"] .warnings-panel,
html[data-sig-motion="off"] .map-legend,
html[data-sig-motion="off"] .ticker-cap,
html[data-sig-motion="off"] .maplibregl-popup-content::after,
html[data-sig-motion="off"] .radar-control-bar::before { animation: none !important; }

/* ============================================================================
   END STORM SIGNATURE THEME LAYER
   ============================================================================ */

/* ============================================================
   TOWER FOLLOW badge (radar pill) — 2026-08-02
   Tri-state 🗼 AUTO / STORM / LOCK, clickable (cycles modes).
   Rollback: delete this block + the rp-follow badge in
   js/radarpill.js (the old .rp-lock style above is untouched).
   ============================================================ */
#radar-pill .rp-follow { cursor: pointer; user-select: none; }
#radar-pill .rp-follow:hover { filter: brightness(1.35); }
#radar-pill .rp-follow-auto  { background: rgba(139,148,158,0.14); color: #9fb2c5; border: 1px solid rgba(139,148,158,0.35); }
#radar-pill .rp-follow-storm { background: rgba(88,166,255,0.16);  color: #79b8ff; border: 1px solid rgba(88,166,255,0.45); }
#radar-pill .rp-follow-lock  { background: rgba(255,179,0,0.16);   color: #ffd98a; border: 1px solid rgba(255,179,0,0.4); }

/* ============================================================
   STORM SIGNATURE — FLOATING ANALYTICS PANELS      2026-08-03
   Extends the 2026-08-02 theme layer to the two self-styled
   floating windows that inject their own <style> at runtime:

     #threatgraph-panel   (⚡ National Threat  — js/threatgraph.js)
     #celltracker-panel   (CELL n rotation popup — js/celltracker.js)

   Their injected <style> tags land AFTER this stylesheet in
   <head>, so every override here is written as
   `html #the-id …` — one extra type selector out-specifies the
   injected `#the-id …` rules without a single !important.

   Both panels can be dragged, and threatgraph can be SCALED
   (transform:scale via its float state) — a transformed element
   resolves background-attachment:fixed against itself, so like
   the radar bar and the map popups these take the LOCAL sweep
   (sig-charge-pseudo, 78%-travel + 22%-rest), phase-locked to
   the global wave by stormsig.js alignSweeps() every 2 s —
   late-created panels (celltracker builds on first cell click)
   join the clock on the next tick.

   Layering — both pseudo-elements are full-bleed overlays ABOVE
   the panel's children (the panels' own children are unpositioned
   except .tg-grip z5 / .tg-tip z10, which stay on top):
     ::after  z1  charge sweep + scan texture   (animated)
     ::before z2  left spine + corner ticks     (static)
   pointer-events:none on both, so chips/buttons/drag all work.

   Chamfer is LEFT corners only on both panels — close buttons
   and the threatgraph resize grip live on the right edge.

   Semantics kept: tg-trend up/down colours, CellTracker chip
   pin-state green (.ctw-on), TDS amber, dBZ badge colours.
   Rollback: delete this block, restore ?v= in index.html.
   ============================================================ */

/* ---- shared: threat-reactive shell -------------------------- */
/* #firewx-panel joins every shared rule but carries a SCOPED palette
   override (below), so the whole skin — border, sweep, spine, ticks —
   renders in permanent fire-amber livery instead of tracking the threat
   level. Guest content wears the uniform in its own colour. */
html #threatgraph-panel,
html #celltracker-panel,
html #firewx-panel {
    border-color: rgba(var(--live-rgb), 0.30);
    border-radius: 0;
    clip-path: polygon(var(--sig-cut) 0, 100% 0, 100% 100%,
                       var(--sig-cut) 100%, 0 calc(100% - var(--sig-cut)),
                       0 var(--sig-cut));
    box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.05),
                0 12px 40px rgba(0, 0, 0, 0.55),
                0 0 26px rgba(var(--live-rgb), 0.12);
    transition: border-color 1.2s ease, box-shadow 1.2s ease;
}

/* ---- shared: charge sweep + scan texture (animated, z1) ------ */
html #threatgraph-panel::after,
html #celltracker-panel::after,
html #firewx-panel::after {
    content: '';
    position: absolute;
    inset: 0;
    pointer-events: none;
    z-index: 1;
    background:
        /* 1 charge sweep — popup-gentle: both cards are data-dense */
        linear-gradient(100deg,
            transparent 43%,
            rgba(var(--live-rgb), calc(0.13 * var(--sig-sweep))) 47%,
            rgba(255, 255, 255,   calc(0.07 * var(--sig-sweep))) 50%,
            rgba(var(--live-rgb), calc(0.13 * var(--sig-sweep))) 53%,
            transparent 57%),
        /* 2 scan texture */
        repeating-linear-gradient(0deg,
            transparent 0 3px, rgba(160, 200, 255, 0.020) 3px 4px);
    background-size: 260% 100%, auto;
    background-repeat: no-repeat, repeat;
    animation: sig-charge-pseudo var(--sig-pulse) linear infinite;
}

/* ---- shared: spine + corner ticks (static, z2) ---------------
   Drawn on an overlay, not the element background, because both
   panels put opaque header bars over their top edge — background
   ticks would vanish under them. Overlay wins. */
html #threatgraph-panel::before,
html #celltracker-panel::before,
html #firewx-panel::before {
    content: '';
    position: absolute;
    inset: 0;
    pointer-events: none;
    z-index: 2;
    opacity: 0.8;
    background:
        /* spine — 2px threat edge, same motif as the warnings panel */
        linear-gradient(180deg,
            transparent 0%, var(--live) 18%, var(--live-2) 55%, transparent 100%)
            0 0 / 2px 100% no-repeat,
        /* top-left tick */
        linear-gradient(var(--live), var(--live)) 7px 7px / 9px 1.5px no-repeat,
        linear-gradient(var(--live), var(--live)) 7px 7px / 1.5px 9px no-repeat,
        /* bottom-left tick */
        linear-gradient(var(--live), var(--live)) 7px calc(100% - 8.5px) / 9px 1.5px no-repeat,
        linear-gradient(var(--live), var(--live)) 7px calc(100% - 16px) / 1.5px 9px no-repeat;
}

/* ---- NATIONAL THREAT specifics ------------------------------- */
html #threatgraph-panel .tg-head {
    border-bottom-color: rgba(var(--live-rgb), 0.25);
}
html #threatgraph-panel .tg-title {
    font-family: var(--font-display, 'Barlow Condensed'), sans-serif;
    font-size: 14px;
    letter-spacing: 1.4px;
    text-transform: uppercase;
    text-shadow: 0 0 14px rgba(var(--live-rgb), 0.30);
}
html #threatgraph-panel .tg-hero-val {
    font-variant-numeric: tabular-nums;
    font-feature-settings: 'tnum' 1;
    text-shadow: 0 0 12px rgba(var(--live-rgb), 0.25);
}
html #threatgraph-panel .tg-chip.active {
    background: rgba(var(--live-rgb), 0.16);
    border-color: rgba(var(--live-rgb), 0.55);
    color: var(--live);
}
html #threatgraph-panel .tg-chip {
    border-radius: 0;
    clip-path: polygon(5px 0, 100% 0, 100% calc(100% - 5px),
                       calc(100% - 5px) 100%, 0 100%, 0 5px);
}
html #threatgraph-panel .tg-grip:hover { color: var(--live); }
html #btn-threat-graph.active {
    color: var(--live);
    border-color: rgba(var(--live-rgb), 0.55);
}
/* tg-trend up/hold/down keep their red/gray/green — they are data. */

/* ---- CELLTRACKER specifics -----------------------------------
   The mint-green chrome border joins the unified threat skin;
   pin-state green INSIDE the card (.ctw-on) is semantic and kept. */
html #celltracker-panel .ctp-head {
    border-bottom-color: rgba(var(--live-rgb), 0.25);
}
html #celltracker-panel .ctp-title {
    font-family: var(--font-display, 'Barlow Condensed'), sans-serif;
    font-size: 14px;
    letter-spacing: 1.2px;
    text-transform: uppercase;
    text-shadow: 0 0 14px rgba(var(--live-rgb), 0.30);
}
html #celltracker-panel .ctp-lbl b,
html #celltracker-panel .ctw-chip b {
    font-variant-numeric: tabular-nums;
    font-feature-settings: 'tnum' 1;
}
html #celltracker-panel .ctw-hint {
    font-family: var(--font-display, 'Barlow Condensed'), sans-serif;
    letter-spacing: 1.1px;
    text-transform: uppercase;
    color: rgba(var(--live-rgb), 0.62);
}

/* ---- FIREWX specifics ----------------------------------------
   Scoped palette: the shared rules above all read --live/--live-rgb,
   so overriding them HERE dresses the fire console in the full
   signature skin (sweep, spine, corner ticks, chamfered shell) in
   permanent fire-amber — it deliberately does NOT track the threat
   level. Fire is guest content on a tornado channel. */
html #firewx-panel {
    --live: #d9a441;
    --live-2: #b45309;
    --live-rgb: 217, 164, 65;
}
html #firewx-panel .fw-title {
    font-family: var(--font-display, 'Barlow Condensed'), sans-serif;
    font-size: 14px;
    letter-spacing: 1.4px;
    text-transform: uppercase;
    text-shadow: 0 0 14px rgba(217, 164, 65, 0.30);
}
html #firewx-panel .fw-until { font-variant-numeric: tabular-nums; }

/* ---- operator motion switch ----------------------------------
   Same single off switch as the rest of the signature layer:
   StormSig.sweep(0) → <html data-sig-motion="off">. The OS
   reduced-motion flag is deliberately NOT consulted here — see
   the sweep manifesto in the 2026-08-02 block above. */
html[data-sig-motion="off"] #threatgraph-panel::after,
html[data-sig-motion="off"] #celltracker-panel::after,
html[data-sig-motion="off"] #firewx-panel::after { animation: none !important; }

/* ============================================================
   END STORM SIGNATURE — FLOATING ANALYTICS PANELS
   ============================================================ */

/* ============================================================
   TOAST EYE-CANDY (2026-08-12) — marching light border, sonar
   icon pings, TE shimmer headline. Companion JS: toasts.js
   (.toast-chase child + .toast-icon-wrap markup).
   ============================================================ */

/* ---- Marching light border ---------------------------------
   A conic-gradient "comet" (tier color with a white core) spinning behind
   a ring mask, so a bright segment chases the card perimeter. TOR chases
   fast, TE fastest; every other tier gets a slow, calm orbit. */
.toast-chase {
    position: absolute;
    inset: 0;
    z-index: 3;
    border-radius: 8px;
    pointer-events: none;
    padding: 2px;   /* ring thickness */
    -webkit-mask: linear-gradient(#fff 0 0) content-box, linear-gradient(#fff 0 0);
    mask: linear-gradient(#fff 0 0) content-box, linear-gradient(#fff 0 0);
    -webkit-mask-composite: xor;
    mask-composite: exclude;
}
.toast-chase::before {
    content: '';
    position: absolute;
    left: 50%;
    top: 50%;
    width: 300%;
    aspect-ratio: 1 / 1;
    transform: translate(-50%, -50%);
    background: conic-gradient(from 0deg,
        transparent 0deg 252deg,
        var(--toast-accent, #4a9eff) 300deg,
        #ffffff 331deg,
        var(--toast-accent, #4a9eff) 345deg,
        transparent 360deg);
    animation: toast-chase-spin 4s linear infinite;
}
.toast--tor .toast-chase::before { animation-duration: 1.9s; }
.toast--te  .toast-chase::before { animation-duration: 1.1s; }
@keyframes toast-chase-spin {
    to { transform: translate(-50%, -50%) rotate(360deg); }
}

/* ---- Sonar-ping icon ---------------------------------------
   The tier icon sits in a colored round chip; radar-style rings expand
   outward from it. Ordinary tiers ping 3 times on arrival then rest;
   TOR/TE ping continuously (TE faster, in its magenta). */
.toast-icon-wrap {
    position: relative;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
    width:  calc(26px * var(--toast-scale, 1));
    height: calc(26px * var(--toast-scale, 1));
    border-radius: 50%;
    background: color-mix(in srgb, var(--toast-accent, #4a9eff) 32%, #0b0f1c);
    border: 1px solid color-mix(in srgb, var(--toast-accent, #4a9eff) 70%, #ffffff);
}
.toast-ping {
    position: absolute;
    inset: 0;
    border-radius: 50%;
    border: 2px solid var(--toast-accent, #4a9eff);
    opacity: 0;
    pointer-events: none;
    animation: toast-ping 1.8s ease-out 3;
}
.toast-ping-2 { animation-delay: 0.6s; }
.toast--tor .toast-ping,
.toast--te  .toast-ping { animation-iteration-count: infinite; }
.toast--te  .toast-ping { border-color: #ff7ae6; animation-duration: 1.2s; }
@keyframes toast-ping {
    0%   { transform: scale(0.55); opacity: 0.9; }
    80%  { transform: scale(2.05); opacity: 0; }
    100% { transform: scale(2.05); opacity: 0; }
}

/* ---- TE shimmer headline -----------------------------------
   Metallic magenta→white sheen sweeping the Tornado Emergency title.
   Guarded by @supports: without background-clip:text the gradient would
   swallow the text entirely, so unsupported engines keep plain white. */
@supports ((-webkit-background-clip: text) or (background-clip: text)) {
    .toast--te .toast-title,
    .toast--te .rtoast-title {
        background: linear-gradient(100deg,
            #ffffff 15%, #ff8ae8 33%, #ffffff 50%, #ffb0f0 67%, #ffffff 85%);
        background-size: 220% 100%;
        -webkit-background-clip: text;
        background-clip: text;
        color: transparent;
        animation: te-title-shimmer 2.4s linear infinite;
    }
}
@keyframes te-title-shimmer {
    to { background-position: -220% 0; }
}
