/*
  Priority4 Go consolidated stylesheet
  Generated from the former page-level CSS files and inline PHP style blocks.
  Vendor CSS stays in app-modern.min.css/icons.min.css. Glass system stays in liquid-glass.css.
*/



/* ==========================================================================
   Source: assets/css/index.css
   ========================================================================== */

/* ============================================================================
 * index.css
 * ----------------------------------------------------------------------------
 * App shell / chrome for /response/index.php. Extracted from the inline
 * <style> block; restyled in Liquid Glass.
 *
 * What's in here:
 *   - Font-size root rules (moved from <style id="fn-fontsize-rules">)
 *   - Top chrome wrapper, hero header, hero ID pills, hamburger menu
 *   - Status bar (with new response-count chips on the right half)
 *   - Pull-to-refresh circle
 *   - Tabbar (frosted glass, strongest blur — most-seen surface)
 *   - Page host & page transitions
 *   - Off-canvas drawer (frosted glass strong, modal-like)
 *   - Desktop boxed-layout media query
 *   - Mobile correction media queries
 *
 * Token sources (read-only — defined in liquid-glass.css):
 *   --fn-* : brand / surface / text
 *   --lg-* : glass material (surface, edge, divider, blur, shadow, radius)
 *
 * Load AFTER liquid-glass.css.
 * ========================================================================= */


/* ─────────────────────────────────────────────────────────────────────────
 * Font-size rules (root). Settings JS toggles data-fn-fontsize on <html>;
 * we never modify these via JS, so they live here permanently.
 * ──────────────────────────────────────────────────────────────────────── */
html { font-size: 18.4px !important; }
html[data-fn-fontsize="standard"] { font-size: 18.4px !important; }
html[data-fn-fontsize="large"]    { font-size: 20px !important; }
html[data-fn-fontsize="xlarge"]   { font-size: 22px !important; }
body { font-size: 1rem !important; }


/* ─────────────────────────────────────────────────────────────────────────
 * Top chrome wrapper — pins the hero + status bar to the top of the
 * viewport. The hero stays a solid brand colour (Liquid Glass keeps hero
 * surfaces solid for identity); only the status bar below uses glass.
 * ──────────────────────────────────────────────────────────────────────── */
/* ─────────────────────────────────────────────────────────────────────────
 * Top chrome wrapper — floating island matching the tabbar.
 *
 *   - Detached from screen edges with margin all around (0.65rem sides,
 *     0.45rem from the safe-area). Stays BELOW the iOS status bar area
 *     so time/wifi/battery render normally over the body backdrop.
 *   - Hero gets ALL FOUR corners at --lg-r-md (1rem). Standard floating-
 *     island roundness, symmetric with the tabbar at the bottom.
 *   - Status bar sits INSIDE the wrapper, below the hero, transparent
 *     — badge + chips float as individual glass tiles.
 * ──────────────────────────────────────────────────────────────────────── */
.fn-top-chrome {
    position: fixed;
    top:   calc(var(--fn-safe-top) + 0.45rem);
    left:  0.3rem;
    right: 0.3rem;
    z-index: 50;
}

.fn-hero {
    background: var(--fn-header-bg);
    color: #fff;
    /* All four corners at the same moderate radius — symmetric with
       the tabbar's floating-island feel. */
    border-radius: var(--lg-r-md);
    box-shadow: 0 14px 36px -10px rgba(0,0,0,.28),
                0 4px 12px -4px rgba(0,0,0,.14);
    overflow: hidden;
    transition: background .25s ease;
}

.fn-hero-inner {
    /* Horizontal padding 0.55rem — bell icon (left) and ff_no/station
       badge (right) sit equally inset from the chrome edges. Tuned
       up from 0.35rem on user feedback: the button + station were
       too close to the chrome edge before. */
    padding: .85rem .55rem 1rem;
    display: flex;
    flex-direction: column;
}

.fn-hero-row1 {
    display: flex;
    align-items: center;
    gap: .55rem;
    min-width: 0;
}

.fn-hero-icon {
    width: 2.1rem;
    height: 2.1rem;
    border-radius: .5rem;
    background: rgba(255,255,255,.18);
    display: inline-flex;
    align-items: center;
    justify-content: center;
    font-size: 1.15rem;
    flex-shrink: 0;
    border: 0;
    padding: 0;
    cursor: pointer;
    font-family: inherit;
    color: inherit;
    transition: filter .12s ease, transform .1s ease;
}
.fn-hero-icon:active {
    transform: scale(.92);
    filter: brightness(.85);
}

.fn-hero-brand-wrap {
    min-width: 0;
    flex: 1 1 auto;
    overflow: hidden;
}
.fn-hero-brand {
    font-weight: 800;
    color: #fff;
    font-size: 1.1rem;
    line-height: 1;
    letter-spacing: -.01em;
}
.fn-hero-subtitle {
    font-size: .74rem;
    opacity: .9;
    line-height: 1;
    margin-top: .22rem;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
.fn-hero-id {
    margin-left: auto;
    flex-shrink: 0;
    background: rgba(255,255,255,.16);
    border-radius: var(--lg-r-sm);
    display: inline-flex;
    align-items: center;
    overflow: hidden;
    line-height: 1;
}
.fn-hero-id-cell {
    padding: .42rem .65rem;
    display: inline-flex;
    align-items: center;
    gap: .3rem;
    font-weight: 700;
    font-size: .8rem;
    color: #fff;
    white-space: nowrap;
}
.fn-hero-id-cell + .fn-hero-id-cell {
    border-left: 1px solid rgba(255,255,255,.18);
}
.fn-hero-id-cell .mdi {
    font-size: .95rem;
    opacity: .85;
}

@media (max-width: 380px) {
    .fn-hero-subtitle {
        display: none;
    }
}


/* ─────────────────────────────────────────────────────────────────────────
 * STATUS BAR removed — the "Awaiting response" badge and per-type count
 * chips that used to live in a strip below the hero are now rendered
 * inside each call card (see .fn-call-myresp in home.css). The hero is
 * the only thing in .fn-top-chrome now, which is why --fn-top-chrome-h
 * dropped from 11rem to 5rem in liquid-glass.css.
 * ──────────────────────────────────────────────────────────────────────── */


/* ─────────────────────────────────────────────────────────────────────────
 * Pull-to-refresh circle — floats below the chrome on pull.
 * Strong frosted glass so it stands out against any page content.
 * ──────────────────────────────────────────────────────────────────────── */
.fn-ptr-circle {
    position: fixed;
    top: calc(var(--fn-top-chrome-h) + .25rem);
    left: 50%;
    z-index: 60;
    width: 3.5rem;
    height: 3.5rem;
    margin-left: -1.75rem;
    border-radius: 50%;
    background-color: var(--lg-surface-strong);
    backdrop-filter: var(--lg-blur-strong);
    -webkit-backdrop-filter: var(--lg-blur-strong);
    border: 1px solid var(--lg-edge-strong);
    box-shadow: var(--lg-shadow-strong);
    color: var(--fn-text);
    display: flex;
    align-items: center;
    justify-content: center;
    pointer-events: none;
    transform: translateY(-5rem) scale(.85);
    opacity: 0;
    transition: transform .25s cubic-bezier(.2,.8,.2,1), opacity .2s ease;
}
.fn-ptr-circle.armed { transition: none; }
.fn-ptr-circle.refreshing {
    transform: translateY(.35rem) scale(1);
    opacity: 1;
}
.fn-ptr-circle .mdi {
    font-size: 1.7rem;
    transition: transform .25s ease, opacity .2s ease;
}
.fn-ptr-circle.ready .mdi.fn-ptr-arrow {
    transform: rotate(180deg);
    color: #198754;
}
.fn-ptr-circle .fn-ptr-spin {
    display: none;
    animation: fnPtrSpin .9s linear infinite;
}
.fn-ptr-circle.refreshing .fn-ptr-arrow { display: none; }
.fn-ptr-circle.refreshing .fn-ptr-spin  { display: inline-block; }

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


/* ─────────────────────────────────────────────────────────────────────────
 * TABBAR — floating glass island
 *
 * Treatment:
 *   - Detached from screen edges (small margin all around) so it reads
 *     as a floating shelf rather than a pinned bar.
 *   - Fully rounded corners, strong frosted glass, top-edge specular
 *     highlight, layered drop shadow underneath.
 *   - Active tab gets a soft glass pill BEHIND its icon+label. Pill is
 *     always rendered (every tab has a ::before) but starts at opacity 0;
 *     adding .active fades it in. This means tab-to-tab transitions
 *     animate smoothly instead of jumping.
 *   - Replaces the old 3px line-on-top indicator entirely.
 *
 * Mobile-only — desktop layout still has `.fn-tabbar { display: none }`
 * in the @media (hover: hover) block further down.
 * ──────────────────────────────────────────────────────────────────────── */
.fn-tabbar {
    position: fixed;
    left:   0.65rem;
    right:  0.65rem;
    bottom: calc(var(--fn-safe-bottom) + 0.45rem);
    z-index: 100;
    height: var(--fn-tabbar-h);

    background-color: var(--lg-tabbar-surface);
    backdrop-filter: var(--lg-blur-strong);
    -webkit-backdrop-filter: var(--lg-blur-strong);
    border: 1px solid var(--lg-edge);
    /* All four corners at the same moderate-pill radius. */
    border-radius: 1.75rem;
    box-shadow: var(--lg-tabbar-shadow);
    overflow: hidden;
    isolation: isolate;

    display: grid;
    grid-template-columns: repeat(5, 1fr);
    transition: background-color .25s ease, border-color .25s ease;
}

/* Removed the ::after specular highlight — in dark mode it created a
   "reflection" line at the top of the tabbar that looked artificial.
   Light mode also reads cleaner without it now that the surface is
   more translucent and the body backdrop provides natural variation. */

.fn-tab {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: .2rem;
    background: transparent;
    border: 0;
    color: var(--fn-tabbar-text);
    cursor: pointer;
    padding: .4rem .25rem;
    font-family: inherit;
    transition: color .18s var(--lg-ease), transform .12s var(--lg-ease);
    position: relative;
    z-index: 1;
}
.fn-tab:active { transform: scale(.95); }

/* Active pill — rendered on every tab, faded in only when .active.
   Inset slightly inside the tab cell so adjacent active pills wouldn't
   touch even if both somehow rendered. Soft inner highlight + soft
   shadow underneath sells the "small floating chip" feel. */
.fn-tab::before {
    content: '';
    position: absolute;
    top:    0.32rem;
    bottom: 0.32rem;
    left:   0.28rem;
    right:  0.28rem;
    /* Radius chosen so the pill's outer corners curve concentrically
       with the tabbar's outer corners. Tabbar = 1.75rem; pill is
       inset ~0.30rem from the tab edge; concentric → 1.75 - 0.30
       = 1.45rem. Makes the active tab read as "nested inside" the
       tabbar shape rather than a smaller pill stuck in a bigger one. */
    border-radius: 1.45rem;
    background-color: var(--lg-tabbar-pill-bg);
    box-shadow: var(--lg-tabbar-pill-shadow);
    opacity: 0;
    transform: scale(0.92);
    transition: opacity .22s var(--lg-ease),
                transform .28s var(--lg-spring);
    z-index: -1;
    pointer-events: none;
}
.fn-tab.active::before {
    opacity: 1;
    transform: scale(1);
}
.fn-tab.active {
    color: var(--lg-tabbar-pill-fg);
}

.fn-tab .mdi {
    /* Was 1.7rem. Shrunk to 1.5rem on user feedback that the active
       pill's content felt too close to the pill edges, especially
       on dark tabbar colours where the pill background is most
       visible. Smaller icon = more breathing inside the pill. */
    font-size: 1.5rem;
    line-height: 1;
    transition: transform .18s var(--lg-ease);
}
.fn-tab.active .mdi {
    transform: scale(1.05);
}
.fn-tab .label {
    /* Was 0.72rem. Shrunk to 0.65rem so the wider labels ("Preplan",
       "Settings") have visible inset from pill edges. */
    font-size: .65rem;
    font-weight: 700;
    line-height: 1;
    letter-spacing: .02em;
}


/* ─────────────────────────────────────────────────────────────────────────
 * Page host & per-page transitions
 * ──────────────────────────────────────────────────────────────────────── */
.fn-page-host {
    position: fixed;
    top: 0;
    left: 0;
    right: 0;
    bottom: 0;
    padding-top: calc(var(--fn-safe-top) + 0.45rem + var(--fn-top-chrome-h) + 0.5rem);
    padding-bottom: calc(var(--fn-tabbar-h) + var(--fn-safe-bottom) + 1.5rem);
    overflow-y: auto;
    overflow-x: hidden;
    -webkit-overflow-scrolling: touch;
    overscroll-behavior: contain;
}
.fn-page {
    display: none;
    opacity: 0;
    transition: opacity .25s ease-in-out;
}
.fn-page.active {
    display: block;
    opacity: 1;
}
.fn-page.fn-page--full.active {
    display: flex;
    flex-direction: column;
    height: calc(100vh - var(--fn-safe-top) - var(--fn-top-chrome-h) - var(--fn-tabbar-h) - var(--fn-safe-bottom) - 2.4rem);
    min-height: 20rem;
}
.fn-page-inner {

    padding: .2rem .85rem;
    margin: 0 auto;
    width: 100%;
    box-sizing: border-box;
    overflow: hidden;
}
.fn-page-loading {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    padding: 3rem 1rem;
    color: var(--fn-text-muted);
}
.fn-page-loading .mdi {
    font-size: 2rem;
    opacity: .4;
    margin-bottom: .4rem;
}


/* ─────────────────────────────────────────────────────────────────────────
 * Hamburger button — only visible on desktop layout.
 * ──────────────────────────────────────────────────────────────────────── */
.fn-hero-menu-btn {
    display: none;
    background: rgba(255, 255, 255, .18);
    border: 0;
    width: 2.1rem;
    height: 2.1rem;
    border-radius: .5rem;
    color: #fff;
    cursor: pointer;
    align-items: center;
    justify-content: center;
    font-size: 1.15rem;
    flex-shrink: 0;
    padding: 0;
    transition: transform .1s ease, background .15s ease;
}
.fn-hero-menu-btn .mdi { line-height: 1; }
.fn-hero-menu-btn:hover  { background: rgba(255, 255, 255, .25); }
.fn-hero-menu-btn:active { transform: scale(.95); }


/* ─────────────────────────────────────────────────────────────────────────
 * Off-canvas drawer — sheet-like, strong frosted glass.
 * ──────────────────────────────────────────────────────────────────────── */
.fn-offcanvas[hidden] { display: none; }
.fn-offcanvas {
    position: fixed;
    inset: 0;
    z-index: 200;
}
.fn-offcanvas-backdrop {
    position: absolute;
    inset: 0;
    background: rgba(0, 0, 0, .55);
    opacity: 0;
    transition: opacity .2s ease;
}
.fn-offcanvas.is-open .fn-offcanvas-backdrop { opacity: 1; }

.fn-offcanvas-panel {
    position: absolute;
    top: 0;
    left: 0;
    bottom: 0;
    width: 280px;
    max-width: 80vw;
    background-color: var(--lg-surface-strong);
    backdrop-filter: var(--lg-blur-strong);
    -webkit-backdrop-filter: var(--lg-blur-strong);
    border-right: 1px solid var(--lg-edge);
    box-shadow: var(--lg-shadow-strong);
    transform: translateX(-100%);
    transition: transform .25s ease;
    display: flex;
    flex-direction: column;
}
.fn-offcanvas.is-open .fn-offcanvas-panel {
    transform: translateX(0);
}
.fn-offcanvas-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 1rem 1rem 1rem 1.25rem;
    border-bottom: 1px solid var(--lg-divider);
}
.fn-offcanvas-title {
    font-weight: 800;
    color: var(--fn-text);
    font-size: 1.05rem;
    letter-spacing: .01em;
}
.fn-offcanvas-close {
    background: transparent;
    border: 0;
    padding: .25rem;
    color: var(--fn-text);
    cursor: pointer;
    font-size: 1.6rem;
    line-height: 1;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 2.1rem;
    height: 2.1rem;
    border-radius: .4rem;
    transition: background .15s ease;
}
.fn-offcanvas-close:hover { background: var(--lg-hover); }

.fn-offcanvas-nav {
    display: flex;
    flex-direction: column;
    padding: .5rem;
    gap: .15rem;
    overflow-y: auto;
}
.fn-offcanvas-link {
    display: flex;
    align-items: center;
    gap: .8rem;
    padding: .75rem .9rem;
    border-radius: var(--lg-r-sm);
    border: 0;
    background: transparent;
    color: var(--fn-text);
    cursor: pointer;
    font-size: 1rem;
    font-weight: 600;
    font-family: inherit;
    text-align: left;
    transition: background .15s ease, color .15s ease;
}
.fn-offcanvas-link:hover  { background: var(--lg-hover); }
.fn-offcanvas-link.active {
    background: var(--fn-brand);
    color: #fff;
}
.fn-offcanvas-link .mdi {
    font-size: 1.3rem;
    flex-shrink: 0;
    line-height: 1;
}


/* ─────────────────────────────────────────────────────────────────────────
 * DESKTOP / WIDE-VIEWPORT — boxed layout for mouse-primary devices.
 * Hides the tabbar, shows the hamburger, gives the chrome a contained
 * frame with a soft drop shadow.
 * ──────────────────────────────────────────────────────────────────────── */
@media (hover: hover) and (pointer: fine) {
    :root {
        --fn-tabbar-h: 0px;
        --fn-safe-bottom: 0px;
    }

    html, body {
        position: static;
        height: auto;
        min-height: 100%;
        overflow-x: hidden;
        overflow-y: auto;
        overscroll-behavior: auto;
    }

    body {
        /* On desktop the body backdrop reads better with a slightly
           deeper base — same gradient pools, slightly more saturation. */
        background-color: #e9edf3;
    }

    .fn-hero-menu-btn { display: inline-flex; }

    .fn-top-chrome {
        position: sticky;
        top: 1rem;
        left: auto;
        right: auto;
        width: calc(100% - 2rem);
        max-width: 1180px;
        margin: 1rem auto 0 auto;
        border-radius: var(--lg-r-md) var(--lg-r-md) 0 0;
        box-shadow: 0 10px 30px rgba(0, 0, 0, .12);
        overflow: hidden;
    }
    .fn-hero { box-shadow: none; }
    .fn-hero-inner { padding: 1.2rem .55rem; }

    .fn-hero-icon,
    .fn-hero-menu-btn {
        width: 1.9rem;
        height: 1.9rem;
        border-radius: .45rem;
        font-size: 1rem;
    }
    .fn-hero-brand { font-size: 1rem; }
    .fn-hero-subtitle { display: none; }
    .fn-hero-id-cell {
        padding: .35rem .55rem;
        font-size: .76rem;
    }

    .fn-ptr-circle { display: none; }
    .fn-tabbar { display: none; }

    .fn-page-host {
    position: relative;
    top: auto;
    left: auto;
    right: auto;
    bottom: auto;
    width: calc(100% - 2rem);
    max-width: 1180px;
    transform: none;
    margin: 0 auto 1rem auto;

    background-color: var(--lg-surface);
    backdrop-filter: var(--lg-blur);
    -webkit-backdrop-filter: var(--lg-blur);
    border: 1px solid var(--lg-edge);
    border-top: 0;
    border-radius: 0 0 var(--lg-r-md) var(--lg-r-md);
    box-shadow: var(--lg-shadow-strong);

    padding-top: 1rem;
    padding-bottom: 1rem;

    height: calc(100vh - var(--fn-top-chrome-h) - 2rem);
    max-height: calc(100vh - var(--fn-top-chrome-h) - 2rem);
    min-height: 0;

    overflow-y: auto;
    overflow-x: hidden;
    overscroll-behavior: auto;
    box-sizing: border-box;
}
    .fn-page-inner {
        /* Was max-width: 1100px which made home/crew/preplan/settings
           visibly narrower than the address page (which uses page--full
           and gets the full page-host width). Now page-inner matches
           page-host (1180px max). Padding tightened from 1rem to 0.85rem
           so the side breathing matches the address stage's
           .fn-addr-stage horizontal padding (.85rem). */
        max-width: 100%;
        padding: 1rem .85rem;
        margin: 0 auto;
    }
    .fn-page.fn-page--full.active {
        height: calc(100vh - var(--fn-top-chrome-h) - 3rem);
        min-height: 28rem;
    }

    .fn-offcanvas {
        pointer-events: none;
    }
    .fn-offcanvas.is-open {
        pointer-events: auto;
    }
    .fn-offcanvas-backdrop {
        background: rgba(49, 58, 70, .25);
    }
    .fn-offcanvas-panel {
        position: absolute;
        top: calc(var(--fn-top-chrome-h) + 1.5rem);
        left: calc((100vw - min(1180px, calc(100vw - 2rem))) / 2);
        bottom: auto;
        width: 280px;
        max-width: calc(100vw - 2rem);
        border-radius: var(--lg-r-lg);
        overflow: hidden;
        box-shadow: 0 14px 35px rgba(0, 0, 0, .18);
        transform: translateY(-.75rem);
        opacity: 0;
        transition: transform .2s ease, opacity .2s ease;
    }
    .fn-offcanvas.is-open .fn-offcanvas-panel {
        transform: translateY(0);
        opacity: 1;
    }
}


/* ─────────────────────────────────────────────────────────────────────────
 * MOBILE — touch-primary corrections. Restores fixed app-shell + scrollable
 * page-host so the chrome stays put while content scrolls.
 * ──────────────────────────────────────────────────────────────────────── */
@media (hover: none) and (pointer: coarse) {
    .fn-page-host:has(#fn-page-home.active) {
        overflow-y: hidden;
    }

    .fn-page-host {
        position: fixed;
        top: 0;
        left: 0;
        right: 0;
        bottom: 0;
        height: auto;
        max-height: none;
        padding-top: calc(var(--fn-safe-top) + 0.45rem + var(--fn-top-chrome-h) + 0.5rem);
        padding-bottom: calc(var(--fn-tabbar-h) + var(--fn-safe-bottom) + 1.5rem);
        overflow-y: auto;
        overflow-x: hidden;
        -webkit-overflow-scrolling: touch;
        overscroll-behavior-y: contain;
        box-sizing: border-box;
    }
    .fn-page-inner { padding-bottom: 0.5rem; }
    #fn-page-settings { padding-bottom: 2.5rem; }

    .fn-page.fn-page--full.active {
        height: calc(100dvh - var(--fn-safe-top) - var(--fn-top-chrome-h) - var(--fn-tabbar-h) - var(--fn-safe-bottom) - 2.4rem);
    }
}



/* ==========================================================================
   Source: assets/css/home.css
   ========================================================================== */

/* ============================================================================
 * home.css
 * ----------------------------------------------------------------------------
 * Home tab — call carousel, call cards, response button grid.
 * Extracted from /response/pages/home.php inline <style>; restyled in
 * Liquid Glass.
 *
 * Includes the scrubber addition (counter + draggable track that replaces
 * the dot strip when call count > DOTS_MAX). The JS that builds it lives
 * inline in home.php; this is just the styling.
 *
 * Load AFTER liquid-glass.css and index.css.
 * ========================================================================= */


/* ─────────────────────────────────────────────────────────────────────────
 * Mobile carousel layout — clamp the home tab to the viewport so only one
 * card is on screen at a time, scrolling internal to .fn-call-body.
 * ──────────────────────────────────────────────────────────────────────── */
@media (hover: none) and (pointer: coarse) {
    #fn-page-home.active {
        height: calc(100dvh - var(--fn-safe-top) - var(--fn-top-chrome-h) - var(--fn-tabbar-h) - var(--fn-safe-bottom) - 2rem);
        overflow: hidden;
    }
    #fn-page-home .fn-page-inner {
        height: 100%;
        padding-top: .1rem;
        /* Bottom padding zeroed — was 0.5rem of wasted space below the
           controls. Reclaiming it lets the card grow without pushing
           the controls under the tabbar. */
        padding-bottom: 0;
        overflow: hidden;
        box-sizing: border-box;
    }
    #fn-page-home .fn-carousel {
        /* Was 3.3rem reserved for controls. Reduced to 2.9rem to give
           the call-card more height. Matched against the controls
           block which is now 2.4rem (arrows) + 0.35rem (top margin)
           + 0.15rem (bottom margin) = 2.9rem. */
        height: calc(100% - 2.9rem);
        overflow-x: auto;
        overflow-y: hidden;
        /* Vertical padding trimmed from 4px to 2px — saves 0.25rem of
           slide vertical reserve, going straight into the call card.
           Horizontal padding zeroed — card now sits at page-inner edge,
           aligned with chrome content edges. */
        padding: 2px 0;
        box-sizing: border-box;
    }
    #fn-page-home .fn-carousel-slide {
        height: 100%;
        padding-right: 3px;
        box-sizing: border-box;
    }
    #fn-page-home .fn-call-card {
        height: 100%;
        min-height: 0;
        width: calc(100% - 1px);
        max-width: calc(100% - 1px);
        overflow: hidden;
    }
    #fn-page-home .fn-call-body {
        overflow-y: hidden;
        overflow-x: hidden;
        -webkit-overflow-scrolling: auto;
        touch-action: pan-x;
        scrollbar-width: none;
        -ms-overflow-style: none;
    }

    #fn-page-home .fn-call-section .value.message {
        overflow-y: auto;
        overflow-x: hidden;
        -webkit-overflow-scrolling: touch;
        touch-action: pan-y;
        scrollbar-width: none;
        -ms-overflow-style: none;
    }
    #fn-page-home .fn-call-body::-webkit-scrollbar {
        display: none;
        width: 0;
        height: 0;
    }
    #fn-page-home .fn-call-section .value.message {
        scrollbar-width: none;
        -ms-overflow-style: none;
    }
    #fn-page-home .fn-call-section .value.message::-webkit-scrollbar {
        display: none;
        width: 0;
        height: 0;
    }
}


/* ─────────────────────────────────────────────────────────────────────────
 * Carousel — horizontal scroll-snap container, one slide per call.
 * ──────────────────────────────────────────────────────────────────────── */
.fn-carousel {
    display: flex;
    flex-direction: row;
    overflow-x: auto;
    overflow-y: hidden;
    scroll-snap-type: x mandatory;
    -webkit-overflow-scrolling: touch;
    touch-action: pan-x;
    scrollbar-width: none;
    -ms-overflow-style: none;
    align-items: flex-start;
    width: 100%;
    border-radius: var(--lg-r-lg);
    box-sizing: border-box;
    scroll-behavior: auto;
    padding: 4px 0;
}
.fn-carousel::-webkit-scrollbar { display: none; }

.fn-carousel-slide {
    flex: 0 0 100%;
    width: 100%;
    max-width: 100%;
    scroll-snap-align: center;
    scroll-snap-stop: always;
    box-sizing: border-box;
    padding-right: 1px;
    min-width: 0;
}
.fn-carousel-slide:last-child { padding-right: 0; }


/* ─────────────────────────────────────────────────────────────────────────
 * Carousel controls — Prev/Next arrows flanking either dots OR the
 * scrubber depending on call count.
 * ──────────────────────────────────────────────────────────────────────── */
.fn-carousel-ctrls {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: .45rem;
    /* Tighter vertical rhythm — was .65rem/.25rem (sum 0.9rem); now
       .35rem/.15rem (sum 0.5rem). Combined with 2.4rem arrows we fit
       cleanly in the 2.9rem carousel reservation. */
    margin: .35rem 0 .15rem;
    padding: 0 .25rem;
}
.fn-carousel-ctrls[hidden] { display: none !important; }

.fn-carousel-arrow {
    flex-shrink: 0;
    width: 2.4rem;
    height: 2.4rem;
    border-radius: 50%;
    border: 1px solid var(--lg-edge);
    background-color: var(--lg-surface);
    backdrop-filter: var(--lg-blur);
    -webkit-backdrop-filter: var(--lg-blur);
    color: var(--fn-text);
    display: flex;
    align-items: center;
    justify-content: center;
    cursor: pointer;
    font-family: inherit;
    padding: 0;
    box-shadow: var(--lg-shadow);
    transition: transform var(--lg-t-base) var(--lg-spring),
                background-color var(--lg-t-base) var(--lg-ease),
                box-shadow var(--lg-t-base) var(--lg-ease),
                opacity .15s ease;
}
.fn-carousel-arrow:active:not(:disabled) {
    transform: scale(.92);
    background-color: var(--lg-pressed);
}
.fn-carousel-arrow:disabled {
    opacity: .35;
    cursor: not-allowed;
}
.fn-carousel-arrow .mdi {
    font-size: 1.3rem;
    line-height: 1;
}

.fn-carousel-arrow.fn-jump {
    background-color: var(--fn-brand);
    background-image: var(--lg-fill-primary);
    color: #fff;
    border-color: transparent;
    backdrop-filter: none;
    -webkit-backdrop-filter: none;
    margin-right: .9rem;
}
.fn-carousel-arrow.fn-jump:active:not(:disabled) {
    filter: brightness(.85);
}
.fn-carousel-arrow.fn-jump .mdi { font-size: 1.2rem; }


/* ─────────────────────────────────────────────────────────────────────────
 * Dots — shown when call count ≤ DOTS_MAX (12). One row, no wrap; the
 * scrubber takes over when there are too many to fit.
 * ──────────────────────────────────────────────────────────────────────── */
.fn-carousel-dots {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: .35rem;
    flex-wrap: wrap;
    flex: 1 1 auto;
}
.fn-carousel-dot {
    width: .55rem;
    height: .55rem;
    border-radius: 50%;
    border: 0;
    background: var(--fn-text-muted);
    opacity: .35;
    padding: 0;
    cursor: pointer;
    transition: opacity .2s, transform .2s, width .25s, background .2s;
}
.fn-carousel-dot.active {
    background: var(--fn-brand);
    opacity: 1;
    width: 1.5rem;
    border-radius: .35rem;
}


/* ─────────────────────────────────────────────────────────────────────────
 * Scrubber — shown when call count > DOTS_MAX. Counter on the left, thin
 * track with draggable thumb. Replaces the dot strip; the JS that wires
 * pointer events lives in home.php.
 * ──────────────────────────────────────────────────────────────────────── */
.fn-carousel-scrubber {
    flex: 1 1 auto;
    display: flex;
    align-items: center;
    gap: .55rem;
    min-width: 0;
    padding: 0 .25rem;
}
.fn-carousel-counter {
    flex: 0 0 auto;
    font-size: .72rem;
    font-weight: 700;
    color: var(--fn-text-muted);
    font-variant-numeric: tabular-nums;
    letter-spacing: .01em;
    user-select: none;
    min-width: 2.8rem;
    text-align: center;
}
.fn-carousel-counter strong {
    color: var(--fn-text);
    font-weight: 800;
}
.fn-carousel-track {
    flex: 1 1 auto;
    position: relative;
    height: 1.5rem;
    cursor: pointer;
    touch-action: none;
    user-select: none;
}
.fn-carousel-track::before {
    content: "";
    position: absolute;
    left: 0; right: 0; top: 50%;
    height: .25rem;
    transform: translateY(-50%);
    background: var(--fn-text-muted);
    opacity: .22;
    border-radius: 999px;
}
.fn-carousel-thumb {
    position: absolute;
    top: 50%;
    width: 1.3rem;
    height: .55rem;
    background: var(--fn-brand);
    border-radius: 999px;
    transform: translate(-50%, -50%);
    transition: left .18s ease, width .15s ease, height .15s ease;
    pointer-events: none;
}
.fn-carousel-track.is-dragging .fn-carousel-thumb {
    transition: none;
    width: 1.6rem;
    height: .7rem;
}


/* ─────────────────────────────────────────────────────────────────────────
 * CALL CARD — the hero element on the home tab. Full Liquid Glass: real
 * blur, frosted-strong surface for readability, specular highlight from
 * the top edge, layered drop shadow.
 *
 * Only one card is visible at a time (carousel snap), so the cost of
 * backdrop-filter is fine — single surface in view.
 * ──────────────────────────────────────────────────────────────────────── */
.fn-call-card {
    position: relative;
    background-color: var(--lg-surface);
    backdrop-filter: var(--lg-blur);
    -webkit-backdrop-filter: var(--lg-blur);
    border: 1px solid var(--lg-edge);
    border-radius: var(--lg-r-lg);
    overflow: hidden;
    box-shadow: var(--lg-shadow);
    width: 100%;
    max-width: 100%;
    min-width: 0;
    box-sizing: border-box;
    transition: box-shadow .25s ease, border-color .25s ease;
    display: flex;
    flex-direction: column;
    /* Y = 2.0rem (was 1.8; bumped to maintain scrubber clearance from
       tabbar after the hero grew from 3.2rem → 4rem). Slide reserve
       still 3.25rem above Y. X = 2.0 + 3.25 + 0.05 buffer = 5.3rem. */
    height: calc(100vh  - var(--fn-safe-top) - var(--fn-top-chrome-h) - var(--fn-tabbar-h) - var(--fn-safe-bottom) - 5.3rem);
    height: calc(100dvh - var(--fn-safe-top) - var(--fn-top-chrome-h) - var(--fn-tabbar-h) - var(--fn-safe-bottom) - 5.3rem);
    min-height: 16rem;
    isolation: isolate;
}

/* Specular top-edge highlight via ::before */
.fn-call-card::before {
    content: "";
    position: absolute;
    inset: 0;
    border-radius: inherit;
    background-image: var(--lg-specular);
    pointer-events: none;
    z-index: 0;
}
.fn-call-card > * { position: relative; z-index: 1; }

/* Selected slide — brand-coloured edge + amplified shadow. */
.fn-carousel-slide.is-selected .fn-call-card {
    border-color: var(--fn-brand);
    box-shadow:
        0 0 0 2px var(--fn-brand-soft),
        0 1px 0 rgba(255,255,255,0.5) inset,
        0 14px 36px -8px rgba(49, 58, 70, .28),
        0 4px 12px -4px rgba(0, 0, 0, .10);
}


/* ─────────────────────────────────────────────────────────────────────────
 * Call card header — pulse-dot ACTIVE/CLOSED/EARLIER badge + time.
 * ──────────────────────────────────────────────────────────────────────── */
.fn-call-header {
    padding: .6rem .85rem;
    background: linear-gradient(135deg, rgba(176,58,46,.10), rgba(176,58,46,.03));
    border-bottom: 1px solid var(--lg-divider);
    display: flex;
    align-items: center;
    gap: .5rem;
    flex-shrink: 0;
}
.fn-call-header.older  { background: var(--lg-surface-subtle); }
.fn-call-header.closed { background: var(--lg-surface-subtle); }

.fn-call-badge {
    display: inline-flex;
    align-items: center;
    gap: .3rem;
    background: var(--fn-accent);
    color: #fff;
    font-size: .65rem;
    font-weight: 800;
    text-transform: uppercase;
    letter-spacing: .06em;
    padding: .25rem .55rem;
    border-radius: 999px;
    flex-shrink: 0;
}
.fn-call-badge::before {
    content: '';
    width: .35rem;
    height: .35rem;
    border-radius: 50%;
    background: #fff;
    animation: fnPulse 1.4s infinite;
}
.fn-call-badge.older  { background: var(--fn-text-muted); }
.fn-call-badge.older::before  { animation: none; }
.fn-call-badge.closed { background: var(--fn-text-muted); }
.fn-call-badge.closed::before { animation: none; }

@keyframes fnPulse {
    0%, 100% { opacity: 1; }
    50% { opacity: .35; }
}

.fn-call-time {
    font-size: .78rem;
    color: var(--fn-text-muted);
    font-weight: 600;
    margin-left: auto;
    font-variant-numeric: tabular-nums;
    white-space: nowrap;
}


/* ─────────────────────────────────────────────────────────────────────────
 * Call body — incident type, address, units, message.
 * ──────────────────────────────────────────────────────────────────────── */
.fn-call-body {
    padding: .85rem .95rem;
    display: flex;
    flex-direction: column;
    gap: .75rem;
    min-width: 0;
    flex: 1 1 auto;
    min-height: 0;
    overflow-y: hidden;
    overflow-x: hidden;
    -webkit-overflow-scrolling: touch;
    overscroll-behavior: contain;
}
.fn-call-body > * { flex-shrink: 0; }

.fn-call-type {
    /* Scales down on narrow screens. Floor at .95rem, ceiling 1.25rem.
       Final guard: nowrap+ellipsis if it still overflows. */
    font-size: clamp(.95rem, 4.2vw, 1.25rem);
    font-weight: 900;
    line-height: 1.15;
    color: var(--fn-text);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    min-width: 0;
}


/* ─────────────────────────────────────────────────────────────────────────
 * Preplan alert banner — solid red CTA at top of call body when a preplan
 * exists for the address. Solid (not glass) because action affordance.
 * ──────────────────────────────────────────────────────────────────────── */
.fn-call-preplan-banner {
    appearance: none;
    -webkit-appearance: none;
    border: 0;
    width: 100%;
    text-align: left;
    font-family: inherit;
    background-image: var(--lg-fill-danger);
    color: #fff;
    border-radius: var(--lg-r-sm);
    padding: .65rem .75rem;
    display: flex;
    align-items: center;
    gap: .65rem;
    cursor: pointer;
    box-shadow: 0 1px 0 rgba(255,255,255,.18) inset,
                0 6px 16px -6px rgba(176, 58, 46, .55),
                0 2px 6px -2px rgba(0,0,0,.15);
    transition: filter .12s ease, transform .1s ease;
    position: relative;
    overflow: hidden;
    flex: 0 0 auto;
}
.fn-call-preplan-banner.secure-only {
    background-image: linear-gradient(135deg, #0b95ad 0%, #086c80 100%);
    box-shadow: 0 1px 0 rgba(255,255,255,.18) inset,
                0 6px 16px -6px rgba(11, 142, 166, .55),
                0 2px 6px -2px rgba(0,0,0,.15);
}
.fn-call-preplan-banner:active {
    transform: scale(.985);
    filter: brightness(.92);
}
.fn-call-preplan-banner-icon {
    font-size: 1.45rem;
    line-height: 1;
    flex-shrink: 0;
    animation: fnPreplanPulse 2.4s ease-in-out infinite;
}
@keyframes fnPreplanPulse {
    0%, 100% { opacity: 1; }
    50% { opacity: .55; }
}
.fn-call-preplan-banner-text {
    flex: 1 1 auto;
    min-width: 0;
    display: flex;
    flex-direction: column;
    gap: .1rem;
}
.fn-call-preplan-banner-title {
    font-size: .82rem;
    font-weight: 800;
    text-transform: uppercase;
    letter-spacing: .05em;
    line-height: 1.1;
}
.fn-call-preplan-banner-sub {
    font-size: .78rem;
    font-weight: 600;
    opacity: .92;
    line-height: 1.25;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.fn-call-preplan-banner-arrow {
    font-size: 1.4rem;
    line-height: 1;
    opacity: .85;
    flex-shrink: 0;
}


/* ─────────────────────────────────────────────────────────────────────────
 * Section blocks — label (small caps with brand tab) + value.
 * ──────────────────────────────────────────────────────────────────────── */
.fn-call-section {
    display: flex;
    flex-direction: column;
    gap: .25rem;
    min-width: 0;
    overflow: auto;
}
.fn-call-section .label {
    font-size: .65rem;
    font-weight: 800;
    text-transform: uppercase;
    color: var(--fn-text-muted);
    letter-spacing: .04em;
    display: inline-flex;
    align-items: center;
    gap: .3rem;
}
.fn-call-section .label::before {
    content: '';
    width: 3px;
    height: 11px;
    background: var(--fn-brand);
    border-radius: 2px;
}
.fn-call-section .value {
    font-size: .92rem;
    font-weight: 600;
    color: var(--fn-text);
    line-height: 1.4;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    min-width: 0;
}
.fn-call-section .value.message {
    font-size: .92rem;
    line-height: 1.5;
    font-weight: 500;
    max-height: 6.2em;
    white-space: normal;
    overflow-y: auto;
    overflow-x: hidden;
    text-overflow: clip;
    -webkit-overflow-scrolling: touch;
    overscroll-behavior: contain;
    word-break: break-word;
    overflow-wrap: anywhere;
    background-color: var(--lg-surface-subtle);
    border: 1px solid var(--lg-edge);
    border-radius: var(--lg-r-sm);
    padding: .4rem .55rem;
    flex-shrink: 0;
}
.fn-call-section .value.message::-webkit-scrollbar {
    width: 4px;
}
.fn-call-section .value.message::-webkit-scrollbar-thumb {
    background: var(--lg-edge-strong);
    border-radius: 2px;
}


/* ─────────────────────────────────────────────────────────────────────────
 * Units list — small brand-coloured pills, horizontally scrollable.
 * ──────────────────────────────────────────────────────────────────────── */
.fn-units-list {
    list-style: none;
    margin: 0;
    padding: 0;
    display: flex;
    flex-wrap: nowrap;
    gap: .35rem;
    overflow-x: auto;
    overflow-y: hidden;
    scrollbar-width: none;
    -ms-overflow-style: none;
    -webkit-overflow-scrolling: touch;
}
.fn-units-list::-webkit-scrollbar { display: none; }
.fn-units-list li {
    background-image: var(--lg-fill-primary);
    color: #fff;
    border-radius: .4rem;
    padding: .28rem .6rem;
    font-weight: 800;
    font-size: .82rem;
    white-space: nowrap;
    flex-shrink: 0;
    box-shadow: 0 1px 0 rgba(255,255,255,.15) inset,
                0 1px 3px rgba(0,0,0,.1);
}


/* ─────────────────────────────────────────────────────────────────────────
 * "YOUR RESPONSE" SUMMARY BLOCK — replaces the old top-of-screen status
 * bar. Now lives inside .fn-call-response-box together with the response
 * buttons, so the two read as one bordered unit (matches the user's
 * design screenshot). Two-column inner layout:
 *
 *   Left:  person icon  +  heading text  +  subtitle
 *   Right: one circle per response type, count of respondents inside
 *
 * The heading text defaults to "YOUR RESPONSE" (muted) and flips to the
 * selected response's label (coloured to its type) once the user taps
 * a button. Circle counts come from the focused call's data.responses;
 * other carousel slides render with em-dash placeholders so the layout
 * doesn't shift when the user swipes to a different card.
 * ──────────────────────────────────────────────────────────────────────── */

/* Outer wrapper that holds BOTH the summary row and the response grid.
   Owns the soft border + tinted background + outer margin; the children
   now sit transparent on top of it. */
.fn-call-response-box {
    margin: .35rem .85rem .85rem;
    padding: .5rem;
    background-color: var(--lg-surface-subtle);
    border: 1px solid rgba(15, 23, 42, 0.12);
    border-radius: var(--lg-r-md);
    display: flex;
    flex-direction: column;
    gap: .5rem;
    flex-shrink: 0;
    box-sizing: border-box;
    /* Subtle inner highlight so the box reads as a single elevated
       surface against the card. Matches the .fn-call-card specular
       treatment, minus the heavy shadow. */
    box-shadow: 0 1px 2px rgba(15, 23, 42, .05);
}

.fn-call-myresp {
    padding: .15rem .25rem .15rem .15rem;
    display: flex;
    align-items: center;
    gap: .65rem;
    flex-shrink: 0;
    min-height: 2.5rem;
    box-sizing: border-box;
    /* No standalone border/background/margin — the .fn-call-response-box
       wrapper handles all of that now. */
}

.fn-call-myresp-left {
    display: flex;
    align-items: center;
    gap: .55rem;
    flex: 1 1 auto;
    min-width: 0;
}

.fn-call-myresp-icon {
    font-size: 1.2rem;
    color: var(--fn-text-muted);
    flex-shrink: 0;
}

.fn-call-myresp-icon.success { color: #198754; }
.fn-call-myresp-icon.danger  { color: var(--fn-accent); }
.fn-call-myresp-icon.warning { color: #d97706; }
.fn-call-myresp-icon.info    { color: #0d6efd; }
.fn-call-myresp-icon.purple  { color: #7c3aed; }
.fn-call-myresp-icon.teal    { color: #0d9488; }
.fn-call-myresp-icon.pink    { color: #db2777; }
.fn-call-myresp-icon.dark    { color: #1f2937; }
.fn-call-myresp-icon.gray    { color: #6b7280; }

/* Heading: bold, all-caps, slightly tracked. Defaults to muted grey;
   when a response is selected, .fn-call-myresp-heading.<color> swaps
   in the type's accent for instant "I know what I picked" feedback.
   Sits directly next to the icon — no longer wrapped in a column
   layout since the subtitle line was removed. */
.fn-call-myresp-heading {
    font-weight: 800;
    font-size: .92rem;
    letter-spacing: .04em;
    text-transform: uppercase;
    color: var(--fn-text-muted);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    min-width: 0;
    flex: 1 1 auto;
    line-height: 1.1;
    transition: color .15s ease;
}
.fn-call-myresp-heading.success { color: #198754; }
.fn-call-myresp-heading.danger  { color: var(--fn-accent); }
.fn-call-myresp-heading.warning { color: #d97706; }
.fn-call-myresp-heading.info    { color: #0d6efd; }
.fn-call-myresp-heading.purple  { color: #7c3aed; }
.fn-call-myresp-heading.teal    { color: #0d9488; }
.fn-call-myresp-heading.pink    { color: #db2777; }
.fn-call-myresp-heading.dark    { color: #1f2937; }
.fn-call-myresp-heading.gray    { color: #6b7280; }

/* Count-circles row. One per response type, coloured by type. The
   circle holds dark-on-tint count text — placeholder "—" for the
   off-screen-card case where data.responses isn't this card's.
   max-width: 60% so a wall of circles can't crowd the heading text. */
.fn-call-myresp-circles {
    display: flex;
    align-items: center;
    gap: .35rem;
    flex: 0 0 auto;
    max-width: 60%;
    overflow: hidden;
}

.fn-call-myresp-circle {
    width: 2rem;
    height: 2rem;
    border-radius: 50%;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    font-weight: 800;
    font-size: .85rem;
    font-variant-numeric: tabular-nums;
    color: var(--fn-text);
    flex-shrink: 0;
    /* Soft-tinted background + matching tinted border keeps the circles
       readable on either a light or dark card surface. Each .color
       modifier below sets both. Slightly stronger fill than before
       since the circles now sit on the response-box's tinted backdrop
       — they'd otherwise wash into it. */
    background-color: rgba(255, 255, 255, .85);
    border: 1px solid var(--lg-edge);
    box-shadow: 0 1px 2px rgba(15, 23, 42, .08);
}

.fn-call-myresp-circle.success { background-color: rgba(25, 135, 84,  .22); border-color: rgba(25, 135, 84,  .40); color: #0f5132; }
.fn-call-myresp-circle.danger  { background-color: rgba(176, 58, 46,  .22); border-color: rgba(176, 58, 46,  .40); color: #842029; }
.fn-call-myresp-circle.warning { background-color: rgba(217, 119, 6,  .24); border-color: rgba(217, 119, 6,  .40); color: #7a3e00; }
.fn-call-myresp-circle.info    { background-color: rgba(13, 110, 253, .22); border-color: rgba(13, 110, 253, .40); color: #084298; }
.fn-call-myresp-circle.purple  { background-color: rgba(124, 58, 237, .22); border-color: rgba(124, 58, 237, .40); color: #4a1d96; }
.fn-call-myresp-circle.teal    { background-color: rgba(13, 148, 136, .22); border-color: rgba(13, 148, 136, .40); color: #0b5a52; }
.fn-call-myresp-circle.pink    { background-color: rgba(219, 39, 119, .22); border-color: rgba(219, 39, 119, .40); color: #831843; }
.fn-call-myresp-circle.dark    { background-color: rgba(31, 41, 55,   .18); border-color: rgba(31, 41, 55,   .35); color: #1f2937; }
.fn-call-myresp-circle.gray    { background-color: rgba(107, 114, 128, .18); border-color: rgba(107, 114, 128, .35); color: #374151; }

/* Tight screens: shrink the circles a hair so 4+ response types still
   fit alongside the heading text without crowding. */
@media (max-width: 380px) {
    .fn-call-myresp-circles { gap: .28rem; }
    .fn-call-myresp-circle  { width: 1.75rem; height: 1.75rem; font-size: .78rem; }
    .fn-call-response-box   { padding: .4rem; gap: .4rem; }
    .fn-call-myresp         { gap: .5rem; }
}


/* ─────────────────────────────────────────────────────────────────────────
 * RESPONSE BUTTON GRID — the "tap to respond" buttons. SOLID coloured
 * fills (Liquid Glass keeps action buttons solid for unambiguous
 * affordance), but pressed/is-mine states get spring + inner highlight.
 * ──────────────────────────────────────────────────────────────────────── */
.fn-resp-grid {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    gap: .4rem;
    /* Padding zeroed out — the .fn-call-response-box wrapper provides
       the outer padding now. */
    padding: 0;
    flex-shrink: 0;
}

.fn-resp-btn {
    border: 0;
    /* Was --lg-r-sm (0.65rem). Bumped to --lg-r-md (1rem) for a
       softer, more pill-like look matching the rest of the redesign. */
    border-radius: var(--lg-r-md);
    color: #fff;
    background: var(--fn-text-muted);
    font-family: inherit;
    font-weight: 800;
    font-size: .68rem;
    text-transform: uppercase;
    letter-spacing: .02em;
    padding: .55rem .25rem;
    min-height: 3rem;
    cursor: pointer;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: .2rem;
    line-height: 1.05;
    transition: filter .12s, transform .1s, opacity .15s, box-shadow .15s;
    box-shadow: 0 1px 0 rgba(255,255,255,.20) inset,
                0 2px 6px rgba(0,0,0,.18);
    overflow: hidden;
    position: relative;
}
.fn-resp-btn span {
    /* fnFitRespButtons() sets an inline font-size — largest that fits.
       Don't ellipsis here; auto-fit avoids truncation by design. */
    white-space: nowrap;
    overflow: hidden;
    max-width: 100%;
    display: block;
    text-align: center;
}
.fn-resp-btn:active:not(:disabled):not(.is-mine) {
    transform: scale(.96);
    filter: brightness(.92);
}
.fn-resp-btn:disabled { cursor: not-allowed; }
.fn-resp-btn .mdi { font-size: 1.1rem; line-height: 1; }

.fn-resp-btn.success { background: #198754; }
.fn-resp-btn.danger  { background: var(--fn-accent); }
.fn-resp-btn.warning { background: #d97706; }
.fn-resp-btn.info    { background: #0d6efd; }
.fn-resp-btn.purple  { background: #7c3aed; }
.fn-resp-btn.teal    { background: #0d9488; }
.fn-resp-btn.pink    { background: #db2777; }
.fn-resp-btn.dark    { background: #1f2937; }
.fn-resp-btn.gray    { background: #6b7280; }

/* User's own response — dimmed + checkmark badge. */
.fn-resp-btn.is-mine {
    cursor: default;
    opacity: .55;
    box-shadow: inset 0 0 0 2px rgba(255,255,255,.5),
                0 1px 3px rgba(0,0,0,.1);
}
.fn-resp-btn.is-mine::after {
    content: '';
    position: absolute;
    top: .3rem;
    right: .3rem;
    width: 1.05rem;
    height: 1.05rem;
    background: rgba(255,255,255,.95);
    border-radius: 50%;
    background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='14' height='14' viewBox='0 0 24 24'><path fill='%23222' d='M9,16.17L4.83,12L3.41,13.41L9,19L21,7L19.59,5.59L9,16.17Z'/></svg>");
    background-repeat: no-repeat;
    background-position: center;
    background-size: 75%;
}


/* ─────────────────────────────────────────────────────────────────────────
 * Empty state — "no active calls".
 * ──────────────────────────────────────────────────────────────────────── */
.fn-empty {
    display: flex;
    flex-direction: column;
    align-items: center;
    text-align: center;
    padding: 3rem 1.5rem 2rem;
    color: var(--fn-text-muted);
}
.fn-empty-icon {
    font-size: 3.5rem;
    line-height: 1;
    opacity: .35;
    color: var(--fn-text);
    margin-bottom: .25rem;
}
.fn-empty-title {
    font-weight: 800;
    font-size: 1.05rem;
    color: var(--fn-text);
    margin: .5rem 0 .35rem;
}
.fn-empty-sub {
    font-size: .85rem;
    color: var(--fn-text-muted);
    line-height: 1.45;
    max-width: 22rem;
}


/* ─────────────────────────────────────────────────────────────────────────
 * In-app confirmation modal — strong frosted glass card on a dim overlay.
 * ──────────────────────────────────────────────────────────────────────── */
.fn-confirm-overlay {
    position: fixed;
    inset: 0;
    background: rgba(0, 0, 0, .55);
    z-index: 200;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 1.5rem;
    opacity: 0;
    pointer-events: none;
    transition: opacity .2s ease;
}
.fn-confirm-overlay.active {
    opacity: 1;
    pointer-events: auto;
}
.fn-confirm-card {
    background-color: var(--lg-surface-strong);
    backdrop-filter: var(--lg-blur-strong);
    -webkit-backdrop-filter: var(--lg-blur-strong);
    border: 1px solid var(--lg-edge-strong);
    color: var(--fn-text);
    border-radius: var(--lg-r-lg);
    max-width: 22rem;
    width: 100%;
    padding: 1.1rem 1.1rem .85rem;
    box-shadow: var(--lg-shadow-strong);
    transform: scale(.92);
    transition: transform .2s ease;
}
.fn-confirm-overlay.active .fn-confirm-card { transform: scale(1); }

.fn-confirm-title {
    font-weight: 800;
    font-size: 1.05rem;
    margin: 0 0 .5rem;
    line-height: 1.3;
}
.fn-confirm-msg {
    font-size: .92rem;
    line-height: 1.45;
    color: var(--fn-text-muted);
    margin: 0 0 .9rem;
}
.fn-confirm-msg strong {
    color: var(--fn-text);
    font-weight: 800;
}
.fn-confirm-actions {
    display: flex;
    gap: .55rem;
}
.fn-confirm-btn {
    flex: 1;
    padding: .7rem .5rem;
    border: 0;
    border-radius: var(--lg-r-sm);
    font-family: inherit;
    font-weight: 800;
    font-size: .9rem;
    cursor: pointer;
    line-height: 1;
}
.fn-confirm-btn.cancel {
    background-color: var(--lg-surface-subtle);
    color: var(--fn-text);
    border: 1px solid var(--lg-edge);
    backdrop-filter: var(--lg-blur-subtle);
    -webkit-backdrop-filter: var(--lg-blur-subtle);
}
.fn-confirm-btn.confirm {
    background-image: var(--lg-fill-primary);
    color: #fff;
}
.fn-confirm-btn:active { filter: brightness(.92); }

/* Desktop: allow the call details area to scroll when needed */
@media (hover: hover) and (pointer: fine) {
    #fn-page-home .fn-call-body {
        overflow-y: auto !important;
        overflow-x: hidden !important;
        -webkit-overflow-scrolling: auto !important;
        overscroll-behavior: contain;
    }

    #fn-page-home .fn-call-section {
        overflow: visible !important;
    }

    #fn-page-home .fn-call-section .value.message {
        overflow-y: auto !important;
        overflow-x: hidden !important;
    }
}

/* ==========================================================================
   Source: assets/css/response.css
   ========================================================================== */

.fn-resp-call-summary {
    background: var(--fn-card-bg);
    border: 1px solid var(--fn-card-border);
    border-radius: .7rem;
    padding: .65rem .85rem;
    margin-bottom: .75rem;
    display: flex;
    align-items: center;
    gap: .55rem;
}
.fn-resp-call-summary .icon {
    width: 2rem; height: 2rem;
    border-radius: .45rem;
    background: var(--fn-accent-soft);
    color: var(--fn-accent);
    display: inline-flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
}
.fn-resp-call-summary .icon .mdi { font-size: 1.15rem; }
.fn-resp-call-summary .info { min-width: 0; flex: 1; }
.fn-resp-call-summary .type {
    font-weight: 800;
    font-size: 1rem;
    color: var(--fn-text);
    line-height: 1.2;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.fn-resp-call-summary .addr {
    font-size: .8rem;
    color: var(--fn-text-muted);
    line-height: 1.25;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    margin-top: .15rem;
}

.fn-resp-group {
    background: var(--fn-card-bg);
    border: 1px solid var(--fn-card-border);
    border-radius: .7rem;
    overflow: hidden;
    margin-bottom: .65rem;
}
.fn-resp-group-header {
    display: flex;
    align-items: center;
    gap: .5rem;
    padding: .55rem .85rem;
    background: var(--fn-tertiary-bg);
    border-bottom: 1px solid var(--fn-card-border);
}
.fn-resp-group-pill {
    width: 1.7rem; height: 1.7rem;
    border-radius: .45rem;
    color: #fff;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
}
.fn-resp-group-pill .mdi { font-size: 1rem; }
.fn-resp-group-pill.success { background: #198754; }
.fn-resp-group-pill.danger  { background: var(--fn-accent); }
.fn-resp-group-pill.warning { background: #d97706; }
.fn-resp-group-pill.info    { background: #0d6efd; }
.fn-resp-group-pill.purple  { background: #7c3aed; }
.fn-resp-group-pill.teal    { background: #0d9488; }
.fn-resp-group-pill.pink    { background: #db2777; }
.fn-resp-group-pill.dark    { background: #1f2937; }
.fn-resp-group-pill.gray    { background: #6b7280; }
.fn-resp-group-label {
    font-weight: 800;
    font-size: .85rem;
    color: var(--fn-text);
    text-transform: uppercase;
    letter-spacing: .03em;
    flex: 1;
    min-width: 0;
}
.fn-resp-group-count {
    font-weight: 800;
    font-size: .8rem;
    color: var(--fn-text-muted);
    background: var(--fn-card-bg);
    padding: .2rem .5rem;
    border-radius: 999px;
    border: 1px solid var(--fn-card-border);
    flex-shrink: 0;
}

.fn-resp-row {
    display: flex;
    align-items: center;
    gap: .55rem;
    padding: .55rem .85rem;
    border-bottom: 1px solid var(--fn-card-border);
}
.fn-resp-row:last-child { border-bottom: 0; }
.fn-resp-row.is-mine { background: rgba(13,110,253,.06); }

.fn-resp-name {
    flex: 1;
    min-width: 0;
    display: flex;
    flex-direction: column;
    gap: .15rem;
}
.fn-resp-name .name {
    font-weight: 700;
    font-size: .95rem;
    color: var(--fn-text);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.fn-resp-name .ff {
    font-size: .72rem;
    color: var(--fn-text-muted);
    font-weight: 600;
}
.fn-resp-name .ff.you {
    color: #0d6efd;
    font-weight: 800;
}

/* ETA pill — Bootstrap-style subtle success green.
   Pale tinted background, dark green text, soft border.
   Reads as "informational success" without being loud. */
.fn-resp-eta {
    display: inline-flex;
    align-items: center;
    gap: .25rem;
    background: #d1e7dd;          /* Bootstrap success-subtle bg */
    color: #0a3622;               /* Bootstrap success-emphasis text */
    border: 1px solid #a3cfbb;    /* Bootstrap success-border-subtle */
    padding: .28rem .5rem;
    border-radius: .4rem;
    font-size: .8rem;
    font-weight: 700;
    font-variant-numeric: tabular-nums;
    white-space: nowrap;
    flex-shrink: 0;
    letter-spacing: .01em;
}
.fn-resp-eta .mdi {
    font-size: .9rem;
    opacity: .85;
}
[data-bs-theme="dark"] .fn-resp-eta {
    background: rgba(25, 135, 84, .18);
    color: #75d8a6;
    border-color: rgba(25, 135, 84, .35);
}

.fn-resp-time {
    font-size: .72rem;
    color: var(--fn-text-muted);
    font-variant-numeric: tabular-nums;
    white-space: nowrap;
    flex-shrink: 0;
}

.fn-empty {
    display: flex;
    flex-direction: column;
    align-items: center;
    text-align: center;
    padding: 3rem 1.5rem 2rem;
    color: var(--fn-text-muted);
}
.fn-empty-icon {
    font-size: 4rem;
    line-height: 1;
    opacity: .35;
    color: var(--fn-text);
    margin-bottom: .25rem;
}
.fn-empty-title {
    font-weight: 800;
    font-size: 1.15rem;
    color: var(--fn-text);
    margin: .5rem 0 .35rem;
}
.fn-empty-sub {
    font-size: .9rem;
    color: var(--fn-text-muted);
    line-height: 1.45;
    max-width: 22rem;
}



/* ==========================================================================
   Source: assets/css/address.css
   ========================================================================== */

/* ============================================================================
 * address.css
 * ----------------------------------------------------------------------------
 * Address tab — Google Map + Street View, hydrants chip, what3words chip,
 * map launch buttons. Combines:
 *
 *   1. Existing /response/assets/css/address.css
 *   2. Inline <style> block extracted from /response/pages/address.php
 *      (the .fn-w3w-chip rules)
 *
 * Restyled with Liquid Glass tokens where appropriate. The map wrap stays
 * with a solid background since the map tiles fill it.
 *
 * Load AFTER liquid-glass.css.
 * ========================================================================= */


/* ─────────────────────────────────────────────────────────────────────────
 * Stage — vertical flex container that fills the page-host content area.
 * Map takes the available space; buttons + chips sit below.
 * ──────────────────────────────────────────────────────────────────────── */
.fn-addr-stage {
    display: flex;
    flex-direction: column;
    /* Gap 0.7rem between items (was 0.5). User said too crammed —
       extra breathing between map, address text, hydrants chip, and
       map buttons. */
    gap: .7rem;
    /* Vertical padding tuned for equal-gap layout:
         - top 0.25rem: small breathing below the status bar — matches
           the gap from AVAILABLE to the call card on the home screen,
           so AVAILABLE → content has the same gap on both screens
         - bottom 0: buttons (last item) sit AT stage bottom, which the
           page--full height calc places exactly 0.5rem above tabbar
           top — same as the gap between every other pair of items */
    padding: 0.25rem .85rem 0;
    height: 100%;
}


/* ─────────────────────────────────────────────────────────────────────────
 * Map wrap — contains <iframe>/canvas map and street-view panorama.
 * Solid surface, not glass — the map tiles cover the entire area.
 * ──────────────────────────────────────────────────────────────────────── */
.fn-map-wrap {
    position: relative;
    flex: 1 1 0;
    min-height: 12rem;
    border-radius: var(--lg-r-md);
    overflow: hidden;
    border: 1px solid var(--lg-edge);
    background: var(--fn-tertiary-bg);
    box-shadow: var(--lg-shadow);
}

#fnMap, #fnPano {
    width: 100%;
    height: 100%;
    min-height: 12rem;
}
#fnPano { display: none; }
.fn-map-wrap.streetview #fnMap { display: none; }
.fn-map-wrap.streetview #fnPano { display: block; }


/* ─────────────────────────────────────────────────────────────────────────
 * Street-view toggle — floats over the top-right of the map. Glass pill
 * so it reads as a control distinct from the map content.
 * ──────────────────────────────────────────────────────────────────────── */
.fn-sv-toggle {
    position: absolute;
    top: .55rem;
    right: .55rem;
    z-index: 5;
    display: inline-flex;
    align-items: center;
    gap: .3rem;
    background: rgba(255, 255, 255, .96);
    color: #1a1a1a;
    border: 0;
    border-radius: 999px;
    padding: .45rem .75rem;
    font-weight: 700;
    font-size: .82rem;
    cursor: pointer;
    box-shadow: 0 2px 8px rgba(0, 0, 0, .25);
}
.fn-sv-toggle .mdi { font-size: 1rem; }
.fn-sv-toggle.disabled {
    opacity: .55;
    cursor: not-allowed;
}
.fn-map-wrap.streetview .fn-sv-toggle {
    background: #1a1a1a;
    color: #fff;
}
[data-bs-theme="dark"] .fn-sv-toggle {
    background: rgba(40, 44, 52, .96);
    color: #fff;
}


/* ─────────────────────────────────────────────────────────────────────────
 * Address text strip beneath the map.
 * NOTE: .fn-map-coords (the lat/long sub-line) is hidden — the user
 * doesn't need GPS coordinates surfaced; the map+address are enough.
 * The element still exists in the DOM so any JS that targets it keeps
 * working, it just doesn't render.
 * ──────────────────────────────────────────────────────────────────────── */
.fn-map-address {
    flex: 0 0 auto;
    font-size: .95rem;
    color: var(--fn-text-muted);
    text-align: center;
    line-height: 1.35;
    padding: 0 .25rem;
}
.fn-map-address strong {
    color: var(--fn-text);
    font-weight: 700;
}
.fn-map-coords {
    display: none;  /* lat/long not shown — was distracting */
}


/* ─────────────────────────────────────────────────────────────────────────
 * Map action buttons — Google + Apple maps launchers.
 * Solid coloured fills (action affordance), but spring + brightness on
 * press matches the Liquid Glass interaction language elsewhere.
 * ──────────────────────────────────────────────────────────────────────── */
.fn-map-actions {
    flex: 0 0 auto;
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: .4rem;
}
.fn-map-actions.single-col {
    grid-template-columns: 1fr;
}

.fn-map-btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: .35rem;
    padding: .5rem .55rem;
    min-height: 2.5rem;
    /* Was --lg-r-sm (0.65rem). Bumped to 1rem to match home response
       buttons and preplan action buttons. */
    border-radius: 1rem;
    font-weight: 800;
    font-size: .85rem;
    letter-spacing: .02em;
    text-decoration: none;
    border: 0;
    cursor: pointer;
    white-space: nowrap;
    line-height: 1;
    box-shadow: 0 1px 0 rgba(255,255,255,.20) inset,
                0 2px 6px rgba(0,0,0,.18);
    transition: filter .12s var(--lg-ease),
                transform .1s var(--lg-ease);
    box-sizing: border-box;
}
.fn-map-btn:active {
    transform: scale(.96);
    filter: brightness(.92);
}
.fn-map-btn .mdi { font-size: 1.1rem; line-height: 1; }
.fn-map-btn.google { background: #4285F4; color: #fff; }
.fn-map-btn.apple  { background: #1a1a1a; color: #fff; }
[data-bs-theme="dark"] .fn-map-btn.apple { background: #383838; }


/* ─────────────────────────────────────────────────────────────────────────
 * Hydrants info chip — red-themed strip between address and buttons.
 * Renders distance to nearest hydrant + count within 200m; flips to a
 * filled-red "warning" state when no hydrants are within 200m so crews
 * know they may have to draft or shuttle water.
 * ──────────────────────────────────────────────────────────────────────── */
.fn-hydrants-info {
    flex: 0 0 auto;
    display: flex;
    align-items: center;
    justify-content: center;
    gap: .4rem;
    width: 100%;
    box-sizing: border-box;
    background: rgba(220, 38, 38, .10);
    color: #b91c1c;
    border: 1px solid rgba(220, 38, 38, .30);
    border-radius: var(--lg-r-sm);
    padding: .5rem .85rem;
    min-height: 2.5rem;
    font-size: .85rem;
    font-weight: 800;
    line-height: 1;
    letter-spacing: .02em;
    transition: background .15s, color .15s, border-color .15s;
}
.fn-hydrants-info[hidden] { display: none !important; }
.fn-hydrants-info .mdi { font-size: 1.1rem; }
.fn-hydrants-info.warn {
    background: var(--fn-accent);
    color: #fff;
    border-color: var(--fn-accent);
}
.fn-hydrants-info.loading {
    background: var(--lg-surface-subtle);
    color: var(--fn-text-muted);
    border-color: var(--lg-edge);
    font-weight: 600;
}
[data-bs-theme="dark"] .fn-hydrants-info {
    background: rgba(220, 38, 38, .18);
    color: #ff8a8a;
    border-color: rgba(220, 38, 38, .38);
}
[data-bs-theme="dark"] .fn-hydrants-info.warn {
    background: var(--fn-accent);
    color: #fff;
    border-color: var(--fn-accent);
}


/* ─────────────────────────────────────────────────────────────────────────
 * what3words auto-detected chip (extracted from settings.php inline).
 * Renders when call data includes a /// address. Tapping opens the w3w
 * app via Universal Links on iOS, falls back to the web page.
 * ──────────────────────────────────────────────────────────────────────── */
#fnAddrRoot .fn-w3w-chip {
    /* Same sizing rules as .fn-hydrants-info / .fn-map-btn so the chip
       + hydrants chip + map buttons read as one coherent action stack. */
    flex: 0 0 auto;
    display: flex;
    align-items: center;
    gap: .55rem;
    width: 100%;
    box-sizing: border-box;
    min-height: 2.5rem;
    padding: .5rem .85rem;
    background: rgba(225, 31, 38, .07);
    border: 1px solid rgba(225, 31, 38, .22);
    border-radius: var(--lg-r-sm);
    color: inherit;
    text-decoration: none;
    font-family: inherit;
    text-align: left;
    -webkit-tap-highlight-color: transparent;
    transition: background .15s var(--lg-ease),
                transform .1s var(--lg-ease);
}
#fnAddrRoot .fn-w3w-chip:active {
    transform: scale(0.99);
    background: rgba(225, 31, 38, .12);
}
#fnAddrRoot .fn-w3w-chip .fn-w3w-prefix {
    color: #E11F26;
    font-weight: 800;
    letter-spacing: -1px;
    font-size: 1rem;
    line-height: 1;
    flex-shrink: 0;
}
#fnAddrRoot .fn-w3w-chip .fn-w3w-words {
    flex: 1;
    font-weight: 700;
    font-size: .92rem;
    word-break: break-word;
    line-height: 1.25;
}
#fnAddrRoot .fn-w3w-chip-icon {
    color: var(--fn-text-muted);
    flex-shrink: 0;
    font-size: 1.05rem;
}
[data-bs-theme="dark"] #fnAddrRoot .fn-w3w-chip {
    background: rgba(225, 31, 38, .14);
    border-color: rgba(225, 31, 38, .35);
}


/* ─────────────────────────────────────────────────────────────────────────
 * Google Maps InfoWindow chrome overrides — hydrant marker popups.
 *
 * Modern Google Maps InfoWindow (2024+) has THREE layers, not two:
 *   .gm-style-iw-c    → outer white card wrapper
 *   .gm-style-iw-chr  → close-button chrome ROW (~32px, holds the X)
 *   .gm-style-iw-d    → content scroll container (where our HTML goes)
 *
 * The .gm-style-iw-chr row reserves its own height at the top of the
 * card. Adjusting .gm-style-iw-c padding alone won't move the title up
 * — content still starts BELOW the chrome row. To make the title sit
 * inline with the X we have to collapse the chrome row to height 0
 * and re-anchor the X via absolute positioning on the close button.
 *
 * Targeting Google's class names is brittle (they can rename in API
 * updates) but it's the only way — InfoWindow chrome isn't reachable
 * via our own class names.
 * ──────────────────────────────────────────────────────────────────────── */

/* Collapse the close-button row so it stops reserving vertical space. */
.gm-style-iw-chr {
    min-height: 0 !important;
    height: 0 !important;
    padding: 0 !important;
    margin: 0 !important;
    border: 0 !important;
    overflow: visible !important;  /* keep X visible even though height=0 */
}

/* Re-anchor the X button to top-right of the card itself (was inside the
   collapsed chrome row). 4px offset matches Google's normal positioning. */
.gm-style-iw-chr .gm-ui-hover-effect,
.gm-style .gm-ui-hover-effect {
    position: absolute !important;
    top: 4px !important;
    right: 4px !important;
    z-index: 2 !important;
}

/* Wrapper padding: top breathing + right room for the X + normal sides */
.gm-style .gm-style-iw-c {
    padding: 8px 36px 10px 12px !important;
}

/* Inner scroll container — kill its padding/overflow so our content
   fills the wrapper edge-to-edge. */
.gm-style .gm-style-iw-d {
    overflow: hidden !important;
    padding: 0 !important;
    max-height: none !important;
}



/* ==========================================================================
   Source: assets/css/preplan.css
   ========================================================================== */

.fn-preplan-controls {
    display: flex;
    flex-direction: column;
    gap: .65rem;
    margin-bottom: .65rem;
}

/* Each search input is wrapped in a "field" with a small label above */
.fn-preplan-field {
    display: flex;
    flex-direction: column;
    gap: .3rem;
    width: 100%;
    box-sizing: border-box;
}

/* Top search fields must stay full width like the range/results cards */
.fn-preplan-controls > .fn-preplan-field {
    padding: 0;
    border-bottom: 0;
    width: 100%;
    max-width: 100%;
    box-sizing: border-box;
}

.fn-preplan-field-head {
    display: inline-flex;
    align-items: center;
    gap: .35rem;
    font-size: .72rem;
    font-weight: 800;
    text-transform: uppercase;
    letter-spacing: .04em;
    color: var(--fn-text-muted);
    padding-left: .15rem;
}

.fn-preplan-field-head .mdi {
    font-size: .9rem;
}

/* Tiny pill that confirms the currently-active Google search anchor */
.fn-preplan-google-anchor {
    display: inline-flex;
    align-items: center;
    gap: .3rem;
    align-self: flex-start;
    font-size: .7rem;
    font-weight: 700;
    color: #0a4d6a;
    background: rgba(13, 202, 240, .18);
    border: 1px solid rgba(13, 202, 240, .45);
    padding: .2rem .55rem;
    border-radius: 999px;
    line-height: 1.25;
    max-width: 100%;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.fn-preplan-google-anchor[hidden] {
    display: none;
}

.fn-preplan-google-anchor .mdi {
    font-size: .85rem;
    flex-shrink: 0;
}

[data-bs-theme="dark"] .fn-preplan-google-anchor {
    color: #7ee0f5;
    background: rgba(13, 202, 240, .12);
    border-color: rgba(13, 202, 240, .35);
}

.fn-preplan-search-row {
    position: relative;
    display: block;
    width: 100%;
    max-width: 100%;
    box-sizing: border-box;
}

.fn-preplan-search-icon {
    position: absolute;
    left: .65rem;
    top: 50%;
    transform: translateY(-50%);
    color: var(--fn-text-muted);
    font-size: 1.15rem;
    pointer-events: none;
}

.fn-preplan-search {
    display: block;
    width: 100%;
    max-width: 100%;
    box-sizing: border-box;
    margin: 0;
    padding: .65rem 2.4rem .65rem 2.3rem;
    border-radius: .55rem;
    border: 1px solid var(--fn-card-border);
    background: var(--fn-card-bg);
    color: var(--fn-text);
    font-family: inherit;
    font-size: .95rem;
    line-height: 1;
    -webkit-appearance: none;
    appearance: none;
    -webkit-box-sizing: border-box;
}

.fn-preplan-search:focus {
    outline: none;
    border-color: var(--fn-brand);
    box-shadow: 0 0 0 3px var(--fn-brand-soft);
}

.fn-preplan-search-clear {
    position: absolute;
    right: .35rem;
    top: 50%;
    transform: translateY(-50%);
    background: transparent;
    border: 0;
    color: var(--fn-text-muted);
    font-size: 1.3rem;
    line-height: 1;
    cursor: pointer;
    padding: .35rem;
    display: flex;
    align-items: center;
    justify-content: center;
}

.fn-preplan-search-clear[hidden] {
    display: none;
}

.fn-preplan-range {
    background: var(--fn-card-bg);
    border: 1px solid var(--fn-card-border);
    border-radius: .65rem;
    padding: .65rem .8rem .55rem;
    transition: opacity .2s;
    box-sizing: border-box;
    width: 100%;
}

.fn-preplan-range.disabled {
    opacity: .55;
}

.fn-preplan-range-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    margin-bottom: .35rem;
}

.fn-preplan-range-label {
    display: inline-flex;
    align-items: center;
    gap: .35rem;
    font-size: .8rem;
    font-weight: 800;
    text-transform: uppercase;
    letter-spacing: .04em;
    color: var(--fn-text-muted);
}

.fn-preplan-range-label .mdi {
    font-size: 1rem;
}

.fn-preplan-range-value {
    font-weight: 800;
    font-size: .95rem;
    color: var(--fn-brand);
    font-variant-numeric: tabular-nums;
}

[data-bs-theme="dark"] .fn-preplan-range-value {
    color: #c5d0db;
}

.fn-preplan-range-slider {
    width: 100%;
    margin: .15rem 0 .25rem;
    -webkit-appearance: none;
    appearance: none;
    height: .35rem;
    border-radius: 999px;
    background: var(--fn-tertiary-bg);
    cursor: pointer;
}

.fn-preplan-range-slider:disabled {
    cursor: not-allowed;
}

.fn-preplan-range-slider::-webkit-slider-thumb {
    -webkit-appearance: none;
    appearance: none;
    width: 1.4rem;
    height: 1.4rem;
    border-radius: 50%;
    background: var(--fn-brand);
    cursor: pointer;
    border: 2px solid #fff;
    box-shadow: 0 1px 4px rgba(0,0,0,.25);
}

.fn-preplan-range-slider::-moz-range-thumb {
    width: 1.4rem;
    height: 1.4rem;
    border-radius: 50%;
    background: var(--fn-brand);
    cursor: pointer;
    border: 2px solid #fff;
    box-shadow: 0 1px 4px rgba(0,0,0,.25);
}

.fn-preplan-range-bounds {
    display: flex;
    justify-content: space-between;
    font-size: .7rem;
    color: var(--fn-text-muted);
    margin-top: -.1rem;
}

.fn-preplan-range-note {
    margin-top: .35rem;
    font-size: .75rem;
    color: var(--fn-text-muted);
    font-style: italic;
}

.fn-preplan-range-note[hidden] {
    display: none;
}

.fn-preplan-status {
    font-size: .8rem;
    color: var(--fn-text-muted);
    margin: .2rem 0 .5rem;
    min-height: 1.1em;
}

.fn-preplan-results {
    display: flex;
    flex-direction: column;
    gap: .55rem;
}

.fn-preplan-card {
    background: var(--fn-card-bg);
    border: 1px solid var(--fn-card-border);
    border-radius: .75rem;
    padding: .75rem .85rem;
    box-shadow: 0 1px 3px rgba(0,0,0,.04);
    display: flex;
    flex-direction: column;
    gap: .55rem;
}

.fn-preplan-card-head {
    display: flex;
    flex-direction: column;
    gap: .15rem;
}

.fn-preplan-card-name {
    font-weight: 800;
    font-size: 1.02rem;
    color: var(--fn-text);
    line-height: 1.2;
    word-wrap: break-word;
}

.fn-preplan-card-addr {
    font-size: .85rem;
    color: var(--fn-text-muted);
    line-height: 1.3;
    word-wrap: break-word;
}

.fn-preplan-card-distance {
    display: inline-flex;
    align-items: center;
    gap: .3rem;
    align-self: flex-start;
    font-size: .72rem;
    font-weight: 800;
    color: #fff;
    background: var(--fn-brand);
    text-transform: uppercase;
    letter-spacing: .04em;
    padding: .25rem .6rem .28rem;
    border-radius: 999px;
    margin-top: .25rem;
    line-height: 1.2;
    box-shadow: 0 1px 2px rgba(0,0,0,.12);
}

.fn-preplan-card-distance .mdi {
    font-size: .9rem;
}

.fn-preplan-card-actions {
    display: flex;
    flex-wrap: wrap;
    gap: .35rem;
}

.fn-preplan-action-btn {
    flex: 1 1 auto;
    min-width: 0;
    border: 0;
    border-radius: .5rem;
    padding: .55rem .65rem;
    font-family: inherit;
    font-weight: 800;
    font-size: .72rem;
    text-transform: uppercase;
    letter-spacing: .02em;
    line-height: 1.05;
    cursor: pointer;
    color: #fff;
    background: var(--fn-brand);
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: .3rem;
    box-shadow: 0 1px 3px rgba(0,0,0,.12);
    transition: filter .12s, transform .1s;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.fn-preplan-action-btn:active {
    transform: scale(.96);
    filter: brightness(.92);
}

.fn-preplan-action-btn .mdi {
    font-size: .95rem;
}

/* Hazards: same red as other "warning/danger" buttons across the app */
.fn-preplan-action-btn.hazards {
    background: var(--fn-accent);
    color: #fff;
}

/* Secure: bootstrap-info-feel cyan. Bright background needs dark text
   for readable contrast (white on cyan fails WCAG). */
.fn-preplan-action-btn.secure {
    background: #0dcaf0;
    color: #fff;
}

.fn-preplan-action-btn.full {
    background: var(--fn-brand);
    color: #fff;
}

.fn-preplan-empty {
    text-align: center;
    padding: 2.5rem 1rem;
    color: var(--fn-text-muted);
}

.fn-preplan-empty .mdi {
    font-size: 2.8rem;
    opacity: .3;
    color: var(--fn-text);
    display: block;
    margin-bottom: .35rem;
}

.fn-preplan-empty-title {
    font-weight: 800;
    color: var(--fn-text);
    margin-bottom: .25rem;
}

.fn-preplan-empty-sub {
    font-size: .85rem;
    line-height: 1.45;
}

/* ── Modal ──────────────────────────────────────────────────
   Modal sits BETWEEN the FN top chrome and the tab bar so the
   header is fully visible AND the navigation tabs stay
   visible/tappable below it. */
.fn-preplan-modal {
    position: fixed;
    top: calc(var(--fn-top-chrome-h) + .25rem);
    left: 0;
    right: 0;
    /* Bottom ends above the tab bar (and any iOS bottom safe area)
       with extra breathing room so the modal isn't pressed against
       the navigation tabs. */
    bottom: calc(var(--fn-tabbar-h) + var(--fn-safe-bottom) + .75rem);
    background: rgba(0,0,0,.55);
    z-index: 250;
    display: flex;
    align-items: stretch;
    justify-content: center;
    padding: .6rem;
    box-sizing: border-box;
    opacity: 0;
    pointer-events: none;
    transition: opacity .2s ease;
}

.fn-preplan-modal[hidden] {
    display: none;
}

.fn-preplan-modal.active {
    opacity: 1;
    pointer-events: auto;
}

.fn-preplan-modal-card {
    position: relative;
    background: var(--fn-body-bg);
    color: var(--fn-text);
    width: 100%;
    max-width: 640px;
    border-radius: .85rem;
    overflow: hidden;
    display: flex;
    flex-direction: column;
    box-shadow: 0 16px 50px rgba(0,0,0,.4);
    transform: scale(.96) translateY(.5rem);
    transition: transform .22s cubic-bezier(.2,.8,.2,1);
    box-sizing: border-box;
}

.fn-preplan-modal.active .fn-preplan-modal-card {
    transform: scale(1) translateY(0);
}

.fn-preplan-modal-head {
    display: flex;
    align-items: center;
    gap: .65rem;
    padding: .85rem .95rem;
    border-bottom: 1px solid var(--fn-card-border);
    background: var(--fn-card-bg);
    flex-shrink: 0;
    transition: background .2s;
}

/* Themed modal headers — match the action button colors so the modal
   carries the same visual identity as whichever button opened it.
   Colors are theme-independent so dark mode just works. */
.fn-preplan-modal-card.theme-hazards .fn-preplan-modal-head {
    background: var(--fn-accent);
    border-bottom-color: rgba(0,0,0,.18);
}

.fn-preplan-modal-card.theme-secure .fn-preplan-modal-head {
    background: #0dcaf0;
    border-bottom-color: rgba(0,0,0,.18);
}

.fn-preplan-modal-card.theme-full .fn-preplan-modal-head {
    background: var(--fn-brand);
    border-bottom-color: rgba(0,0,0,.25);
}

/* Title/sub text colors per theme — white on red & navy, dark on cyan
   (cyan needs dark text for contrast). */
.fn-preplan-modal-card.theme-hazards .fn-preplan-modal-title,
.fn-preplan-modal-card.theme-full .fn-preplan-modal-title {
    color: #fff;
}

.fn-preplan-modal-card.theme-hazards .fn-preplan-modal-sub,
.fn-preplan-modal-card.theme-full .fn-preplan-modal-sub {
    color: rgba(255,255,255,.85);
}

.fn-preplan-modal-card.theme-secure .fn-preplan-modal-title {
    color: #fff;
}

.fn-preplan-modal-card.theme-secure .fn-preplan-modal-sub {
    color: rgba(255, 255, 255, .85);
}

.fn-preplan-modal-title-wrap {
    flex: 1;
    min-width: 0;
}

.fn-preplan-modal-title {
    font-weight: 800;
    font-size: 1.1rem;
    line-height: 1.2;
    color: var(--fn-text);
    overflow: hidden;
    text-overflow: ellipsis;
}

.fn-preplan-modal-sub {
    font-size: .8rem;
    color: var(--fn-text-muted);
    line-height: 1.3;
    margin-top: .15rem;
    overflow: hidden;
    text-overflow: ellipsis;
}

.fn-preplan-modal-filter {
    position: relative;
    padding: .55rem .85rem;
    border-bottom: 1px solid var(--fn-card-border);
    flex-shrink: 0;
    display: flex;
    align-items: center;
    gap: .4rem;
}

.fn-preplan-modal-filter[hidden] {
    display: none;
}

.fn-preplan-modal-filter .mdi {
    color: var(--fn-text-muted);
    font-size: 1.1rem;
}

.fn-preplan-modal-filter-input {
    flex: 1;
    padding: .45rem .55rem;
    border-radius: .5rem;
    border: 1px solid var(--fn-card-border);
    background: var(--fn-card-bg);
    color: var(--fn-text);
    font-family: inherit;
    font-size: .9rem;
    -webkit-appearance: none;
    appearance: none;
}

.fn-preplan-modal-filter-input:focus {
    outline: none;
    border-color: var(--fn-brand);
    box-shadow: 0 0 0 2px var(--fn-brand-soft);
}

.fn-preplan-modal-body {
    overflow-y: auto;
    -webkit-overflow-scrolling: touch;
    flex: 1 1 0;
    min-height: 0;
    /* Bottom padding so the floating close FAB doesn't cover the
       last item when scrolled to the end */
    padding: .35rem 0 4rem;
}

/* Modal detail rows only.
   This was previously using .fn-preplan-field globally, which also
   affected the two search inputs at the top and made them appear narrower. */
#fnPreplanModalBody .fn-preplan-field {
    padding: .55rem .95rem .6rem;
    border-bottom: 1px solid var(--fn-card-border);
}

#fnPreplanModalBody .fn-preplan-field:last-child {
    border-bottom: 0;
}

#fnPreplanModalBody .fn-preplan-field[hidden] {
    display: none;
}

.fn-preplan-field-label {
    font-size: .68rem;
    font-weight: 800;
    text-transform: uppercase;
    letter-spacing: .04em;
    color: var(--fn-text-muted);
    margin-bottom: .15rem;
    display: inline-flex;
    align-items: center;
    gap: .25rem;
}

.fn-preplan-field-label::before {
    content: '';
    width: 3px;
    height: 10px;
    background: var(--fn-brand);
    border-radius: 2px;
}

.fn-preplan-field-value {
    font-size: .95rem;
    line-height: 1.45;
    color: var(--fn-text);
    word-break: break-word;
    white-space: pre-wrap;
}

.fn-preplan-modal-prose {
    padding: 1rem 1rem 4rem;   /* extra bottom for the FAB */
    font-size: 1rem;
    line-height: 1.55;
    color: var(--fn-text);
    white-space: pre-wrap;
    word-break: break-word;
}

/* Google Places Autocomplete dropdown — lift above the FN tab bar
   (z-index 100) but stay below our modal (z-index 250). Theme for
   dark mode so it doesn't look like a foreign white box. */
.pac-container {
    z-index: 200 !important;
    border-radius: .5rem;
    box-shadow: 0 8px 24px rgba(0,0,0,.18), 0 1px 4px rgba(0,0,0,.08);
    margin-top: .25rem;
    font-family: inherit;
}

[data-bs-theme="dark"] .pac-container {
    background: var(--fn-card-bg);
    border: 1px solid var(--fn-card-border);
}

[data-bs-theme="dark"] .pac-item {
    background: var(--fn-card-bg);
    color: var(--fn-text);
    border-top-color: var(--fn-card-border);
}

[data-bs-theme="dark"] .pac-item:hover,
[data-bs-theme="dark"] .pac-item-selected {
    background: var(--fn-tertiary-bg);
}

[data-bs-theme="dark"] .pac-item-query,
[data-bs-theme="dark"] .pac-matched {
    color: var(--fn-text);
}

/* Persistent bottom-right close FAB — sits over the modal body
   so it's always reachable regardless of scroll position. */
.fn-preplan-modal-fab-close {
    position: absolute;
    right: .85rem;
    bottom: .85rem;
    width: 3.2rem;
    height: 3.2rem;
    border-radius: 50%;
    background: var(--fn-brand);
    color: #fff;
    border: 0;
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 0;
    box-shadow: 0 4px 14px rgba(0,0,0,.3), 0 1px 4px rgba(0,0,0,.18);
    z-index: 5;
    transition: transform .12s, filter .12s;
}

.fn-preplan-modal-fab-close:active {
    transform: scale(.93);
    filter: brightness(.9);
}

.fn-preplan-modal-fab-close .mdi {
    font-size: 1.55rem;
    line-height: 1;
}

/* FAB color follows the modal theme so it matches the header.
   Cyan needs a dark icon for contrast (same rule as the button). */
.fn-preplan-modal-card.theme-hazards .fn-preplan-modal-fab-close {
    background: var(--fn-accent);
    color: #fff;
}

.fn-preplan-modal-card.theme-secure .fn-preplan-modal-fab-close {
    background: #0dcaf0;
    color: #fff;
}

.fn-preplan-modal-card.theme-full .fn-preplan-modal-fab-close {
    background: var(--fn-brand);
    color: #fff;
}



/* ==========================================================================
   Source: assets/css/settings.css
   ========================================================================== */

/* ============================================================================
 * settings.css
 * ----------------------------------------------------------------------------
 * Settings tab — section cards, segmented controls, dropdowns, link rows,
 * sign-out button. Combines what used to live in two places:
 *
 *   1. The original /response/assets/css/settings.css (which was already
 *      linked).
 *   2. The inline <style> block in /response/pages/settings.php (extra
 *      polish rules that loaded after).
 *
 * Both are now merged here. Restyled in Liquid Glass.
 *
 * Key change: the segmented controls (Theme / Header color / Tab bar color
 * / Font size / Metric+Imperial / etc.) used to use --fn-card-bg as the
 * active-button background. In dark mode that's #23272C, which is nearly
 * identical to the container's --fn-tertiary-bg #2A2F35 — there was no
 * visible difference between active and inactive. Now the active button
 * gets the brand-pill treatment (solid slate light, lighter slate dark,
 * white text either way) so it matches the tabbar's "you are here" pill.
 *
 * Load AFTER liquid-glass.css.
 * ========================================================================= */


/* ─────────────────────────────────────────────────────────────────────────
 * Section + title (e.g. "Display", "Calls", "Activity")
 * ──────────────────────────────────────────────────────────────────────── */
.fn-set-section {
    margin-bottom: .85rem;
}
.fn-set-title {
    font-size: .68rem;
    font-weight: 800;
    text-transform: uppercase;
    letter-spacing: .05em;
    color: var(--fn-text-muted);
    margin: 0 0 .35rem .25rem;
}


/* ─────────────────────────────────────────────────────────────────────────
 * Settings card — frosted glass surface that groups related rows.
 * Cards stack vertically; multiple per page; each renders backdrop-filter.
 * Performance is fine because they're not animated.
 * ──────────────────────────────────────────────────────────────────────── */
.fn-set-card {
    background-color: var(--lg-surface);
    backdrop-filter: var(--lg-blur);
    -webkit-backdrop-filter: var(--lg-blur);
    border: 1px solid var(--lg-edge);
    border-radius: var(--lg-r-md);
    box-shadow: var(--lg-shadow);
    overflow: hidden;
}

.fn-set-row {
    display: flex;
    align-items: center;
    gap: .65rem;
    padding: .55rem .75rem;
    border-bottom: 1px solid var(--lg-divider);
    min-height: 2.4rem;
}
.fn-set-row:last-child {
    border-bottom: 0;
}

.fn-set-label {
    font-weight: 600;
    font-size: .88rem;
    color: var(--fn-text);
    flex-shrink: 0;
}
.fn-set-value {
    margin-left: auto;
    color: var(--fn-text-muted);
    font-weight: 600;
    font-size: .88rem;
}


/* ─────────────────────────────────────────────────────────────────────────
 * Hint banner — info / advisory note under a row. Tinted strip at the
 * bottom of a card. The blue-tint variant is the default; the danger
 * variant is for stronger "heads-up" advisories (red tint).
 *
 * Rules in here merged from settings.php's inline <style> block.
 * ──────────────────────────────────────────────────────────────────────── */
.fn-set-hint {
    padding: .35rem .75rem .55rem;
    border-top: 1px solid var(--lg-divider);
    background: var(--lg-surface-subtle);
    color: var(--fn-text-muted);
    font-size: .77rem;
    line-height: 1.35;
    display: flex;
    align-items: flex-start;
    gap: .35rem;
}
.fn-set-hint .mdi {
    font-size: .95rem;
    flex-shrink: 0;
    line-height: 1.4;
    opacity: .85;
}

/* Info-tinted variant (was inline in settings.php). Light blue wash;
   the icon picks up a brand-ish slate. */
#fnSettingsRoot .fn-set-card > .fn-set-hint {
    background: rgba(13, 110, 253, .07);
    color: var(--fn-text-muted);
    border-top: 1px solid var(--lg-divider);
    border-radius: 0;
    margin: 0;
    padding: .6rem .9rem;
    display: flex;
    align-items: center;
    gap: .45rem;
    font-size: .78rem;
    line-height: 1.4;
}
#fnSettingsRoot .fn-set-card > .fn-set-hint:last-child {
    border-bottom-left-radius: inherit;
    border-bottom-right-radius: inherit;
}
#fnSettingsRoot .fn-set-card > .fn-set-hint .mdi {
    color: var(--fn-brand);
    opacity: .85;
    font-size: 1rem;
    flex-shrink: 0;
}
[data-bs-theme="dark"] #fnSettingsRoot .fn-set-card > .fn-set-hint {
    background: rgba(13, 110, 253, .14);
}
[data-bs-theme="dark"] #fnSettingsRoot .fn-set-card > .fn-set-hint .mdi {
    color: #6ea3ff;     /* lighter blue so the icon shows against dark */
}

/* Danger-tinted variant — stronger advisory (red wash). */
#fnSettingsRoot .fn-set-card > .fn-set-hint-danger {
    background: rgba(220, 53, 69, .08);
    color: var(--fn-text-muted);
    border-top: 1px solid var(--lg-divider);
    border-radius: 0;
    margin: 0;
    padding: .6rem .9rem;
    display: flex;
    align-items: center;
    gap: .45rem;
    font-size: .78rem;
    line-height: 1.4;
}
#fnSettingsRoot .fn-set-card > .fn-set-hint-danger:last-child {
    border-bottom-left-radius: inherit;
    border-bottom-right-radius: inherit;
}
#fnSettingsRoot .fn-set-card > .fn-set-hint-danger .mdi {
    color: #dc3545;
    opacity: .9;
    font-size: 1rem;
    flex-shrink: 0;
}
[data-bs-theme="dark"] #fnSettingsRoot .fn-set-card > .fn-set-hint-danger {
    background: rgba(220, 53, 69, .16);
}
[data-bs-theme="dark"] #fnSettingsRoot .fn-set-card > .fn-set-hint-danger .mdi {
    color: #ff6b78;
}


#fnSettingsRoot .fn-set-card .fn-fam-body > .fn-set-hint {
    background: rgba(13, 110, 253, .07);
    color: var(--fn-text-muted);
    border: 1px solid var(--lg-divider);
    border-radius: 0 0 var(--lg-r-sm) var(--lg-r-sm);
    margin: 0;
    padding: .6rem .9rem;
    display: flex;
    align-items: flex-start;
    gap: .45rem;
    font-size: .78rem;
    line-height: 1.4;
}

#fnSettingsRoot .fn-set-card .fn-fam-body > .fn-set-hint .mdi {
    color: var(--fn-brand);
    opacity: .85;
    font-size: 1rem;
    flex-shrink: 0;
    line-height: 1.4;
}

[data-bs-theme="dark"] #fnSettingsRoot .fn-set-card .fn-fam-body > .fn-set-hint {
    background: rgba(13, 110, 253, .14);
}

[data-bs-theme="dark"] #fnSettingsRoot .fn-set-card .fn-fam-body > .fn-set-hint .mdi {
    color: #6ea3ff;
}
/* ─────────────────────────────────────────────────────────────────────────
 * SEGMENTED CONTROL — Settings buttons
 *
 * Used on the Settings page for Units, Theme, Header color, Tab bar color,
 * and Font size. The control is grid-based so each choice gets an equal
 * column and the button contents stay centered. The outer grey track and
 * inner selected pill use related radius values so the shape feels consistent.
 * ──────────────────────────────────────────────────────────────────────── */
.fn-segmented {
    --fn-segment-radius: .82rem;
    --fn-segment-padding: .18rem;
    --fn-segment-option-radius: calc(var(--fn-segment-radius) - var(--fn-segment-padding));

    margin-left: auto;
    display: inline-grid;
    grid-auto-flow: column;
    grid-auto-columns: 1fr;
    align-items: center;

    width: 175px;
    max-width: 100%;

    background-color: rgba(15, 23, 42, .11);
    backdrop-filter: var(--lg-blur-subtle);
    -webkit-backdrop-filter: var(--lg-blur-subtle);
    border: 1px solid rgba(15, 23, 42, .12);
    border-radius: var(--fn-segment-radius);
    padding: var(--fn-segment-padding);
    gap: .16rem;
    box-shadow: inset 0 1px 2px rgba(15, 23, 42, .06);
}

.fn-segmented button {
    min-width: 0;
    width: 100%;

    background: transparent;
    border: 0;
    color: var(--fn-text-muted);
    padding: .42rem .25rem;
    font-weight: 800;
    font-size: .7rem;
    border-radius: var(--fn-segment-option-radius);
    cursor: pointer;
    transition: background-color .18s var(--lg-ease),
                color .18s var(--lg-ease),
                box-shadow .18s var(--lg-ease),
                transform .08s var(--lg-ease);
    font-family: inherit;
    display: flex;
    align-items: center;
    justify-content: center;
    gap: .25rem;
    line-height: 1.05;
    text-align: center;
    white-space: nowrap;
}

.fn-segmented button:active {
    transform: scale(.98);
}

.fn-segmented button.active {
    background-color: rgba(255, 255, 255, .96);
    color: var(--fn-text);
    box-shadow: 0 1px 3px rgba(15, 23, 42, .14);
}


[data-bs-theme="dark"] .fn-segmented {
    background-color: rgba(255, 255, 255, .10);
    border-color: rgba(255, 255, 255, .13);
    box-shadow: inset 0 1px 2px rgba(0, 0, 0, .18);
}

[data-bs-theme="dark"] .fn-segmented button.active {
    background-color: rgba(255, 255, 255, .18);
    color: #fff;
    box-shadow: 0 1px 3px rgba(0, 0, 0, .22);
}


/* ─────────────────────────────────────────────────────────────────────────
 * Color dot — inline swatch inside segmented buttons (Header color row,
 * Tab bar color row). Border had hardcoded rgba(0,0,0,.15) which was
 * invisible against the new brand-slate active button. Token now picks
 * up a theme-appropriate edge.
 * ──────────────────────────────────────────────────────────────────────── */
.fn-color-dot {
    display: inline-block;
    width: .65rem;
    height: .65rem;
    border-radius: 50%;
    border: 1px solid var(--lg-edge-strong);
    flex-shrink: 0;
    box-shadow: 0 0 0 1px rgba(0, 0, 0, .12);
}
[data-bs-theme="dark"] .fn-color-dot {
    box-shadow: 0 0 0 1px rgba(255, 255, 255, .15);
}


/* ─────────────────────────────────────────────────────────────────────────
 * Dropdown — used for "Show calls from the past" and similar.
 * Frosted glass surface so it matches the card it sits in.
 * ──────────────────────────────────────────────────────────────────────── */
.fn-set-select {
    margin-left: auto;
    appearance: none;
    -webkit-appearance: none;
    background-color: var(--lg-surface-subtle);
    backdrop-filter: var(--lg-blur-subtle);
    -webkit-backdrop-filter: var(--lg-blur-subtle);
    color: var(--fn-text);
    border: 1px solid var(--lg-edge);
    border-radius: var(--lg-r-sm);
    padding: .35rem 1.85rem .35rem .6rem;
    font-size: .82rem;
    font-weight: 700;
    cursor: pointer;
    /* Chevron stroke colour picked from currentColor so it follows
       --fn-text — invisible in dark mode no more. */
    background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='12' height='8' viewBox='0 0 12 8'><path fill='none' stroke='%236B7280' stroke-width='2' stroke-linecap='round' stroke-linejoin='round' d='M1 1l5 5 5-5'/></svg>");
    background-repeat: no-repeat;
    background-position: right .55rem center;
}
[data-bs-theme="dark"] .fn-set-select {
    /* Inline chevron uses %236B7280 stroke — readable in dark too,
       but swap to a lighter gray for higher contrast. */
    background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='12' height='8' viewBox='0 0 12 8'><path fill='none' stroke='%239099A4' stroke-width='2' stroke-linecap='round' stroke-linejoin='round' d='M1 1l5 5 5-5'/></svg>");
}


/* ─────────────────────────────────────────────────────────────────────────
 * Navigation link rows — Call History / Manage Accounts / Clear cache.
 * ──────────────────────────────────────────────────────────────────────── */
.fn-set-link {
    display: flex;
    align-items: center;
    gap: .55rem;
    padding: .85rem 1rem;
    border-bottom: 1px solid var(--lg-divider);
    color: var(--fn-text);
    text-decoration: none;
    font-weight: 600;
    font-size: .9rem;
    cursor: pointer;
    min-height: 2.4rem;
    transition: background-color .15s var(--lg-ease);
}
.fn-set-link:last-child {
    border-bottom: 0;
}
.fn-set-link:active {
    background: var(--lg-pressed);
}
.fn-set-link > .mdi:first-child {
    font-size: 1.1rem;
    color: var(--fn-text-muted);
    flex-shrink: 0;
}
.fn-set-link span {
    flex: 1 1 auto;
}
.fn-set-chev {
    margin-left: auto;
    opacity: .5;
    flex-shrink: 0;
}

/* Button rendered as a link row (e.g. Clear cached app data). */
.fn-set-link-btn {
    appearance: none;
    -webkit-appearance: none;
    width: 100%;
    background: transparent;
    border: 0;
    border-bottom: 1px solid var(--lg-divider);
    text-align: left;
    font-family: inherit;
}
.fn-set-link-btn:last-child {
    border-bottom: 0;
}

/* Monospace version label inside the Clear-cache button. */
.fn-set-version {
    flex: 0 0 auto;
    margin-left: auto;
    padding-right: .35rem;
    font-size: .68rem;
    font-weight: 500;
    font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
    color: var(--fn-text-muted);
    opacity: .8;
}
.fn-set-version:empty {
    display: none;
}


/* ─────────────────────────────────────────────────────────────────────────
 * Sign-out button — solid red CTA at the bottom. Stays solid (no glass)
 * because action affordance.
 * ──────────────────────────────────────────────────────────────────────── */
.fn-set-signout {
    width: 100%;
    background-image: var(--lg-fill-danger);
    color: #fff;
    border: 0;
    border-radius: var(--lg-r-sm);
    padding: .7rem;
    font-weight: 800;
    font-size: .95rem;
    cursor: pointer;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: .4rem;
    box-shadow: 0 1px 0 rgba(255,255,255,.18) inset,
                0 4px 12px -4px rgba(176, 58, 46, .45),
                0 2px 6px -2px rgba(0,0,0,.15);
    font-family: inherit;
    transition: filter .12s var(--lg-ease), transform .1s var(--lg-ease);
}
.fn-set-signout:active {
    filter: brightness(.9);
    transform: scale(.98);
}
.fn-set-signout .mdi {
    font-size: 1.1rem;
}



/* ==========================================================================
   Source: assets/css/dashboard.css
   ========================================================================== */

/* ============================================================
 * FireNotify — Dashboard (Liquid Glass)
 *
 * Drop-in replacement for the wall-display station dashboard
 * served at /response/dashboard.php. The same selectors and
 * variable namespace from the previous build are preserved so
 * the dashboard's JS keeps working untouched; only the visual
 * treatment changes.
 *
 * Treatment notes:
 *   - Deep gradient body with a slow drift on the brand-red
 *     ember layer, so the dashboard never feels static even
 *     when "Standing By."
 *   - Every card is a frosted-glass surface (backdrop-filter
 *     blur + low-alpha white tint) floating over the gradient.
 *   - Brand red (#c0282d) is the single accent — it sits on
 *     the topbar bell, "Active" badge, alert flash, and the
 *     idle progress bar. Status colors (success/danger/etc)
 *     are reserved for responder state.
 *   - Designed for wall displays at viewing distances of 6-10
 *     feet: large type, high contrast, motion only where it
 *     conveys information.
 * ========================================================= */

:root {
    /* Background layers */
    --d-bg-base:       #07090d;
    --d-bg-mid:        #0e1218;
    --d-bg-glow:       rgba(192, 40, 45, 0.28);
    --d-bg-glow-2:     rgba(60, 100, 200, 0.12);

    /* Frosted glass surfaces */
    --d-surface:       rgba(255, 255, 255, 0.04);
    --d-surface-2:     rgba(255, 255, 255, 0.06);
    --d-surface-3:     rgba(255, 255, 255, 0.09);
    --d-surface-hover: rgba(255, 255, 255, 0.08);
    --d-border:        rgba(255, 255, 255, 0.10);
    --d-border-strong: rgba(255, 255, 255, 0.18);

    /* Type ramp */
    --d-text:    rgba(255, 255, 255, 0.95);
    --d-text-2:  rgba(255, 255, 255, 0.68);
    --d-text-3:  rgba(255, 255, 255, 0.42);

    /* Brand + status palette */
    --d-brand:     #c0282d;
    --d-brand-2:   #ff6b6b;
    --d-accent:    #ef4444;
    --d-success:   #10b981;
    --d-warning:   #f59e0b;
    --d-info:      #3b82f6;
    --d-purple:    #a855f7;
    --d-teal:      #14b8a6;
    --d-pink:      #ec4899;
    --d-dark:      #475569;
    --d-gray:      #94a3b8;

    /* Topbar */
    --d-topbar-bg: linear-gradient(135deg,
        rgba(192, 40, 45, 0.92) 0%,
        rgba(135, 30, 35, 0.92) 60%,
        rgba(60, 18, 22, 0.92) 100%);
    --d-topbar-fg: #ffffff;

    /* Tinted card backgrounds — used on top of the glass to
       hint at semantic meaning without overwhelming. */
    --d-call-tint:    radial-gradient(1200px 320px at 0% 0%,
                          rgba(239, 68, 68, 0.10), transparent 65%);
    --d-resp-tint:    radial-gradient(1000px 280px at 100% 0%,
                          rgba(59, 130, 246, 0.07), transparent 60%);
    --d-standby-tint: radial-gradient(800px 200px at 50% 0%,
                          rgba(59, 130, 246, 0.10), transparent 70%);
    --d-resp-head-bg: rgba(59, 130, 246, 0.07);
    --d-summary-bg:   linear-gradient(180deg,
                          rgba(255, 255, 255, 0.025),
                          rgba(255, 255, 255, 0));

    /* Responder-cell tints — each color group has a subtle
       fill, a stronger border for the icon, and a clean text
       color. Picking the right tone for "low-info but visible
       from across the room" is the whole game. */
    --d-cell-success: rgba(16, 185, 129, 0.13);
    --d-cell-danger:  rgba(239, 68, 68, 0.13);
    --d-cell-warning: rgba(245, 158, 11, 0.13);
    --d-cell-info:    rgba(59, 130, 246, 0.13);
    --d-cell-purple:  rgba(168, 85, 247, 0.13);
    --d-cell-teal:    rgba(20, 184, 166, 0.13);
    --d-cell-pink:    rgba(236, 72, 153, 0.13);
    --d-cell-dark:    rgba(71, 85, 105, 0.20);
    --d-cell-gray:    rgba(148, 163, 184, 0.16);

    --d-head-height:  4.25rem;
    --d-radius:       1.1rem;
    --d-radius-sm:    .65rem;
    --d-card-head-height: 3.25rem;

    /* Pill / badge text colors. Hard-coded pale shades only work
       on dark backgrounds — in light mode they're invisible. By
       routing through these vars we get correct contrast in
       both modes. Dark-mode values are the same pale tints we
       had before; light-mode values (in the @media block below)
       switch to the deepest stop of each ramp so the text reads
       like a label, not a watermark. */
    --d-pill-success-text: #a7f3d0;
    --d-pill-danger-text:  #fecaca;
    --d-pill-warning-text: #fde68a;
    --d-pill-info-text:    #bfdbfe;
    --d-pill-purple-text:  #e9d5ff;
    --d-pill-teal-text:    #99f6e4;
    --d-pill-pink-text:    #fbcfe8;
    --d-pill-dark-text:    #cbd5e1;
    --d-pill-gray-text:    #e2e8f0;

    --d-tab-active-text:   #bfdbfe;
    --d-tab-active-bg:     rgba(59, 130, 246, 0.18);

    --d-units-text:        #dbeafe;
    --d-units-bg:          rgba(59, 130, 246, 0.18);
    --d-units-border:      rgba(59, 130, 246, 0.32);

    --d-cell-eta-text:     #ffffff;
    --d-cell-eta-bg:       rgba(0, 0, 0, 0.25);
}

/* Light-mode override for the rare case the dashboard is run
   on a daytime display where dark mode hurts. Backdrop-filter
   still applies — frosted glass works on light backgrounds too. */
@media (prefers-color-scheme: light) {
    :root {
        /* Body is pure white in light mode so the .d-main grid gap
           between cards shows the same color as the cards themselves.
           Previously the body was light-grey-blue (#eef1f6), which
           the grid gap revealed as visible darker channels running
           between the cards. White-on-white means: gap and cards are
           the same color, so the gap reads as deliberate spacing
           rather than a strip of "something behind." Card definition
           comes from their 1px border and rounded corner. */
        --d-bg-base:       #ffffff;
        --d-bg-mid:        #ffffff;
        --d-bg-glow:       rgba(192, 40, 45, 0.025);
        --d-bg-glow-2:     rgba(60, 100, 200, 0.020);

        --d-surface:       rgba(255, 255, 255, 0.96);
        --d-surface-2:     rgba(248, 250, 252, 0.88);
        --d-surface-3:     rgba(248, 250, 252, 0.95);
        --d-surface-hover: rgba(255, 255, 255, 1);
        --d-border:        rgba(15, 23, 42, 0.10);
        --d-border-strong: rgba(15, 23, 42, 0.18);

        --d-text:    rgba(15, 23, 42, 0.92);
        --d-text-2:  rgba(15, 23, 42, 0.62);
        --d-text-3:  rgba(15, 23, 42, 0.40);

        --d-call-tint:    radial-gradient(1200px 320px at 0% 0%,
                              rgba(192, 40, 45, 0.06), transparent 65%);
        --d-resp-tint:    radial-gradient(1000px 280px at 100% 0%,
                              rgba(59, 130, 246, 0.05), transparent 60%);
        --d-standby-tint: radial-gradient(800px 200px at 50% 0%,
                              rgba(59, 130, 246, 0.06), transparent 70%);
        --d-resp-head-bg: rgba(59, 130, 246, 0.05);
        --d-summary-bg:   linear-gradient(180deg,
                              rgba(15, 23, 42, 0.02),
                              rgba(15, 23, 42, 0));

        --d-cell-success: rgba(16, 185, 129, 0.12);
        --d-cell-danger:  rgba(192, 40, 45, 0.10);
        --d-cell-warning: rgba(245, 158, 11, 0.16);
        --d-cell-info:    rgba(59, 130, 246, 0.10);
        --d-cell-purple:  rgba(168, 85, 247, 0.10);
        --d-cell-teal:    rgba(20, 184, 166, 0.12);
        --d-cell-pink:    rgba(236, 72, 153, 0.10);
        --d-cell-dark:    rgba(71, 85, 105, 0.14);
        --d-cell-gray:    rgba(148, 163, 184, 0.18);

        /* Light-mode pill text — use the deepest stop of each
           color so the label reads sharply on the faint
           background tint. Pale tints (from dark mode) read as
           invisible watermarks here. */
        --d-pill-success-text: #065f46;  /* emerald-900 */
        --d-pill-danger-text:  #7f1d1d;  /* red-900 */
        --d-pill-warning-text: #78350f;  /* amber-900 */
        --d-pill-info-text:    #1e3a8a;  /* blue-900 */
        --d-pill-purple-text:  #581c87;  /* purple-900 */
        --d-pill-teal-text:    #134e4a;  /* teal-900 */
        --d-pill-pink-text:    #831843;  /* pink-900 */
        --d-pill-dark-text:    #1e293b;  /* slate-800 */
        --d-pill-gray-text:    #334155;  /* slate-700 */

        --d-tab-active-text:   #1e3a8a;
        --d-tab-active-bg:     rgba(59, 130, 246, 0.12);

        --d-units-text:        #1e3a8a;
        --d-units-bg:          rgba(59, 130, 246, 0.12);
        --d-units-border:      rgba(59, 130, 246, 0.30);

        --d-cell-eta-text:     #ffffff;
        --d-cell-eta-bg:       rgba(15, 23, 42, 0.55);
    }
}

/* ── Base ──────────────────────────────────────────────── */
* { box-sizing: border-box; }

html, body {
    height: 100%; width: 100%; margin: 0;
    color: var(--d-text);
    font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, system-ui, sans-serif;
    overflow: hidden;
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
    font-feature-settings: 'cv11', 'ss01', 'ss03';
}

/* The "stage" — full-viewport gradient with two drifting
   ember layers. ::before is the static base gradient; ::after
   carries the slow-drifting brand-red glow that gives the
   dashboard a sense of life without animating actual content. */
body {
    background: var(--d-bg-base);
    position: relative;
    isolation: isolate;
}
body::before {
    content: '';
    position: fixed;
    inset: 0;
    z-index: -2;
    background:
        radial-gradient(ellipse 80% 60% at 80% 0%,
            var(--d-bg-glow) 0%, transparent 55%),
        radial-gradient(ellipse 70% 50% at 0% 100%,
            var(--d-bg-glow-2) 0%, transparent 55%),
        linear-gradient(180deg,
            var(--d-bg-base) 0%,
            var(--d-bg-mid) 60%,
            var(--d-bg-base) 100%);
}
body::after {
    /* Slow-drifting ember layer — 60s rotation pulls the warm
       light around the screen so the dashboard never looks
       like a frozen poster. Pointer-events none + z-index -1
       keep it strictly visual. */
    content: '';
    position: fixed;
    inset: -20%;
    z-index: -1;
    background: radial-gradient(circle at 30% 40%,
        rgba(192, 40, 45, 0.10) 0%,
        transparent 35%);
    animation: dEmberDrift 60s ease-in-out infinite alternate;
    pointer-events: none;
}
@keyframes dEmberDrift {
    0%   { transform: translate(0, 0)        rotate(0deg); }
    50%  { transform: translate(8%, -4%)     rotate(15deg); }
    100% { transform: translate(-6%, 6%)     rotate(-10deg); }
}

/* Hide the drifting ember layer in light mode. The warm rotation
   looks gorgeous on a dark base but on a light gradient it just
   creates a patchy pink fog that bleeds through the gaps between
   cards. Same goes for backdrop-filter on cards in light mode —
   blurring 96%-opaque white over a near-white background is wasted
   GPU work and produces a faintly muddy halo. Flat solid surfaces
   read cleaner. */
@media (prefers-color-scheme: light) {
    body::after { display: none; }
    body::before {
        background: var(--d-bg-base);
    }
    /* No outer box-shadow on cards in light mode. Every shadow
       attempt — directional, negative-spread, asymmetric — still
       bled enough into the gap between cards that two adjacent
       cards' shadows summed into a visible muddy strip down the
       middle. And card shadows reaching the screen edges were
       what made the four screen corners look subtly darker than
       the rest of the body. Card definition now comes purely
       from: a 1px border, a 1.1rem rounded corner, and a 96%-
       opaque white surface against the light-grey body. The
       inner highlight on the top edge keeps the Liquid Glass
       "lit edge" feel without putting any pigment outside the
       card itself. */
    .d-card {
        backdrop-filter: none;
        -webkit-backdrop-filter: none;
        border-color: rgba(15, 23, 42, 0.12);
        box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.95);
    }
    /* Topbar's wide red shadow was casting 32px in every direction
       — that's what was tinting the top corners of the screen pink.
       In light mode, replace it with a tight 1px hairline below
       the topbar that reads as a divider, not a glow. */
    .d-topbar {
        backdrop-filter: none;
        -webkit-backdrop-filter: none;
        box-shadow:
            0 1px 0 rgba(15, 23, 42, 0.06),
            inset 0 1px 0 rgba(255, 255, 255, 0.16);
    }
}

/* ── Layout shell ──────────────────────────────────────── */
.d-shell {
    display: grid;
    grid-template-rows: auto 1fr;
    height: 100vh; width: 100vw;
    gap: 1rem;
    padding: 1rem 1.25rem 1.25rem;
    overflow: hidden;
    position: relative;
    z-index: 1;
}

/* ── Topbar — brand-red frosted strip ──────────────────── */
.d-topbar {
    display: flex;
    align-items: center;
    gap: 1rem;
    height: var(--d-head-height);
    padding: 0 1.25rem;
    background: var(--d-topbar-bg);
    color: var(--d-topbar-fg);
    border-radius: var(--d-radius);
    border: 1px solid rgba(255, 255, 255, 0.08);
    backdrop-filter: blur(20px) saturate(160%);
    -webkit-backdrop-filter: blur(20px) saturate(160%);
    box-shadow:
            0 4px 14px rgba(15, 23, 42, 0.18),
    inset 0 1px 0 rgba(255, 255, 255, 0.10);
    position: relative;
    overflow: hidden;
}
.d-topbar::before {
    /* Hairline highlight along the top edge — the
       characteristic Liquid Glass "lit edge" look. */
    content: '';
    position: absolute;
    top: 0; left: 8%; right: 8%;
    height: 1px;
    background: linear-gradient(90deg,
        transparent,
        rgba(255, 255, 255, 0.50),
        transparent);
    pointer-events: none;
}

.d-brand {
    display: flex; align-items: center; gap: .55rem;
    font-size: 1.32rem;
    font-weight: 800;
    letter-spacing: 0.005em;
    color: #fff;
    text-shadow: 0 1px 2px rgba(0, 0, 0, 0.25);
}
.d-brand .mdi {
    font-size: 1.7rem;
    line-height: 1;
    filter: drop-shadow(0 1px 2px rgba(0, 0, 0, 0.25));
}

.d-station {
    display: inline-flex; align-items: center; gap: .4rem;
    padding: .35rem .75rem;
    border-radius: 999px;
    background: rgba(255, 255, 255, 0.14);
    border: 1px solid rgba(255, 255, 255, 0.22);
    font-size: .95rem;
    font-weight: 700;
    letter-spacing: .04em;
    text-transform: uppercase;
    color: #fff;
}
.d-station .mdi { font-size: 1.05rem; line-height: 1; }

.d-spacer { flex: 1; }

.d-status {
    display: inline-flex; align-items: center; gap: .45rem;
    padding: .35rem .75rem;
    border-radius: 999px;
    background: rgba(16, 185, 129, 0.18);
    border: 1px solid rgba(16, 185, 129, 0.40);
    font-size: .85rem;
    font-weight: 700;
    letter-spacing: .04em;
    text-transform: uppercase;
    color: #d1fae5;
    transition: background .2s, border-color .2s, color .2s;
}
.d-status .dot {
    width: .55rem; height: .55rem;
    border-radius: 50%;
    background: #10b981;
    box-shadow: 0 0 0 0 rgba(16, 185, 129, 0.55);
    animation: dLivePulse 1.6s ease-in-out infinite;
}
.d-status.offline {
    background: rgba(245, 158, 11, 0.18);
    border-color: rgba(245, 158, 11, 0.45);
    color: #fde68a;
}
.d-status.offline .dot {
    background: #f59e0b;
    box-shadow: 0 0 0 0 rgba(245, 158, 11, 0.55);
}
@keyframes dLivePulse {
    0%, 100% { box-shadow: 0 0 0 0 rgba(16, 185, 129, 0.55); }
    50%      { box-shadow: 0 0 0 8px rgba(16, 185, 129, 0); }
}

.d-clock {
    font-variant-numeric: tabular-nums;
    font-size: 1.45rem;
    font-weight: 800;
    color: #fff;
    text-shadow: 0 1px 2px rgba(0, 0, 0, 0.25);
    letter-spacing: .02em;
    min-width: 9.5rem;
    text-align: right;
}

/* ── Main grid — three frosted cards ────────────────────
   Default split is wide-friendly:
     Call (1.5fr) | Responders (1.5fr) | Idle (1fr collapsed)
   When .is-idle is set, the call card collapses to a small
   "Standing By" panel and the idle feed grows to take the
   center stage. */
.d-main {
    display: grid;
    grid-template-columns: 1.5fr 1.5fr 1fr;
    gap: 1rem;
    min-height: 0;
    overflow: hidden;
}
.d-main.is-idle {
    grid-template-columns: 1fr 1fr 2fr;
}

/* ── Card base — frosted glass surface ─────────────────── */
.d-card {
    position: relative;
    background: var(--d-surface);
    border: 1px solid var(--d-border);
    border-radius: var(--d-radius);
    backdrop-filter: blur(24px) saturate(160%);
    -webkit-backdrop-filter: blur(24px) saturate(160%);
    box-shadow:
        0 20px 50px rgba(0, 0, 0, 0.35),
        0 2px 8px rgba(0, 0, 0, 0.15),
        inset 0 1px 0 rgba(255, 255, 255, 0.07);
    overflow: hidden;
    display: flex;
    flex-direction: column;
    min-height: 0;
}
.d-card::after {
    /* Subtle highlight along the top edge — same Liquid Glass
       lit-edge motif as the topbar. */
    content: '';
    position: absolute;
    top: 0; left: 10%; right: 10%;
    height: 1px;
    background: linear-gradient(90deg,
        transparent,
        rgba(255, 255, 255, 0.18),
        transparent);
    pointer-events: none;
}

/* ── Call card ─────────────────────────────────────────── */
.d-call {
    background-image: var(--d-call-tint);
}
.d-call-empty {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    flex: 1;
    text-align: center;
    padding: 2rem;
    background: var(--d-standby-tint);
}
.d-call-empty .icon-wrap {
    width: 5.5rem; height: 5.5rem;
    border-radius: 50%;
    background: rgba(255, 255, 255, 0.05);
    border: 1px solid rgba(255, 255, 255, 0.10);
    display: flex; align-items: center; justify-content: center;
    margin-bottom: 1.1rem;
}
.d-call-empty .icon-wrap .mdi {
    font-size: 2.8rem;
    color: var(--d-text-2);
}
.d-call-empty .title {
    font-size: 1.85rem;
    font-weight: 800;
    color: var(--d-text);
    margin-bottom: .4rem;
    letter-spacing: -0.01em;
}
.d-call-empty .sub {
    font-size: 1rem;
    color: var(--d-text-2);
    max-width: 28ch;
    line-height: 1.4;
}

.d-call-active {
    display: flex;
    flex-direction: column;
    flex: 1;
    min-height: 0;
}
.d-call-head {
    display: flex; align-items: center; justify-content: space-between;
    min-height: var(--d-card-head-height);
    padding: 0 1.2rem;
    border-bottom: 1px solid var(--d-border);
    flex-shrink: 0;
    background: rgba(239, 68, 68, 0.07);
}
.badge-newest {
    display: inline-flex; align-items: center; gap: .35rem;
    padding: .3rem .7rem .32rem;
    border-radius: 999px;
    background: var(--d-brand);
    color: #fff;
    font-size: .72rem;
    font-weight: 900;
    letter-spacing: .12em;
    text-transform: uppercase;
    box-shadow: 0 2px 10px rgba(192, 40, 45, 0.45);
}
.badge-newest.is-active {
    animation: dBadgePulse 2.4s ease-in-out infinite;
}
.badge-newest.is-call {
    background: var(--d-dark);
    box-shadow: none;
}
@keyframes dBadgePulse {
    0%, 100% { box-shadow: 0 2px 10px rgba(192, 40, 45, 0.45); }
    50%      { box-shadow: 0 2px 18px rgba(192, 40, 45, 0.75),
                            0 0 0 6px rgba(192, 40, 45, 0.10); }
}
.age {
    display: inline-flex; align-items: center; gap: .3rem;
    font-size: .92rem;
    font-weight: 700;
    color: var(--d-text-2);
    font-variant-numeric: tabular-nums;
}
.age .mdi { font-size: 1.05rem; line-height: 1; }

.d-call-body {
    flex: 1;
    overflow-y: auto;
    padding: 1.1rem 1.3rem 1.3rem;
    display: flex;
    flex-direction: column;
    gap: 1rem;
}
.d-call-type {
    font-size: 2.4rem;
    font-weight: 900;
    line-height: 1.1;
    color: var(--d-text);
    letter-spacing: -0.02em;
    text-shadow: 0 1px 2px rgba(0, 0, 0, 0.15);
}
.d-call-time {
    font-size: .92rem;
    color: var(--d-text-2);
    margin-top: .35rem;
    font-variant-numeric: tabular-nums;
}

.d-call-section {
    padding: .7rem .9rem .8rem;
    background: var(--d-surface-2);
    border: 1px solid var(--d-border);
    border-radius: var(--d-radius-sm);
}
.d-call-section .label {
    font-size: .68rem;
    font-weight: 800;
    text-transform: uppercase;
    letter-spacing: .12em;
    color: var(--d-text-3);
    margin-bottom: .3rem;
}
.d-call-section .value {
    font-size: 1.05rem;
    font-weight: 600;
    color: var(--d-text);
    line-height: 1.4;
    word-break: break-word;
}
.d-call-section .value.message {
    font-weight: 500;
    color: var(--d-text-2);
    font-size: .95rem;
}

.d-units-list {
    list-style: none;
    margin: 0;
    padding: 0;
    display: flex;
    flex-wrap: wrap;
    gap: .35rem;
}
.d-units-list li {
    display: inline-flex; align-items: center;
    padding: .25rem .6rem .28rem;
    border-radius: 999px;
    background: var(--d-units-bg);
    border: 1px solid var(--d-units-border);
    color: var(--d-units-text);
    font-size: .82rem;
    font-weight: 700;
    letter-spacing: .04em;
    font-variant-numeric: tabular-nums;
}

.d-other-calls {
    margin-top: .25rem;
    padding: .7rem .9rem .8rem;
    background: var(--d-surface);
    border: 1px solid var(--d-border);
    border-radius: var(--d-radius-sm);
}
.d-other-calls .label {
    font-size: .68rem;
    font-weight: 800;
    text-transform: uppercase;
    letter-spacing: .12em;
    color: var(--d-text-3);
    margin-bottom: .35rem;
}
.d-other-call-row {
    display: flex; justify-content: space-between; align-items: center;
    padding: .35rem 0;
    border-bottom: 1px solid var(--d-border);
    font-size: .9rem;
}
.d-other-call-row:last-child { border-bottom: 0; }
.d-other-call-row .type { color: var(--d-text); font-weight: 600; }
.d-other-call-row .time { color: var(--d-text-3); font-size: .8rem; font-variant-numeric: tabular-nums; }

/* ── Responders card ───────────────────────────────────── */
.d-resp {
    background-image: var(--d-resp-tint);
}
.d-resp-head {
    display: flex; align-items: center; justify-content: space-between;
    min-height: var(--d-card-head-height);
    padding: 0 1.2rem;
    border-bottom: 1px solid var(--d-border);
    background: var(--d-resp-head-bg);
    flex-shrink: 0;
}
.d-resp-head .title {
    display: inline-flex; align-items: center; gap: .5rem;
    font-size: 1.05rem;
    font-weight: 800;
    color: var(--d-text);
    letter-spacing: -0.005em;
}
.d-resp-head .title .mdi {
    font-size: 1.3rem;
    line-height: 1;
    color: var(--d-info);
}
.d-resp-head .count {
    font-size: .85rem;
    font-weight: 700;
    color: var(--d-text-2);
    font-variant-numeric: tabular-nums;
}

.d-resp-summary {
    display: flex;
    flex-wrap: wrap;
    gap: .4rem;
    padding: .65rem 1.2rem .35rem;
    background: var(--d-summary-bg);
    flex-shrink: 0;
}
.d-resp-summary:empty { display: none; }

.d-resp-pill {
    display: inline-flex; align-items: center; gap: .3rem;
    padding: .28rem .65rem .3rem;
    border-radius: 999px;
    font-size: .78rem;
    font-weight: 800;
    letter-spacing: .04em;
    text-transform: uppercase;
    background: var(--d-cell-info);
    border: 1px solid rgba(59, 130, 246, 0.30);
    color: var(--d-pill-info-text);
    font-variant-numeric: tabular-nums;
}
.d-resp-pill .mdi { font-size: .9rem; line-height: 1; }
.d-resp-pill.success { background: var(--d-cell-success);
    border-color: rgba(16, 185, 129, 0.30); color: var(--d-pill-success-text); }
.d-resp-pill.danger  { background: var(--d-cell-danger);
    border-color: rgba(239, 68, 68, 0.30);  color: var(--d-pill-danger-text); }
.d-resp-pill.warning { background: var(--d-cell-warning);
    border-color: rgba(245, 158, 11, 0.32); color: var(--d-pill-warning-text); }
.d-resp-pill.info    { background: var(--d-cell-info);
    border-color: rgba(59, 130, 246, 0.30); color: var(--d-pill-info-text); }
.d-resp-pill.purple  { background: var(--d-cell-purple);
    border-color: rgba(168, 85, 247, 0.30); color: var(--d-pill-purple-text); }
.d-resp-pill.teal    { background: var(--d-cell-teal);
    border-color: rgba(20, 184, 166, 0.30); color: var(--d-pill-teal-text); }
.d-resp-pill.pink    { background: var(--d-cell-pink);
    border-color: rgba(236, 72, 153, 0.30); color: var(--d-pill-pink-text); }
.d-resp-pill.dark    { background: var(--d-cell-dark);
    border-color: rgba(71, 85, 105, 0.40);  color: var(--d-pill-dark-text); }
.d-resp-pill.gray    { background: var(--d-cell-gray);
    border-color: rgba(148, 163, 184, 0.34); color: var(--d-pill-gray-text); }
.d-resp-pill.no-response {
    background: var(--d-cell-gray);
    border-color: rgba(148, 163, 184, 0.34);
    color: var(--d-pill-gray-text);
}

.d-resp-grid {
    flex: 1;
    overflow: hidden;
    padding: .65rem 1.2rem 1rem;
    display: grid;
    gap: .55rem;
    grid-template-columns: repeat(auto-fill, minmax(13rem, 1fr));
    align-content: start;
}
.d-resp-grid[data-density="medium"] {
    gap: .45rem;
    grid-template-columns: repeat(auto-fill, minmax(11rem, 1fr));
}
.d-resp-grid[data-density="high"] {
    gap: .35rem;
    grid-template-columns: repeat(auto-fill, minmax(9.5rem, 1fr));
}
.d-resp-grid[data-density="high"] .d-resp-cell {
    padding: .4rem .55rem;
    font-size: .82rem;
}
.d-resp-grid[data-density="high"] .cell-icon {
    font-size: 1.05rem;
}

.d-resp-empty-wrap {
    grid-column: 1 / -1;
    display: flex;
    align-items: center;
    justify-content: center;
    min-height: 8rem;
}
.d-resp-empty {
    display: inline-flex; align-items: center; gap: .55rem;
    padding: .85rem 1.25rem;
    border-radius: var(--d-radius-sm);
    background: var(--d-surface-2);
    border: 1px dashed var(--d-border-strong);
    color: var(--d-text-2);
    font-size: .95rem;
    font-weight: 600;
}
.d-resp-empty .mdi { font-size: 1.3rem; color: var(--d-text-3); }

.d-resp-sep {
    grid-column: 1 / -1;
    height: 1px;
    background: linear-gradient(90deg,
        transparent,
        var(--d-border-strong),
        transparent);
    margin: .25rem 0;
}

.d-resp-cell {
    display: flex; align-items: center; gap: .55rem;
    padding: .55rem .7rem;
    border-radius: var(--d-radius-sm);
    background: var(--d-cell-info);
    border: 1px solid rgba(59, 130, 246, 0.22);
    backdrop-filter: blur(8px);
    -webkit-backdrop-filter: blur(8px);
    min-width: 0;
    transition: background .15s, transform .12s;
}
.d-resp-cell .cell-icon {
    font-size: 1.4rem;
    color: var(--d-info);
    flex-shrink: 0;
    line-height: 1;
}
.d-resp-cell .cell-text {
    display: flex;
    flex-direction: column;
    min-width: 0;
    line-height: 1.15;
}
.d-resp-cell .cell-ff {
    font-size: .85rem;
    font-weight: 800;
    color: var(--d-text);
    font-variant-numeric: tabular-nums;
}
.d-resp-cell .cell-name {
    font-size: .75rem;
    color: var(--d-text-2);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.d-resp-cell .cell-eta {
    margin-left: auto;
    padding: .2rem .55rem .22rem;
    border-radius: 999px;
    background: var(--d-cell-eta-bg);
    color: var(--d-cell-eta-text);
    font-size: .72rem;
    font-weight: 800;
    letter-spacing: .04em;
    font-variant-numeric: tabular-nums;
    flex-shrink: 0;
}

/* Per-color responder cell variants. Each one swaps:
     - background tint
     - border color (more saturated)
     - icon color (full saturation) */
.d-resp-cell.success { background: var(--d-cell-success);
    border-color: rgba(16, 185, 129, 0.32); }
.d-resp-cell.success .cell-icon { color: var(--d-success); }
.d-resp-cell.danger  { background: var(--d-cell-danger);
    border-color: rgba(239, 68, 68, 0.32); }
.d-resp-cell.danger  .cell-icon { color: var(--d-accent); }
.d-resp-cell.warning { background: var(--d-cell-warning);
    border-color: rgba(245, 158, 11, 0.34); }
.d-resp-cell.warning .cell-icon { color: var(--d-warning); }
.d-resp-cell.info    { background: var(--d-cell-info);
    border-color: rgba(59, 130, 246, 0.32); }
.d-resp-cell.info    .cell-icon { color: var(--d-info); }
.d-resp-cell.purple  { background: var(--d-cell-purple);
    border-color: rgba(168, 85, 247, 0.32); }
.d-resp-cell.purple  .cell-icon { color: var(--d-purple); }
.d-resp-cell.teal    { background: var(--d-cell-teal);
    border-color: rgba(20, 184, 166, 0.32); }
.d-resp-cell.teal    .cell-icon { color: var(--d-teal); }
.d-resp-cell.pink    { background: var(--d-cell-pink);
    border-color: rgba(236, 72, 153, 0.32); }
.d-resp-cell.pink    .cell-icon { color: var(--d-pink); }
.d-resp-cell.dark    { background: var(--d-cell-dark);
    border-color: rgba(71, 85, 105, 0.42); }
.d-resp-cell.dark    .cell-icon { color: #cbd5e1; }
.d-resp-cell.gray    { background: var(--d-cell-gray);
    border-color: rgba(148, 163, 184, 0.36); }
.d-resp-cell.gray    .cell-icon { color: var(--d-gray); }

/* ── Idle / Training feed card ─────────────────────────── */
.d-idle {
    background-image: var(--d-standby-tint);
}
.d-idle-head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: .85rem;
    min-height: var(--d-card-head-height);
    padding: 0 1.2rem;
    border-bottom: 1px solid var(--d-border);
    flex-shrink: 0;
}
.d-idle-tabs {
    display: none;
}
.d-idle-tab {
    display: inline-flex; align-items: center; gap: .35rem;
    padding: .28rem .65rem .3rem;
    border-radius: 999px;
    font-size: .72rem;
    font-weight: 800;
    letter-spacing: .08em;
    text-transform: uppercase;
    background: var(--d-surface-2);
    border: 1px solid var(--d-border);
    color: var(--d-text-3);
}
.d-idle-tab .mdi { font-size: .85rem; }
.d-idle-tab.active {
    background: var(--d-tab-active-bg);
    border-color: rgba(59, 130, 246, 0.40);
    color: var(--d-tab-active-text);
    box-shadow: 0 0 0 1px rgba(59, 130, 246, 0.10),
                0 2px 8px rgba(59, 130, 246, 0.20);
}
.d-idle-title-wrap {
    min-width: 0;
    margin-bottom: 0;
}
.kicker {
    font-size: .7rem;
    font-weight: 800;
    text-transform: uppercase;
    letter-spacing: .12em;
    color: var(--d-text-3);
    margin-bottom: .25rem;
}
.d-idle-title-wrap .title {
    font-size: 1.05rem;
    font-weight: 800;
    color: var(--d-text);
    letter-spacing: -0.01em;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
.d-idle-meta {
    display: inline-flex; align-items: center; gap: .35rem;
    padding: .25rem .65rem .27rem;
    border-radius: 999px;
    background: var(--d-surface-2);
    border: 1px solid var(--d-border);
    font-size: .78rem;
    font-weight: 700;
    color: var(--d-text-2);
    font-variant-numeric: tabular-nums;
}
.d-idle-meta .mdi { font-size: .9rem; line-height: 1; }

.d-idle-feed {
    flex: 1;
    overflow: hidden;
    display: flex;
    gap: 1rem;
    padding: 1.2rem 1.2rem .9rem;
}
.d-idle-icon {
    flex-shrink: 0;
    width: 4.5rem; height: 4.5rem;
    border-radius: 1rem;
    display: flex; align-items: center; justify-content: center;
    background: var(--d-cell-info);
    border: 1px solid rgba(59, 130, 246, 0.30);
}
.d-idle-icon .mdi {
    font-size: 2.4rem;
    color: var(--d-info);
}
/* Idle icon color variants — match training/safety priority colors */
.d-idle-icon.red    { background: var(--d-cell-danger);
    border-color: rgba(239, 68, 68, 0.36); }
.d-idle-icon.red    .mdi { color: var(--d-accent); }
.d-idle-icon.yellow { background: var(--d-cell-warning);
    border-color: rgba(245, 158, 11, 0.38); }
.d-idle-icon.yellow .mdi { color: var(--d-warning); }
.d-idle-icon.green  { background: var(--d-cell-success);
    border-color: rgba(16, 185, 129, 0.36); }
.d-idle-icon.green  .mdi { color: var(--d-success); }
.d-idle-icon.blue   { background: var(--d-cell-info);
    border-color: rgba(59, 130, 246, 0.36); }
.d-idle-icon.blue   .mdi { color: var(--d-info); }
.d-idle-icon.purple { background: var(--d-cell-purple);
    border-color: rgba(168, 85, 247, 0.36); }
.d-idle-icon.purple .mdi { color: var(--d-purple); }

.d-idle-content {
    flex: 1;
    min-width: 0;
    overflow: hidden;
    display: flex;
    flex-direction: column;
    gap: .35rem;
}
.d-idle-category {
    font-size: .72rem;
    font-weight: 800;
    text-transform: uppercase;
    letter-spacing: .12em;
    color: var(--d-text-3);
}
.d-idle-feed-title {
    font-size: 1.55rem;
    font-weight: 800;
    color: var(--d-text);
    line-height: 1.2;
    letter-spacing: -0.01em;
    /* Allow up to ~3 lines before truncating; long messages
       become more readable on a wall display this way. */
    display: -webkit-box;
    -webkit-line-clamp: 3;
    -webkit-box-orient: vertical;
    overflow: hidden;
}
.d-idle-feed-detail {
    font-size: 1rem;
    line-height: 1.45;
    color: var(--d-text-2);
    /* 4 lines max for the body text. */
    display: -webkit-box;
    -webkit-line-clamp: 4;
    -webkit-box-orient: vertical;
    overflow: hidden;
}
.d-idle-sources {
    margin-top: .35rem;
    display: flex;
    flex-wrap: wrap;
    gap: .35rem;
}
.d-idle-sources span {
    display: inline-flex; align-items: center; gap: .3rem;
    padding: .2rem .55rem .22rem;
    border-radius: 999px;
    background: var(--d-surface-2);
    border: 1px solid var(--d-border);
    font-size: .72rem;
    font-weight: 700;
    color: var(--d-text-2);
}
.d-idle-sources .mdi { font-size: .85rem; line-height: 1; }

.d-idle-foot {
    flex-shrink: 0;
    padding: .65rem 1.2rem 1rem;
    border-top: 1px solid var(--d-border);
    display: grid;
    grid-template-columns: auto 1fr auto;
    align-items: center;
    gap: .85rem;
    background: var(--d-summary-bg);
}
.d-idle-foot .count {
    font-size: .82rem;
    font-weight: 700;
    color: var(--d-text-2);
    font-variant-numeric: tabular-nums;
}
.d-idle-foot .hint {
    font-size: .78rem;
    color: var(--d-text-3);
    font-style: italic;
    text-align: right;
}
.d-idle-progress {
    height: 6px;
    border-radius: 999px;
    background: rgba(255, 255, 255, 0.08);
    overflow: hidden;
    box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.18);
}
.d-idle-progress-bar {
    height: 100%;
    background: linear-gradient(90deg, var(--d-brand), var(--d-brand-2));
    border-radius: 999px;
    transition: width .8s ease-out;
    box-shadow: 0 0 8px rgba(192, 40, 45, 0.45);
}

/* ── New-call flash overlay ────────────────────────────── */
/* Full-screen border glow + brief brand-red wash when a new
   call arrives. Big and dramatic by design — this is the one
   thing that absolutely must be noticed from across the bay. */
.d-alert-flash {
    position: fixed;
    inset: 0;
    z-index: 1000;
    pointer-events: none;
    opacity: 0;
    background:
        radial-gradient(ellipse 80% 60% at 50% 50%,
            rgba(192, 40, 45, 0) 50%,
            rgba(192, 40, 45, 0.35) 100%);
    box-shadow: inset 0 0 0 0 rgba(239, 68, 68, 0.9);
    transition: opacity .25s ease;
}
.d-alert-flash.active {
    opacity: 1;
    animation: dAlertFlashPulse 1.5s ease-out infinite;
}
@keyframes dAlertFlashPulse {
    0%, 100% {
        box-shadow:
            inset 0 0 0 12px rgba(239, 68, 68, 0.85),
            inset 0 0 60px 30px rgba(239, 68, 68, 0.30);
    }
    50% {
        box-shadow:
            inset 0 0 0 6px rgba(239, 68, 68, 0.55),
            inset 0 0 80px 50px rgba(239, 68, 68, 0.15);
    }
}


/* ── Light-mode cleanup — remove muddy card gaps ─────────
   The grid gap shows the page behind the cards. In light mode,
   keep the shell, main grid, and cards on the same true-white
   surface and remove outside shadows so adjacent cards do not
   create darker channels between their rounded corners. */
@media (prefers-color-scheme: light) {
    body,
    body::before,
    .d-shell,
    .d-main {
        background: #ffffff !important;
    }

    body::after {
        display: none !important;
    }

    .d-card {
        background-color: #ffffff !important;
        backdrop-filter: none !important;
        -webkit-backdrop-filter: none !important;
        border: 1px solid rgba(15, 23, 42, 0.12) !important;
        box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.95) !important;
        overflow: hidden;
    }

    .d-call,
    .d-resp,
    .d-idle {
        background-color: #ffffff !important;
    }
}

/* ── Responsive — for smaller secondary displays ────────
   Below 900px the three-column layout collapses to a column
   stack; below 600px the topbar wraps. The dashboard is
   primarily designed for 1080p+ wall displays but a captain
   on an iPad mini in the truck cab should still get value. */
@media (max-width: 900px) {
    .d-main {
        grid-template-columns: 1fr;
        grid-template-rows: auto auto 1fr;
    }
    .d-main.is-idle {
        grid-template-columns: 1fr;
    }
    .d-call-type { font-size: 1.85rem; }
}
@media (max-width: 600px) {
    .d-shell {
        padding: .65rem .75rem .75rem;
        gap: .65rem;
    }
    .d-topbar {
        flex-wrap: wrap;
        height: auto;
        padding: .65rem .85rem;
        gap: .5rem;
    }
    .d-brand { font-size: 1.1rem; }
    .d-brand .mdi { font-size: 1.4rem; }
    .d-clock { font-size: 1.15rem; min-width: 0; }
    .d-call-type { font-size: 1.4rem; }
}

/* ── Print — leave the page styled minimally in case anyone
   ever does a screen capture for an after-action report. */
@media print {
    body::before, body::after { display: none !important; }
    .d-alert-flash { display: none !important; }
    .d-card {
        backdrop-filter: none !important;
        -webkit-backdrop-filter: none !important;
        box-shadow: none !important;
    }
}

/* ============================================================
 * Wall-display operating modes
 *
 * is-active:    newest call is under 1 hour old; show call + responders.
 * is-aged-call: newest call remains visible, but responder window is closed;
 *               show call + training/safety.
 * is-idle:      no call to show; show standing-by + training/safety.
 *
 * This screen is intended for TVs and fixed dashboards. Do not depend on
 * scrolling to reveal important information.
 * ========================================================= */
.d-main.is-active {
    grid-template-columns: minmax(18rem, .85fr) minmax(0, 2.15fr);
}
.d-main.is-active .d-idle {
    display: none;
}

.d-main.is-aged-call {
    grid-template-columns: minmax(22rem, 1fr) minmax(0, 1.25fr);
}
.d-main.is-aged-call .d-resp {
    display: none;
}
.d-main.is-aged-call .d-idle {
    display: flex;
}

.d-main.is-idle {
    grid-template-columns: minmax(18rem, .8fr) minmax(0, 2.2fr);
}
.d-main.is-idle .d-resp {
    display: none;
}
.d-main.is-idle .d-idle {
    display: flex;
}

/* No dashboard scrolling: tighten call details so the card itself fits. */
.d-call-body {
    overflow: hidden;
    gap: .7rem;
    padding: .9rem 1rem 1rem;
}
.d-call-type {
    font-size: clamp(1.55rem, 2.1vw, 2.4rem);
}
.d-call-section {
    padding: .58rem .72rem .65rem;
}
.d-call-section .value {
    font-size: clamp(.86rem, .95vw, 1.05rem);
    line-height: 1.25;
}
.d-call-section .value.message {
    display: -webkit-box;
    -webkit-line-clamp: 3;
    -webkit-box-orient: vertical;
    overflow: hidden;
}
.d-other-calls {
    margin: 0 .9rem .9rem;
    padding: .55rem .7rem;
}

/* Responders are the primary display during the first hour. */
.d-main.is-active .d-resp-grid {
    padding: .55rem .8rem .75rem;
    gap: .34rem;
    grid-template-columns: repeat(auto-fill, minmax(8.25rem, 1fr));
    grid-auto-rows: min-content;
    align-content: start;
    overflow: hidden;
}
.d-resp-grid[data-density="medium"] {
    gap: .32rem;
    grid-template-columns: repeat(auto-fill, minmax(8.75rem, 1fr));
}
.d-resp-grid[data-density="high"] {
    gap: .28rem;
    grid-template-columns: repeat(auto-fill, minmax(7.75rem, 1fr));
}
.d-resp-grid[data-density="ultra"] {
    gap: .24rem;
    grid-template-columns: repeat(auto-fill, minmax(7rem, 1fr));
}

.d-resp-grid[data-density="medium"] .d-resp-cell,
.d-resp-grid[data-density="high"] .d-resp-cell,
.d-resp-grid[data-density="ultra"] .d-resp-cell {
    padding: .31rem .42rem;
    gap: .34rem;
    min-height: 2.32rem;
}
.d-resp-grid[data-density="medium"] .cell-icon,
.d-resp-grid[data-density="high"] .cell-icon,
.d-resp-grid[data-density="ultra"] .cell-icon {
    font-size: .95rem;
}
.d-resp-grid[data-density="medium"] .cell-ff,
.d-resp-grid[data-density="high"] .cell-ff,
.d-resp-grid[data-density="ultra"] .cell-ff {
    font-size: .7rem;
}
.d-resp-grid[data-density="medium"] .cell-name,
.d-resp-grid[data-density="high"] .cell-name,
.d-resp-grid[data-density="ultra"] .cell-name {
    font-size: .62rem;
}
.d-resp-grid[data-density="medium"] .cell-eta,
.d-resp-grid[data-density="high"] .cell-eta,
.d-resp-grid[data-density="ultra"] .cell-eta {
    font-size: .58rem;
    padding: .1rem .28rem;
}

.d-resp-head {
    min-height: var(--d-card-head-height);
    padding: 0 .9rem;
}
.d-resp-summary {
    padding: .45rem .9rem .32rem;
    gap: .28rem;
}
.d-resp-pill {
    padding: .2rem .48rem .22rem;
    font-size: .66rem;
}

/* Visible responder group headers for TV readability. */
.d-resp-group-title {
    grid-column: 1 / -1;
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: .6rem;
    margin: .12rem 0 -.05rem;
    padding: .16rem .46rem .18rem;
    border-radius: .42rem;
    background: rgba(255, 255, 255, 0.055);
    border: 1px solid var(--d-border);
    color: var(--d-text-2);
    font-size: .58rem;
    font-weight: 900;
    letter-spacing: .1em;
    line-height: 1;
    text-transform: uppercase;
}
.d-resp-group-title.success { border-color: rgba(16, 185, 129, 0.32); }
.d-resp-group-title.danger  { border-color: rgba(239, 68, 68, 0.32); }
.d-resp-group-title.warning { border-color: rgba(245, 158, 11, 0.34); }
.d-resp-group-title.info    { border-color: rgba(59, 130, 246, 0.32); }
.d-resp-group-title.purple  { border-color: rgba(168, 85, 247, 0.32); }
.d-resp-group-title.teal    { border-color: rgba(20, 184, 166, 0.32); }
.d-resp-group-title.pink    { border-color: rgba(236, 72, 153, 0.32); }
.d-resp-group-title.dark    { border-color: rgba(71, 85, 105, 0.42); }
.d-resp-group-title.gray    { border-color: rgba(148, 163, 184, 0.36); }

/* Training/safety is secondary during aged-call display. */
.d-main.is-aged-call .d-idle-head,
.d-main.is-active .d-idle-head {
    min-height: var(--d-card-head-height);
    padding: 0 .85rem;
}
.d-main.is-aged-call .d-idle-tabs,
.d-main.is-active .d-idle-tabs {
    display: none;
}
.d-main.is-aged-call .d-idle-feed,
.d-main.is-active .d-idle-feed {
    padding: .85rem;
    gap: .7rem;
}
.d-main.is-aged-call .d-idle-icon,
.d-main.is-active .d-idle-icon {
    width: 3.2rem;
    height: 3.2rem;
    border-radius: .75rem;
}
.d-main.is-aged-call .d-idle-icon .mdi,
.d-main.is-active .d-idle-icon .mdi {
    font-size: 1.7rem;
}
.d-main.is-aged-call .d-idle-feed-title,
.d-main.is-active .d-idle-feed-title {
    font-size: clamp(1.05rem, 1.25vw, 1.45rem);
    line-height: 1.15;
    -webkit-line-clamp: 3;
}
.d-main.is-aged-call .d-idle-feed-detail,
.d-main.is-active .d-idle-feed-detail {
    font-size: clamp(.8rem, .9vw, 1rem);
    line-height: 1.28;
    -webkit-line-clamp: 5;
}
.d-main.is-aged-call .d-idle-sources,
.d-main.is-active .d-idle-sources {
    display: none;
}
.d-main.is-aged-call .d-idle-foot,
.d-main.is-active .d-idle-foot {
    padding: .45rem .8rem;
}

/* Light mode needs the same clean white surface across hidden gaps. */
@media (prefers-color-scheme: light) {
    .d-main.is-active,
    .d-main.is-aged-call,
    .d-main.is-idle {
        background: #ffffff !important;
    }
    .d-resp-group-title {
        background: rgba(15, 23, 42, 0.035);
    }
}

@media (max-width: 900px) {
    .d-main.is-active,
    .d-main.is-aged-call,
    .d-main.is-idle {
        grid-template-columns: 1fr;
    }
    .d-main.is-active .d-idle,
    .d-main.is-aged-call .d-resp,
    .d-main.is-idle .d-resp {
        display: none;
    }
}


/* ── Dashboard polish: equal card headers + remove low-value feed chrome ── */
.d-call-head,
.d-resp-head,
.d-idle-head {
    height: var(--d-card-head-height);
    min-height: var(--d-card-head-height);
    max-height: var(--d-card-head-height);
}

.d-idle-meta,
.d-idle-foot .count,
.d-idle-foot .hint {
    display: none !important;
}

.d-idle-foot {
    grid-template-columns: 1fr;
    padding: .45rem .85rem .65rem;
}

.d-main.is-aged-call .d-idle-feed {
    padding: 1rem 1rem .75rem;
}

.d-main.is-aged-call .d-idle-feed-title {
    font-size: clamp(1.25rem, 1.55vw, 1.85rem);
    -webkit-line-clamp: 3;
}

.d-main.is-aged-call .d-idle-feed-detail {
    font-size: clamp(.95rem, 1.05vw, 1.2rem);
    -webkit-line-clamp: 6;
}


/* ============================================================
 * Responder-name wall-display refinement
 *
 * The active responder window must show full names, not clipped
 * fragments. The responder panel gets more width during the
 * first-hour active window, and the grid cells use wider columns
 * with wrapping names.
 * ========================================================= */
.d-main.is-active {
    grid-template-columns: minmax(16rem, .58fr) minmax(0, 2.42fr);
}

.d-main.is-active .d-call-body {
    padding: .78rem .85rem .9rem;
    gap: .55rem;
}

.d-main.is-active .d-call-section {
    padding: .48rem .62rem .55rem;
}

.d-main.is-active .d-call-type {
    font-size: clamp(1.35rem, 1.75vw, 2.05rem);
}

.d-main.is-active .d-resp-grid {
    padding: .52rem .72rem .72rem;
    gap: .30rem;
    grid-template-columns: repeat(auto-fill, minmax(12rem, 1fr));
}

.d-main.is-active .d-resp-grid[data-density="medium"],
.d-main.is-active .d-resp-grid[data-density="high"],
.d-main.is-active .d-resp-grid[data-density="ultra"] {
    grid-template-columns: repeat(auto-fill, minmax(11.35rem, 1fr));
}

.d-main.is-active .d-resp-grid[data-density="medium"] .d-resp-cell,
.d-main.is-active .d-resp-grid[data-density="high"] .d-resp-cell,
.d-main.is-active .d-resp-grid[data-density="ultra"] .d-resp-cell {
    min-height: 2.55rem;
    padding: .34rem .46rem;
}

.d-main.is-active .d-resp-cell {
    align-items: flex-start;
}

.d-main.is-active .d-resp-cell .cell-text {
    flex: 1 1 auto;
    min-width: 0;
}

.d-main.is-active .d-resp-cell .cell-name {
    display: block;
    white-space: normal;
    overflow: visible;
    text-overflow: clip;
    line-height: 1.12;
    max-height: 2.3em;
}

.d-main.is-active .d-resp-grid[data-density="medium"] .cell-name,
.d-main.is-active .d-resp-grid[data-density="high"] .cell-name,
.d-main.is-active .d-resp-grid[data-density="ultra"] .cell-name {
    font-size: .68rem;
}

.d-main.is-active .d-resp-grid[data-density="medium"] .cell-ff,
.d-main.is-active .d-resp-grid[data-density="high"] .cell-ff,
.d-main.is-active .d-resp-grid[data-density="ultra"] .cell-ff {
    font-size: .68rem;
}

.d-main.is-active .d-resp-cell .cell-eta {
    align-self: center;
}

/* Keep group labels compact so Available remains clearly first without
   burning too much vertical space. */
.d-main.is-active .d-resp-group-title {
    margin: .08rem 0 -.08rem;
    padding: .14rem .42rem .16rem;
}

/* ── Correction: keep call card at the previous active-call width ──
   The responder-name pass made the call column too narrow. During the
   first-hour responder window, preserve the call panel and let responder
   names gain space through wider responder cells, not by squeezing the call. */
.d-main.is-active {
    grid-template-columns: minmax(22rem, .85fr) minmax(0, 2.15fr) !important;
}

.d-main.is-active .d-call-body {
    padding: 1.1rem 1.3rem 1.3rem !important;
    gap: 1rem !important;
}

.d-main.is-active .d-call-section {
    padding: .7rem .9rem .8rem !important;
}

.d-main.is-active .d-call-type {
    font-size: 2.4rem !important;
}

/* Keep responder names readable without stealing width from the call card. */
.d-main.is-active .d-resp-grid {
    padding: .65rem .9rem .9rem !important;
    gap: .38rem !important;
    grid-template-columns: repeat(auto-fill, minmax(13rem, 1fr)) !important;
}

.d-main.is-active .d-resp-grid[data-density="medium"],
.d-main.is-active .d-resp-grid[data-density="high"],
.d-main.is-active .d-resp-grid[data-density="ultra"] {
    grid-template-columns: repeat(auto-fill, minmax(12.25rem, 1fr)) !important;
}

.d-main.is-active .d-resp-cell {
    min-height: 2.7rem !important;
    padding: .42rem .55rem !important;
    gap: .42rem !important;
}

.d-main.is-active .d-resp-cell .cell-name {
    white-space: normal !important;
    overflow: visible !important;
    text-overflow: clip !important;
    line-height: 1.08 !important;
    max-height: 2.2em !important;
}

@media (max-width: 900px) {
    .d-main.is-active {
        grid-template-columns: 1fr !important;
    }
}

/* ============================================================
 * Call-card fit refinement
 *
 * The dashboard is a fixed TV display, so the call card cannot
 * depend on scrolling. Keep the call column width from the prior
 * pass, but reduce the internal type scale and spacing so call
 * details fit. Comments are the only field allowed to truncate,
 * and they are limited to two rows.
 * ========================================================= */
.d-main.is-active {
    grid-template-columns: minmax(22rem, .85fr) minmax(0, 2.15fr) !important;
}

.d-main.is-active .d-call-body,
.d-main.is-aged-call .d-call-body {
    overflow: hidden !important;
    padding: .72rem .88rem .82rem !important;
    gap: .48rem !important;
}

.d-main.is-active .d-call-type,
.d-main.is-aged-call .d-call-type {
    font-size: clamp(1.25rem, 1.35vw, 1.75rem) !important;
    line-height: 1.06 !important;
    letter-spacing: -.015em !important;
    margin: 0 !important;
    overflow-wrap: anywhere;
}

.d-main.is-active .d-call-time,
.d-main.is-aged-call .d-call-time {
    font-size: clamp(.74rem, .78vw, .88rem) !important;
    margin-top: .18rem !important;
}

.d-main.is-active .d-call-section,
.d-main.is-aged-call .d-call-section {
    padding: .42rem .55rem .48rem !important;
    border-radius: .52rem !important;
}

.d-main.is-active .d-call-section .label,
.d-main.is-aged-call .d-call-section .label {
    font-size: .58rem !important;
    letter-spacing: .105em !important;
    margin-bottom: .16rem !important;
}

.d-main.is-active .d-call-section .value,
.d-main.is-aged-call .d-call-section .value {
    font-size: clamp(.78rem, .82vw, .94rem) !important;
    line-height: 1.16 !important;
}

.d-main.is-active .d-call-section .value.message,
.d-main.is-aged-call .d-call-section .value.message {
    display: -webkit-box !important;
    -webkit-line-clamp: 2 !important;
    -webkit-box-orient: vertical !important;
    overflow: hidden !important;
    line-height: 1.18 !important;
}

.d-main.is-active .d-units-list,
.d-main.is-aged-call .d-units-list {
    gap: .24rem !important;
}

.d-main.is-active .d-units-list li,
.d-main.is-aged-call .d-units-list li {
    padding: .16rem .42rem .18rem !important;
    font-size: .68rem !important;
    line-height: 1.05 !important;
}

.d-main.is-active .d-other-calls,
.d-main.is-aged-call .d-other-calls {
    margin: 0 .72rem .72rem !important;
    padding: .42rem .55rem !important;
}

.d-main.is-active .d-other-calls .label,
.d-main.is-aged-call .d-other-calls .label {
    font-size: .58rem !important;
    margin-bottom: .2rem !important;
}

.d-main.is-active .d-other-call-row,
.d-main.is-aged-call .d-other-call-row {
    padding: .24rem 0 !important;
    font-size: .76rem !important;
}

.d-main.is-active .d-other-call-row .time,
.d-main.is-aged-call .d-other-call-row .time {
    font-size: .68rem !important;
}

/* On 1080p-height displays, save a bit more vertical space without
   changing the overall card width. */
@media (max-height: 900px) {
    .d-main.is-active .d-call-body,
    .d-main.is-aged-call .d-call-body {
        padding: .58rem .72rem .68rem !important;
        gap: .38rem !important;
    }

    .d-main.is-active .d-call-type,
    .d-main.is-aged-call .d-call-type {
        font-size: clamp(1.12rem, 1.2vw, 1.55rem) !important;
    }

    .d-main.is-active .d-call-section,
    .d-main.is-aged-call .d-call-section {
        padding: .34rem .46rem .39rem !important;
    }
}

/* ============================================================
 * Call-card height tuning
 *
 * Width stays exactly as-is. This restores some vertical scale so
 * the call card uses more of the available TV height while still
 * preventing scroll. Comments remain capped at two lines.
 * ========================================================= */
.d-main.is-active .d-call-body,
.d-main.is-aged-call .d-call-body {
    padding: .95rem 1.05rem 1rem !important;
    gap: .68rem !important;
}

.d-main.is-active .d-call-type,
.d-main.is-aged-call .d-call-type {
    font-size: clamp(1.55rem, 1.62vw, 2.08rem) !important;
    line-height: 1.08 !important;
}

.d-main.is-active .d-call-time,
.d-main.is-aged-call .d-call-time {
    font-size: clamp(.82rem, .86vw, .98rem) !important;
    margin-top: .24rem !important;
}

.d-main.is-active .d-call-section,
.d-main.is-aged-call .d-call-section {
    padding: .58rem .72rem .64rem !important;
    border-radius: .62rem !important;
}

.d-main.is-active .d-call-section .label,
.d-main.is-aged-call .d-call-section .label {
    font-size: .64rem !important;
    margin-bottom: .24rem !important;
}

.d-main.is-active .d-call-section .value,
.d-main.is-aged-call .d-call-section .value {
    font-size: clamp(.9rem, .92vw, 1.06rem) !important;
    line-height: 1.22 !important;
}

.d-main.is-active .d-call-section .value.message,
.d-main.is-aged-call .d-call-section .value.message {
    -webkit-line-clamp: 2 !important;
    line-height: 1.22 !important;
    max-height: calc(1.22em * 2) !important;
}

.d-main.is-active .d-units-list,
.d-main.is-aged-call .d-units-list {
    gap: .32rem !important;
}

.d-main.is-active .d-units-list li,
.d-main.is-aged-call .d-units-list li {
    padding: .22rem .52rem .24rem !important;
    font-size: .76rem !important;
    line-height: 1.08 !important;
}

.d-main.is-active .d-other-calls,
.d-main.is-aged-call .d-other-calls {
    margin: 0 .95rem .95rem !important;
    padding: .52rem .68rem !important;
}

.d-main.is-active .d-other-calls .label,
.d-main.is-aged-call .d-other-calls .label {
    font-size: .64rem !important;
    margin-bottom: .28rem !important;
}

.d-main.is-active .d-other-call-row,
.d-main.is-aged-call .d-other-call-row {
    padding: .3rem 0 !important;
    font-size: .84rem !important;
}

.d-main.is-active .d-other-call-row .time,
.d-main.is-aged-call .d-other-call-row .time {
    font-size: .74rem !important;
}

/* 1080p-height displays still get the larger call card treatment,
   just slightly compressed compared with 4K. */
@media (max-height: 900px) {
    .d-main.is-active .d-call-body,
    .d-main.is-aged-call .d-call-body {
        padding: .78rem .9rem .84rem !important;
        gap: .55rem !important;
    }

    .d-main.is-active .d-call-type,
    .d-main.is-aged-call .d-call-type {
        font-size: clamp(1.38rem, 1.45vw, 1.88rem) !important;
    }

    .d-main.is-active .d-call-section,
    .d-main.is-aged-call .d-call-section {
        padding: .5rem .62rem .56rem !important;
    }

    .d-main.is-active .d-call-section .value,
    .d-main.is-aged-call .d-call-section .value {
        font-size: clamp(.84rem, .86vw, .98rem) !important;
    }
}


/* ============================================================
 * Theme state colours
 *
 * Keep the red Priority4 emergency theme whenever a call is on
 * screen. When there is no call and the dashboard is in idle mode,
 * switch the primary chrome and neutral accents to #1f2937.
 * ============================================================ */
:root {
    --d-idle-base: #1f2937;
    --d-idle-base-2: #111827;
    --d-idle-base-3: #374151;
    --d-idle-glow: rgba(31, 41, 55, 0.34);
}

body.d-mode-idle {
    --d-brand: #1f2937;
    --d-brand-2: #4b5563;
    --d-bg-glow: rgba(31, 41, 55, 0.26);
    --d-bg-glow-2: rgba(75, 85, 99, 0.16);
    --d-topbar-bg: linear-gradient(135deg,
        rgba(31, 41, 55, 0.96) 0%,
        rgba(17, 24, 39, 0.96) 58%,
        rgba(55, 65, 81, 0.96) 100%);
    --d-standby-tint: radial-gradient(800px 220px at 50% 0%,
        rgba(31, 41, 55, 0.18), transparent 72%);
    --d-tab-active-bg: rgba(31, 41, 55, 0.28);
    --d-tab-active-text: #f9fafb;
}

body.d-mode-idle::before {
    background:
        radial-gradient(ellipse 80% 60% at 80% 0%,
            rgba(31, 41, 55, 0.32) 0%, transparent 55%),
        radial-gradient(ellipse 70% 50% at 0% 100%,
            rgba(75, 85, 99, 0.14) 0%, transparent 55%),
        linear-gradient(180deg,
            var(--d-bg-base) 0%,
            var(--d-bg-mid) 60%,
            var(--d-bg-base) 100%);
}

body.d-mode-idle::after {
    background: radial-gradient(circle at 30% 40%,
        rgba(31, 41, 55, 0.16) 0%,
        transparent 36%);
}

body.d-mode-idle .d-topbar {
    background: var(--d-topbar-bg) !important;
    box-shadow:
        0 12px 32px rgba(31, 41, 55, 0.30),
        inset 0 1px 0 rgba(255, 255, 255, 0.12) !important;
}

body.d-mode-idle .d-status {
    background: rgba(255, 255, 255, 0.13);
    border-color: rgba(255, 255, 255, 0.22);
    color: #ffffff;
}

body.d-mode-idle .d-status .dot {
    background: #d1d5db;
    animation: none;
    box-shadow: 0 0 0 4px rgba(209, 213, 219, 0.16);
}

body.d-mode-idle .d-idle-tab.active,
body.d-mode-idle .d-idle-meta,
body.d-mode-idle .d-idle-sources span {
    border-color: rgba(31, 41, 55, 0.34);
}

body.d-mode-idle .d-idle-icon.blue {
    background: rgba(31, 41, 55, 0.20);
    border-color: rgba(31, 41, 55, 0.38);
}

body.d-mode-idle .d-idle-icon.blue .mdi {
    color: #9ca3af;
}

body.d-mode-idle .d-idle-progress-bar {
    background: linear-gradient(90deg, #1f2937, #4b5563) !important;
    box-shadow: 0 0 8px rgba(31, 41, 55, 0.45) !important;
}

/* In light mode the idle dashboard still uses the #1f2937 chrome,
   but the card bodies remain clean white so the rounded corners stay crisp. */
@media (prefers-color-scheme: light) {
    body.d-mode-idle,
    body.d-mode-idle::before,
    body.d-mode-idle .d-shell,
    body.d-mode-idle .d-main {
        background: #ffffff !important;
    }

    body.d-mode-idle .d-topbar {
        background: linear-gradient(135deg, #1f2937 0%, #111827 62%, #374151 100%) !important;
        box-shadow:
            0 1px 0 rgba(15, 23, 42, 0.08),
            inset 0 1px 0 rgba(255, 255, 255, 0.16) !important;
    }

    body.d-mode-idle .d-idle-icon.blue {
        background: rgba(31, 41, 55, 0.10);
        border-color: rgba(31, 41, 55, 0.24);
    }

    body.d-mode-idle .d-idle-icon.blue .mdi {
        color: #1f2937;
    }
}

/* ============================================================
 * TV screen-real-estate pass
 *
 * Current active-call view has the right split, but the content was
 * sitting too high with too much unused vertical space. This pass keeps
 * the call width stable, gives responder rows a little more visual
 * weight, and still leaves capacity for more responders / longer call
 * content without introducing scrolling.
 * ============================================================ */
:root {
    --d-card-head-height: 3.72rem;
}

/* Active view: preserve the call-card width and give the responder panel
   the rest. This keeps the call readable while maintaining room for up to
   the high-20s responder count. */
.d-main.is-active {
    grid-template-columns: minmax(28rem, .9fr) minmax(0, 2.2fr) !important;
    gap: 1rem !important;
}

/* Normalize all visible card headers. */
.d-call-head,
.d-resp-head,
.d-idle-head {
    min-height: var(--d-card-head-height) !important;
}

.d-call-head,
.d-resp-head {
    display: flex !important;
    align-items: center !important;
}

.d-idle-head {
    display: flex !important;
    flex-direction: column !important;
    justify-content: center !important;
}

/* Call card: use more of the vertical space without depending on scroll.
   Comments remain capped elsewhere at two lines. */
.d-main.is-active .d-call-body,
.d-main.is-aged-call .d-call-body {
    padding: 1.08rem 1.08rem 1.05rem !important;
    gap: .76rem !important;
    overflow: hidden !important;
}

.d-main.is-active .d-call-type,
.d-main.is-aged-call .d-call-type {
    font-size: clamp(1.72rem, 1.85vw, 2.3rem) !important;
    line-height: 1.08 !important;
    letter-spacing: -.018em !important;
}

.d-main.is-active .d-call-time,
.d-main.is-aged-call .d-call-time {
    font-size: clamp(.88rem, .9vw, 1rem) !important;
    margin-top: .25rem !important;
}

.d-main.is-active .d-call-section,
.d-main.is-aged-call .d-call-section {
    padding: .68rem .78rem .72rem !important;
    min-height: 3.55rem !important;
    border-radius: .7rem !important;
}

.d-main.is-active .d-call-section .label,
.d-main.is-aged-call .d-call-section .label {
    font-size: .66rem !important;
    margin-bottom: .22rem !important;
}

.d-main.is-active .d-call-section .value,
.d-main.is-aged-call .d-call-section .value {
    font-size: clamp(.94rem, .96vw, 1.08rem) !important;
    line-height: 1.22 !important;
}

.d-main.is-active .d-call-section .value.message,
.d-main.is-aged-call .d-call-section .value.message {
    -webkit-line-clamp: 2 !important;
    max-height: calc(1.22em * 2) !important;
}

.d-main.is-active .d-units-list li,
.d-main.is-aged-call .d-units-list li {
    font-size: .82rem !important;
    padding: .24rem .58rem .26rem !important;
}

.d-main.is-active .d-other-calls,
.d-main.is-aged-call .d-other-calls {
    margin: 0 1.05rem 1.05rem !important;
    padding: .6rem .72rem !important;
}

.d-main.is-active .d-other-call-row,
.d-main.is-aged-call .d-other-call-row {
    padding: .34rem 0 !important;
    font-size: .88rem !important;
}

/* Responder card: slightly larger rows and clearer lanes, while keeping
   enough room for 28+ responders on 1080p/4K displays. */
.d-main.is-active .d-resp-summary {
    padding: .6rem 1rem .34rem !important;
    gap: .42rem !important;
}

.d-main.is-active .d-resp-grid {
    padding: .6rem 1rem 1rem !important;
    gap: .46rem !important;
    grid-template-columns: repeat(auto-fill, minmax(13.75rem, 1fr)) !important;
    align-content: start !important;
    overflow: hidden !important;
}

.d-main.is-active .d-resp-grid[data-density="medium"],
.d-main.is-active .d-resp-grid[data-density="high"],
.d-main.is-active .d-resp-grid[data-density="ultra"] {
    grid-template-columns: repeat(auto-fill, minmax(12.75rem, 1fr)) !important;
}

.d-main.is-active .d-resp-cell {
    min-height: 3.05rem !important;
    padding: .48rem .62rem !important;
    gap: .46rem !important;
    align-items: center !important;
}

.d-main.is-active .d-resp-cell .cell-ff {
    font-size: .78rem !important;
    line-height: 1.08 !important;
}

.d-main.is-active .d-resp-cell .cell-name {
    font-size: .72rem !important;
    line-height: 1.12 !important;
    white-space: normal !important;
    overflow: visible !important;
    text-overflow: clip !important;
    max-height: 2.3em !important;
}

.d-main.is-active .d-resp-cell .cell-eta {
    font-size: .7rem !important;
    padding: .18rem .48rem .2rem !important;
}

.d-main.is-active .d-resp-group-title {
    margin: .12rem 0 -.04rem !important;
    padding: .18rem .52rem .2rem !important;
    font-size: .64rem !important;
}

/* If the screen height is tighter, compress only slightly. */
@media (max-height: 900px) {
    .d-main.is-active .d-call-body,
    .d-main.is-aged-call .d-call-body {
        padding: .92rem .94rem .92rem !important;
        gap: .62rem !important;
    }

    .d-main.is-active .d-call-type,
    .d-main.is-aged-call .d-call-type {
        font-size: clamp(1.5rem, 1.58vw, 2rem) !important;
    }

    .d-main.is-active .d-call-section,
    .d-main.is-aged-call .d-call-section {
        min-height: 3.25rem !important;
        padding: .58rem .68rem .62rem !important;
    }

    .d-main.is-active .d-resp-grid {
        gap: .38rem !important;
        grid-template-columns: repeat(auto-fill, minmax(12.9rem, 1fr)) !important;
    }

    .d-main.is-active .d-resp-grid[data-density="medium"],
    .d-main.is-active .d-resp-grid[data-density="high"],
    .d-main.is-active .d-resp-grid[data-density="ultra"] {
        grid-template-columns: repeat(auto-fill, minmax(12rem, 1fr)) !important;
    }

    .d-main.is-active .d-resp-cell {
        min-height: 2.78rem !important;
        padding: .4rem .54rem !important;
    }
}

@media (max-width: 900px) {
    .d-main.is-active {
        grid-template-columns: 1fr !important;
    }
}


/* ── Response summary / status lanes polish ───────────────
   The response summary row is driven by response_types from the
   agency-specific table. Make the row use the full card width and
   make the lane headers carry the same status color theme as the
   responder cells. */
.d-main.is-active .d-resp-summary,
.d-resp-summary {
    display: grid !important;
    grid-template-columns: repeat(auto-fit, minmax(10.75rem, 1fr)) !important;
    width: 100% !important;
    align-items: stretch !important;
    padding: .56rem 1rem .42rem !important;
    gap: .45rem !important;
}

.d-main.is-active .d-resp-pill,
.d-resp-pill {
    width: 100% !important;
    justify-content: center !important;
    min-height: 1.95rem !important;
    padding: .28rem .6rem .3rem !important;
    font-size: .72rem !important;
    white-space: nowrap !important;
}

.d-resp-pill.no-response {
    background: var(--d-cell-gray) !important;
    border-color: rgba(148, 163, 184, 0.38) !important;
    color: var(--d-pill-gray-text) !important;
}

/* Status lane dividers: keep the same color language as the response
   buttons instead of looking like plain/empty separator lines. */
.d-main.is-active .d-resp-group-title,
.d-resp-group-title {
    border-width: 1px !important;
    box-shadow: inset 0 1px 0 rgba(255,255,255,.18) !important;
}

.d-resp-group-title.success {
    background: var(--d-cell-success) !important;
    border-color: rgba(16, 185, 129, 0.42) !important;
    color: var(--d-pill-success-text) !important;
}
.d-resp-group-title.danger {
    background: var(--d-cell-danger) !important;
    border-color: rgba(239, 68, 68, 0.42) !important;
    color: var(--d-pill-danger-text) !important;
}
.d-resp-group-title.warning {
    background: var(--d-cell-warning) !important;
    border-color: rgba(245, 158, 11, 0.46) !important;
    color: var(--d-pill-warning-text) !important;
}
.d-resp-group-title.info {
    background: var(--d-cell-info) !important;
    border-color: rgba(59, 130, 246, 0.42) !important;
    color: var(--d-pill-info-text) !important;
}
.d-resp-group-title.purple {
    background: var(--d-cell-purple) !important;
    border-color: rgba(168, 85, 247, 0.42) !important;
    color: var(--d-pill-purple-text) !important;
}
.d-resp-group-title.teal {
    background: var(--d-cell-teal) !important;
    border-color: rgba(20, 184, 166, 0.42) !important;
    color: var(--d-pill-teal-text) !important;
}
.d-resp-group-title.pink {
    background: var(--d-cell-pink) !important;
    border-color: rgba(236, 72, 153, 0.42) !important;
    color: var(--d-pill-pink-text) !important;
}
.d-resp-group-title.dark {
    background: var(--d-cell-dark) !important;
    border-color: rgba(71, 85, 105, 0.48) !important;
    color: var(--d-pill-dark-text) !important;
}
.d-resp-group-title.gray,
.d-resp-group-title.no-response {
    background: var(--d-cell-gray) !important;
    border-color: rgba(148, 163, 184, 0.44) !important;
    color: var(--d-pill-gray-text) !important;
}

@media (max-width: 1200px) {
    .d-main.is-active .d-resp-summary,
    .d-resp-summary {
        grid-template-columns: repeat(2, minmax(0, 1fr)) !important;
    }
}

/* ── Darker responder status lane dividers ─────────────────
   Stronger tinted backgrounds so AVAILABLE / SCENE /
   UNAVAILABLE divider bars read as real section headers on TV,
   while keeping text contrast high in both light and dark modes. */
.d-main.is-active .d-resp-group-title,
.d-resp-group-title {
    border-width: 1px !important;
    font-weight: 950 !important;
    letter-spacing: .13em !important;
    box-shadow:
        inset 0 1px 0 rgba(255,255,255,.22),
        0 1px 2px rgba(15,23,42,.06) !important;
}

.d-resp-group-title.success {
    background: rgba(6, 95, 70, 0.18) !important;
    border-color: rgba(6, 95, 70, 0.50) !important;
    color: #064e3b !important;
}
.d-resp-group-title.danger {
    background: rgba(127, 29, 29, 0.16) !important;
    border-color: rgba(127, 29, 29, 0.52) !important;
    color: #7f1d1d !important;
}
.d-resp-group-title.warning {
    background: rgba(146, 64, 14, 0.18) !important;
    border-color: rgba(146, 64, 14, 0.55) !important;
    color: #78350f !important;
}
.d-resp-group-title.info {
    background: rgba(30, 58, 138, 0.16) !important;
    border-color: rgba(30, 58, 138, 0.50) !important;
    color: #1e3a8a !important;
}
.d-resp-group-title.purple {
    background: rgba(88, 28, 135, 0.16) !important;
    border-color: rgba(88, 28, 135, 0.50) !important;
    color: #581c87 !important;
}
.d-resp-group-title.teal {
    background: rgba(19, 78, 74, 0.17) !important;
    border-color: rgba(19, 78, 74, 0.52) !important;
    color: #134e4a !important;
}
.d-resp-group-title.pink {
    background: rgba(131, 24, 67, 0.16) !important;
    border-color: rgba(131, 24, 67, 0.50) !important;
    color: #831843 !important;
}
.d-resp-group-title.dark {
    background: rgba(30, 41, 59, 0.20) !important;
    border-color: rgba(30, 41, 59, 0.55) !important;
    color: #1e293b !important;
}
.d-resp-group-title.gray,
.d-resp-group-title.no-response {
    background: rgba(51, 65, 85, 0.16) !important;
    border-color: rgba(51, 65, 85, 0.50) !important;
    color: #334155 !important;
}

@media (prefers-color-scheme: dark) {
    .d-resp-group-title.success {
        background: rgba(16, 185, 129, 0.24) !important;
        border-color: rgba(16, 185, 129, 0.58) !important;
        color: #d1fae5 !important;
    }
    .d-resp-group-title.danger {
        background: rgba(239, 68, 68, 0.24) !important;
        border-color: rgba(239, 68, 68, 0.58) !important;
        color: #fee2e2 !important;
    }
    .d-resp-group-title.warning {
        background: rgba(245, 158, 11, 0.25) !important;
        border-color: rgba(245, 158, 11, 0.62) !important;
        color: #fef3c7 !important;
    }
    .d-resp-group-title.info {
        background: rgba(59, 130, 246, 0.24) !important;
        border-color: rgba(59, 130, 246, 0.58) !important;
        color: #dbeafe !important;
    }
    .d-resp-group-title.purple {
        background: rgba(168, 85, 247, 0.24) !important;
        border-color: rgba(168, 85, 247, 0.58) !important;
        color: #f3e8ff !important;
    }
    .d-resp-group-title.teal {
        background: rgba(20, 184, 166, 0.24) !important;
        border-color: rgba(20, 184, 166, 0.58) !important;
        color: #ccfbf1 !important;
    }
    .d-resp-group-title.pink {
        background: rgba(236, 72, 153, 0.24) !important;
        border-color: rgba(236, 72, 153, 0.58) !important;
        color: #fce7f3 !important;
    }
    .d-resp-group-title.dark,
    .d-resp-group-title.gray,
    .d-resp-group-title.no-response {
        background: rgba(148, 163, 184, 0.22) !important;
        border-color: rgba(148, 163, 184, 0.54) !important;
        color: #f8fafc !important;
    }
}

/* ============================================================
 * Final state theme override
 * Active response window remains red. Idle and aged-call
 * (non-emergency mode) use #1f2937 / blue-slate chrome.
 * ============================================================ */
body.d-mode-idle,
body.d-mode-aged-call {
    --d-brand: #1f2937;
    --d-brand-2: #475569;
    --d-accent: #1f2937;
    --d-bg-glow: rgba(31, 41, 55, 0.30);
    --d-bg-glow-2: rgba(59, 130, 246, 0.14);
    --d-topbar-bg: linear-gradient(135deg,
        #1f2937 0%,
        #273447 56%,
        #111827 100%);
    --d-call-tint: radial-gradient(1100px 320px at 0% 0%,
        rgba(31, 41, 55, 0.15), transparent 66%);
    --d-standby-tint: radial-gradient(900px 260px at 50% 0%,
        rgba(59, 130, 246, 0.12), transparent 72%);
    --d-tab-active-bg: rgba(31, 41, 55, 0.34);
    --d-tab-active-text: #f8fafc;
}

body.d-mode-idle::before,
body.d-mode-aged-call::before {
    background:
        radial-gradient(ellipse 80% 60% at 80% 0%,
            rgba(31, 41, 55, 0.34) 0%, transparent 55%),
        radial-gradient(ellipse 70% 50% at 0% 100%,
            rgba(59, 130, 246, 0.15) 0%, transparent 55%),
        linear-gradient(180deg,
            var(--d-bg-base) 0%,
            var(--d-bg-mid) 60%,
            var(--d-bg-base) 100%) !important;
}

body.d-mode-idle::after,
body.d-mode-aged-call::after {
    background: radial-gradient(circle at 30% 40%,
        rgba(31, 41, 55, 0.18) 0%,
        transparent 36%) !important;
}

body.d-mode-idle .d-topbar,
body.d-mode-aged-call .d-topbar {
    background: var(--d-topbar-bg) !important;
    box-shadow:
        0 12px 32px rgba(31, 41, 55, 0.30),
        inset 0 1px 0 rgba(255, 255, 255, 0.12) !important;
}

/* Aged-call screen still displays a call, but it is no longer in the
   active responder window, so remove the red emergency header treatment. */
body.d-mode-aged-call .d-call {
    background-image: var(--d-call-tint) !important;
}

body.d-mode-aged-call .d-call-head {
    background: rgba(31, 41, 55, 0.16) !important;
    border-bottom-color: rgba(148, 163, 184, 0.22) !important;
}

body.d-mode-aged-call .badge-newest.is-call {
    background: #1f2937 !important;
    color: #ffffff !important;
    box-shadow: 0 2px 10px rgba(31, 41, 55, 0.32) !important;
}

body.d-mode-idle .d-status,
body.d-mode-aged-call .d-status {
    background: rgba(255, 255, 255, 0.13) !important;
    border-color: rgba(255, 255, 255, 0.22) !important;
    color: #ffffff !important;
}

body.d-mode-idle .d-status .dot,
body.d-mode-aged-call .d-status .dot {
    background: #d1d5db !important;
    animation: none !important;
    box-shadow: 0 0 0 4px rgba(209, 213, 219, 0.16) !important;
}

body.d-mode-idle .d-idle,
body.d-mode-aged-call .d-idle {
    background-image: var(--d-standby-tint) !important;
}

body.d-mode-idle .d-idle-tab.active,
body.d-mode-aged-call .d-idle-tab.active,
body.d-mode-idle .d-idle-meta,
body.d-mode-aged-call .d-idle-meta,
body.d-mode-idle .d-idle-sources span,
body.d-mode-aged-call .d-idle-sources span {
    border-color: rgba(31, 41, 55, 0.34) !important;
}

body.d-mode-idle .d-idle-icon.blue,
body.d-mode-aged-call .d-idle-icon.blue {
    background: rgba(31, 41, 55, 0.20) !important;
    border-color: rgba(31, 41, 55, 0.38) !important;
}

body.d-mode-idle .d-idle-icon.blue .mdi,
body.d-mode-aged-call .d-idle-icon.blue .mdi {
    color: #9ca3af !important;
}

body.d-mode-idle .d-idle-progress-bar,
body.d-mode-aged-call .d-idle-progress-bar {
    background: linear-gradient(90deg, #1f2937, #475569) !important;
    box-shadow: 0 0 8px rgba(31, 41, 55, 0.45) !important;
}

@media (prefers-color-scheme: light) {
    body.d-mode-idle,
    body.d-mode-aged-call,
    body.d-mode-idle::before,
    body.d-mode-aged-call::before,
    body.d-mode-idle .d-shell,
    body.d-mode-aged-call .d-shell,
    body.d-mode-idle .d-main,
    body.d-mode-aged-call .d-main {
        background: #ffffff !important;
    }

    body.d-mode-idle .d-topbar,
    body.d-mode-aged-call .d-topbar {
        background: linear-gradient(135deg, #1f2937 0%, #334155 62%, #111827 100%) !important;
        box-shadow:
            0 1px 0 rgba(15, 23, 42, 0.08),
            inset 0 1px 0 rgba(255, 255, 255, 0.16) !important;
    }

    body.d-mode-aged-call .d-call-head {
        background: rgba(31, 41, 55, 0.08) !important;
        border-bottom-color: rgba(15, 23, 42, 0.12) !important;
    }

    body.d-mode-idle .d-idle-icon.blue,
    body.d-mode-aged-call .d-idle-icon.blue {
        background: rgba(31, 41, 55, 0.10) !important;
        border-color: rgba(31, 41, 55, 0.24) !important;
    }

    body.d-mode-idle .d-idle-icon.blue .mdi,
    body.d-mode-aged-call .d-idle-icon.blue .mdi {
        color: #1f2937 !important;
    }
}

/* ============================================================
 * Final responder lane spacing / divider contrast override
 * - Summary pills stay equal-width across the row.
 * - Add clear breathing room before each next status lane.
 * - Use darker divider bars with high-contrast text.
 * ============================================================ */

.d-main.is-active .d-resp-summary,
.d-resp-summary {
    grid-template-columns: repeat(auto-fit, minmax(10.75rem, 1fr)) !important;
    column-gap: .58rem !important;
    row-gap: .42rem !important;
}

.d-main.is-active .d-resp-pill,
.d-resp-pill {
    min-width: 0 !important;
    text-align: center !important;
}

/* Base lane header sizing. Keep headers compact, but make them read
   like actual section bars instead of thin separator lines. */
.d-main.is-active .d-resp-group-title,
.d-resp-group-title {
    margin: .28rem 0 .42rem !important;
    padding: .24rem .62rem .26rem !important;
    min-height: 1.32rem !important;
    border-radius: .42rem !important;
    border-width: 1px !important;
    font-size: .66rem !important;
    font-weight: 950 !important;
    letter-spacing: .14em !important;
    line-height: 1 !important;
    box-shadow:
        inset 0 1px 0 rgba(255,255,255,.18),
        0 1px 2px rgba(15,23,42,.10) !important;
}

/* Add the requested spacer between one status group’s content and the
   next status divider. The first AVAILABLE divider stays tucked close
   under the summary row. */
.d-main.is-active .d-resp-grid > .d-resp-group-title:not(:first-child),
.d-resp-grid > .d-resp-group-title:not(:first-child) {
    margin-top: 1.05rem !important;
}

.d-main.is-active .d-resp-grid > .d-resp-group-title:first-child,
.d-resp-grid > .d-resp-group-title:first-child {
    margin-top: .18rem !important;
}

/* Dark section bars — readable on light TV displays and still clear
   in dark mode because text is forced to near-white. */
.d-resp-group-title.success {
    background: linear-gradient(180deg, rgba(6, 95, 70, .98), rgba(5, 78, 61, .98)) !important;
    border-color: rgba(16, 185, 129, .64) !important;
    color: #ecfdf5 !important;
}

.d-resp-group-title.danger {
    background: linear-gradient(180deg, rgba(127, 29, 29, .98), rgba(105, 23, 23, .98)) !important;
    border-color: rgba(239, 68, 68, .64) !important;
    color: #fef2f2 !important;
}

.d-resp-group-title.warning {
    background: linear-gradient(180deg, rgba(146, 64, 14, .98), rgba(120, 53, 15, .98)) !important;
    border-color: rgba(245, 158, 11, .68) !important;
    color: #fffbeb !important;
}

.d-resp-group-title.info {
    background: linear-gradient(180deg, rgba(30, 58, 138, .98), rgba(30, 64, 175, .98)) !important;
    border-color: rgba(59, 130, 246, .64) !important;
    color: #eff6ff !important;
}

.d-resp-group-title.purple {
    background: linear-gradient(180deg, rgba(88, 28, 135, .98), rgba(76, 29, 149, .98)) !important;
    border-color: rgba(168, 85, 247, .64) !important;
    color: #faf5ff !important;
}

.d-resp-group-title.teal {
    background: linear-gradient(180deg, rgba(19, 78, 74, .98), rgba(17, 94, 89, .98)) !important;
    border-color: rgba(20, 184, 166, .64) !important;
    color: #f0fdfa !important;
}

.d-resp-group-title.pink {
    background: linear-gradient(180deg, rgba(131, 24, 67, .98), rgba(112, 26, 117, .98)) !important;
    border-color: rgba(236, 72, 153, .64) !important;
    color: #fdf2f8 !important;
}

.d-resp-group-title.dark,
.d-resp-group-title.gray,
.d-resp-group-title.no-response {
    background: linear-gradient(180deg, rgba(31, 41, 55, .98), rgba(15, 23, 42, .98)) !important;
    border-color: rgba(148, 163, 184, .58) !important;
    color: #f8fafc !important;
}

/* On shorter 1080p-style displays, keep the extra spacing but do not
   let it burn too much vertical room. */
@media (max-height: 900px) {
    .d-main.is-active .d-resp-grid > .d-resp-group-title:not(:first-child),
    .d-resp-grid > .d-resp-group-title:not(:first-child) {
        margin-top: .82rem !important;
    }

    .d-main.is-active .d-resp-group-title,
    .d-resp-group-title {
        margin-bottom: .34rem !important;
        min-height: 1.22rem !important;
        padding-top: .2rem !important;
        padding-bottom: .22rem !important;
    }
}


/* ============================================================
 * FINAL OVERRIDE — responder summary alignment + real spacers
 * ============================================================ */

/* Summary count row: equal width, content horizontally and vertically centered. */
.d-main.is-active .d-resp-summary,
.d-resp-summary {
    display: grid !important;
    grid-template-columns: repeat(auto-fit, minmax(10.5rem, 1fr)) !important;
    align-items: center !important;
    justify-items: stretch !important;
    gap: .5rem !important;
    padding: .62rem 1.1rem .58rem !important;
}

.d-main.is-active .d-resp-pill,
.d-resp-pill {
    width: 100% !important;
    min-height: 2.05rem !important;
    display: inline-flex !important;
    align-items: center !important;
    justify-content: center !important;
    text-align: center !important;
    line-height: 1 !important;
    padding: .38rem .55rem !important;
}

.d-main.is-active .d-resp-pill .mdi,
.d-resp-pill .mdi {
    display: inline-flex !important;
    align-items: center !important;
    justify-content: center !important;
    line-height: 1 !important;
}

/* Real grid spacer inserted by dashboard.php between status groups.
   Margin alone was not reliable in the CSS grid, so this forces a full-width row. */
.d-resp-group-spacer {
    grid-column: 1 / -1 !important;
    height: .82rem !important;
    min-height: .82rem !important;
    width: 100% !important;
    display: block !important;
}

/* Keep divider/header bars tight to their own content; the spacer now handles the gap. */
.d-main.is-active .d-resp-group-title,
.d-resp-group-title {
    margin: 0 0 .42rem 0 !important;
    min-height: 1.34rem !important;
    display: flex !important;
    align-items: center !important;
    justify-content: space-between !important;
    padding: .25rem .65rem .27rem !important;
    line-height: 1 !important;
}

/* First status divider under the summary row. */
.d-main.is-active .d-resp-grid > .d-resp-group-title:first-child,
.d-resp-grid > .d-resp-group-title:first-child {
    margin-top: 0 !important;
}

/* Darker divider bars with readable text. */
.d-resp-group-title.success {
    background: linear-gradient(180deg, #047857 0%, #065f46 100%) !important;
    border-color: rgba(16, 185, 129, .78) !important;
    color: #ecfdf5 !important;
}

.d-resp-group-title.danger {
    background: linear-gradient(180deg, #991b1b 0%, #7f1d1d 100%) !important;
    border-color: rgba(248, 113, 113, .78) !important;
    color: #fef2f2 !important;
}

.d-resp-group-title.warning {
    background: linear-gradient(180deg, #a16207 0%, #78350f 100%) !important;
    border-color: rgba(251, 191, 36, .82) !important;
    color: #fffbeb !important;
}

.d-resp-group-title.info {
    background: linear-gradient(180deg, #1d4ed8 0%, #1e3a8a 100%) !important;
    border-color: rgba(96, 165, 250, .78) !important;
    color: #eff6ff !important;
}

.d-resp-group-title.purple {
    background: linear-gradient(180deg, #7e22ce 0%, #581c87 100%) !important;
    border-color: rgba(192, 132, 252, .78) !important;
    color: #faf5ff !important;
}

.d-resp-group-title.teal {
    background: linear-gradient(180deg, #0f766e 0%, #134e4a 100%) !important;
    border-color: rgba(45, 212, 191, .78) !important;
    color: #f0fdfa !important;
}

.d-resp-group-title.pink {
    background: linear-gradient(180deg, #be185d 0%, #831843 100%) !important;
    border-color: rgba(244, 114, 182, .78) !important;
    color: #fdf2f8 !important;
}

.d-resp-group-title.dark,
.d-resp-group-title.gray,
.d-resp-group-title.no-response {
    background: linear-gradient(180deg, #334155 0%, #1f2937 100%) !important;
    border-color: rgba(148, 163, 184, .72) !important;
    color: #f8fafc !important;
}

@media (max-height: 900px) {
    .d-resp-group-spacer {
        height: .68rem !important;
        min-height: .68rem !important;
    }

    .d-main.is-active .d-resp-summary,
    .d-resp-summary {
        padding-top: .52rem !important;
        padding-bottom: .50rem !important;
    }
}

/* ============================================================
 * HARD FIX: responder status group spacing + summary centering
 * Spacer is now inserted AFTER each group, before the next divider.
 * This makes the visual sequence: divider -> content -> blank space -> divider.
 * ============================================================ */

.d-main.is-active .d-resp-summary,
.d-resp-summary {
    display: grid !important;
    grid-template-columns: repeat(auto-fit, minmax(10.75rem, 1fr)) !important;
    align-items: center !important;
    justify-items: stretch !important;
    column-gap: .70rem !important;
    row-gap: .45rem !important;
    padding: .72rem .95rem .70rem !important;
}

.d-main.is-active .d-resp-pill,
.d-resp-pill {
    width: 100% !important;
    height: 2.05rem !important;
    min-height: 2.05rem !important;
    display: flex !important;
    align-items: center !important;
    justify-content: center !important;
    text-align: center !important;
    gap: .42rem !important;
    margin: 0 !important;
    line-height: 1 !important;
}

.d-resp-grid > .d-resp-group-spacer {
    grid-column: 1 / -1 !important;
    height: 1.18rem !important;
    min-height: 1.18rem !important;
    max-height: 1.18rem !important;
    display: block !important;
    width: 100% !important;
    margin: 0 !important;
    padding: 0 !important;
    border: 0 !important;
    background: transparent !important;
    pointer-events: none !important;
}

.d-main.is-active .d-resp-group-title,
.d-resp-group-title {
    margin: 0 0 .42rem 0 !important;
    padding: .28rem .70rem .30rem !important;
    min-height: 1.42rem !important;
    display: flex !important;
    align-items: center !important;
    justify-content: space-between !important;
    line-height: 1 !important;
    font-size: .68rem !important;
    font-weight: 950 !important;
    letter-spacing: .15em !important;
    color: #ffffff !important;
}

.d-resp-group-title.success {
    background: linear-gradient(180deg, #047857 0%, #064e3b 100%) !important;
    border-color: rgba(16, 185, 129, .86) !important;
}

.d-resp-group-title.danger {
    background: linear-gradient(180deg, #991b1b 0%, #7f1d1d 100%) !important;
    border-color: rgba(248, 113, 113, .86) !important;
}

.d-resp-group-title.warning {
    background: linear-gradient(180deg, #92400e 0%, #78350f 100%) !important;
    border-color: rgba(251, 191, 36, .88) !important;
}

.d-resp-group-title.info {
    background: linear-gradient(180deg, #1d4ed8 0%, #1e3a8a 100%) !important;
    border-color: rgba(96, 165, 250, .86) !important;
}

.d-resp-group-title.purple {
    background: linear-gradient(180deg, #7e22ce 0%, #581c87 100%) !important;
    border-color: rgba(192, 132, 252, .86) !important;
}

.d-resp-group-title.teal {
    background: linear-gradient(180deg, #0f766e 0%, #134e4a 100%) !important;
    border-color: rgba(45, 212, 191, .86) !important;
}

.d-resp-group-title.pink {
    background: linear-gradient(180deg, #be185d 0%, #831843 100%) !important;
    border-color: rgba(244, 114, 182, .86) !important;
}

.d-resp-group-title.dark,
.d-resp-group-title.gray,
.d-resp-group-title.no-response {
    background: linear-gradient(180deg, #334155 0%, #1f2937 100%) !important;
    border-color: rgba(148, 163, 184, .78) !important;
}

@media (max-height: 900px) {
    .d-resp-grid > .d-resp-group-spacer {
        height: .95rem !important;
        min-height: .95rem !important;
        max-height: .95rem !important;
    }
}


/* ============================================================
 * Station Board aged-call / idle layout
 * Turns the right-side filler card into a useful station board.
 * ========================================================= */
.d-idle-head {
    justify-content: space-between;
    text-align: left;
}

.d-idle-title-wrap {
    margin: 0;
}

.d-idle-title-wrap .title {
    text-align: left;
}

.d-station-board {
    flex: 1;
    min-height: 0;
    display: grid;
    grid-template-rows: minmax(0, 1fr) auto;
    gap: 1rem;
    padding: 1.15rem 1.2rem 1rem;
}

.d-station-board .d-idle-feed {
    padding: 0;
}

.d-board-feature {
    align-items: flex-start;
    border-radius: calc(var(--d-radius) - .25rem);
    background: linear-gradient(180deg, rgba(255,255,255,.055), rgba(255,255,255,.015));
    border: 1px solid var(--d-border);
    padding: 1.2rem !important;
}

.d-board-feature .d-idle-icon {
    width: 4.25rem;
    height: 4.25rem;
    border-radius: 1rem;
}

.d-board-feature .d-idle-icon .mdi {
    font-size: 2.25rem;
}

.d-board-feature .d-idle-feed-title {
    font-size: clamp(1.65rem, 2vw, 2.35rem) !important;
    line-height: 1.12 !important;
    -webkit-line-clamp: 3 !important;
}

.d-board-feature .d-idle-feed-detail {
    font-size: clamp(1.05rem, 1.25vw, 1.35rem) !important;
    line-height: 1.35 !important;
    -webkit-line-clamp: 5 !important;
    max-width: 70rem;
}

.d-board-panels {
    display: grid;
    grid-template-columns: repeat(3, minmax(0, 1fr));
    gap: .8rem;
}

.d-board-panel {
    min-width: 0;
    border-radius: .95rem;
    border: 1px solid var(--d-border);
    background: rgba(255,255,255,.045);
    padding: .85rem .95rem;
    display: flex;
    flex-direction: column;
    justify-content: center;
    gap: .32rem;
}

.d-board-panel .panel-label {
    display: flex;
    align-items: center;
    gap: .38rem;
    color: var(--d-text-3);
    font-size: .68rem;
    font-weight: 900;
    letter-spacing: .11em;
    text-transform: uppercase;
}

.d-board-panel .panel-label .mdi {
    font-size: 1rem;
    color: var(--d-info);
}

.d-board-panel .panel-value {
    min-width: 0;
    color: var(--d-text);
    font-size: clamp(1rem, 1.1vw, 1.25rem);
    font-weight: 900;
    line-height: 1.15;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.d-board-panel .panel-sub {
    min-width: 0;
    color: var(--d-text-2);
    font-size: clamp(.78rem, .82vw, .95rem);
    line-height: 1.25;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.d-idle-foot {
    padding: 0 .95rem .75rem !important;
    border-top: 0;
    background: transparent;
}

.d-idle-foot .d-idle-progress {
    width: 100%;
}

@media (prefers-color-scheme: light) {
    .d-board-feature,
    .d-board-panel {
        background: rgba(248,250,252,.72);
        border-color: rgba(15,23,42,.11);
    }
}

@media (max-width: 1200px) {
    .d-board-panels {
        grid-template-columns: 1fr;
    }
}


/* ============================================================
 * Station Board v2 — larger useful lower card and left alignment
 * ============================================================ */
.d-idle,
.d-idle * {
    text-align: left;
}

.d-idle-head {
    align-items: flex-start !important;
    justify-content: flex-start !important;
    text-align: left !important;
}

.d-idle-title-wrap,
.d-idle-title-wrap .title,
.d-idle-title-wrap .kicker,
.kicker {
    text-align: left !important;
}

.d-station-board {
    grid-template-rows: minmax(0, 1.15fr) auto;
    gap: 1rem;
}

.d-board-feature {
    align-items: flex-start !important;
    justify-content: flex-start !important;
    text-align: left !important;
    min-height: 0;
}

.d-board-feature .d-idle-content {
    align-items: flex-start !important;
    justify-content: flex-start !important;
    text-align: left !important;
}

.d-board-feature .d-idle-category,
.d-board-feature .d-idle-feed-title,
.d-board-feature .d-idle-feed-detail,
.d-board-feature .d-idle-sources {
    text-align: left !important;
    margin-left: 0 !important;
    margin-right: auto !important;
}

.d-board-feature .d-idle-feed-title {
    max-width: 68rem;
}

.d-board-feature .d-idle-feed-detail {
    max-width: 78rem;
}

.d-board-panels {
    grid-template-columns: 1fr !important;
}

.d-board-last-call {
    min-height: 10rem;
    padding: 1rem 1.1rem 1.1rem !important;
    gap: .85rem;
}

.d-board-last-call .panel-topline {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: 1rem;
    min-width: 0;
}

.d-board-last-call .panel-value {
    white-space: normal !important;
    overflow: visible !important;
    text-overflow: clip !important;
    font-size: clamp(1.15rem, 1.3vw, 1.55rem) !important;
    line-height: 1.12 !important;
}

.d-board-last-call .panel-sub {
    white-space: normal !important;
    overflow: visible !important;
    text-overflow: clip !important;
}

.panel-call-age {
    flex-shrink: 0;
    padding: .35rem .7rem;
    border-radius: 999px;
    background: rgba(31, 41, 55, .12);
    border: 1px solid rgba(31, 41, 55, .18);
    color: var(--d-text-2);
    font-size: .82rem;
    font-weight: 900;
    letter-spacing: .03em;
    white-space: nowrap;
}

.d-board-response-counts {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(10.5rem, 1fr));
    gap: .55rem;
    width: 100%;
}

.d-board-count-pill {
    min-width: 0;
    min-height: 2.65rem;
    display: flex;
    align-items: center;
    justify-content: center;
    gap: .45rem;
    padding: .55rem .75rem;
    border-radius: 999px;
    background: var(--d-cell-info);
    border: 1px solid rgba(59, 130, 246, .28);
    color: var(--d-pill-info-text);
    font-size: .84rem;
    font-weight: 900;
    letter-spacing: .04em;
    text-transform: uppercase;
    font-variant-numeric: tabular-nums;
}

.d-board-count-pill .mdi {
    font-size: 1rem;
    line-height: 1;
    flex-shrink: 0;
}

.d-board-count-pill .count-label {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.d-board-count-pill strong {
    font-size: 1rem;
    line-height: 1;
}

.d-board-count-pill.success {
    background: var(--d-cell-success);
    border-color: rgba(16, 185, 129, .36);
    color: var(--d-pill-success-text);
}
.d-board-count-pill.danger {
    background: var(--d-cell-danger);
    border-color: rgba(239, 68, 68, .36);
    color: var(--d-pill-danger-text);
}
.d-board-count-pill.warning {
    background: var(--d-cell-warning);
    border-color: rgba(245, 158, 11, .40);
    color: var(--d-pill-warning-text);
}
.d-board-count-pill.info {
    background: var(--d-cell-info);
    border-color: rgba(59, 130, 246, .36);
    color: var(--d-pill-info-text);
}
.d-board-count-pill.purple {
    background: var(--d-cell-purple);
    border-color: rgba(168, 85, 247, .36);
    color: var(--d-pill-purple-text);
}
.d-board-count-pill.teal {
    background: var(--d-cell-teal);
    border-color: rgba(20, 184, 166, .36);
    color: var(--d-pill-teal-text);
}
.d-board-count-pill.pink {
    background: var(--d-cell-pink);
    border-color: rgba(236, 72, 153, .36);
    color: var(--d-pill-pink-text);
}
.d-board-count-pill.dark {
    background: var(--d-cell-dark);
    border-color: rgba(71, 85, 105, .44);
    color: var(--d-pill-dark-text);
}
.d-board-count-pill.gray,
.d-board-count-pill.no-response {
    background: rgba(148, 163, 184, .18);
    border-color: rgba(100, 116, 139, .34);
    color: var(--d-pill-gray-text);
}

@media (prefers-color-scheme: light) {
    .panel-call-age {
        background: rgba(31, 41, 55, .08);
        border-color: rgba(31, 41, 55, .15);
    }
    .d-board-count-pill.no-response {
        color: #334155;
    }
}

/* ============================================================
   Station board response-count card — vertical count rows
   Gives the Last Call card more height and places each response
   type on its own full-width line so labels like NOT RESPONDED
   do not truncate.
   ============================================================ */

.d-station-board {
    grid-template-rows: minmax(0, 1fr) auto !important;
    gap: 1.1rem !important;
}

.d-board-last-call {
    min-height: 14rem !important;
    padding: 1.15rem 1.25rem 1.25rem !important;
    gap: 1rem !important;
}

.d-board-last-call .panel-topline {
    padding-bottom: .75rem;
    border-bottom: 1px solid rgba(148, 163, 184, .22);
}

.d-board-response-counts {
    display: grid !important;
    grid-template-columns: 1fr !important;
    gap: .55rem !important;
    width: 100%;
}

.d-board-count-pill {
    width: 100%;
    min-height: 2.75rem !important;
    border-radius: .8rem !important;
    justify-content: space-between !important;
    padding: .58rem .85rem !important;
    gap: .65rem !important;
    font-size: .86rem !important;
    letter-spacing: .055em !important;
}

.d-board-count-pill .mdi {
    font-size: 1.05rem !important;
}

.d-board-count-pill .count-label {
    flex: 1;
    min-width: 0;
    overflow: visible !important;
    text-overflow: clip !important;
    white-space: nowrap !important;
}

.d-board-count-pill strong {
    min-width: 2.25rem;
    text-align: right;
    font-size: 1.12rem !important;
    font-weight: 950;
}

/* Use the available height better on large TV-style displays. */
@media (min-width: 1400px) and (min-height: 800px) {
    .d-board-last-call {
        min-height: 15.25rem !important;
    }

    .d-board-count-pill {
        min-height: 3rem !important;
        font-size: .9rem !important;
    }
}

/* ============================================================
 * Station Board header alignment fix
 * Vertically centers the Training & Safety title block inside
 * the card header while keeping all text left-aligned.
 * ============================================================ */
.d-idle-head {
    display: flex !important;
    flex-direction: row !important;
    align-items: center !important;
    justify-content: flex-start !important;
    min-height: var(--d-card-head-height) !important;
    padding-top: 0 !important;
    padding-bottom: 0 !important;
    text-align: left !important;
}

.d-idle-title-wrap {
    display: flex !important;
    flex-direction: column !important;
    justify-content: center !important;
    align-self: stretch !important;
    min-height: var(--d-card-head-height) !important;
    margin: 0 !important;
    text-align: left !important;
}

.d-idle-title-wrap .kicker,
.d-idle-title-wrap .title,
.kicker {
    margin-left: 0 !important;
    margin-right: 0 !important;
    text-align: left !important;
}

.d-idle-title-wrap .kicker,
.kicker {
    margin-top: 0 !important;
    margin-bottom: .22rem !important;
    line-height: 1 !important;
}

.d-idle-title-wrap .title {
    margin: 0 !important;
    line-height: 1.12 !important;
}


/* ============================================================
   Idle footer/progress removed
   The station board has enough useful content without the
   rotating-message progress bar. Keep this hidden even if an
   older PHP template still outputs the element.
   ============================================================ */
.d-idle-foot,
.d-idle-progress,
.d-idle-progress-bar {
    display: none !important;
}

.d-idle {
    padding-bottom: 0;
}

/* ============================================================
   FINAL CAPACITY PASS — active responder board
   - Removes the oversized blank space between status groups.
   - Keeps a small, readable break before the next divider.
   - Tightens high/ultra density so 40 responders can fit on
     1080p/4K wall displays without scrolling.
   ============================================================ */

/* Less vertical waste between AVAILABLE / UNAVAILABLE / SCENE sections. */
.d-main.is-active .d-resp-grid > .d-resp-group-spacer,
.d-resp-grid > .d-resp-group-spacer {
    grid-column: 1 / -1 !important;
    height: .42rem !important;
    min-height: .42rem !important;
    max-height: .42rem !important;
    display: block !important;
    width: 100% !important;
    margin: 0 !important;
    padding: 0 !important;
    border: 0 !important;
    background: transparent !important;
}

/* Keep dividers tight to their own section. The spacer above now handles separation. */
.d-main.is-active .d-resp-group-title,
.d-resp-group-title {
    margin: 0 0 .24rem 0 !important;
    min-height: 1.26rem !important;
    padding: .20rem .62rem .22rem !important;
    font-size: .64rem !important;
    line-height: 1 !important;
}

/* Summary row: centered, but not oversized. */
.d-main.is-active .d-resp-summary,
.d-resp-summary {
    padding: .58rem .95rem .50rem !important;
    gap: .52rem !important;
    align-items: center !important;
}

.d-main.is-active .d-resp-pill,
.d-resp-pill {
    height: 1.88rem !important;
    min-height: 1.88rem !important;
    padding: .30rem .52rem !important;
    align-items: center !important;
    justify-content: center !important;
}

/* Default active grid uses more columns and less vertical height. */
.d-main.is-active .d-resp-grid {
    padding: .55rem .95rem .85rem !important;
    gap: .38rem !important;
    grid-template-columns: repeat(auto-fill, minmax(11.35rem, 1fr)) !important;
    align-content: start !important;
    overflow: hidden !important;
}

/* High density: used around the current 20s responder count. */
.d-main.is-active .d-resp-grid[data-density="high"] {
    gap: .32rem !important;
    grid-template-columns: repeat(auto-fill, minmax(10.65rem, 1fr)) !important;
}

.d-main.is-active .d-resp-grid[data-density="high"] .d-resp-cell {
    min-height: 2.52rem !important;
    padding: .38rem .52rem !important;
    gap: .40rem !important;
}

.d-main.is-active .d-resp-grid[data-density="high"] .cell-ff {
    font-size: .74rem !important;
}

.d-main.is-active .d-resp-grid[data-density="high"] .cell-name {
    font-size: .68rem !important;
    line-height: 1.08 !important;
    max-height: 2.15em !important;
}

.d-main.is-active .d-resp-grid[data-density="high"] .cell-eta {
    font-size: .66rem !important;
    padding: .15rem .40rem .17rem !important;
}

/* Ultra density: 25+ responders. Built to keep roughly 40 responders visible. */
.d-main.is-active .d-resp-grid[data-density="ultra"] {
    gap: .26rem !important;
    grid-template-columns: repeat(auto-fill, minmax(9.75rem, 1fr)) !important;
}

.d-main.is-active .d-resp-grid[data-density="ultra"] .d-resp-cell {
    min-height: 2.12rem !important;
    padding: .28rem .42rem !important;
    gap: .32rem !important;
    border-radius: .55rem !important;
}

.d-main.is-active .d-resp-grid[data-density="ultra"] .cell-icon {
    font-size: .88rem !important;
}

.d-main.is-active .d-resp-grid[data-density="ultra"] .cell-ff {
    font-size: .66rem !important;
    line-height: 1.05 !important;
}

.d-main.is-active .d-resp-grid[data-density="ultra"] .cell-name {
    font-size: .60rem !important;
    line-height: 1.05 !important;
    max-height: 2.1em !important;
}

.d-main.is-active .d-resp-grid[data-density="ultra"] .cell-eta {
    font-size: .56rem !important;
    padding: .08rem .28rem .10rem !important;
}

.d-main.is-active .d-resp-grid[data-density="ultra"] .d-resp-group-title {
    min-height: 1.08rem !important;
    padding: .16rem .50rem .18rem !important;
    font-size: .56rem !important;
    margin-bottom: .20rem !important;
}

.d-main.is-active .d-resp-grid[data-density="ultra"] > .d-resp-group-spacer {
    height: .30rem !important;
    min-height: .30rem !important;
    max-height: .30rem !important;
}

/* Shorter TV/browser heights need the compact settings earlier. */
@media (max-height: 900px) {
    .d-main.is-active .d-resp-grid > .d-resp-group-spacer,
    .d-resp-grid > .d-resp-group-spacer {
        height: .34rem !important;
        min-height: .34rem !important;
        max-height: .34rem !important;
    }

    .d-main.is-active .d-resp-grid {
        padding-top: .48rem !important;
        padding-bottom: .72rem !important;
        gap: .30rem !important;
    }

    .d-main.is-active .d-resp-grid[data-density="high"] {
        grid-template-columns: repeat(auto-fill, minmax(10.25rem, 1fr)) !important;
        gap: .26rem !important;
    }

    .d-main.is-active .d-resp-grid[data-density="high"] .d-resp-cell {
        min-height: 2.34rem !important;
        padding: .32rem .46rem !important;
    }

    .d-main.is-active .d-resp-grid[data-density="ultra"] {
        grid-template-columns: repeat(auto-fill, minmax(9.35rem, 1fr)) !important;
        gap: .22rem !important;
    }

    .d-main.is-active .d-resp-grid[data-density="ultra"] .d-resp-cell {
        min-height: 1.98rem !important;
        padding: .24rem .38rem !important;
    }
}

/* ============================================================
   Dynamic responder fit
   Start with the comfortable card sizing, then dashboard.php
   measures the real rendered height and steps through these
   densities only when the responder area would overflow.
   ============================================================ */
.d-main.is-active .d-resp-grid {
    --resp-cell-min: 15.5rem;
    grid-template-columns: repeat(auto-fill, minmax(var(--resp-cell-min), 1fr)) !important;
    gap: .42rem .55rem !important;
    padding: .72rem 1rem .9rem !important;
    align-content: start !important;
    overflow: hidden !important;
}

.d-main.is-active .d-resp-grid[data-density="low"] {
    --resp-cell-min: 15.5rem;
}

.d-main.is-active .d-resp-grid[data-density="medium"] {
    --resp-cell-min: 13.75rem;
    gap: .36rem .48rem !important;
}

.d-main.is-active .d-resp-grid[data-density="high"] {
    --resp-cell-min: 12rem;
    gap: .32rem .42rem !important;
}

.d-main.is-active .d-resp-grid[data-density="ultra"] {
    --resp-cell-min: 10.75rem;
    gap: .26rem .34rem !important;
}

.d-main.is-active .d-resp-grid[data-density="micro"] {
    --resp-cell-min: 9.25rem;
    gap: .22rem .28rem !important;
}

/* Comfortable default. */
.d-main.is-active .d-resp-grid[data-density="low"] .d-resp-cell {
    min-height: 3.25rem !important;
    padding: .48rem .65rem !important;
    gap: .5rem !important;
}
.d-main.is-active .d-resp-grid[data-density="low"] .cell-icon { font-size: 1.15rem !important; }
.d-main.is-active .d-resp-grid[data-density="low"] .cell-ff { font-size: .86rem !important; }
.d-main.is-active .d-resp-grid[data-density="low"] .cell-name { font-size: .74rem !important; line-height: 1.05 !important; }
.d-main.is-active .d-resp-grid[data-density="low"] .cell-eta { font-size: .72rem !important; padding: .16rem .45rem !important; }

/* Step 1: keep names, only tighten width/spacing. */
.d-main.is-active .d-resp-grid[data-density="medium"] .d-resp-cell {
    min-height: 3rem !important;
    padding: .42rem .56rem !important;
    gap: .44rem !important;
}
.d-main.is-active .d-resp-grid[data-density="medium"] .cell-icon { font-size: 1.08rem !important; }
.d-main.is-active .d-resp-grid[data-density="medium"] .cell-ff { font-size: .82rem !important; }
.d-main.is-active .d-resp-grid[data-density="medium"] .cell-name { font-size: .70rem !important; line-height: 1.04 !important; }
.d-main.is-active .d-resp-grid[data-density="medium"] .cell-eta { font-size: .68rem !important; padding: .14rem .40rem !important; }

/* Step 2: still readable on a TV, but more rows/columns fit. */
.d-main.is-active .d-resp-grid[data-density="high"] .d-resp-cell {
    min-height: 2.72rem !important;
    padding: .36rem .48rem !important;
    gap: .38rem !important;
}
.d-main.is-active .d-resp-grid[data-density="high"] .cell-icon { font-size: 1rem !important; }
.d-main.is-active .d-resp-grid[data-density="high"] .cell-ff { font-size: .78rem !important; }
.d-main.is-active .d-resp-grid[data-density="high"] .cell-name { font-size: .66rem !important; line-height: 1.02 !important; }
.d-main.is-active .d-resp-grid[data-density="high"] .cell-eta { font-size: .64rem !important; padding: .12rem .35rem !important; }

/* Step 3: only used when the grid is running out of height. */
.d-main.is-active .d-resp-grid[data-density="ultra"] .d-resp-cell {
    min-height: 2.35rem !important;
    padding: .30rem .40rem !important;
    gap: .30rem !important;
}
.d-main.is-active .d-resp-grid[data-density="ultra"] .cell-icon { font-size: .92rem !important; }
.d-main.is-active .d-resp-grid[data-density="ultra"] .cell-ff { font-size: .72rem !important; }
.d-main.is-active .d-resp-grid[data-density="ultra"] .cell-name { font-size: .60rem !important; line-height: 1 !important; }
.d-main.is-active .d-resp-grid[data-density="ultra"] .cell-eta { font-size: .58rem !important; padding: .10rem .30rem !important; }

/* Last resort for very large response counts. This keeps the numbers visible
   without forcing scrolling. Full names remain available in each cell title. */
.d-main.is-active .d-resp-grid[data-density="micro"] .d-resp-cell,
.d-main.is-active .d-resp-grid.is-at-min-density .d-resp-cell {
    min-height: 2.05rem !important;
    padding: .24rem .34rem !important;
    gap: .24rem !important;
}
.d-main.is-active .d-resp-grid[data-density="micro"] .cell-icon,
.d-main.is-active .d-resp-grid.is-at-min-density .cell-icon { font-size: .82rem !important; }
.d-main.is-active .d-resp-grid[data-density="micro"] .cell-ff,
.d-main.is-active .d-resp-grid.is-at-min-density .cell-ff { font-size: .68rem !important; }
.d-main.is-active .d-resp-grid[data-density="micro"] .cell-name,
.d-main.is-active .d-resp-grid.is-at-min-density .cell-name { display: none !important; }
.d-main.is-active .d-resp-grid[data-density="micro"] .cell-eta,
.d-main.is-active .d-resp-grid.is-at-min-density .cell-eta { font-size: .54rem !important; padding: .08rem .25rem !important; }

/* Group spacing: small, deliberate space. The JS spacer is still present, but
   it should never create a huge empty band. */
.d-main.is-active .d-resp-grid > .d-resp-group-spacer,
.d-resp-grid > .d-resp-group-spacer {
    grid-column: 1 / -1 !important;
    height: .48rem !important;
    min-height: .48rem !important;
    margin: 0 !important;
    padding: 0 !important;
}
.d-main.is-active .d-resp-grid[data-density="high"] > .d-resp-group-spacer,
.d-main.is-active .d-resp-grid[data-density="ultra"] > .d-resp-group-spacer,
.d-main.is-active .d-resp-grid[data-density="micro"] > .d-resp-group-spacer {
    height: .28rem !important;
    min-height: .28rem !important;
}

.d-main.is-active .d-resp-group-title {
    min-height: 1.32rem !important;
    height: 1.32rem !important;
    margin: .05rem 0 .12rem !important;
    padding: .12rem .55rem !important;
    align-items: center !important;
}
.d-main.is-active .d-resp-grid[data-density="ultra"] .d-resp-group-title,
.d-main.is-active .d-resp-grid[data-density="micro"] .d-resp-group-title {
    min-height: 1.12rem !important;
    height: 1.12rem !important;
    font-size: .56rem !important;
    padding: .08rem .42rem !important;
}



/* ==========================================================================
   Source: assets/css/accounts-admin.css
   ========================================================================== */

:root {
    --fn-brand:        #313a46;
    --fn-brand-soft:   rgba(49, 58, 70, .10);
    --fn-accent:       #B03A2E;
    --fn-accent-soft:  rgba(176, 58, 46, .10);
    --fn-header-bg:    var(--fn-brand);
    --fn-safe-top:     max(env(safe-area-inset-top, 0px), 2.75rem);
    --fn-safe-bottom:  max(env(safe-area-inset-bottom, 0px), .5rem);
}

:root,
[data-bs-theme="light"] {
    --fn-body-bg:        #FFFFFF;
    --fn-card-bg:        #F5F5F7;
    --fn-card-border:    #E3E5E9;
    --fn-text:           #1F2328;
    --fn-text-muted:     #6B7280;
    --fn-tertiary-bg:    #EEF0F3;
    --fn-shadow:         rgba(0,0,0,.06);
}
[data-bs-theme="dark"] {
    --fn-body-bg:        #1a1d21;
    --fn-card-bg:        #23272C;
    --fn-card-border:    #2E343B;
    --fn-text:           #E6E8EB;
    --fn-text-muted:     #9099A4;
    --fn-tertiary-bg:    #2A2F35;
    --fn-shadow:         rgba(0,0,0,.3);
}

* { -webkit-tap-highlight-color: transparent; }

html, body {
    margin: 0;
    background: var(--fn-body-bg);
    color: var(--fn-text);
    font-family: system-ui, -apple-system, 'Segoe UI', Roboto, sans-serif;
    -webkit-font-smoothing: antialiased;
}

body {
        padding-bottom: calc(var(--fn-safe-bottom) + 1rem);
    }
    

/* Admin top bar — title only, no back button inside it */
.fn-admin-bar {
    position: fixed;
    top: 0; left: 0; right: 0;
    z-index: 50;
    background: var(--fn-header-bg);
    color: #fff;
    padding-top: var(--fn-safe-top);
    box-shadow: 0 2px 8px rgba(0,0,0,.10);
}
.fn-admin-bar-inner {
    display: flex;
    align-items: center;
    padding: .55rem .85rem;
    min-height: 3.4rem;
    box-sizing: border-box;
}
.fn-admin-title {
    font-weight: 800;
    font-size: 1.05rem;
    line-height: 1;
    color: #fff;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

/* Back link — lives on the page content, top-left, quiet text */
.fn-page-back-link {
    display: inline-flex;
    align-items: center;
    gap: .15rem;
    color: var(--fn-text-muted);
    background: transparent;
    border: 0;
    padding: .35rem .25rem;
    margin: 0 0 .65rem -.25rem;
    font-weight: 700;
    font-size: .9rem;
    text-decoration: none;
    cursor: pointer;
    line-height: 1;
}
.fn-page-back-link:hover, .fn-page-back-link:active {
    color: var(--fn-text);
}
.fn-page-back-link .mdi {
    font-size: 1.2rem;
}

.fn-admin-container {
    max-width: 720px;
    margin: 0 auto;
    padding: .85rem 1rem 1rem;
}

@media (hover: hover) and (pointer: fine) {
        .fn-admin-container {
            max-width: calc(100% - 2rem);
            width: calc(100% - 2rem);
            padding: 1rem 1.25rem 1.5rem;
        }
    }

/* Page-specific styles below */

.fn-msg {
    position: relative;
    padding: .65rem 2.5rem .65rem .85rem;
    border-radius: .55rem;
    margin-bottom: .75rem;
    font-size: .88rem;
    font-weight: 600;
}
.fn-msg.success { background: rgba(25,135,84,.12);  color: #0f5132; border: 1px solid rgba(25,135,84,.4); }
.fn-msg.danger  { background: rgba(220,53,69,.12);  color: #842029; border: 1px solid rgba(220,53,69,.4); }
.fn-msg.info    { background: rgba(13,110,253,.10); color: #084298; border: 1px solid rgba(13,110,253,.3); }

.fn-msg-close {
    position: absolute;
    top: 50%;
    right: .4rem;
    transform: translateY(-50%);
    background: transparent;
    border: 0;
    color: currentColor;
    opacity: .55;
    width: 1.8rem; height: 1.8rem;
    border-radius: 50%;
    display: inline-flex;
    align-items: center; justify-content: center;
    cursor: pointer;
    padding: 0;
    transition: opacity .12s, background .12s, transform .08s;
}
.fn-msg-close:hover  { opacity: 1; background: rgba(0,0,0,.08); }
.fn-msg-close:active { transform: translateY(-50%) scale(.9); }
.fn-msg-close .mdi { font-size: 1.1rem; line-height: 1; }
[data-bs-theme="dark"] .fn-msg-close:hover { background: rgba(255,255,255,.08); }

[data-bs-theme="dark"] .fn-msg.success { color: #75d8a6; }
[data-bs-theme="dark"] .fn-msg.danger  { color: #ea868f; }
[data-bs-theme="dark"] .fn-msg.info    { color: #6ea8fe; }

.fn-code-reveal {
    background: var(--fn-accent);
    color: #fff;
    padding: 1rem 1.25rem;
    border-radius: .8rem;
    margin-bottom: .85rem;
    text-align: center;
    box-shadow: 0 4px 14px rgba(176,58,46,.25);
}
.fn-code-reveal .label {
    font-size: .72rem; font-weight: 700; text-transform: uppercase;
    letter-spacing: .05em; opacity: .8;
}
.fn-code-reveal .code {
    font-family: 'SF Mono','Monaco','Menlo','Consolas',monospace;
    font-size: 2rem; font-weight: 800; letter-spacing: .25em;
    margin: .3rem 0 .15rem;
}
.fn-code-reveal .who { font-size: .85rem; opacity: .9; }
.fn-code-reveal .copy-btn {
    margin-top: .55rem; background: rgba(255,255,255,.18);
    color: #fff; border: 0; border-radius: 999px;
    padding: .35rem .85rem; font-weight: 700; font-size: .8rem; cursor: pointer;
}
.fn-code-reveal .note {
    font-size: .72rem; margin-top: .5rem; opacity: .85; line-height: 1.4;
}

.fn-add-form {
    background: var(--fn-card-bg);
    border: 1px solid var(--fn-card-border);
    border-radius: .8rem;
    padding: .85rem 1rem;
    margin-bottom: 1rem;
}
.fn-add-form summary {
    cursor: pointer; font-weight: 700; color: var(--fn-text);
    list-style: none; display: flex; align-items: center; gap: .35rem;
}
.fn-add-form summary::after { content: '＋'; margin-left: auto; font-size: 1.2rem; }
.fn-add-form[open] summary::after { content: '×'; }
.fn-add-form .role-row { margin-top: .85rem; }
.fn-add-form .form-grid {
    display: grid; grid-template-columns: 1fr 1fr; gap: .5rem; margin-top: .5rem;
}
.fn-add-form .form-grid .full { grid-column: 1 / -1; }
.fn-add-form input, .fn-add-form select {
    width: 100%; padding: .5rem .65rem; border-radius: .5rem;
    border: 1px solid var(--fn-card-border);
    background: var(--fn-body-bg); color: var(--fn-text);
    font-size: .9rem;
}
.fn-add-form button {
    background: var(--fn-brand); color: #fff; border: 0;
    border-radius: .5rem; padding: .55rem 1rem;
    font-weight: 700; cursor: pointer; margin-top: .5rem;
}
.fn-add-form .role-help {
    font-size: .72rem; color: var(--fn-text-muted);
    margin-top: .4rem; line-height: 1.4;
    padding: .5rem .65rem; background: var(--fn-tertiary-bg);
    border-radius: .4rem;
}
.fn-add-form .role-help strong { color: var(--fn-text); }
.fn-add-form .station-help {
    font-size: .72rem; color: var(--fn-text-muted);
    margin-top: .25rem; line-height: 1.4;
}
.fn-add-form .station-help a {
    color: var(--fn-brand); font-weight: 700; text-decoration: underline;
}

.fn-add-form[data-role="Dashboard"] .fields-firefighter { display: none; }

/* ── Search box (above the user list) ───────────────────────── */
.fn-search {
    position: relative;
    margin-bottom: .75rem;
}
.fn-search input {
    width: 100%;
    box-sizing: border-box;
    padding: .65rem .75rem .65rem 2.25rem;
    border-radius: .55rem;
    border: 1px solid var(--fn-card-border);
    background: var(--fn-card-bg);
    color: var(--fn-text);
    font-size: .95rem;
    font-family: inherit;
}
.fn-search input:focus {
    outline: none;
    border-color: var(--fn-brand);
    background: var(--fn-body-bg);
}
.fn-search .mdi-magnify {
    position: absolute;
    left: .65rem;
    top: 50%;
    transform: translateY(-50%);
    color: var(--fn-text-muted);
    font-size: 1.15rem;
    pointer-events: none;
}
.fn-search-clear {
    position: absolute;
    right: .35rem;
    top: 50%;
    transform: translateY(-50%);
    background: var(--fn-tertiary-bg);
    border: 0;
    width: 1.7rem; height: 1.7rem;
    border-radius: 50%;
    color: var(--fn-text-muted);
    display: none;
    align-items: center; justify-content: center;
    cursor: pointer;
    padding: 0;
}
.fn-search-clear.is-visible { display: inline-flex; }
.fn-search-clear .mdi { font-size: 1rem; line-height: 1; }

.fn-empty-state {
    text-align: center;
    padding: 1.5rem;
    color: var(--fn-text-muted);
    font-size: .9rem;
}

/* ── User list rows (two-line layout) ───────────────────────── */
/* Line 1: full-width name with FF# / station inline as muted suffix.
   Line 2: role badge on the left, action controls (Code btn + role
   dropdown) pushed to the right with margin-left:auto. */
.fn-user-row {
    background: var(--fn-card-bg);
    border: 1px solid var(--fn-card-border);
    border-radius: .65rem;
    padding: .7rem .85rem;
    margin-bottom: .4rem;
    display: flex; flex-direction: column; gap: .5rem;
}
.fn-user-row.disabled { opacity: .55; }

.fn-user-line-1 {
    line-height: 1.3;
    word-break: break-word;
}
.fn-user-name {
    font-weight: 700;
    font-size: .95rem;
    color: var(--fn-text);
}
.fn-user-meta-inline {
    font-size: .8rem;
    color: var(--fn-text-muted);
    font-weight: 500;
}

.fn-user-line-2 {
    display: flex;
    align-items: center;
    gap: .4rem;
}
.fn-user-line-2 .fn-user-actions { margin-left: auto; }

.fn-user-actions { display: flex; gap: .35rem; align-items: center; }
.fn-user-actions form { margin: 0; }
.fn-user-actions button {
    background: var(--fn-tertiary-bg);
    border: 1px solid var(--fn-card-border);
    border-radius: .4rem;
    padding: .35rem .55rem;
    font-size: .75rem; font-weight: 700;
    color: var(--fn-text); cursor: pointer;
    display: inline-flex; align-items: center; gap: .25rem;
}
.fn-user-actions button:hover { border-color: var(--fn-brand); }
.fn-user-actions select {
    border: 1px solid var(--fn-card-border);
    border-radius: .4rem; padding: .3rem .4rem;
    font-size: .75rem;
    background: var(--fn-body-bg); color: var(--fn-text);
    font-weight: 700;
}

.fn-role-pill {
    font-size: .65rem; font-weight: 800;
    text-transform: uppercase; letter-spacing: .05em;
    padding: .15rem .45rem;
    border-radius: 999px;
    color: #fff;
    display: inline-block;
}
.fn-role-pill.Admin     { background: var(--fn-accent); }
.fn-role-pill.User      { background: #6c757d; }
.fn-role-pill.Disabled  { background: #343a40; }
.fn-role-pill.Dashboard { background: #0d6efd; }



/* ==========================================================================
   Source: assets/css/responses-config.css
   ========================================================================== */

:root {
    --fn-brand:        #313a46;
    --fn-brand-soft:   rgba(49, 58, 70, .10);
    --fn-accent:       #B03A2E;
    --fn-accent-soft:  rgba(176, 58, 46, .10);
    --fn-header-bg:    var(--fn-brand);
    --fn-safe-top:     max(env(safe-area-inset-top, 0px), 2.75rem);
    --fn-safe-bottom:  max(env(safe-area-inset-bottom, 0px), .5rem);
}

:root,
[data-bs-theme="light"] {
    --fn-body-bg:        #FFFFFF;
    --fn-card-bg:        #F5F5F7;
    --fn-card-border:    #E3E5E9;
    --fn-text:           #1F2328;
    --fn-text-muted:     #6B7280;
    --fn-tertiary-bg:    #EEF0F3;
    --fn-shadow:         rgba(0,0,0,.06);
}
[data-bs-theme="dark"] {
    --fn-body-bg:        #1a1d21;
    --fn-card-bg:        #23272C;
    --fn-card-border:    #2E343B;
    --fn-text:           #E6E8EB;
    --fn-text-muted:     #9099A4;
    --fn-tertiary-bg:    #2A2F35;
    --fn-shadow:         rgba(0,0,0,.3);
}

* { -webkit-tap-highlight-color: transparent; }

html, body {
    margin: 0;
    background: var(--fn-body-bg);
    color: var(--fn-text);
    font-family: system-ui, -apple-system, 'Segoe UI', Roboto, sans-serif;
    -webkit-font-smoothing: antialiased;
}

 body {
        padding-bottom: calc(var(--fn-safe-bottom) + 1rem);
    }
    

/* Safe-area shading at the very top — same idea as the main app's
   liquid-glass.css body::before. Light fade so iOS time/wifi/battery
   stays readable on the light body. */
body::before {
    content: "";
    position: fixed;
    top: 0;
    left: 0;
    right: 0;
    height: var(--fn-safe-top);
    background: linear-gradient(to bottom,
        rgba(15, 17, 21, 0.70) 0%,
        rgba(15, 17, 21, 0.25) 65%,
        transparent           100%);
    z-index: 1;
    pointer-events: none;
}

/* Admin top bar — branded hero with bell, brand, subtitle, user/station.
   Floating glass island — matches the main app's hero. Side margins
   0.3rem from screen edge, 0.45rem below safe-area, all four corners
   rounded, soft drop shadow. */
.fn-admin-bar {
    position: fixed;
    top: calc(var(--fn-safe-top) + 0.45rem);
    left: 0.3rem;
    right: 0.3rem;
    z-index: 50;
    background: var(--fn-header-bg);
    color: #fff;
    border-radius: 1rem;
    box-shadow: 0 14px 36px -10px rgba(0,0,0,.28),
                0 4px 12px -4px rgba(0,0,0,.14);
    overflow: hidden;
}
.fn-admin-bar-inner {
    display: flex;
    align-items: center;
    gap: .55rem;
    padding: .55rem .55rem;
    min-height: 3.4rem;
    box-sizing: border-box;
}
.fn-admin-bell {
    width: 2.2rem;
    height: 2.2rem;
    border-radius: .55rem;
    background: rgba(255,255,255,.16);
    color: #fff;
    border: 0;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    cursor: pointer;
    text-decoration: none;
    flex-shrink: 0;
}
.fn-admin-bell:active { transform: scale(.95); }
.fn-admin-bell .mdi { font-size: 1.2rem; }
.fn-admin-brand-wrap {
    flex: 1 1 auto;
    min-width: 0;
    display: flex;
    flex-direction: column;
}
.fn-admin-brand {
    font-weight: 800;
    font-size: 1rem;
    line-height: 1.1;
    color: #fff;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
.fn-admin-subtitle {
    font-size: .78rem;
    font-weight: 500;
    color: rgba(255,255,255,.78);
    line-height: 1.2;
}
.fn-admin-title {
    font-weight: 800;
    font-size: 1.05rem;
    line-height: 1;
    color: #fff;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
.fn-admin-id {
    display: inline-flex;
    background: rgba(255,255,255,.10);
    border-radius: .5rem;
    overflow: hidden;
    flex-shrink: 0;
}
.fn-admin-id-cell {
    display: inline-flex;
    align-items: center;
    gap: .25rem;
    padding: .35rem .5rem;
    font-size: .78rem;
    font-weight: 700;
    color: #fff;
    line-height: 1;
}
.fn-admin-id-cell + .fn-admin-id-cell {
    border-left: 1px solid rgba(255,255,255,.12);
}
.fn-admin-id-cell .mdi {
    font-size: 1rem;
    opacity: .85;
}

/* Back link — on page content, top-left, quiet */
.fn-page-back-link {
    display: inline-flex;
    align-items: center;
    gap: .15rem;
    color: var(--fn-text-muted);
    background: transparent;
    border: 0;
    padding: .35rem .25rem;
    margin: 0 0 .65rem -.25rem;
    font-weight: 700;
    font-size: .9rem;
    text-decoration: none;
    cursor: pointer;
    line-height: 1;
}
.fn-page-back-link:hover, .fn-page-back-link:active {
    color: var(--fn-text);
}
.fn-page-back-link .mdi {
    font-size: 1.2rem;
}

.fn-admin-container {
    max-width: 720px;
    margin: 0 auto;
    padding: .85rem 1rem 1rem;
}

@media (hover: hover) and (pointer: fine) {
        .fn-admin-container {
            max-width: calc(100% - 2rem);
            width: calc(100% - 2rem);
            padding: 1rem 1.25rem 1.5rem;
        }
    }


.fn-section-title {
    font-size: .72rem; font-weight: 800;
    text-transform: uppercase; letter-spacing: .04em;
    color: var(--fn-text-muted);
    margin: 1.1rem 0 .5rem;
}

.fn-rt-panel {
    background: var(--fn-card-bg);
    border: 1px solid var(--fn-card-border);
    border-radius: .8rem;
    padding: 1rem;
    margin-bottom: .8rem;
}

.fn-field { margin-bottom: .8rem; }
.fn-field-label {
    font-size: .72rem; font-weight: 800;
    text-transform: uppercase; letter-spacing: .04em;
    color: var(--fn-text-muted);
    margin-bottom: .35rem;
    display: flex; align-items: center; gap: .3rem;
}
.fn-field-label .count {
    font-weight: 600; font-size: .7rem;
    color: var(--fn-text-muted); margin-left: auto;
}
.fn-field-label .count.over { color: var(--fn-accent); font-weight: 800; }

.fn-text-input {
    width: 100%;
    padding: .55rem .7rem;
    border-radius: .5rem;
    border: 1px solid var(--fn-card-border);
    background: var(--fn-body-bg);
    color: var(--fn-text);
    font-size: 1rem;
    font-weight: 700;
}
.fn-text-input:focus { outline: 0; border-color: var(--fn-brand); }
.fn-text-input:disabled {
    background: var(--fn-tertiary-bg);
    color: var(--fn-text-muted);
    cursor: not-allowed;
}

.fn-color-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(3rem, 1fr));
    gap: .4rem;
}
.fn-color-option {
    cursor: pointer;
    aspect-ratio: 1;
    border-radius: .5rem;
    border: 3px solid transparent;
    display: flex; align-items: center; justify-content: center;
    color: #fff;
    transition: transform .1s, border-color .15s;
    position: relative;
    box-shadow: 0 1px 3px rgba(0,0,0,.1);
}
.fn-color-option:hover { transform: scale(1.05); }
.fn-color-option .mdi {
    font-size: 1.4rem;
    opacity: 0;
    transition: opacity .15s;
}
.fn-color-option.selected .mdi { opacity: 1; }
.fn-color-option.selected {
    border-color: rgba(255,255,255,.6);
    box-shadow: 0 0 0 3px var(--fn-brand), 0 1px 3px rgba(0,0,0,.15);
}

.fn-icon-search {
    margin-bottom: .5rem;
    width: 100%;
    padding: .45rem .7rem;
    border-radius: .5rem;
    border: 1px solid var(--fn-card-border);
    background: var(--fn-body-bg);
    color: var(--fn-text);
    font-size: .9rem;
}

.fn-icon-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(2.6rem, 1fr));
    gap: .35rem;
    max-height: 14rem;
    overflow-y: auto;
    padding: .35rem;
    border: 1px solid var(--fn-card-border);
    border-radius: .55rem;
    background: var(--fn-body-bg);
}
.fn-icon-option {
    cursor: pointer;
    aspect-ratio: 1;
    border-radius: .4rem;
    background: var(--fn-tertiary-bg);
    border: 2px solid transparent;
    display: flex; align-items: center; justify-content: center;
    color: var(--fn-text);
    transition: background .15s, border-color .15s;
}
.fn-icon-option:hover { background: var(--fn-brand-soft); }
.fn-icon-option.selected {
    border-color: var(--fn-brand);
    background: var(--fn-brand-soft);
}
.fn-icon-option .mdi { font-size: 1.4rem; }
.fn-icon-option.hidden { display: none; }

.fn-preview {
    margin-top: .85rem;
    padding: .75rem;
    background: var(--fn-tertiary-bg);
    border-radius: .55rem;
    display: flex; align-items: center; gap: .5rem;
}
.fn-preview-label {
    font-size: .7rem; font-weight: 800;
    text-transform: uppercase; color: var(--fn-text-muted);
    letter-spacing: .04em;
}
.fn-preview-btn {
    flex: 1;
    min-height: 3.2rem;
    padding: .45rem .5rem;
    border-radius: .55rem;
    color: #fff;
    display: inline-flex;
    flex-direction: column;
    align-items: center; justify-content: center;
    gap: .15rem;
    font-weight: 800;
    line-height: 1.05;
    text-align: center;
}
.fn-preview-btn .mdi { font-size: 1.35rem; line-height: 1; }
.fn-preview-btn .lbl {
    font-size: .75rem;
    text-transform: uppercase;
    letter-spacing: .03em;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    max-width: 100%;
}

.fn-actions {
    display: flex; gap: .5rem; margin-top: .85rem;
}
.fn-btn {
    border: 0; border-radius: .5rem;
    padding: .55rem 1rem; font-weight: 700; cursor: pointer;
    font-size: .9rem;
}
.fn-btn-primary { background: var(--fn-brand); color: #fff; flex: 1; }
.fn-btn-secondary {
    background: var(--fn-tertiary-bg);
    border: 1px solid var(--fn-card-border);
    color: var(--fn-text);
}

.fn-protected-note {
    background: rgba(13,110,253,.08);
    border: 1px solid rgba(13,110,253,.25);
    color: var(--fn-text);
    font-size: .78rem;
    padding: .4rem .65rem;
    border-radius: .4rem;
    margin-top: .5rem;
    display: flex; align-items: center; gap: .35rem;
}
.fn-protected-note .mdi { color: #0d6efd; }

.fn-rt-row {
    background: var(--fn-card-bg);
    border: 1px solid var(--fn-card-border);
    border-radius: .55rem;
    padding: .55rem .75rem;
    margin-bottom: .4rem;
    display: flex; align-items: center; gap: .65rem;
    position: relative;
}
.fn-rt-row.protected {
    background: rgba(13,110,253,.05);
    border-color: rgba(13,110,253,.2);
}
.fn-rt-color-pill {
    width: 2rem; height: 2rem;
    border-radius: .45rem;
    display: inline-flex;
    align-items: center; justify-content: center;
    color: #fff; flex-shrink: 0;
}
.fn-rt-color-pill .mdi { font-size: 1.25rem; }
.fn-rt-meta { flex: 1; min-width: 0; }
.fn-rt-label {
    font-weight: 800; color: var(--fn-text); font-size: 1rem;
    display: flex; align-items: center; gap: .35rem;
    flex-wrap: wrap;
}
.fn-rt-icon-name { font-size: .7rem; color: var(--fn-text-muted); font-family: monospace; }
.fn-rt-station {
    font-size: .65rem; font-weight: 800;
    text-transform: uppercase; letter-spacing: .04em;
    background: var(--fn-brand-soft); color: var(--fn-brand);
    padding: .15rem .4rem; border-radius: 999px;
}
.fn-rt-protected-badge {
    font-size: .65rem; font-weight: 800;
    text-transform: uppercase; letter-spacing: .04em;
    background: rgba(13,110,253,.15);
    color: #0d6efd;
    padding: .15rem .4rem; border-radius: 999px;
    display: inline-flex; align-items: center; gap: .2rem;
}
.fn-rt-protected-badge .mdi { font-size: .8rem; }
.fn-rt-actions { display: flex; gap: .35rem; }
.fn-rt-actions button {
    background: var(--fn-tertiary-bg);
    border: 1px solid var(--fn-card-border);
    border-radius: .4rem;
    padding: .35rem .55rem;
    font-size: .75rem; font-weight: 700;
    color: var(--fn-text);
    cursor: pointer;
}
.fn-rt-actions button:hover { border-color: var(--fn-brand); }
.fn-rt-actions button.danger:hover { border-color: var(--fn-accent); color: var(--fn-accent); }
.fn-rt-actions button:disabled {
    opacity: .35;
    cursor: not-allowed;
}
.fn-rt-actions button:disabled:hover {
    border-color: var(--fn-card-border);
    color: var(--fn-text);
}


/* ─────────────────────────────────────────────────────────────────────────
 * SCROLL UNLOCK — override liquid-glass.css's `html, body { overflow:
 * hidden; height: 100% }`. That rule is correct for the SPA shell
 * (index.php), where scrolling happens inside the .fn-page-host
 * container. THIS page is a standalone route with no inner scroll
 * container — without the override below, the body is locked at viewport
 * height and the Existing-buttons list past the fold is unreachable.
 *
 * `!important` here is deliberate: there's a touch-device @media query
 * in liquid-glass.css that re-applies `overflow: hidden` with the same
 * selector + identical specificity, so source order alone can lose on
 * iOS Safari. Forcing the values guarantees this page scrolls in every
 * browser / device combination.
 * ──────────────────────────────────────────────────────────────────────── */
html, body {
    overflow: visible !important;
    height:   auto    !important;
}
@media (hover: none) and (pointer: coarse) {
    html, body {
        overflow: visible !important;
        height:   auto    !important;
        position: static  !important;
    }
}



/* ==========================================================================
   Source: assets/css/login.css
   ========================================================================== */

body {
    background: #313a46;
    min-height: 100vh;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 1rem;
    margin: 0;
}
.login-card {
    background: #fff;
    border-radius: 1rem;
    padding: 1.6rem;
    max-width: 400px;
    width: 100%;
    box-shadow: 0 18px 40px rgba(0,0,0,.25);
}
.login-icon {
    width: 3.2rem;
    height: 3.2rem;
    border-radius: 1rem;
    background: #313a46;
    color: #fff;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    font-size: 1.8rem;
    margin-bottom: 1rem;
}
.login-card h4 { margin: 0 0 .25rem; font-weight: 800; }
.login-card p  { margin: 0 0 1.2rem; color: #6c757d; font-size: .9rem; }

.fn-code-input {
    font-family: 'SF Mono', 'Monaco', 'Menlo', 'Consolas', monospace;
    font-size: 1.4rem;
    font-weight: 700;
    text-align: center;
    letter-spacing: .25em;
    padding: .85rem;
}
.fn-code-input::placeholder {
    color: #ced4da;
    letter-spacing: .25em;
}

.btn-fn-primary {
    background: #313a46;
    color: #fff;
    border: 0;
    border-radius: 999px;
    padding: .85rem 1rem;
    font-weight: 800;
    font-size: 1rem;
    width: 100%;
    transition: filter .15s;
}
.btn-fn-primary:hover { filter: brightness(1.15); color: #fff; }
.btn-fn-primary:disabled { opacity: .5; }


/* ─────────────────────────────────────────────────────────────────────────
 * Demo button — floats in the bottom-right corner of the login page,
 * pointing at /response/demo/. Exists primarily so Apple App Review
 * reviewers (who don't have a real department access code) can launch
 * a stubbed read-only build of the app and evaluate it.
 *
 * Style: glass pill on the dark slate body. Reads as a clearly secondary
 * action — visible enough to find, subtle enough not to compete with
 * the centered SIGN IN card.
 *
 * Safe-area aware so it doesn't tuck under the home indicator on iPhone
 * or get clipped by the rounded corner of iPad in landscape.
 * ──────────────────────────────────────────────────────────────────────── */
.fn-demo-btn {
    position: fixed;
    bottom: calc(env(safe-area-inset-bottom, 0px) + 1rem);
    right:  calc(env(safe-area-inset-right,  0px) + 1rem);
    z-index: 10;

    display: inline-flex;
    align-items: center;
    gap: .4rem;

    padding: .65rem 1.1rem;
    border-radius: 999px;

    background: rgba(255, 255, 255, 0.12);
    color: #fff;
    border: 1px solid rgba(255, 255, 255, 0.22);
    backdrop-filter: blur(12px) saturate(140%);
    -webkit-backdrop-filter: blur(12px) saturate(140%);
    box-shadow: 0 4px 16px rgba(0, 0, 0, 0.20);

    text-decoration: none;
    font-weight: 700;
    font-size: .9rem;
    letter-spacing: .03em;
    line-height: 1;

    transition: background .15s, transform .12s, filter .15s;
    -webkit-tap-highlight-color: transparent;
}
.fn-demo-btn:hover,
.fn-demo-btn:focus {
    background: rgba(255, 255, 255, 0.20);
    color: #fff;
    outline: none;
}
.fn-demo-btn:active {
    transform: scale(.96);
    filter: brightness(.92);
}
.fn-demo-btn .mdi {
    font-size: 1.15rem;
    line-height: 1;
}



/* ==========================================================================
   Source: inline <style id="fn-fontsize-rules"> in history.php
   ========================================================================== */

html { font-size: 18.4px !important; }
html[data-fn-fontsize="standard"] { font-size: 18.4px !important; }
html[data-fn-fontsize="large"]    { font-size: 20px !important; }
html[data-fn-fontsize="xlarge"]   { font-size: 22px !important; }
body { font-size: 1rem !important; }



/* ==========================================================================
   Source: inline <style> in history.php
   ========================================================================== */

/* ── Shared shell tokens & layout ────────────────────────── */
:root {
    --fn-brand:        #313a46;
    --fn-brand-soft:   rgba(49, 58, 70, .10);
    --fn-accent:       #B03A2E;
    --fn-accent-soft:  rgba(176, 58, 46, .10);
    --fn-header-bg:    var(--fn-brand);
    --fn-safe-top:     max(env(safe-area-inset-top, 0px), 2.75rem);
    --fn-safe-bottom:  max(env(safe-area-inset-bottom, 0px), .5rem);
}

:root,
[data-bs-theme="light"] {
    --fn-body-bg:        #FFFFFF;
    --fn-card-bg:        #F5F5F7;
    --fn-card-border:    #E3E5E9;
    --fn-text:           #1F2328;
    --fn-text-muted:     #6B7280;
    --fn-tertiary-bg:    #EEF0F3;
    --fn-shadow:         rgba(0,0,0,.06);
}
[data-bs-theme="dark"] {
    --fn-body-bg:        #1a1d21;
    --fn-card-bg:        #23272C;
    --fn-card-border:    #2E343B;
    --fn-text:           #E6E8EB;
    --fn-text-muted:     #9099A4;
    --fn-tertiary-bg:    #2A2F35;
    --fn-shadow:         rgba(0,0,0,.3);
}

* { -webkit-tap-highlight-color: transparent; }

html, body {
    margin: 0;
    background: var(--fn-body-bg);
    color: var(--fn-text);
    font-family: system-ui, -apple-system, 'Segoe UI', Roboto, sans-serif;
    -webkit-font-smoothing: antialiased;
}

body {
    padding-top: calc(var(--fn-safe-top) + 3.4rem);
    padding-bottom: calc(var(--fn-safe-bottom) + 1rem);
}

/* Modal-open lock: stop the underlying page from scrolling
   behind the sheet. We keep this off the html element on iOS
   because adding it there causes a noticeable jump as the
   address bar resizes; body-only is enough for our case. */
body.fn-modal-open {
    overflow: hidden;
}

.fn-admin-bar {
    position: fixed;
    top: 0; left: 0; right: 0;
    z-index: 50;
    background: var(--fn-header-bg);
    color: #fff;
    padding-top: var(--fn-safe-top);
    box-shadow: 0 2px 8px rgba(0,0,0,.10);
}
.fn-admin-bar-inner {
    display: flex;
    align-items: center;
    padding: .55rem .85rem;
    min-height: 3.4rem;
    box-sizing: border-box;
}
.fn-admin-title {
    font-weight: 800;
    font-size: 1.05rem;
    line-height: 1;
    color: #fff;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.fn-page-back-link {
    display: inline-flex;
    align-items: center;
    gap: .15rem;
    color: var(--fn-text-muted);
    background: transparent;
    border: 0;
    padding: .35rem .25rem;
    margin: 0 0 .5rem -.25rem;
    font-weight: 700;
    font-size: .9rem;
    text-decoration: none;
    cursor: pointer;
    line-height: 1;
}
.fn-page-back-link:hover, .fn-page-back-link:active { color: var(--fn-text); }
.fn-page-back-link .mdi { font-size: 1.2rem; }

.fn-admin-container {
    max-width: 720px;
    margin: 0 auto;
    padding: .85rem 1rem 1rem;
}

/* ── Sticky search bar ───────────────────────────────────── */
.fn-search-wrap {
    position: sticky;
    top: calc(var(--fn-safe-top) + 3.4rem);
    z-index: 20;
    background: var(--fn-body-bg);
    padding: .5rem 0 .65rem;
    margin: 0 -1rem .25rem;
    padding-left: 1rem;
    padding-right: 1rem;
    border-bottom: 1px solid transparent;
    transition: border-color .15s ease, box-shadow .15s ease;
}
.fn-search-wrap.scrolled {
    border-bottom-color: var(--fn-card-border);
    box-shadow: 0 2px 6px rgba(0,0,0,.04);
}

.fn-search-inner { position: relative; }
.fn-search-icon {
    position: absolute;
    left: .7rem;
    top: 50%;
    transform: translateY(-50%);
    font-size: 1.2rem;
    color: var(--fn-text-muted);
    pointer-events: none;
    line-height: 1;
}
.fn-search-input {
    width: 100%;
    box-sizing: border-box;
    padding: .65rem .85rem .65rem 2.4rem;
    border: 1px solid var(--fn-card-border);
    border-radius: 999px;
    font-size: .92rem;
    background: var(--fn-card-bg);
    color: var(--fn-text);
    font-family: inherit;
    -webkit-appearance: none;
    appearance: none;
    min-height: 2.6rem;
    outline: none;
    transition: border-color .12s, background .12s;
}
.fn-search-input:focus {
    border-color: var(--fn-brand);
    background: var(--fn-body-bg);
}
.fn-search-clear {
    position: absolute;
    right: .35rem;
    top: 50%;
    transform: translateY(-50%);
    background: var(--fn-tertiary-bg);
    border: 0;
    width: 1.7rem;
    height: 1.7rem;
    border-radius: 50%;
    color: var(--fn-text-muted);
    display: none;
    align-items: center;
    justify-content: center;
    cursor: pointer;
    padding: 0;
}
.fn-search-clear.show { display: inline-flex; }
.fn-search-clear .mdi { font-size: 1.05rem; line-height: 1; }

.fn-result-bar {
    display: flex;
    align-items: center;
    justify-content: space-between;
    margin-bottom: .5rem;
    min-height: 1.25rem;
}
.fn-result-count {
    font-size: .72rem;
    color: var(--fn-text-muted);
    font-weight: 700;
}

/* ── Compact list rows ────────────────────────────────────── */
.fn-list-item {
    background: var(--fn-card-bg);
    border: 1px solid var(--fn-card-border);
    border-left: 4px solid var(--fn-text-muted);
    border-radius: .6rem;
    padding: .55rem .65rem .6rem .75rem;
    margin-bottom: .35rem;
    cursor: pointer;
    transition: transform .08s, background .12s;
    display: flex;
    align-items: center;
    gap: .55rem;
    -webkit-tap-highlight-color: rgba(0,0,0,.04);
    user-select: none;
}
.fn-list-item:active {
    transform: scale(.995);
    background: var(--fn-tertiary-bg);
}
.fn-list-item.c-success { border-left-color: #198754; }
.fn-list-item.c-danger  { border-left-color: var(--fn-accent); }
.fn-list-item.c-warning { border-left-color: #d97706; }
.fn-list-item.c-info    { border-left-color: #0d6efd; }
.fn-list-item.c-purple  { border-left-color: #7c3aed; }
.fn-list-item.c-teal    { border-left-color: #0d9488; }
.fn-list-item.c-pink    { border-left-color: #db2777; }
.fn-list-item.c-dark    { border-left-color: #1f2937; }
.fn-list-item.c-gray    { border-left-color: #6b7280; }

.fn-list-main {
    flex: 1;
    min-width: 0;
    display: flex;
    flex-direction: column;
    gap: .1rem;
}

.fn-list-line1 {
    display: flex;
    align-items: baseline;
    gap: .5rem;
}
.fn-list-type {
    flex: 1;
    font-weight: 800;
    font-size: .92rem;
    color: var(--fn-text);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    min-width: 0;
    line-height: 1.2;
}
.fn-list-time {
    font-size: .7rem;
    color: var(--fn-text-muted);
    font-weight: 700;
    white-space: nowrap;
    flex-shrink: 0;
    font-variant-numeric: tabular-nums;
}

.fn-list-line2 {
    display: flex;
    align-items: center;
    gap: .45rem;
    font-size: .76rem;
    color: var(--fn-text-muted);
    line-height: 1.25;
}
.fn-list-addr {
    flex: 1;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    min-width: 0;
}
.fn-list-respcount {
    flex-shrink: 0;
    background: var(--fn-tertiary-bg);
    border: 1px solid var(--fn-card-border);
    color: var(--fn-text-muted);
    font-weight: 700;
    font-size: .68rem;
    padding: .1rem .4rem;
    border-radius: 999px;
    display: inline-flex;
    align-items: center;
    gap: .2rem;
}
.fn-list-respcount .mdi { font-size: .8rem; }

/* Compact icon at the right showing this user's response on the
   call. Color-matched to the left border. */
.fn-list-mine-icon {
    flex-shrink: 0;
    width: 1.6rem;
    height: 1.6rem;
    border-radius: 50%;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    color: #fff;
    font-size: 1rem;
    background: var(--fn-text-muted);
}
.fn-list-mine-icon.c-success { background: #198754; }
.fn-list-mine-icon.c-danger  { background: var(--fn-accent); }
.fn-list-mine-icon.c-warning { background: #d97706; }
.fn-list-mine-icon.c-info    { background: #0d6efd; }
.fn-list-mine-icon.c-purple  { background: #7c3aed; }
.fn-list-mine-icon.c-teal    { background: #0d9488; }
.fn-list-mine-icon.c-pink    { background: #db2777; }
.fn-list-mine-icon.c-dark    { background: #1f2937; }
.fn-list-mine-icon.c-gray    { background: #6b7280; }
.fn-list-mine-icon.c-none {
    background: transparent;
    color: var(--fn-text-muted);
    border: 1px dashed var(--fn-card-border);
}

.fn-list-chev {
    flex-shrink: 0;
    color: var(--fn-text-muted);
    opacity: .4;
    font-size: 1.3rem;
    line-height: 1;
}

/* ── Status badge (used in modal header) ─────────────────── */
.fn-card-status {
    font-size: .62rem;
    font-weight: 800;
    text-transform: uppercase;
    letter-spacing: .05em;
    padding: .15rem .5rem;
    border-radius: 999px;
    color: #fff;
    flex-shrink: 0;
}
.fn-card-status.active { background: var(--fn-accent); }
.fn-card-status.closed { background: #6c757d; }

/* ── Pill (reused in modal for response labels) ──────────── */
.fn-pill {
    display: inline-flex;
    align-items: center;
    gap: .25rem;
    font-size: .68rem;
    font-weight: 800;
    text-transform: uppercase;
    letter-spacing: .04em;
    padding: .2rem .55rem;
    border-radius: 999px;
    color: #fff;
    white-space: nowrap;
    line-height: 1;
}
.fn-pill .mdi { font-size: .85rem; line-height: 1; }
.fn-pill.c-success { background: #198754; }
.fn-pill.c-danger  { background: var(--fn-accent); }
.fn-pill.c-warning { background: #d97706; }
.fn-pill.c-info    { background: #0d6efd; }
.fn-pill.c-purple  { background: #7c3aed; }
.fn-pill.c-teal    { background: #0d9488; }
.fn-pill.c-pink    { background: #db2777; }
.fn-pill.c-dark    { background: #1f2937; }
.fn-pill.c-gray    { background: #6b7280; }
.fn-pill.c-none {
    background: var(--fn-tertiary-bg);
    color: var(--fn-text-muted);
    border: 1px solid var(--fn-card-border);
}

/* ── Detail modal (bottom-sheet style) ────────────────────── */
.fn-modal-overlay {
    position: fixed;
    inset: 0;
    z-index: 200;
    background: rgba(0, 0, 0, .55);
    opacity: 0;
    pointer-events: none;
    transition: opacity .2s ease;
    display: flex;
    align-items: flex-end;
    justify-content: center;
}
.fn-modal-overlay.is-open {
    opacity: 1;
    pointer-events: auto;
}

.fn-modal {
    background: var(--fn-body-bg);
    color: var(--fn-text);
    width: 100%;
    max-width: 600px;
    /* Almost full-height — leaves a small strip of the page
       visible at the top so it still feels like a sheet, not a
       full takeover. Long content scrolls inside the body. */
    height: 90vh;
    height: 90dvh;
    border-radius: 1rem 1rem 0 0;
    box-shadow: 0 -8px 32px rgba(0, 0, 0, .25);
    transform: translateY(100%);
    transition: transform .25s cubic-bezier(.2,.85,.3,1);
    display: flex;
    flex-direction: column;
    overflow: hidden;
    position: relative;
}
.fn-modal-overlay.is-open .fn-modal {
    transform: translateY(0);
}

.fn-modal-handle {
    position: absolute;
    top: .35rem;
    left: 50%;
    transform: translateX(-50%);
    width: 2.4rem;
    height: .3rem;
    border-radius: 999px;
    background: var(--fn-text-muted);
    opacity: .3;
    pointer-events: none;
}

.fn-modal-header {
    flex-shrink: 0;
    display: flex;
    align-items: center;
    gap: .5rem;
    padding: 1.15rem 1rem .55rem;
    border-bottom: 1px solid var(--fn-card-border);
    background: var(--fn-body-bg);
}
.fn-modal-header-text {
    flex: 1;
    min-width: 0;
    display: flex;
    flex-direction: column;
    gap: .15rem;
}
.fn-modal-time {
    font-size: .7rem;
    color: var(--fn-text-muted);
    font-weight: 700;
    font-variant-numeric: tabular-nums;
}
.fn-modal-title {
    font-weight: 800;
    font-size: 1rem;
    color: var(--fn-text);
    line-height: 1.25;
    word-break: break-word;
}

.fn-modal-close {
    background: var(--fn-tertiary-bg);
    border: 0;
    width: 2.1rem;
    height: 2.1rem;
    border-radius: 50%;
    color: var(--fn-text);
    cursor: pointer;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    font-size: 1.3rem;
    padding: 0;
    flex-shrink: 0;
}
.fn-modal-close .mdi { line-height: 1; }
.fn-modal-close:active { transform: scale(.92); }

.fn-modal-body {
    /* flex: 1 + min-height: 0 is the iOS scroll fix. .fn-modal is a
       flex column with overflow:hidden; without these two, the
       default min-height:auto on flex items keeps this container
       at its content's intrinsic height, the parent clips the
       overflow, and the user can't scroll because the scroll
       container itself is never constrained below its content. */
    flex: 1;
    min-height: 0;
    overflow-y: auto;
    -webkit-overflow-scrolling: touch;
    overscroll-behavior: contain;
    padding: .85rem 1rem;
    /* Extra buffer at the bottom for rounded screen corners on
       newer iPhones, plus the safe-area inset for the home
       indicator. Before: 1.2rem — kept clipping the last line. */
    padding-bottom: calc(2.75rem + env(safe-area-inset-bottom, 0px));
}

.fn-modal-section {
    margin-bottom: 1.1rem;
}
.fn-modal-section:last-child { margin-bottom: 0; }

.fn-modal-section-title {
    font-size: .62rem;
    font-weight: 800;
    text-transform: uppercase;
    letter-spacing: .05em;
    color: var(--fn-text-muted);
    margin-bottom: .35rem;
}
.fn-modal-addr {
    font-size: .92rem;
    color: var(--fn-text);
    line-height: 1.35;
    word-break: break-word;
}
.fn-modal-mine-row {
    display: flex;
    align-items: center;
    gap: .5rem;
    flex-wrap: wrap;
}

.fn-resp-group { margin-bottom: .55rem; }
.fn-resp-group:last-child { margin-bottom: 0; }
.fn-resp-group-head {
    display: flex;
    align-items: center;
    gap: .35rem;
    margin-bottom: .2rem;
    flex-wrap: wrap;
}
.fn-resp-group-count {
    font-size: .72rem;
    color: var(--fn-text-muted);
    font-weight: 700;
    font-variant-numeric: tabular-nums;
}
.fn-resp-names {
    font-size: .88rem;
    color: var(--fn-text);
    line-height: 1.45;
    padding-left: .15rem;
    word-break: break-word;
}
.fn-resp-name.is-me {
    font-weight: 800;
    color: var(--fn-text);
}
.fn-resp-name.is-me::after {
    content: ' (you)';
    font-weight: 700;
    color: var(--fn-accent);
    font-size: .85em;
}
.fn-resp-empty {
    font-size: .85rem;
    color: var(--fn-text-muted);
    font-style: italic;
}

@media (min-width: 600px) {
    .fn-modal-overlay {
        align-items: center;
        padding: 1rem;
    }
    .fn-modal {
        border-radius: 1rem;
        /* Desktop: still aim for half-height, but allow growth up
           to 82vh if content is long, and don't shrink below 50vh
           for short content so the sheet doesn't feel tiny when
           centered on a big screen. */
        height: auto;
        min-height: 50vh;
        max-height: 82vh;
        transform: translateY(2rem);
    }
    .fn-modal-overlay.is-open .fn-modal {
        transform: translateY(0);
    }
    .fn-modal-handle { display: none; }
    .fn-modal-header { padding-top: .9rem; }
}

.fn-empty {
    text-align: center;
    padding: 3rem 1rem;
    color: var(--fn-text-muted);
}
.fn-empty .mdi { font-size: 3rem; opacity: .35; }
.fn-empty-title {
    font-weight: 700;
    color: var(--fn-text);
    margin-top: .5rem;
}
.fn-empty-sub {
    font-size: .85rem;
    margin-top: .25rem;
}
.fn-loading {
    padding: 2rem 1rem;
    text-align: center;
    color: var(--fn-text-muted);
    font-size: .9rem;
}
.fn-loading .mdi { font-size: 1.5rem; opacity: .5; margin-right: .35rem; vertical-align: -3px; }



/* ==========================================================================
   Source: inline <style> in apparatus.php
   ========================================================================== */

/* ===========================================================
   apparatus.php — light default, dark override
   =========================================================== */
:root {
    --ap-bg-base:        #f3f5f8;
    --ap-bg-mid:         #ffffff;

    --ap-surface:        #ffffff;
    --ap-surface-2:      #f8fafc;
    --ap-surface-3:      #eef2f6;
    --ap-surface-hover:  #f1f5f9;

    --ap-border:         rgba(15, 23, 42, 0.10);
    --ap-border-strong:  rgba(15, 23, 42, 0.20);

    --ap-text:           #0f172a;
    --ap-text-muted:     #475569;
    --ap-text-dim:       #94a3b8;

    --ap-brand:          #c0282d;
    --ap-brand-2:        #e94047;
    --ap-brand-soft:     rgba(192, 40, 45, 0.10);

    --ap-accent:         #d97706;
    --ap-accent-soft:    rgba(217, 119, 6, 0.12);
    --ap-success:        #059669;
    --ap-success-soft:   rgba(5, 150, 105, 0.10);
    --ap-info:           #2563eb;
    --ap-info-soft:      rgba(37, 99, 235, 0.08);

    --ap-hazard:         #dc2626;
    --ap-hazard-bg:      linear-gradient(135deg, #fee2e2 0%, #fecaca 100%);
    --ap-hazard-border:  #f87171;
    --ap-hazard-text:    #7f1d1d;

    --ap-radius:         1.1rem;
    --ap-radius-sm:      0.65rem;

    --ap-shadow-card:
        0 8px 22px -10px rgba(15, 23, 42, 0.18),
        0 2px 4px  -1px  rgba(15, 23, 42, 0.06),
        inset 0 1px 0 rgba(255, 255, 255, 0.9);

    --ap-shadow-topbar:
        0 12px 28px -10px rgba(192, 40, 45, 0.32),
        inset 0 1px 0 rgba(255, 255, 255, 0.20);
}

html[data-theme="dark"] {
    --ap-bg-base:        #0a0d12;
    --ap-bg-mid:         #11151c;
    --ap-surface:        rgba(255, 255, 255, 0.04);
    --ap-surface-2:      rgba(255, 255, 255, 0.075);
    --ap-surface-3:      rgba(255, 255, 255, 0.12);
    --ap-surface-hover:  rgba(255, 255, 255, 0.10);
    --ap-border:         rgba(255, 255, 255, 0.08);
    --ap-border-strong:  rgba(255, 255, 255, 0.18);
    --ap-text:           #e8eaed;
    --ap-text-muted:     #95a0ae;
    --ap-text-dim:       #5a6371;
    --ap-brand-soft:     rgba(192, 40, 45, 0.18);
    --ap-accent:         #f59e0b;
    --ap-accent-soft:    rgba(245, 158, 11, 0.16);
    --ap-success:        #10b981;
    --ap-success-soft:   rgba(16, 185, 129, 0.16);
    --ap-info:           #3b82f6;
    --ap-info-soft:      rgba(59, 130, 246, 0.14);
    --ap-hazard:         #f87171;
    --ap-hazard-bg:      linear-gradient(135deg, rgba(220, 38, 38, 0.30) 0%, rgba(185, 28, 28, 0.40) 100%);
    --ap-hazard-border:  rgba(248, 113, 113, 0.55);
    --ap-hazard-text:    #fecaca;
    --ap-shadow-card:
        0 12px 30px rgba(0, 0, 0, 0.36),
        0 4px 10px  rgba(0, 0, 0, 0.20),
        inset 0 1px 0 rgba(255, 255, 255, 0.06);
    --ap-shadow-topbar:
        0 12px 32px rgba(192, 40, 45, 0.30),
        inset 0 1px 0 rgba(255, 255, 255, 0.12);
}

html { font-size: 16px; }
html[data-fn-fontsize="large"]  { font-size: 17.5px; }
html[data-fn-fontsize="xlarge"] { font-size: 19px; }

* { -webkit-tap-highlight-color: transparent; box-sizing: border-box; }

html, body {
    margin: 0;
    padding: 0;
    background: var(--ap-bg-base);
    color: var(--ap-text);
    font-family: -apple-system, BlinkMacSystemFont, 'SF Pro Text', 'Segoe UI', system-ui, sans-serif;
    -webkit-font-smoothing: antialiased;
    overflow: hidden;
}
body {
    position: relative;
    isolation: isolate;
    height: 100vh;
    height: 100dvh;
}
body::before {
    content: '';
    position: fixed;
    inset: 0;
    z-index: -2;
    background:
        radial-gradient(ellipse 70% 60% at 50% 0%, var(--ap-brand-soft) 0%, transparent 55%),
        var(--ap-bg-base);
}
html[data-theme="dark"] body::after {
    content: '';
    position: fixed;
    inset: -10%;
    z-index: -1;
    background:
        radial-gradient(circle at 30% 40%, rgba(192,40,45,0.06) 0%, transparent 40%),
        radial-gradient(circle at 70% 60%, rgba(192,40,45,0.04) 0%, transparent 40%);
    animation: apEmberDrift 90s linear infinite;
    pointer-events: none;
}
@keyframes apEmberDrift {
    0%   { transform: rotate(0deg)   scale(1);    }
    50%  { transform: rotate(180deg) scale(1.05); }
    100% { transform: rotate(360deg) scale(1);    }
}

/* Phone gate */
.ap-too-small {
    display: none;
    position: fixed;
    inset: 0;
    z-index: 1000;
    padding: 2rem;
    text-align: center;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    background: var(--ap-bg-base);
    color: var(--ap-text);
}
.ap-too-small .mdi { font-size: 4rem; color: var(--ap-brand); margin-bottom: 1rem; }
.ap-too-small h2 { margin: 0 0 0.5rem; font-size: 1.4rem; font-weight: 800; }
.ap-too-small p  { margin: 0; color: var(--ap-text-muted); max-width: 24rem; line-height: 1.5; }

@media (max-width: 759px) {
    .ap-too-small { display: flex; }
    .ap-shell { display: none !important; }
}

/* Shell */
.ap-shell {
    display: grid;
    grid-template-rows: auto minmax(0, 1fr) auto;
    height: 100vh;
    height: 100dvh;
    padding:
        max(1.75rem, env(safe-area-inset-top))
        max(1.75rem, env(safe-area-inset-right))
        max(1.75rem, env(safe-area-inset-bottom))
        max(1.75rem, env(safe-area-inset-left));
    gap: 0.7rem;
    overflow: hidden;
}

/* ── Topbar ───────────────────────────────────────────────── */
:root {
    /* Default header color: red (matches main app's default).
       Switched by html[data-header-color] below. Fully opaque
       so the body bg can't show through. */
    --ap-topbar-bg: linear-gradient(135deg, #c0282d 0%, #961e23 100%);
    --ap-topbar-shadow:
        0 12px 28px -10px rgba(192, 40, 45, 0.32),
        inset 0 1px 0 rgba(255, 255, 255, 0.20);
}
html[data-header-color="dark"] {
    --ap-topbar-bg: linear-gradient(135deg, #313a46 0%, #1e242d 100%);
    --ap-topbar-shadow:
        0 12px 28px -10px rgba(15, 23, 42, 0.40),
        inset 0 1px 0 rgba(255, 255, 255, 0.10);
}

.ap-topbar {
    background: var(--ap-topbar-bg);
    border: 1px solid rgba(255, 255, 255, 0.10);
    border-radius: var(--ap-radius);
    padding: 1.1rem 1.25rem;
    color: #fff;
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 1rem;
    box-shadow: var(--ap-topbar-shadow, var(--ap-shadow-topbar));
}
.ap-topbar-left  { display: flex; align-items: center; gap: 0.75rem; min-width: 0; }
.ap-topbar-left > .mdi { font-size: 1.8rem; color: rgba(255,255,255,0.95); flex-shrink: 0; line-height: 1; }
.ap-topbar-titles { min-width: 0; line-height: 1.15; }
.ap-topbar-brand  { font-size: 1.2rem; font-weight: 800; letter-spacing: -0.01em; line-height: 1.15; }
.ap-topbar-unit   {
    font-size: 0.82rem;
    opacity: 0.88;
    font-weight: 600;
    letter-spacing: 0.04em;
    text-transform: uppercase;
    margin-top: 0.15rem;
}
.ap-topbar-right { display: flex; align-items: center; gap: 0.7rem; flex-shrink: 0; }
.ap-live-pill {
    background: rgba(0, 0, 0, 0.25);
    border: 1px solid rgba(255, 255, 255, 0.20);
    border-radius: 999px;
    padding: 0.3rem 0.7rem;
    font-size: 0.72rem;
    font-weight: 800;
    letter-spacing: 0.08em;
    display: inline-flex;
    align-items: center;
    gap: 0.4rem;
    line-height: 1;
}
.ap-live-dot {
    width: 0.5rem; height: 0.5rem;
    border-radius: 50%;
    background: #34d399;
    box-shadow: 0 0 6px #34d399;
    animation: apLivePulse 2s ease-in-out infinite;
}
@keyframes apLivePulse {
    0%, 100% { opacity: 1; transform: scale(1);    }
    50%      { opacity: .6; transform: scale(0.85); }
}
.ap-clock {
    font-variant-numeric: tabular-nums;
    font-size: 1.5rem;
    font-weight: 800;
    letter-spacing: 0.02em;
    line-height: 1;
}
/* Theme toggle icon button (moved from bottom nav to topbar) */
.ap-theme-btn {
    background: rgba(0, 0, 0, 0.25);
    border: 1px solid rgba(255, 255, 255, 0.20);
    color: #fff;
    border-radius: 50%;
    width: 2.4rem;
    height: 2.4rem;
    cursor: pointer;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    font-family: inherit;
    transition: background 0.15s, transform 0.08s;
    line-height: 1;
    padding: 0;
}
.ap-theme-btn:hover  { background: rgba(0, 0, 0, 0.40); }
.ap-theme-btn:active { transform: scale(0.92); }
.ap-theme-btn .mdi   { font-size: 1.4rem; line-height: 1; }

/* ── Main ─────────────────────────────────────────────────── */
.ap-main { overflow: hidden; min-height: 0; }
.ap-panel { display: none; height: 100%; min-height: 0; }
.ap-panel[data-active="true"] { display: block; }

/* Standing By */
.ap-standing-by {
    height: 100%;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    text-align: center;
    padding: 2rem;
    color: var(--ap-text-muted);
}
.ap-standing-by .mdi { font-size: 5rem; color: var(--ap-text-dim); margin-bottom: 1rem; opacity: 0.8; }
.ap-standing-by h1 { margin: 0; font-size: 3rem; font-weight: 800; color: var(--ap-text); letter-spacing: -0.02em; }
.ap-standing-by-unit    { margin: 0.85rem 0 0; font-size: 1.2rem; font-weight: 700; color: var(--ap-text); }
.ap-standing-by-station { margin: 0.2rem 0 0; font-size: 0.9rem; font-weight: 600; color: var(--ap-text-muted); letter-spacing: 0.05em; text-transform: uppercase; }
.ap-standing-by-note    { margin: 1.5rem 0 0; font-size: 0.88rem; color: var(--ap-text-dim); }

/* Panel is a flex column so the standing-by view (no call) and
   the call layout both fill the available height. */
.ap-panel-call {
    display: none;
}
.ap-panel-call[data-active="true"] {
    display: flex;
    flex-direction: column;
    height: 100%;
    min-height: 0;
    gap: 0.45rem;
}

/* Call header right column — Received time stacked above a
   small "Load other call" trigger. */
.ap-call-header-right {
    display: flex;
    flex-direction: column;
    align-items: flex-end;
    gap: 0.25rem;
    flex-shrink: 0;
}
.ap-call-load-trigger {
    background: var(--ap-brand-soft);
    border: 1px solid rgba(192, 40, 45, 0.22);
    color: var(--ap-brand-2);
    border-radius: 999px;
    padding: 0.5rem 1.1rem;
    font-size: 0.95rem;
    font-weight: 800;
    cursor: pointer;
    font-family: inherit;
    display: inline-flex;
    align-items: center;
    gap: 0.4rem;
    transition: background 0.15s, color 0.15s, transform 0.08s;
    white-space: nowrap;
    flex-shrink: 0;
}
.ap-call-load-trigger:hover {
    background: var(--ap-brand);
    color: #fff;
    border-color: var(--ap-brand);
}
.ap-call-load-trigger:active { transform: scale(0.97); }
.ap-call-load-trigger .mdi { font-size: 1.25rem; }

/* Call layout fills the remaining height inside the panel.
   Two columns: call info on the left, map on the right.
   Responders moved to the Crew tab. */
.ap-call-layout {
    flex: 1 1 auto;
    display: grid;
    grid-template-columns: 1fr 1fr;
    grid-template-rows: minmax(0, 1fr);
    grid-template-areas: "call map";
    gap: 0.55rem;
    height: 100%;
    min-height: 0;
    overflow: hidden;
}
.ap-card-call       { grid-area: call;       }
.ap-card-map        { grid-area: map;        }

@media (max-width: 1023px) {
    .ap-call-layout {
        grid-template-columns: 1fr;
        grid-template-areas:
            "call"
            "map";
        grid-template-rows: minmax(0, auto) minmax(18rem, 1fr);
    }
}

/* Cards */
.ap-card {
    background: var(--ap-surface);
    border: 1px solid var(--ap-border);
    border-radius: var(--ap-radius);
    padding: 0.7rem 0.85rem;
    box-shadow: var(--ap-shadow-card);
    min-height: 0;
    display: flex;
    flex-direction: column;
    overflow: hidden;
}
html[data-theme="dark"] .ap-card {
    backdrop-filter: blur(24px) saturate(160%);
    -webkit-backdrop-filter: blur(24px) saturate(160%);
}
.ap-card-title {
    font-size: 0.88rem;
    font-weight: 800;
    text-transform: uppercase;
    letter-spacing: 0.06em;
    color: var(--ap-text-muted);
    margin: 0 0 0.55rem;
    display: flex;
    align-items: center;
    gap: 0.45rem;
    flex-shrink: 0;
}
.ap-card-title .mdi { font-size: 1.2rem; color: var(--ap-brand-2); }

/* Incident card content */
.ap-call-type {
    font-size: 1.4rem;
    font-weight: 800;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    padding: 0.5rem 1.1rem;
    border-radius: 999px;
    background: var(--ap-brand-soft);
    color: var(--ap-brand-2);
    display: inline-flex;
    align-items: center;
    justify-content: flex-start;
    flex: 1 1 auto;
    min-width: 0;
    line-height: 1.15;
    text-align: left;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.ap-call-address {
    font-size: 1.5rem;
    font-weight: 800;
    color: var(--ap-text);
    line-height: 1.15;
    margin: 0 0 0.2rem;
    letter-spacing: -0.01em;
    flex-shrink: 0;
}
.ap-call-cross {
    font-size: 1.1rem;
    color: var(--ap-text-muted);
    font-weight: 600;
    margin-bottom: 0.4rem;
    flex-shrink: 0;
}
.ap-call-meta-item { display: inline-flex; align-items: center; gap: 0.25rem; }
.ap-call-meta-item strong { color: var(--ap-text); font-weight: 700; }
.ap-call-meta-item .mdi { font-size: 0.85rem; }

/* Header row — pill row on top (type pill expands to fill,
   Load Other Call button on the right), Received-at on its
   own line below at a slightly larger size. */
.ap-call-header-row {
    display: flex;
    flex-direction: column;
    gap: 0.5rem;
    margin-bottom: 0.55rem;
    flex-shrink: 0;
}
.ap-call-pill-row {
    display: flex;
    align-items: stretch;
    gap: 0.4rem;
    width: 100%;
}
.ap-call-received {
    display: inline-flex;
    align-items: center;
    gap: 0.4rem;
    color: var(--ap-text-muted);
    flex-shrink: 0;
    padding-left: 0.2rem;
}
.ap-call-received .mdi { font-size: 1.2rem; }
.ap-call-received-label {
    font-size: 0.76rem;
    text-transform: uppercase;
    letter-spacing: 0.06em;
    font-weight: 800;
}
.ap-call-received strong {
    color: var(--ap-text);
    font-weight: 800;
    font-variant-numeric: tabular-nums;
    font-size: 1.2rem;
}

/* Units — its own row, prominent so it's readable from a distance */
/* Units (trucks) — per-unit red pill chips, horizontal scroll.
   Pattern lifted from home.php's .fn-units-list so the apparatus
   page reads the same as the responder home tab. */
.ap-units-list {
    list-style: none;
    margin: 0.1rem 0 0.5rem;
    padding: 0;
    display: flex;
    flex-wrap: nowrap;
    gap: 0.4rem;
    overflow-x: auto;
    overflow-y: hidden;
    scrollbar-width: none;
    -ms-overflow-style: none;
    -webkit-overflow-scrolling: touch;
    align-self: stretch;
    flex-shrink: 0;
}
.ap-units-list::-webkit-scrollbar { display: none; }
.ap-units-list li {
    background: var(--ap-brand);
    color: #fff;
    border-radius: 0.4rem;
    padding: 0.4rem 0.8rem;
    font-weight: 800;
    font-size: 0.95rem;
    letter-spacing: 0.01em;
    white-space: nowrap;
    flex-shrink: 0;
    box-shadow: 0 1px 2px rgba(0,0,0,0.08);
}

.ap-hazards {
    background: var(--ap-hazard-bg);
    border: 2px solid var(--ap-hazard-border);
    border-radius: var(--ap-radius-sm);
    padding: 0.45rem 0.65rem;
    margin: 0 0 0.45rem;
    display: flex;
    align-items: flex-start;
    gap: 0.5rem;
    flex-shrink: 0;
    box-shadow:
        0 0 0 3px rgba(220, 38, 38, 0.07),
        0 2px 6px rgba(220, 38, 38, 0.14);
}
.ap-hazards-icon {
    flex-shrink: 0;
    color: var(--ap-hazard);
    font-size: 1.4rem;
    line-height: 1;
    animation: apHazardPulse 2.2s ease-in-out infinite;
}
@keyframes apHazardPulse {
    0%, 100% { opacity: 1; transform: scale(1);    }
    50%      { opacity: 0.65; transform: scale(0.92); }
}
.ap-hazards-body { min-width: 0; flex: 1; }
.ap-hazards-label {
    font-size: 0.6rem;
    font-weight: 900;
    letter-spacing: 0.12em;
    color: var(--ap-hazard);
    text-transform: uppercase;
    line-height: 1;
    margin-bottom: 0.15rem;
}
.ap-hazards-text {
    font-size: 0.85rem;
    font-weight: 700;
    color: var(--ap-hazard-text);
    line-height: 1.25;
}

.ap-preplan-line {
    font-size: 0.76rem;
    color: var(--ap-text-muted);
    margin-bottom: 0.4rem;
    display: flex;
    align-items: center;
    gap: 0.35rem;
    flex-shrink: 0;
}
.ap-preplan-line .mdi { color: var(--ap-info); font-size: 0.95rem; }
.ap-preplan-line strong { color: var(--ap-text); font-weight: 700; }
.ap-preplan-dist {
    color: var(--ap-text-dim);
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    font-size: 0.62rem;
    margin-left: auto;
}

.ap-call-message {
    background: var(--ap-surface-2);
    border: 1px solid var(--ap-border);
    border-radius: var(--ap-radius-sm);
    padding: 0.55rem 0.7rem;
    color: var(--ap-text);
    font-size: 0.95rem;
    line-height: 1.4;
    margin-bottom: 0.45rem;
    flex-shrink: 1;
    min-height: 0;
    display: -webkit-box;
    -webkit-line-clamp: 2;
    line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
    white-space: pre-line;
}

.ap-map-buttons {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 0.35rem;
    margin-bottom: 0.35rem;
    flex-shrink: 0;
}
.ap-map-btn {
    background: var(--ap-surface-2);
    border: 1px solid var(--ap-border);
    border-radius: var(--ap-radius-sm);
    padding: 0.5rem 0.4rem;
    color: var(--ap-text);
    font-weight: 700;
    font-size: 0.78rem;
    text-decoration: none;
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 0.3rem;
    cursor: pointer;
    transition: background 0.15s, border-color 0.15s, transform 0.08s;
    white-space: nowrap;
}
.ap-map-btn:hover  { background: var(--ap-surface-hover); border-color: var(--ap-border-strong); }
.ap-map-btn:active { transform: scale(0.97); }
.ap-map-btn .mdi   { font-size: 1.05rem; color: var(--ap-brand-2); }

/* Apple Maps button — black background, white text + Apple logo */
.ap-map-btn.is-apple {
    background: #000;
    color: #fff;
    border-color: #000;
}
.ap-map-btn.is-apple:hover {
    background: #1a1a1a;
    border-color: #1a1a1a;
}
.ap-map-btn.is-apple .mdi {
    color: #fff;
}

/* Google Maps button — Google's recognizable branded button:
   white background, light grey border, dark grey text, with
   the multi-color Google map pin tint on the icon. */
.ap-map-btn.is-google {
    background: #ffffff;
    color: #3c4043;
    border-color: #dadce0;
    box-shadow: 0 1px 2px rgba(60, 64, 67, 0.08);
}
.ap-map-btn.is-google:hover {
    background: #f8f9fa;
    border-color: #c9ccd0;
}
.ap-map-btn.is-google .mdi {
    color: #4285f4;   /* Google blue */
    font-size: 1.15rem;
}
/* Dark mode — Google's dark sign-in button surface: dark slate
   with light text. The Google blue G stays the same. */
html[data-theme="dark"] .ap-map-btn.is-google {
    background: #131314;
    color: #e3e3e3;
    border-color: #5f6368;
    box-shadow: 0 1px 2px rgba(0, 0, 0, 0.3);
}
html[data-theme="dark"] .ap-map-btn.is-google:hover {
    background: #1c1c1d;
    border-color: #8e918f;
}

.ap-preplan-actions {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 0.35rem;
    flex-shrink: 0;
}
.ap-action-btn {
    background: transparent;
    color: var(--ap-brand-2);
    border: 1.5px solid var(--ap-brand);
    border-radius: var(--ap-radius-sm);
    padding: 0.5rem 0.4rem;
    font-size: 0.78rem;
    font-weight: 700;
    cursor: pointer;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 0.3rem;
    transition: background 0.15s, color 0.15s, border-color 0.15s, transform 0.08s;
    font-family: inherit;
    text-decoration: none;
    white-space: nowrap;
}
.ap-action-btn:hover  {
    background: var(--ap-brand);
    color: #fff;
    border-color: var(--ap-brand);
}
.ap-action-btn:active { transform: scale(0.97); }
.ap-action-btn .mdi   { font-size: 1rem; }
.ap-action-btn-secure {
    color: var(--ap-text);
    border-color: var(--ap-text);
}
.ap-action-btn-secure:hover {
    background: var(--ap-text);
    color: var(--ap-surface);
    border-color: var(--ap-text);
}

/* Dark mode keeps the outline language — accents shift to
   tones that read on dark surfaces. Colors stay in-family. */
html[data-theme="dark"] .ap-action-btn {
    background: transparent;
    color: #fca5a5;             /* lighter red for dark surfaces */
    border-color: #fca5a5;
}
html[data-theme="dark"] .ap-action-btn:hover {
    background: var(--ap-brand);
    color: #fff;
    border-color: var(--ap-brand);
}
html[data-theme="dark"] .ap-action-btn-secure {
    background: transparent;
    color: #e3e3e3;
    border-color: #8e918f;
}
html[data-theme="dark"] .ap-action-btn-secure:hover {
    background: rgba(255, 255, 255, 0.08);
    color: #fff;
    border-color: #e3e3e3;
}

.ap-action-btn[aria-disabled="true"] {
    background: transparent;
    color: var(--ap-text-muted);
    border-color: var(--ap-border);
    cursor: not-allowed;
}
.ap-action-btn[aria-disabled="true"]:hover {
    background: transparent;
    color: var(--ap-text-muted);
    border-color: var(--ap-border);
}
html[data-theme="dark"] .ap-action-btn[aria-disabled="true"] {
    background: transparent;
    color: var(--ap-text-dim);
    border-color: #3a3d40;
}

.ap-no-preplan {
    font-size: 0.76rem;
    color: var(--ap-text-dim);
    background: var(--ap-surface-2);
    border: 1px dashed var(--ap-border-strong);
    border-radius: var(--ap-radius-sm);
    padding: 0.4rem 0.65rem;
    margin: 0.1rem 0 0.45rem;
    text-align: center;
    flex-shrink: 0;
}

/* ── Responders card ──────────────────────────────────────── */
.ap-resp-counts {
    display: grid;
    grid-template-columns: repeat(4, 1fr);
    gap: 0.35rem;
    margin-bottom: 0.6rem;
    flex-shrink: 0;
}
.ap-resp-count {
    background: var(--ap-surface-2);
    border: 1px solid var(--ap-border);
    border-radius: var(--ap-radius-sm);
    padding: 0.4rem 0.3rem;
    text-align: center;
    cursor: pointer;
    transition: background 0.15s, border-color 0.15s, transform 0.08s;
    user-select: none;
}
.ap-resp-count:hover  { border-color: var(--ap-border-strong); }
.ap-resp-count:active { transform: scale(0.97); }
.ap-resp-count[data-active="true"] {
    background: var(--ap-surface);
    border-color: var(--ap-brand);
    box-shadow: 0 0 0 2px var(--ap-brand-soft), 0 2px 6px rgba(15, 23, 42, 0.10);
}
.ap-resp-count-num   { font-size: 1.35rem; font-weight: 800; line-height: 1; color: var(--ap-text); font-variant-numeric: tabular-nums; }
.ap-resp-count-label { margin-top: 0.18rem; font-size: 0.6rem; font-weight: 800; text-transform: uppercase; letter-spacing: 0.06em; color: var(--ap-text-muted); }
.ap-resp-count.is-all         .ap-resp-count-num { color: var(--ap-text); }
.ap-resp-count.is-available   .ap-resp-count-num { color: var(--ap-success); }
.ap-resp-count.is-unavailable .ap-resp-count-num { color: var(--ap-brand-2); }
.ap-resp-count.is-scene       .ap-resp-count-num { color: var(--ap-accent); }

/* Compact responder tally — lives inside the call card.
   Read-only summary (no filter behavior — that's only on the
   full responders card in the Crew tab). margin-top: auto
   keeps it pinned to the bottom of the card regardless of how
   much content is above it. */
.ap-resp-summary {
    display: grid;
    grid-template-columns: repeat(4, 1fr);
    gap: 0.35rem;
    margin-top: auto;
    flex-shrink: 0;
}
.ap-resp-summary-item {
    background: var(--ap-surface-2);
    border: 1px solid var(--ap-border);
    border-radius: var(--ap-radius-sm);
    padding: 0.45rem 0.3rem;
    text-align: center;
    user-select: none;
}
.ap-resp-summary-num {
    font-size: 1rem;
    font-weight: 800;
    line-height: 1;
    font-variant-numeric: tabular-nums;
    color: var(--ap-text);
    display: block;
}
.ap-resp-summary-label {
    margin-top: 0.22rem;
    font-size: 0.62rem;
    font-weight: 800;
    text-transform: uppercase;
    letter-spacing: 0.06em;
    color: var(--ap-text-muted);
    display: block;
}
.ap-resp-summary-item.is-available   .ap-resp-summary-num { color: var(--ap-success); }
.ap-resp-summary-item.is-unavailable .ap-resp-summary-num { color: var(--ap-brand-2); }
.ap-resp-summary-item.is-scene       .ap-resp-summary-num { color: var(--ap-accent); }

.ap-resp-list[data-filter="available"]   li[data-bucket]:not([data-bucket="available"])   { display: none; }
.ap-resp-list[data-filter="scene"]       li[data-bucket]:not([data-bucket="scene"])       { display: none; }
.ap-resp-list[data-filter="unavailable"] li[data-bucket]:not([data-bucket="unavailable"]) { display: none; }

.ap-resp-list {
    list-style: none;
    margin: 0;
    padding: 0;
    overflow-y: auto;
    -webkit-overflow-scrolling: touch;
    min-height: 0;
    flex: 1;
}
.ap-resp-list li {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    padding: 0.45rem 0.1rem;
    border-bottom: 1px solid var(--ap-border);
    font-size: 0.88rem;
}
.ap-resp-list li:last-child { border-bottom: 0; }
.ap-resp-dot {
    width: 0.55rem;
    height: 0.55rem;
    border-radius: 50%;
    flex-shrink: 0;
    box-shadow: 0 0 0 2px var(--ap-surface);
}
.ap-resp-name { flex: 1; font-weight: 600; color: var(--ap-text); }
.ap-resp-label { font-size: 0.65rem; color: var(--ap-text-muted); text-transform: uppercase; letter-spacing: 0.05em; font-weight: 700; }
.ap-resp-time { font-size: 0.72rem; color: var(--ap-text-muted); font-variant-numeric: tabular-nums; margin-left: 0.4rem; }
.ap-resp-empty { text-align: center; padding: 1.2rem 0.5rem; color: var(--ap-text-dim); font-size: 0.88rem; }

/* ── Map card ─────────────────────────────────────────────── */
.ap-card-map {
    padding: 0.5rem 0.6rem;
    display: flex;
    flex-direction: column;
    gap: 0.35rem;
    min-height: 0;
    overflow: hidden;     /* clip rather than overflow if cramped */
}
.ap-map-wrap {
    position: relative;
    flex: 1 1 0;
    min-height: 0;        /* was 180px — would refuse to shrink */
    border-radius: var(--ap-radius-sm);
    overflow: hidden;
    background: var(--ap-surface-2);
    border: 1px solid var(--ap-border);
}
#apMap { position: absolute; inset: 0; }
.ap-map-fallback {
    position: absolute;
    inset: 0;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    text-align: center;
    padding: 1rem;
    color: var(--ap-text-muted);
    font-size: 0.82rem;
}
.ap-map-fallback .mdi {
    font-size: 2rem;
    color: var(--ap-text-dim);
    margin-bottom: 0.4rem;
    opacity: 0.7;
}
.ap-map-fallback-title {
    font-weight: 800;
    color: var(--ap-text);
    margin-bottom: 0.15rem;
    font-size: 0.92rem;
}

/* Hydrants chip — sits at top of map card, always visible */
.ap-hydrants-info {
    display: flex;
    align-items: center;
    gap: 0.6rem;
    padding: 0.7rem 1rem;
    background: rgba(220, 38, 38, 0.10);
    border: 1px solid rgba(220, 38, 38, 0.32);
    border-radius: var(--ap-radius-sm);
    font-size: 1.05rem;
    font-weight: 800;
    color: var(--ap-text);
    flex-shrink: 0;
    line-height: 1.2;
}
html[data-theme="dark"] .ap-hydrants-info {
    background: rgba(220, 38, 38, 0.20);
    border-color: rgba(220, 38, 38, 0.42);
}
.ap-hydrants-info[hidden] { display: none; }
.ap-hydrants-info > .mdi { font-size: 1.55rem; color: var(--ap-hazard); flex-shrink: 0; }
.ap-hydrants-info.is-loading { opacity: 0.75; }
.ap-hydrants-info.is-loading > .mdi { animation: apSyncSpin 1.4s linear infinite; }
.ap-hydrants-info.is-warn {
    background: var(--ap-accent-soft);
    border-color: var(--ap-accent);
    color: var(--ap-accent);
}
.ap-hydrants-info.is-warn > .mdi { color: var(--ap-accent); }
.ap-hydrants-info.is-error {
    background: rgba(120, 120, 120, 0.12);
    border-color: rgba(120, 120, 120, 0.45);
    color: var(--ap-text-muted);
    opacity: 1;
}
.ap-hydrants-info.is-error > .mdi {
    color: var(--ap-text-muted);
    animation: none;
}

/* Map actions row — Apple, Google, Map. (Street View lives
   inside the Map modal now, toggled from there.) */
.ap-map-actions {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    gap: 0.35rem;
    flex-shrink: 0;
}
.ap-map-actions .ap-map-btn,
.ap-map-actions .ap-streetview-btn {
    padding: 0.6rem 0.4rem;
    font-size: 1rem;
    min-width: 0;
}
.ap-map-actions .ap-map-btn .mdi,
.ap-map-actions .ap-streetview-btn .mdi {
    font-size: 1.25rem;
}

/* Street View button — matches Apple/Google Maps buttons */
.ap-streetview-btn {
    background: var(--ap-surface-2);
    color: var(--ap-text);
    border: 1px solid var(--ap-border);
    border-radius: var(--ap-radius-sm);
    padding: 0.5rem 0.6rem;
    font-size: 0.8rem;
    font-weight: 700;
    cursor: pointer;
    font-family: inherit;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 0.35rem;
    transition: background 0.15s, border-color 0.15s, transform 0.08s;
    flex-shrink: 0;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
.ap-streetview-btn:hover {
    background: var(--ap-surface-hover);
    border-color: var(--ap-border-strong);
}
.ap-streetview-btn:active { transform: scale(0.97); }
.ap-streetview-btn .mdi { font-size: 1.1rem; color: var(--ap-brand-2); }
.ap-streetview-btn:disabled,
.ap-streetview-btn[aria-disabled="true"] {
    opacity: 0.45;
    cursor: not-allowed;
}

/* ── Street View modal ────────────────────────────────────── */
.ap-sv-modal {
    position: fixed;
    inset: 0;
    z-index: 700;
    background: rgba(0, 0, 0, 0.7);
    display: none;
    align-items: center;
    justify-content: center;
    padding: 2rem 1rem;     /* mt-2/mb-2 stacked twice from the original */
    opacity: 0;
    transition: opacity 0.2s ease;
}
.ap-sv-modal.is-open { display: flex; opacity: 1; }
.ap-sv-modal-card {
    position: relative;
    width: 100%;
    height: 100%;
    max-width: 80rem;
    max-height: calc(100vh - 4rem);
    background: var(--ap-surface);
    border-radius: var(--ap-radius);
    overflow: hidden;
    box-shadow: 0 24px 60px rgba(0, 0, 0, 0.5);
    display: flex;
    flex-direction: column;
}
.ap-sv-modal-head {
    display: flex;
    align-items: center;
    gap: 0.75rem;
    padding: 1rem;
    background: var(--ap-text);
    color: var(--ap-surface);
    flex-shrink: 0;
}
html[data-theme="dark"] .ap-sv-modal-head {
    background: #1e242d;
    color: var(--ap-text);
}
.ap-sv-modal-head > .mdi {
    font-size: 1.4rem;
    color: inherit;
}
.ap-sv-modal-titles { flex: 1; min-width: 0; }
.ap-sv-modal-title {
    font-weight: 800;
    font-size: 1.05rem;
    line-height: 1.2;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.ap-sv-modal-sub {
    font-size: 0.78rem;
    opacity: 0.8;
    line-height: 1.3;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.ap-sv-modal-body {
    position: relative;
    flex: 1 1 auto;
    min-height: 0;
    background: #000;
}
#apStreetViewPano,
#apMapModalCanvas { position: absolute; inset: 0; }
#apStreetViewPano[hidden],
#apMapModalCanvas[hidden] { display: none !important; }

/* Floating view toggle — bottom-center of the modal body.
   Sits over the map / street view content. Out of the way of
   the header. */
.ap-view-toggle-fab {
    position: absolute;
    left: 50%;
    bottom: 1.1rem;
    transform: translateX(-50%);
    background: rgba(15, 23, 42, 0.88);
    color: #fff;
    border: 0;
    border-radius: 999px;
    padding: 0.7rem 1.3rem;
    font-family: inherit;
    font-size: 0.92rem;
    font-weight: 800;
    cursor: pointer;
    display: inline-flex;
    align-items: center;
    gap: 0.45rem;
    box-shadow:
        0 6px 18px rgba(0, 0, 0, 0.35),
        0 1px 3px rgba(0, 0, 0, 0.20);
    backdrop-filter: blur(8px) saturate(140%);
    -webkit-backdrop-filter: blur(8px) saturate(140%);
    z-index: 10;
    transition: background 0.15s, transform 0.08s;
    line-height: 1;
}
.ap-view-toggle-fab:hover  { background: rgba(15, 23, 42, 0.95); }
.ap-view-toggle-fab:active { transform: translateX(-50%) scale(0.96); }
.ap-view-toggle-fab .mdi   { font-size: 1.2rem; line-height: 1; }
.ap-view-toggle-fab:disabled {
    opacity: 0.4;
    cursor: not-allowed;
}

/* Recenter FAB — circular, bottom-LEFT corner of the modal
   body. Animates the map back to the call pin when tapped.
   Hidden in Street View mode (managed by apUpdateViewModeUI). */
.ap-map-recenter-fab {
    position: absolute;
    left: 1.1rem;
    bottom: 1.1rem;
    width: 2.85rem;
    height: 2.85rem;
    padding: 0;
    border: 0;
    border-radius: 50%;
    background: rgba(15, 23, 42, 0.88);
    color: #fff;
    cursor: pointer;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    box-shadow:
        0 6px 18px rgba(0, 0, 0, 0.35),
        0 1px 3px rgba(0, 0, 0, 0.20);
    backdrop-filter: blur(8px) saturate(140%);
    -webkit-backdrop-filter: blur(8px) saturate(140%);
    z-index: 10;
    transition: background 0.15s, transform 0.08s;
}
.ap-map-recenter-fab:hover  { background: rgba(15, 23, 42, 0.95); }
.ap-map-recenter-fab:active { transform: scale(0.93); }
.ap-map-recenter-fab .mdi   { font-size: 1.45rem; line-height: 1; }
.ap-map-recenter-fab[hidden] { display: none; }
.ap-sv-modal-x {
    background: rgba(255, 255, 255, 0.15);
    border: 1px solid rgba(255, 255, 255, 0.25);
    color: inherit;
    border-radius: 50%;
    width: 2.4rem;
    height: 2.4rem;
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
    padding: 0;
    transition: background 0.15s, transform 0.08s;
    font-family: inherit;
}
.ap-sv-modal-x:hover  { background: rgba(255, 255, 255, 0.28); }
.ap-sv-modal-x:active { transform: scale(0.92); }
.ap-sv-modal-x .mdi   { font-size: 1.35rem; line-height: 1; }
html[data-theme="dark"] .ap-sv-modal-x {
    background: rgba(255, 255, 255, 0.06);
    border-color: rgba(255, 255, 255, 0.15);
}

/* Apparatus hydrant popups only.
   Keep these scoped so the Address hydrant InfoWindow keeps the normal
   Google close button positioned inline with the hydrant title. */
.gm-style .gm-style-iw-c:has(.ap-hydrant-popup-close) {
    border-radius: 0.55rem;
    padding: 0.6rem 0.85rem !important;
}
.gm-style .gm-style-iw-d:has(.ap-hydrant-popup-close) {
    overflow: auto !important;
}
/* Hide Google's default close X only when the apparatus popup renders its
   own close button inside the popup header. */
.gm-style .gm-style-iw-c:has(.ap-hydrant-popup-close) .gm-ui-hover-effect {
    display: none !important;
}
.ap-hydrant-popup-head {
    display: grid;
    grid-template-columns: minmax(0, 1fr) auto;
    align-items: center;
    column-gap: 0.75rem;

    width: 100%;
    margin: 0 0 0.55rem 0;
    padding: 0 0 0.45rem 0;

    border-bottom: 1px solid #e5e7eb;
}

.ap-hydrant-popup-title {
    min-width: 0;

    font-weight: 800;
    font-size: 1rem;
    color: #0f172a;
    line-height: 1.2;

    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.ap-hydrant-popup-close {
    width: 1.65rem;
    height: 1.65rem;

    display: inline-flex;
    align-items: center;
    justify-content: center;

    padding: 0;
    margin: 0;

    background: transparent;
    border: 0;
    border-radius: 50%;

    color: #6b7280;
    font-size: 1.45rem;
    line-height: 1;
    cursor: pointer;
    font-family: inherit;
}

.ap-hydrant-popup-close:hover {
    background: #f3f4f6;
    color: #374151;
}
.ap-hydrant-popup-close:active { transform: scale(0.92); }

/* ── BENCHMARKS PAGE — 3-col grid of buttons ──────────────── */
.ap-bench-page {
    height: 100%;
    overflow-y: auto;
    padding-right: 0.25rem;
}
.ap-bench-section {
    margin-bottom: 0.85rem;
}
.ap-bench-section:last-child { margin-bottom: 0; }
.ap-bench-section-title {
    font-size: 0.92rem;
    font-weight: 800;
    text-transform: uppercase;
    letter-spacing: 0.06em;
    color: var(--ap-text-muted);
    margin: 0 0 0.55rem;
    display: flex;
    align-items: center;
    gap: 0.45rem;
}
.ap-bench-section-title .mdi { font-size: 1.2rem; color: var(--ap-brand-2); }
.ap-bench-section-title.is-exception .mdi { color: var(--ap-accent); }

/* Timeline empty state — shown when no benchmarks have been
   pressed yet. Hidden as soon as the first one fires. */
.ap-bench-empty {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 0.6rem;
    padding: 1rem 0.85rem;
    background: var(--ap-surface-2);
    border: 1.5px dashed var(--ap-border-strong);
    border-radius: var(--ap-radius-sm);
    color: var(--ap-text-muted);
    font-size: 0.88rem;
    font-weight: 600;
    text-align: center;
    line-height: 1.3;
}
.ap-bench-empty .mdi {
    font-size: 1.4rem;
    color: var(--ap-text-muted);
    opacity: 0.7;
    flex-shrink: 0;
}
.ap-bench-empty[hidden] { display: none; }

.ap-bench-grid {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    gap: 0.45rem;
}
@media (max-width: 900px) {
    .ap-bench-grid { grid-template-columns: repeat(2, 1fr); }
}
@media (max-width: 600px) {
    .ap-bench-grid { grid-template-columns: 1fr; }
}

.ap-bench-btn {
    width: 100%;
    background: var(--ap-surface);
    border: 1px solid var(--ap-border);
    border-radius: var(--ap-radius-sm);
    padding: 0.7rem 0.85rem;
    color: var(--ap-text);
    font-size: 0.9rem;
    font-weight: 700;
    text-align: left;
    cursor: pointer;
    font-family: inherit;
    display: flex;
    flex-direction: column;
    gap: 0.15rem;
    transition: background 0.15s, border-color 0.15s, transform 0.08s, box-shadow 0.15s;
    line-height: 1.25;
    min-width: 0;
    box-shadow: var(--ap-shadow-card);
}
.ap-bench-btn:hover  { border-color: var(--ap-border-strong); transform: translateY(-1px); }
.ap-bench-btn:active { transform: scale(0.98); }
.ap-bench-btn .ap-bench-label {
    display: block;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
.ap-bench-btn .ap-bench-time {
    font-size: 0.74rem;
    font-variant-numeric: tabular-nums;
    color: var(--ap-text-muted);
    font-weight: 700;
    letter-spacing: 0.02em;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
.ap-bench-btn.is-pressed {
    background: var(--ap-success-soft);
    border-color: var(--ap-success);
    color: var(--ap-success);
}
.ap-bench-btn.is-pressed .ap-bench-time { color: var(--ap-success); }
.ap-bench-btn.is-exception.is-pressed {
    background: var(--ap-accent-soft);
    border-color: var(--ap-accent);
    color: var(--ap-accent);
}
.ap-bench-btn.is-exception.is-pressed .ap-bench-time { color: var(--ap-accent); }

.ap-bench-empty {
    padding: 1.5rem 1rem;
    text-align: center;
    color: var(--ap-text-dim);
    font-size: 0.95rem;
    background: var(--ap-surface);
    border: 1px dashed var(--ap-border-strong);
    border-radius: var(--ap-radius-sm);
}

/* ── CREW PAGE ────────────────────────────────────────────── */
/* Two columns × two rows: Responders fills the left column,
   Add Crew sits top-right, On this truck sits bottom-right. */
.ap-crew-page {
    height: 100%;
    display: grid;
    grid-template-columns: 1fr 1fr;
    grid-template-rows: minmax(0, 1fr) minmax(0, 1fr);
    grid-template-areas:
        "responders add"
        "responders truck";
    gap: 0.7rem;
    min-height: 0;
}
/* Order in the HTML: Responders, On this truck, Add Crew. */
.ap-crew-page > :nth-child(1) { grid-area: responders; }
.ap-crew-page > :nth-child(2) { grid-area: truck; }
.ap-crew-page > :nth-child(3) { grid-area: add; }
@media (max-width: 900px) {
    .ap-crew-page {
        grid-template-columns: 1fr;
        grid-template-rows: auto auto auto;
        grid-template-areas:
            "responders"
            "add"
            "truck";
    }
}
.ap-crew-card { /* shares ap-card styles */ }

.ap-crew-on-list, .ap-crew-roster {
    list-style: none;
    margin: 0;
    padding: 0;
    overflow-y: auto;
    min-height: 0;
    flex: 1;
}
.ap-crew-on-item, .ap-crew-roster-item {
    display: flex;
    align-items: center;
    gap: 0.55rem;
    padding: 0.55rem 0.6rem;
    border: 1px solid var(--ap-border);
    border-radius: var(--ap-radius-sm);
    background: var(--ap-surface-2);
    margin-bottom: 0.35rem;
    font-size: 0.9rem;
}
.ap-crew-on-item:last-child, .ap-crew-roster-item:last-child { margin-bottom: 0; }
.ap-crew-dot {
    width: 0.55rem; height: 0.55rem; border-radius: 50%;
    flex-shrink: 0; background: var(--ap-text-dim);
}
.ap-crew-on-item .ap-crew-dot { background: var(--ap-success); }
.ap-crew-name { flex: 1; font-weight: 700; color: var(--ap-text); min-width: 0; }
.ap-crew-meta {
    font-size: 0.72rem; color: var(--ap-text-muted); font-weight: 700;
    letter-spacing: 0.03em; text-transform: uppercase;
    white-space: nowrap;
}
.ap-crew-time { font-size: 0.72rem; color: var(--ap-text-muted); font-variant-numeric: tabular-nums; }
.ap-crew-btn {
    background: var(--ap-surface);
    border: 1px solid var(--ap-border);
    border-radius: 999px;
    width: 1.8rem; height: 1.8rem;
    cursor: pointer;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    color: var(--ap-text);
    font-family: inherit;
    flex-shrink: 0;
    transition: background 0.15s, border-color 0.15s, transform 0.08s;
}
.ap-crew-btn:hover  { border-color: var(--ap-border-strong); }
.ap-crew-btn:active { transform: scale(0.92); }
.ap-crew-btn .mdi { font-size: 1.1rem; line-height: 1; }
.ap-crew-btn-add    { color: var(--ap-success); border-color: var(--ap-success); }
.ap-crew-btn-add:hover    { background: var(--ap-success-soft); }
.ap-crew-btn-remove { color: var(--ap-brand-2); border-color: var(--ap-brand); }
.ap-crew-btn-remove:hover { background: var(--ap-brand-soft); }
.ap-crew-btn[disabled],
.ap-crew-btn[aria-disabled="true"] {
    opacity: 0.45;
    cursor: not-allowed;
    pointer-events: none;
}

.ap-crew-roster-item.is-on-truck {
    opacity: 0.5;
}
.ap-crew-roster-item.is-on-truck::after {
    content: 'On truck';
    font-size: 0.65rem;
    font-weight: 800;
    color: var(--ap-success);
    text-transform: uppercase;
    letter-spacing: 0.05em;
}

.ap-crew-search {
    position: relative;
    margin-bottom: 0.55rem;
    flex-shrink: 0;
}
.ap-crew-search input {
    width: 100%;
    box-sizing: border-box;
    padding: 0.55rem 0.75rem 0.55rem 2.1rem;
    border-radius: var(--ap-radius-sm);
    border: 1px solid var(--ap-border);
    background: var(--ap-surface-2);
    color: var(--ap-text);
    font-size: 0.9rem;
    font-family: inherit;
}
.ap-crew-search input:focus {
    outline: none;
    border-color: var(--ap-brand);
    background: var(--ap-surface);
}
.ap-crew-search .mdi {
    position: absolute;
    left: 0.6rem; top: 50%;
    transform: translateY(-50%);
    color: var(--ap-text-muted);
    font-size: 1.1rem;
    pointer-events: none;
}

.ap-crew-station-label {
    font-size: 0.62rem;
    font-weight: 800;
    text-transform: uppercase;
    letter-spacing: 0.08em;
    color: var(--ap-text-dim);
    padding: 0.5rem 0.1rem 0.25rem;
}

.ap-crew-empty {
    text-align: center;
    padding: 1.5rem 0.5rem;
    color: var(--ap-text-dim);
    font-size: 0.9rem;
}

/* ── Settings panel ───────────────────────────────────────── */
/* Settings panel must scroll inside the fixed apparatus shell.
   The shell is a three-row grid: topbar / main / nav. The main row is
   overflow:hidden, so the active Settings panel has to become a flex column
   and the card itself becomes the scroll container. */
.ap-panel-settings[data-active="true"] {
    display: flex;
    flex-direction: column;
    height: 100%;
    min-height: 0;
    overflow: hidden;
}

.ap-panel-settings .ap-card {
    flex: 1 1 auto;
    height: 100%;
    min-height: 0;
    overflow-y: auto;
    overflow-x: hidden;
    -webkit-overflow-scrolling: touch;
    overscroll-behavior: contain;

    /* Extra breathing so the final Sign out row/button is reachable and not
       jammed against the bottom navigation/safe area. */
    padding-bottom: calc(1.25rem + env(safe-area-inset-bottom));
}

.ap-panel-settings .ap-settings-row {
    flex-shrink: 0;
}

.ap-panel-settings .ap-btn-signout {
    margin-bottom: 0.5rem;
}
.ap-settings-row {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 1rem;
    padding: 0.7rem 0;
    border-bottom: 1px solid var(--ap-border);
}
.ap-settings-row:last-child { border-bottom: 0; }
.ap-settings-label { font-weight: 700; color: var(--ap-text); font-size: 0.95rem; }
.ap-settings-hint  { font-size: 0.78rem; color: var(--ap-text-muted); margin-top: 0.15rem; }
.ap-segmented {
    display: inline-flex;
    background: var(--ap-surface-2);
    border: 1px solid var(--ap-border);
    border-radius: var(--ap-radius-sm);
    padding: 0.2rem;
    gap: 0.15rem;
}
.ap-segmented button {
    background: transparent;
    border: 0;
    border-radius: 0.4rem;
    padding: 0.4rem 0.85rem;
    font-size: 0.82rem;
    font-weight: 700;
    color: var(--ap-text-muted);
    cursor: pointer;
    font-family: inherit;
    transition: background 0.15s, color 0.15s;
}
.ap-segmented button.active {
    background: var(--ap-surface);
    color: var(--ap-text);
    box-shadow: 0 1px 3px rgba(15, 23, 42, 0.08);
}
.ap-btn-signout {
    background: transparent;
    border: 1px solid var(--ap-brand);
    color: var(--ap-brand-2);
    border-radius: var(--ap-radius-sm);
    padding: 0.6rem 1.2rem;
    font-size: 0.88rem;
    font-weight: 700;
    cursor: pointer;
    font-family: inherit;
}
.ap-btn-signout:hover { background: var(--ap-brand-soft); }

/* Sync button — used in settings to refresh the preplan cache.
   Outline style: info-blue border + text, transparent bg.
   Hover fills with info-blue. */
.ap-btn-sync {
    background: transparent;
    color: var(--ap-info);
    border: 1.5px solid var(--ap-info);
    border-radius: var(--ap-radius-sm);
    padding: 0.6rem 1.1rem;
    font-size: 0.88rem;
    font-weight: 700;
    cursor: pointer;
    font-family: inherit;
    display: inline-flex;
    align-items: center;
    gap: 0.45rem;
    transition: background 0.15s, color 0.15s, border-color 0.15s, transform 0.08s;
}
.ap-btn-sync:hover  {
    background: var(--ap-info);
    color: #fff;
}
.ap-btn-sync:active { transform: scale(0.97); }
.ap-btn-sync:disabled { opacity: 0.6; cursor: not-allowed; }
.ap-btn-sync .mdi { font-size: 1.15rem; line-height: 1; }
.ap-btn-sync .mdi.is-spinning {
    animation: apSyncSpin 0.9s linear infinite;
}
.ap-btn-sync.is-syncing {
    animation: apSyncPulse 1.4s ease-in-out infinite;
}
/* Sync button gets a soft amber pulse when a clear-cache happened
   and we need the user to re-sync. */
.ap-btn-sync.is-recommended {
    box-shadow: 0 0 0 0 rgba(245, 158, 11, 0.6);
    animation: apSyncRecommend 1.6s ease-in-out infinite;
}
@keyframes apSyncRecommend {
    0%   { box-shadow: 0 0 0 0   rgba(245, 158, 11, 0.55); }
    70%  { box-shadow: 0 0 0 10px rgba(245, 158, 11, 0);    }
    100% { box-shadow: 0 0 0 0   rgba(245, 158, 11, 0);    }
}

/* Clear app cache button + helper text */
.ap-btn-clear-cache {
    background: transparent;
    border: 1px solid var(--ap-border-strong);
    color: var(--ap-text);
    border-radius: var(--ap-radius-sm);
    padding: 0.6rem 1.1rem;
    font-size: 0.88rem;
    font-weight: 700;
    cursor: pointer;
    font-family: inherit;
    display: inline-flex;
    align-items: center;
    gap: 0.45rem;
    transition: background 0.15s, color 0.15s, transform 0.08s;
}
.ap-btn-clear-cache:hover {
    background: var(--ap-hazard-bg);
    color: var(--ap-hazard);
    border-color: var(--ap-hazard-border);
}
.ap-btn-clear-cache:active { transform: scale(0.97); }
.ap-btn-clear-cache:disabled { opacity: 0.6; cursor: not-allowed; }
.ap-btn-clear-cache .mdi { font-size: 1.15rem; }
.ap-sync-recommend {
    display: flex;
    align-items: center;
    gap: 0.35rem;
    margin-top: 0.4rem;
    padding: 0.4rem 0.65rem;
    background: rgba(245, 158, 11, 0.13);
    border: 1px solid rgba(245, 158, 11, 0.35);
    color: #b45309;
    border-radius: var(--ap-radius-sm);
    font-size: 0.84rem;
    font-weight: 700;
}
.ap-sync-recommend[hidden] { display: none; }
.ap-sync-recommend .mdi { font-size: 1rem; color: #d97706; }
html[data-theme="dark"] .ap-sync-recommend {
    background: rgba(245, 158, 11, 0.18);
    border-color: rgba(245, 158, 11, 0.45);
    color: #fbbf24;
}
html[data-theme="dark"] .ap-sync-recommend .mdi { color: #fbbf24; }
.ap-sw-version-line {
    font-family: ui-monospace, "SF Mono", Menlo, Consolas, monospace;
    font-size: 0.76rem !important;
    opacity: 0.7;
    margin-top: 0.15rem;
}
.ap-sw-version-line span { color: var(--ap-text); font-weight: 700; }
@keyframes apSyncSpin {
    from { transform: rotate(0deg);   }
    to   { transform: rotate(360deg); }
}
@keyframes apSyncPulse {
    0%, 100% { filter: brightness(1);    }
    50%      { filter: brightness(1.18); box-shadow: 0 0 0 4px rgba(37, 99, 235, 0.18); }
}

/* ── Bottom nav — 6 buttons ───────────────────────────────── */
:root {
    --ap-nav-bg:               var(--ap-surface);
    --ap-nav-border:           var(--ap-border);
    --ap-nav-text:             var(--ap-text-muted);
    --ap-nav-text-active:      var(--ap-brand-2);
    --ap-nav-bg-active:        var(--ap-brand-soft);
}
html[data-tabbar-color="dark"] {
    --ap-nav-bg:          #313a46;
    --ap-nav-border:      #252c35;
    --ap-nav-text:        rgba(255, 255, 255, 0.65);
    --ap-nav-text-active: #ffffff;
    --ap-nav-bg-active:   rgba(255, 255, 255, 0.13);
}

.ap-nav {
    background: var(--ap-nav-bg);
    border: 1px solid var(--ap-nav-border);
    border-radius: var(--ap-radius);
    padding: 0.3rem;
    display: grid;
    grid-template-columns: repeat(6, 1fr);
    gap: 0.25rem;
    margin-bottom: max(0.3rem, env(safe-area-inset-bottom));
    box-shadow: var(--ap-shadow-card);
}
.ap-nav-btn {
    background: transparent;
    border: 0;
    border-radius: var(--ap-radius-sm);
    padding: 0.95rem 0.4rem;
    color: var(--ap-nav-text);
    font-family: inherit;
    font-size: 0.92rem;
    font-weight: 700;
    cursor: pointer;
    display: flex;
    flex-direction: row;
    align-items: center;
    justify-content: center;
    gap: 0.5rem;
    transition: background 0.15s, color 0.15s;
}
.ap-nav-btn .mdi  { font-size: 1.6rem; }
.ap-nav-btn:hover { color: var(--ap-nav-text-active); }
.ap-nav-btn[data-active="true"] {
    background: var(--ap-nav-bg-active);
    color: var(--ap-nav-text-active);
}

/* ── Modals (generic) ─────────────────────────────────────── */
.ap-modal-overlay {
    position: fixed;
    inset: 0;
    z-index: 500;
    background: rgba(0, 0, 0, 0.55);
    display: none;
    align-items: center;
    justify-content: center;
    padding: 1rem;
    opacity: 0;
    transition: opacity 0.18s ease;
}
.ap-modal-overlay.is-open { display: flex; opacity: 1; }
.ap-modal {
    background: var(--ap-surface);
    border: 1px solid var(--ap-border);
    border-radius: var(--ap-radius);
    padding: 1.25rem 1.5rem 1.25rem;
    max-width: 32rem;
    width: 100%;
    box-shadow: 0 24px 60px rgba(0, 0, 0, 0.35);
    transform: translateY(1rem) scale(0.98);
    transition: transform 0.2s ease;
    max-height: calc(100vh - 2rem);
    display: flex;
    flex-direction: column;
    min-height: 0;
}
.ap-modal-overlay.is-open .ap-modal { transform: translateY(0) scale(1); }
.ap-modal-large { max-width: 56rem; }
.ap-modal-header {
    display: flex;
    align-items: center;
    gap: 0.55rem;
    margin-bottom: 0.85rem;
    flex-shrink: 0;
}
.ap-modal-header > .mdi {
    color: var(--ap-brand);
    font-size: 1.5rem;
}
.ap-modal-title { font-size: 1.05rem; font-weight: 800; color: var(--ap-text); flex: 1; min-width: 0; }
.ap-modal-x {
    background: var(--ap-surface-2);
    border: 1px solid var(--ap-border);
    border-radius: 50%;
    width: 2rem; height: 2rem;
    cursor: pointer;
    color: var(--ap-text);
    display: inline-flex; align-items: center; justify-content: center;
    font-family: inherit; flex-shrink: 0;
}
.ap-modal-x .mdi { font-size: 1.2rem; line-height: 1; }
.ap-modal-body {
    background: var(--ap-surface-2);
    border: 1px solid var(--ap-border);
    border-radius: var(--ap-radius-sm);
    padding: 0.85rem 1rem;
    font-size: 0.95rem;
    color: var(--ap-text);
    line-height: 1.5;
    overflow-y: auto;
    min-height: 0;
    flex: 1;
}
.ap-modal-foot {
    margin-top: 1rem;
    display: flex;
    justify-content: flex-end;
    gap: 0.5rem;
    flex-shrink: 0;
}
.ap-modal-btn {
    border-radius: var(--ap-radius-sm);
    padding: 0.55rem 1.2rem;
    font-weight: 700;
    cursor: pointer;
    font-family: inherit;
    font-size: 0.9rem;
    border: 1px solid transparent;
}
.ap-modal-btn-secondary {
    background: var(--ap-surface);
    border-color: var(--ap-border-strong);
    color: var(--ap-text);
}
.ap-modal-btn-secondary:hover { background: var(--ap-surface-hover); }
.ap-modal-btn-primary {
    background: var(--ap-brand);
    color: #fff;
    border-color: var(--ap-brand);
}
.ap-modal-btn-primary:hover { background: var(--ap-brand-2); }
.ap-modal-btn.is-danger {
    background: #dc2626;
    border-color: #dc2626;
    color: #fff;
}
.ap-modal-btn.is-danger:hover { background: #b91c1c; }

/* Unlock submit button — info-blue (matches the Restricted
   card button that opened the unlock modal). Outline style
   in dark mode for the same visual language as the rest of
   the dark-mode action surfaces. */
#apUnlockSubmit {
    background: #0dcaf0;
    border-color: #0dcaf0;
    color: #fff;
}
#apUnlockSubmit:hover { background: #0bb6d8; border-color: #0bb6d8; }
html[data-theme="dark"] #apUnlockSubmit {
    background: transparent;
    border: 1.5px solid #0dcaf0;
    color: #0dcaf0;
}
html[data-theme="dark"] #apUnlockSubmit:hover {
    background: #0dcaf0;
    color: #fff;
    border-color: #0dcaf0;
}

/* Load Call modal items — info on left, LOAD button on right */
.ap-call-load-item {
    display: flex;
    align-items: center;
    gap: 0.85rem;
    width: 100%;
    background: var(--ap-surface);
    border: 0;
    border-bottom: 1px solid var(--ap-border);
    text-align: left;
    padding: 0.7rem 1rem;
    color: var(--ap-text);
    font-family: inherit;
}
.ap-call-load-item:last-child { border-bottom: 0; }
.ap-call-load-item.is-current { background: var(--ap-brand-soft); }
.ap-call-load-item-info { flex: 1 1 auto; min-width: 0; }
.ap-call-load-item-row {
    display: flex;
    align-items: center;
    gap: 0.55rem;
    margin-bottom: 0.25rem;
}
.ap-call-load-item-type {
    font-size: 0.62rem;
    font-weight: 800;
    text-transform: uppercase;
    letter-spacing: 0.08em;
    padding: 0.2rem 0.55rem;
    border-radius: 999px;
    background: var(--ap-brand-soft);
    color: var(--ap-brand-2);
    flex-shrink: 0;
}
.ap-call-load-item.is-current .ap-call-load-item-type {
    background: var(--ap-brand);
    color: #fff;
}
.ap-call-load-item-time {
    font-size: 0.78rem;
    color: var(--ap-text-muted);
    font-variant-numeric: tabular-nums;
    font-weight: 600;
}
.ap-call-load-item-addr {
    font-size: 0.95rem;
    font-weight: 800;
    color: var(--ap-text);
    line-height: 1.2;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.ap-call-load-item-cross {
    font-size: 0.78rem;
    color: var(--ap-text-muted);
    margin-top: 0.1rem;
}
.ap-call-load-item-btn {
    background: var(--ap-brand);
    color: #fff;
    border: 0;
    border-radius: var(--ap-radius-sm);
    padding: 0.5rem 0.95rem;
    font-size: 0.78rem;
    font-weight: 800;
    letter-spacing: 0.08em;
    cursor: pointer;
    font-family: inherit;
    transition: background 0.15s, transform 0.08s;
    flex-shrink: 0;
    white-space: nowrap;
}
.ap-call-load-item-btn:hover  { background: var(--ap-brand-2); }
.ap-call-load-item-btn:active { transform: scale(0.97); }
.ap-call-load-item-badge {
    font-size: 0.62rem;
    font-weight: 800;
    letter-spacing: 0.08em;
    color: var(--ap-brand-2);
    background: #fff;
    border: 1px solid var(--ap-brand);
    border-radius: 999px;
    padding: 0.3rem 0.65rem;
    flex-shrink: 0;
}

/* ── Unlock Restricted modal ───────────────────────────────── */
.ap-unlock-prompt {
    margin: 0 0 0.85rem;
    font-size: 0.88rem;
    color: var(--ap-text);
    line-height: 1.45;
}
.ap-unlock-code {
    width: 100%;
    box-sizing: border-box;
    text-align: center;
    font-size: 1.8rem;
    letter-spacing: 0.4em;
    padding: 0.7rem 0.85rem;
    border: 1px solid var(--ap-border);
    border-radius: var(--ap-radius-sm);
    background: var(--ap-surface);
    color: var(--ap-text);
    font-family: ui-monospace, "SF Mono", Menlo, Consolas, monospace;
    font-weight: 800;
}
.ap-unlock-code:focus {
    outline: none;
    border-color: #0dcaf0;
    box-shadow: 0 0 0 3px rgba(13, 202, 240, 0.22);
}
.ap-unlock-error {
    background: var(--ap-hazard-bg);
    border: 1px solid var(--ap-hazard-border);
    color: var(--ap-hazard);
    border-radius: var(--ap-radius-sm);
    padding: 0.55rem 0.75rem;
    font-size: 0.85rem;
    font-weight: 700;
    margin-top: 0.7rem;
    line-height: 1.35;
}
.ap-unlock-result { /* shown post-success */ }
.ap-unlock-success {
    background: var(--ap-success-soft);
    border: 1px solid var(--ap-success);
    color: var(--ap-success);
    border-radius: var(--ap-radius-sm);
    padding: 0.6rem 0.85rem;
    font-size: 0.85rem;
    font-weight: 700;
    margin-bottom: 0.85rem;
    display: flex;
    align-items: center;
    gap: 0.4rem;
}
.ap-unlock-success .mdi { font-size: 1.2rem; }
.ap-unlock-data {
    background: var(--ap-surface-2);
    border: 1px solid var(--ap-border);
    border-radius: var(--ap-radius-sm);
    padding: 0.85rem 1rem;
    font-size: 0.96rem;
    line-height: 1.5;
    white-space: pre-wrap;
    word-break: break-word;
    color: var(--ap-text);
    max-height: 60vh;
    overflow-y: auto;
}

/* Restricted button on preplan card list — outline style,
   info-blue. Same color as Secure (they're related actions). */
.ap-pp-result-btn.is-restricted {
    color: #0dcaf0;
    border-color: #0dcaf0;
}
.ap-pp-result-btn.is-restricted:hover {
    background: #0dcaf0;
    color: #fff;
    border-color: #0dcaf0;
}

/* Preplans modal */
.ap-pp-search { margin-bottom: 0.6rem; position: relative; }
.ap-pp-search input {
    width: 100%; box-sizing: border-box;
    padding: 0.55rem 0.75rem 0.55rem 2.1rem;
    border-radius: var(--ap-radius-sm);
    border: 1px solid var(--ap-border);
    background: var(--ap-surface);
    color: var(--ap-text);
    font-size: 0.95rem;
    font-family: inherit;
}
.ap-pp-search input:focus { outline: none; border-color: var(--ap-brand); }
.ap-pp-search .mdi {
    position: absolute; left: 0.6rem; top: 50%;
    transform: translateY(-50%);
    color: var(--ap-text-muted); font-size: 1.1rem;
    pointer-events: none;
}
.ap-pp-table {
    width: 100%;
    border-collapse: collapse;
    font-size: 0.88rem;
}
.ap-pp-table thead th {
    text-align: left;
    font-size: 0.66rem;
    font-weight: 800;
    text-transform: uppercase;
    letter-spacing: 0.08em;
    color: var(--ap-text-muted);
    padding: 0.45rem 0.6rem;
    border-bottom: 1px solid var(--ap-border);
    cursor: pointer;
    user-select: none;
    background: var(--ap-surface);
    position: sticky;
    top: 0;
    z-index: 1;
}
.ap-pp-table thead th:hover { color: var(--ap-text); }
.ap-pp-table thead th.is-sorted::after {
    content: ' \25BC';   /* ▼ */
    font-size: 0.7em;
    margin-left: 0.2rem;
    color: var(--ap-brand);
}
.ap-pp-table thead th.is-sorted.is-asc::after { content: ' \25B2'; }
.ap-pp-table tbody td {
    padding: 0.55rem 0.6rem;
    border-bottom: 1px solid var(--ap-border);
    vertical-align: top;
}
.ap-pp-table tbody tr {
    cursor: pointer;
    transition: background 0.1s;
}
.ap-pp-table tbody tr:hover { background: var(--ap-surface-hover); }
.ap-pp-table tbody tr:last-child td { border-bottom: 0; }
.ap-pp-name { font-weight: 700; color: var(--ap-text); }
.ap-pp-dist { font-variant-numeric: tabular-nums; color: var(--ap-text-muted); white-space: nowrap; }
.ap-pp-hazard-pill {
    display: inline-flex;
    align-items: center;
    gap: 0.2rem;
    background: var(--ap-hazard-bg);
    color: var(--ap-hazard-text);
    border: 1px solid var(--ap-hazard-border);
    border-radius: 999px;
    padding: 0.1rem 0.5rem;
    font-size: 0.65rem;
    font-weight: 800;
    text-transform: uppercase;
    letter-spacing: 0.05em;
}
.ap-pp-hazard-pill .mdi { font-size: 0.85rem; }

.ap-pp-detail .ap-modal-back {
    background: var(--ap-surface-2);
    border: 1px solid var(--ap-border);
    border-radius: var(--ap-radius-sm);
    padding: 0.4rem 0.9rem;
    color: var(--ap-text);
    font-weight: 700;
    cursor: pointer;
    font-family: inherit;
    font-size: 0.85rem;
    display: inline-flex;
    align-items: center;
    gap: 0.3rem;
    margin-bottom: 0.85rem;
}
.ap-pp-detail .ap-modal-back:hover { background: var(--ap-surface-hover); }
.ap-pp-detail-name {
    font-size: 1.4rem;
    font-weight: 800;
    color: var(--ap-text);
    margin: 0 0 0.2rem;
    letter-spacing: -0.01em;
}
.ap-pp-detail-address {
    color: var(--ap-text-muted);
    margin: 0 0 0.85rem;
}

/* ── PREPLANS PANEL ───────────────────────────────────────── */
.ap-panel-preplans { height: 100%; min-height: 0; }
.ap-panel-preplans .ap-pp-card {
    height: 100%;
    display: flex;
    flex-direction: column;
}
.ap-pp-meta {
    margin-left: auto;
    font-size: 0.7rem;
    font-weight: 700;
    text-transform: none;
    letter-spacing: 0;
    color: var(--ap-text-dim);
    display: inline-flex;
    align-items: center;
    gap: 0.3rem;
}
.ap-pp-meta.is-offline { color: var(--ap-info); }
.ap-pp-meta .mdi       { color: inherit; font-size: 0.95rem; }

.ap-pp-status {
    font-size: 0.78rem;
    color: var(--ap-text-muted);
    min-height: 1.1em;
    margin: 0.15rem 0 0.5rem;
    flex-shrink: 0;
}

/* Two-column search row — substring + Google address autocomplete */
.ap-pp-search-row {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 0.5rem;
    margin-bottom: 0.55rem;
    flex-shrink: 0;
}
.ap-pp-search-row .ap-pp-search { margin-bottom: 0; }
@media (max-width: 700px) {
    .ap-pp-search-row { grid-template-columns: 1fr; gap: 0.4rem; }
}

/* Active geo-sort indicator — shows the current Google address +
   a clear button. Tinted info-blue so it reads as "filter active". */
.ap-pp-geo-pill {
    display: inline-flex;
    align-items: center;
    gap: 0.4rem;
    background: var(--ap-info-soft);
    color: var(--ap-info);
    border: 1px solid var(--ap-info);
    border-radius: 999px;
    padding: 0.25rem 0.4rem 0.25rem 0.7rem;
    font-size: 0.76rem;
    font-weight: 700;
    margin-bottom: 0.45rem;
    flex-shrink: 0;
    align-self: flex-start;
    max-width: 100%;
}
.ap-pp-geo-pill[hidden] { display: none; }
.ap-pp-geo-pill > .mdi { font-size: 1rem; flex-shrink: 0; }
.ap-pp-geo-pill > span { font-weight: 600; }
.ap-pp-geo-pill strong {
    font-weight: 800;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    min-width: 0;
}
.ap-pp-geo-pill button {
    background: transparent;
    border: 0;
    color: inherit;
    cursor: pointer;
    padding: 0;
    width: 1.5rem;
    height: 1.5rem;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    border-radius: 50%;
    flex-shrink: 0;
    font-family: inherit;
}
.ap-pp-geo-pill button:hover { background: rgba(37, 99, 235, 0.18); }
.ap-pp-geo-pill button .mdi { font-size: 1rem; }

/* Google's Places autocomplete dropdown — make it match our look */
.pac-container {
    border-radius: var(--ap-radius-sm);
    border: 1px solid var(--ap-border);
    box-shadow: 0 8px 28px rgba(15, 23, 42, 0.18);
    margin-top: 0.3rem;
    font-family: inherit;
    z-index: 9999 !important;
}
.pac-item {
    padding: 0.55rem 0.75rem;
    cursor: pointer;
    font-size: 0.85rem;
    border-top: 1px solid var(--ap-border);
}
.pac-item:first-child { border-top: 0; }
.pac-item:hover { background: var(--ap-surface-hover); }
.pac-item-query { font-size: inherit; color: var(--ap-text); font-weight: 700; }
.pac-matched { color: var(--ap-brand); }

.ap-pp-results {
    display: flex;
    flex-direction: column;
    gap: 0.55rem;
    flex: 1 1 auto;
    min-height: 0;
    overflow-y: auto;
    -webkit-overflow-scrolling: touch;
    overscroll-behavior: contain;
    padding-bottom: 0.4rem;
}
.ap-pp-results::-webkit-scrollbar { width: 6px; }
.ap-pp-results::-webkit-scrollbar-thumb {
    background: var(--ap-border-strong);
    border-radius: 3px;
}

/* Result cards — horizontal layout: info on left, action
   buttons inline on the right. Info column stacks name,
   address, then distance pill underneath — all left-aligned. */
.ap-pp-result {
    background: var(--ap-surface);
    border: 1px solid var(--ap-border);
    border-radius: var(--ap-radius-sm);
    padding: 0.65rem 0.8rem;
    display: flex;
    align-items: center;
    gap: 0.7rem;
    box-shadow: 0 1px 3px rgba(0, 0, 0, 0.04);
}
html[data-theme="dark"] .ap-pp-result {
    background: var(--ap-surface-2);
}
.ap-pp-result-info {
    flex: 1 1 auto;
    min-width: 0;
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: 0.18rem;
}
.ap-pp-result-name {
    font-weight: 800;
    font-size: 1rem;
    color: var(--ap-text);
    line-height: 1.2;
    max-width: 100%;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.ap-pp-result-row2 {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    width: 100%;
    min-width: 0;
    /* Address + distance hug the left side together; any
       leftover horizontal space goes to the right of the pill,
       between row2 and the action buttons. */
    justify-content: flex-start;
}
.ap-pp-result-addr {
    flex: 0 1 auto;     /* don't grow; shrink only if overflowing */
    min-width: 0;
    font-size: 0.82rem;
    color: var(--ap-text-muted);
    line-height: 1.25;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.ap-pp-result-distance {
    display: inline-flex;
    align-items: center;
    gap: 0.2rem;
    font-size: 0.7rem;
    font-weight: 800;
    color: #fff;
    background: var(--ap-brand);
    text-transform: uppercase;
    letter-spacing: 0.03em;
    padding: 0.18rem 0.5rem;
    border-radius: 999px;
    line-height: 1.2;
    box-shadow: 0 1px 2px rgba(0, 0, 0, 0.12);
    flex-shrink: 0;
}
.ap-pp-result-distance.is-near {
    background: #198754;     /* bs5 success — within 100 m */
}
.ap-pp-result-distance .mdi { font-size: 0.8rem; }

.ap-pp-result-actions {
    display: flex;
    gap: 0.35rem;
    flex-shrink: 0;
    align-items: stretch;
}
/* Preplan card action buttons — outline style. All buttons
   the same width regardless of label length so a card with
   "Hazards | Secure | Full" reads visually balanced. */
.ap-pp-result-btn {
    flex: 0 0 7rem;
    width: 7rem;
    background: transparent;
    border: 1.5px solid var(--ap-brand);
    color: var(--ap-brand);
    border-radius: 0.55rem;
    padding: 0.5rem 0.4rem;
    font-family: inherit;
    font-weight: 800;
    font-size: 0.72rem;
    text-transform: uppercase;
    letter-spacing: 0.03em;
    line-height: 1;
    cursor: pointer;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 0.3rem;
    transition: background 0.12s, color 0.12s, border-color 0.12s, transform 0.1s;
    white-space: nowrap;
}
.ap-pp-result-btn:active   { transform: scale(0.97); }
.ap-pp-result-btn .mdi     { font-size: 0.95rem; }

/* Action-specific colors — each modifier sets its outline
   color, then hover fills the bg with that same color and
   switches the text to white. */
.ap-pp-result-btn.is-hazards {
    color: var(--ap-hazard);
    border-color: var(--ap-hazard);
}
.ap-pp-result-btn.is-hazards:hover {
    background: var(--ap-hazard);
    color: #fff;
}
.ap-pp-result-btn.is-secure {
    color: #0dcaf0;
    border-color: #0dcaf0;
}
.ap-pp-result-btn.is-secure:hover {
    background: #0dcaf0;
    color: #fff;
}
.ap-pp-result-btn.is-full {
    color: #6c757d;
    border-color: #6c757d;
}
.ap-pp-result-btn.is-full:hover {
    background: #6c757d;
    color: #fff;
}

/* Empty state */
.ap-pp-empty {
    text-align: center;
    padding: 1rem 1rem 1.4rem;
    color: var(--ap-text-muted);
}
.ap-pp-empty .mdi {
    font-size: 2.2rem;
    opacity: 0.35;
    color: var(--ap-text);
    display: block;
    margin-bottom: 0.25rem;
}
.ap-pp-empty-title {
    font-weight: 800;
    color: var(--ap-text);
    margin-bottom: 0.25rem;
}
.ap-pp-empty-sub {
    font-size: 0.85rem;
    line-height: 1.45;
}

/* ── PREPLAN MODAL (body-level overlay) ───────────────────── */
/* Sizing matches the Map modal: 2rem top/bottom padding, 1rem
   L/R; max-height calc(100vh - 4rem); max-width 80rem. */
.ap-pp-modal {
    position: fixed;
    inset: 0;
    z-index: 600;
    background: rgba(0, 0, 0, 0.55);
    backdrop-filter: blur(8px) saturate(160%);
    -webkit-backdrop-filter: blur(8px) saturate(160%);
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 2rem 1rem;
    opacity: 0;
    pointer-events: none;
    transition: opacity 0.2s ease;
}
html[data-theme="dark"] .ap-pp-modal {
    background: rgba(15, 17, 21, 0.55);
}
.ap-pp-modal[hidden]      { display: none; }
.ap-pp-modal.is-open      { opacity: 1; pointer-events: auto; }
.ap-pp-modal-card {
    position: relative;
    background: var(--ap-surface);
    color: var(--ap-text);
    width: 100%;
    max-width: 80rem;
    height: 100%;
    max-height: calc(100vh - 4rem);
    border-radius: var(--ap-radius);
    overflow: hidden;
    display: flex;
    flex-direction: column;
    box-shadow: 0 16px 50px rgba(0, 0, 0, 0.4);
    transform: scale(0.97) translateY(0.5rem);
    transition: transform 0.2s ease;
}
.ap-pp-modal.is-open .ap-pp-modal-card { transform: scale(1) translateY(0); }

.ap-pp-modal-head {
    display: flex;
    align-items: center;
    gap: 0.65rem;
    padding: 0.85rem 1rem;
    border-bottom: 1px solid var(--ap-border);
    background: var(--ap-surface-2);
    flex-shrink: 0;
    transition: background 0.2s, border-color 0.2s;
}
.ap-pp-modal-titles { flex: 1; min-width: 0; }
.ap-pp-modal-title {
    font-weight: 800;
    font-size: 1.1rem;
    line-height: 1.2;
    color: var(--ap-text);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.ap-pp-modal-sub {
    font-size: 0.82rem;
    color: var(--ap-text-muted);
    line-height: 1.3;
    margin-top: 0.1rem;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* Themed headers — match the action button that opened the modal */
.ap-pp-modal-card.is-hazards .ap-pp-modal-head { background: var(--ap-hazard);  border-bottom-color: rgba(0, 0, 0, 0.18); }
.ap-pp-modal-card.is-secure  .ap-pp-modal-head { background: #0dcaf0;           border-bottom-color: rgba(0, 0, 0, 0.18); }
.ap-pp-modal-card.is-full    .ap-pp-modal-head { background: #6c757d;           border-bottom-color: rgba(0, 0, 0, 0.18); }
.ap-pp-modal-card.is-hazards .ap-pp-modal-title,
.ap-pp-modal-card.is-secure  .ap-pp-modal-title,
.ap-pp-modal-card.is-full    .ap-pp-modal-title { color: #fff; }
.ap-pp-modal-card.is-hazards .ap-pp-modal-sub,
.ap-pp-modal-card.is-secure  .ap-pp-modal-sub,
.ap-pp-modal-card.is-full    .ap-pp-modal-sub { color: rgba(255, 255, 255, 0.85); }

.ap-pp-modal-filter {
    position: relative;
    padding: 0.55rem 0.85rem;
    border-bottom: 1px solid var(--ap-border);
    background: var(--ap-surface);
    flex-shrink: 0;
    display: flex;
    align-items: center;
    gap: 0.4rem;
}
.ap-pp-modal-filter[hidden] { display: none; }
.ap-pp-modal-filter > .mdi { color: var(--ap-text-muted); font-size: 1.1rem; }
.ap-pp-modal-filter input {
    flex: 1;
    padding: 0.5rem 0.6rem;
    border-radius: var(--ap-radius-sm);
    border: 1px solid var(--ap-border);
    background: var(--ap-surface-2);
    color: var(--ap-text);
    font-family: inherit;
    font-size: 0.95rem;
}
.ap-pp-modal-filter input:focus {
    outline: none;
    border-color: var(--ap-brand);
    background: var(--ap-surface);
}

.ap-pp-modal-body {
    overflow-y: auto;
    -webkit-overflow-scrolling: touch;
    flex: 1 1 0;
    min-height: 0;
    padding: 0.35rem 0 4.5rem;   /* extra bottom for the FAB */
    background: var(--ap-surface);
}

/* Full Preplan field rows */
.ap-pp-modal-body .ap-pp-field {
    padding: 0.6rem 1rem 0.65rem;
    border-bottom: 1px solid var(--ap-border);
}
.ap-pp-modal-body .ap-pp-field:last-child { border-bottom: 0; }
.ap-pp-modal-body .ap-pp-field[hidden]    { display: none; }
.ap-pp-field-label {
    font-size: 0.68rem;
    font-weight: 800;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    color: var(--ap-text-muted);
    margin-bottom: 0.18rem;
    display: inline-flex;
    align-items: center;
    gap: 0.3rem;
}
.ap-pp-field-label::before {
    content: '';
    width: 3px;
    height: 11px;
    background: var(--ap-brand);
    border-radius: 2px;
    display: inline-block;
}
.ap-pp-field-value {
    font-size: 0.95rem;
    line-height: 1.45;
    color: var(--ap-text);
    word-break: break-word;
    white-space: pre-wrap;
}

/* Hazards / Secure prose body */
.ap-pp-modal-prose {
    padding: 1rem 1.1rem 5rem;
    font-size: 1rem;
    line-height: 1.55;
    color: var(--ap-text);
    white-space: pre-wrap;
    word-break: break-word;
}

/* Floating close FAB — always reachable */
.ap-pp-modal-fab-close {
    position: absolute;
    right: 0.85rem;
    bottom: 0.85rem;
    width: 3.2rem;
    height: 3.2rem;
    border-radius: 50%;
    background: var(--ap-brand);
    color: #fff;
    border: 0;
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 0;
    box-shadow: 0 4px 14px rgba(0, 0, 0, 0.3), 0 1px 4px rgba(0, 0, 0, 0.18);
    z-index: 5;
    transition: transform 0.12s, filter 0.12s;
}
.ap-pp-modal-fab-close:active { transform: scale(0.93); filter: brightness(0.9); }
.ap-pp-modal-fab-close:hover  { filter: brightness(1.1); }
.ap-pp-modal-fab-close .mdi   { font-size: 1.55rem; line-height: 1; }

/* FAB matches the theme of the modal header */
.ap-pp-modal-card.is-hazards .ap-pp-modal-fab-close { background: var(--ap-hazard); }
.ap-pp-modal-card.is-secure  .ap-pp-modal-fab-close { background: #0dcaf0; color: #fff; }
.ap-pp-modal-card.is-full    .ap-pp-modal-fab-close { background: #6c757d; color: #fff; }



/* ==========================================================================
   Source: inline <style id="fn-fontsize-rules"> in export.php
   ========================================================================== */

html { font-size: 18.4px !important; }
html[data-fn-fontsize="standard"] { font-size: 18.4px !important; }
html[data-fn-fontsize="large"]    { font-size: 20px !important; }
html[data-fn-fontsize="xlarge"]   { font-size: 22px !important; }
body { font-size: 1rem !important; }



/* ==========================================================================
   Source: inline <style> in export.php
   ========================================================================== */

:root {
    --fn-brand:        #313a46;
    --fn-brand-soft:   rgba(49, 58, 70, .10);
    --fn-accent:       #B03A2E;
    --fn-accent-soft:  rgba(176, 58, 46, .10);
    --fn-safe-top:     max(env(safe-area-inset-top, 0px), 2.75rem);
    --fn-safe-bottom:  max(env(safe-area-inset-bottom, 0px), .5rem);
}

* { -webkit-tap-highlight-color: transparent; }

/* Defensive scroll rules — keep these in case any cached
   liquid-glass / service-worker copy tries to set overflow:hidden.
   Standalone admin pages need to be free-scrolling at all times. */
html, body {
    overflow-y: auto !important;
    overflow-x: hidden;
    height: auto !important;
    margin: 0;
}

html, body {
    background: var(--fn-body-bg);
    color: var(--fn-text);
    font-family: system-ui, -apple-system, 'Segoe UI', Roboto, sans-serif;
    -webkit-font-smoothing: antialiased;
}

/* ── Body padding ──────────────────────────────────────────
   On MOBILE, .fn-top-chrome is position:fixed (taken out of
   flow), so body needs padding-top to clear it.
   On DESKTOP, .fn-top-chrome is position:sticky and IS the
   first in-flow element — adding body padding-top there just
   creates a giant empty band above the hero. So the padding
   is mobile-only. */
body {
    padding-bottom: calc(var(--fn-safe-bottom) + 1rem);
}
@media (hover: none) and (pointer: coarse) {
    body {
        padding-bottom: calc(var(--fn-safe-bottom) + 1rem);
    }
}

.fn-page-back-link {
    display: inline-flex;
    align-items: center;
    gap: .15rem;
    color: var(--fn-text-muted);
    background: transparent;
    border: 0;
    padding: .35rem .25rem;
    margin: 0 0 .65rem -.25rem;
    font-weight: 700;
    font-size: .9rem;
    text-decoration: none;
    cursor: pointer;
    line-height: 1;
}
.fn-page-back-link:hover, .fn-page-back-link:active { color: var(--fn-text); }
.fn-page-back-link .mdi { font-size: 1.2rem; }

/* ── Container ─────────────────────────────────────────────
   Mobile: 720px max-width is way more than the viewport
   anyway, so this just means "full width". On desktop, match
   the hero's 1180px so the content lines up edge-to-edge with
   the floating hero card above it. */
.fn-admin-container {
    max-width: 720px;
    margin: 0 auto;
    padding: .85rem 1rem 1rem;
}
@media (hover: hover) and (pointer: fine) {
    .fn-admin-container {
        max-width: calc(100% - 2rem);
        width: calc(100% - 2rem);
        padding: 1rem 1.25rem 1.5rem;
    }
}

/* Section cards — match the modal body styling in
   accounts-admin.php so the two admin pages feel like one family. */
.fn-exp-section { margin-bottom: 1rem; }
.fn-exp-section-title {
    font-size: .68rem;
    font-weight: 800;
    text-transform: uppercase;
    letter-spacing: .05em;
    color: var(--fn-text-muted);
    margin: 0 0 .4rem .15rem;
}
.fn-exp-card {
    background: var(--fn-card-bg);
    border: 1px solid var(--fn-card-border);
    border-radius: .8rem;
    padding: .85rem 1rem;
}

.fn-exp-row {
    display: flex;
    align-items: center;
    gap: .75rem;
    padding: .55rem 0;
    border-bottom: 1px solid var(--fn-card-border);
}
.fn-exp-row:first-child { padding-top: 0; }
.fn-exp-row:last-child  { padding-bottom: 0; border-bottom: 0; }
.fn-exp-row > label {
    flex: 0 0 9rem;
    font-weight: 700;
    color: var(--fn-text-muted);
    font-size: .88rem;
}
.fn-exp-control {
    flex: 1 1 auto;
    min-width: 0;
}

/* On the narrowest phones, stack label above control so the
   right-hand col gets full width — better for the 3-per-row
   quick-set pill grid. */
@media (max-width: 460px) {
    .fn-exp-row {
        flex-direction: column;
        align-items: stretch;
        gap: .4rem;
        padding: .65rem 0;
    }
    .fn-exp-row > label { flex: 0 0 auto; }
}

input[type="date"].fn-exp-input,
input[type="text"].fn-exp-input,
select.fn-exp-input {
    width: 100%;
    box-sizing: border-box;
    padding: .55rem .7rem;
    border-radius: .5rem;
    border: 1px solid var(--fn-card-border);
    background: var(--fn-body-bg);
    color: var(--fn-text);
    font-size: .92rem;
    font-family: inherit;
    min-height: 2.35rem;
}
input.fn-exp-input:focus,
select.fn-exp-input:focus {
    outline: none;
    border-color: var(--fn-brand);
}

/* ── Quick-set pills ───────────────────────────────────────
   3-per-row grid. Each pill expands to fill its column slot,
   so 6 pills become 2 neat rows. On mobile the col is full-
   width (label stacks above), so each pill is ~1/3 of the
   row width — easy to tap. */
.fn-exp-quick {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    gap: .4rem;
    margin-top: .4rem;
}
.fn-exp-quick button {
    background: transparent;
    border: 1.5px solid var(--fn-brand);
    color: var(--fn-brand);
    border-radius: 999px;
    padding: .45rem .5rem;
    font-size: .82rem;
    font-weight: 700;
    font-family: inherit;
    cursor: pointer;
    text-align: center;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    transition: background .12s, color .12s, transform .08s;
}
.fn-exp-quick button:hover  { background: var(--fn-brand); color: #fff; }
.fn-exp-quick button:active { transform: scale(.97); }
[data-bs-theme="dark"] .fn-exp-quick button {
    border-color: var(--fn-text);
    color: var(--fn-text);
}
[data-bs-theme="dark"] .fn-exp-quick button:hover {
    background: var(--fn-text);
    color: var(--fn-body-bg);
}

.fn-exp-checks {
    display: flex;
    flex-wrap: wrap;
    gap: .4rem 1.1rem;
}
.fn-exp-checks label {
    display: inline-flex;
    align-items: center;
    gap: .4rem;
    font-weight: 600;
    color: var(--fn-text);
    cursor: pointer;
    padding: .25rem .35rem;
    font-size: .9rem;
}
.fn-exp-radios {
    display: flex;
    flex-direction: column;
    gap: .55rem;
}
.fn-exp-radios > label {
    display: flex;
    align-items: flex-start;
    gap: .5rem;
    cursor: pointer;
    font-weight: 700;
    color: var(--fn-text);
}
.fn-exp-radios input { margin-top: .25rem; flex-shrink: 0; }
.fn-exp-radios .desc {
    color: var(--fn-text-muted);
    font-size: .8rem;
    font-weight: 500;
    margin-top: .1rem;
}

.fn-exp-hint {
    font-size: .76rem;
    color: var(--fn-text-muted);
    margin-top: .45rem;
    display: flex;
    align-items: flex-start;
    gap: .35rem;
    line-height: 1.4;
}
.fn-exp-hint .mdi { font-size: 1rem; line-height: 1.4; flex-shrink: 0; }

.fn-exp-submit-wrap {
    display: flex;
    justify-content: center;
    margin-top: 1.5rem;
}
.fn-exp-submit {
    background: var(--fn-brand);
    color: #fff;
    border: 0;
    border-radius: .55rem;
    padding: .85rem 1.75rem;
    font-weight: 800;
    font-size: 1rem;
    cursor: pointer;
    font-family: inherit;
    transition: background .12s, transform .08s;
    display: inline-flex;
    align-items: center;
    gap: .5rem;
    min-width: 16rem;
    justify-content: center;
}
.fn-exp-submit:active { transform: scale(.99); }
.fn-exp-submit:hover  { background: #232a35; }
.fn-exp-submit .mdi   { font-size: 1.3rem; }



/* ==========================================================================
   Source: inline <style> in sw-bootstrap.php
   ========================================================================== */

/* Offline banner — sits ON TOP of the floating hero chrome
   (.fn-top-chrome → .fn-hero from index.css) when the device is
   offline. Coordinates, height, and shape mirror the hero exactly
   so the banner appears to REPLACE the hero, not stack above it.

   Why this approach: with the floating-chrome design, the hero is
   already inset from the screen edges and the safe-area top. The
   banner just needs to slot into that same footprint at a higher
   z-index. Earlier version pinned to top: 0 with 80px of padding
   to clear the Dynamic Island; redundant now that the hero handles
   safe-area math via var(--fn-safe-top).

   Red-tinted so it reads as a real warning to the firefighter. */
#fnOfflineBanner {
    position: fixed;
    /* Same coordinates as .fn-top-chrome — must use the SAME
       safe-top resolution as the hero or the two won't align.
       The hero uses var(--fn-safe-top) (defined in liquid-glass.css
       as max(env, 0px) but overridden on admin pages to have a
       2.75rem minimum). Using env() directly would land at a
       different y-position than the hero on those pages. The
       var() with env() fallback handles both cases:
         - liquid-glass loaded → var resolves to its definition
         - liquid-glass not loaded → falls back to raw env(). */
    top:   calc(var(--fn-safe-top, env(safe-area-inset-top, 0px)) + 0.45rem);
    left:  0.3rem;
    right: 0.3rem;
    z-index: 9999;

    /* Explicit height matching hero. Default = hero default
       (.85 + 2.1 + 1 = 3.95rem). Mobile @media bumps to match
       hero's mobile (1.2 + 2.1 + 1.2 = 4.5rem). Switched from
       min-height because Safari on iPad was rendering the banner
       ~0.5rem taller than the hero even with identical min-height
       values — explicit height with box-sizing: border-box gives
       a guaranteed match. */
    height: 3.43rem;

    display: flex;
    align-items: center;
    justify-content: center;
    gap: .5rem;
    /* Horizontal padding only — flex centering handles vertical. */
    padding: 0 1rem;
    box-sizing: border-box;

    background: #b03a2e;
    color: #fff;
    /* Match hero's all-four-corners radius. */
    border-radius: 1rem;
    /* Match hero's drop shadow exactly. */
    box-shadow: 0 14px 36px -10px rgba(0,0,0,.28),
                0 4px 12px -4px rgba(0,0,0,.14);

    font-size: .9rem;
    font-weight: 800;
    letter-spacing: .03em;
    text-align: center;
    line-height: 1.3;
}
#fnOfflineBanner[hidden] { display: none !important; }
#fnOfflineBanner .mdi { font-size: 1.2rem; line-height: 1; }

/* Mobile (touch) — match the hero's mobile height bump.
   index.css mobile @media sets .fn-hero-inner padding to
   1.2rem .55rem, yielding hero height = 1.2 + 2.1 + 1.2 = 4.5rem.
   Banner mirrors that. */
@media (hover: none) and (pointer: coarse) {
    #fnOfflineBanner { height: 4.0rem; }
}



/* ==========================================================================
   Source: inline <style> in login.php
   ========================================================================== */

.fn-demo-btn {
    position: fixed;
    /* Was 1rem each side; bumped to 2rem so the button sits clearly
       inset from the screen corner instead of crowding against it. */
    bottom: calc(env(safe-area-inset-bottom, 0px) + 2rem);
    right:  calc(env(safe-area-inset-right,  0px) + 2rem);
    z-index: 10;

    display: inline-flex;
    align-items: center;
    gap: .4rem;

    padding: .65rem 1.1rem;
    border-radius: 999px;

    background: rgba(255, 255, 255, 0.12);
    color: #fff;
    border: 1px solid rgba(255, 255, 255, 0.22);
    backdrop-filter: blur(12px) saturate(140%);
    -webkit-backdrop-filter: blur(12px) saturate(140%);
    box-shadow: 0 4px 16px rgba(0, 0, 0, 0.20);

    text-decoration: none;
    font-weight: 700;
    font-size: .9rem;
    letter-spacing: .03em;
    line-height: 1;

    transition: background .15s, transform .12s, filter .15s;
    -webkit-tap-highlight-color: transparent;
}
.fn-demo-btn:hover,
.fn-demo-btn:focus,
.fn-demo-btn:visited {
    background: rgba(255, 255, 255, 0.20);
    color: #fff;
    text-decoration: none;
    outline: none;
}
.fn-demo-btn:active {
    transform: scale(.96);
    filter: brightness(.92);
}
.fn-demo-btn .mdi {
    font-size: 1.15rem;
    line-height: 1;
}



/* ==========================================================================
   Source: inline <style id="fn-fontsize-rules"> in accounts-admin.php
   ========================================================================== */

html { font-size: 18.4px !important; }
html[data-fn-fontsize="standard"] { font-size: 18.4px !important; }
html[data-fn-fontsize="large"]    { font-size: 20px !important; }
html[data-fn-fontsize="xlarge"]   { font-size: 22px !important; }
body { font-size: 1rem !important; }



/* ==========================================================================
   Source: inline <style> in accounts-admin.php
   ========================================================================== */

:root {
    --fn-brand:        #313a46;
    --fn-brand-soft:   rgba(49, 58, 70, .10);
    --fn-accent:       #B03A2E;
    --fn-accent-soft:  rgba(176, 58, 46, .10);
    --fn-header-bg:    var(--fn-brand);
    --fn-safe-top:     max(env(safe-area-inset-top, 0px), 2.75rem);
    --fn-safe-bottom:  max(env(safe-area-inset-bottom, 0px), .5rem);
}

:root,
[data-bs-theme="light"] {
    --fn-body-bg:        #FFFFFF;
    --fn-card-bg:        #F5F5F7;
    --fn-card-border:    #E3E5E9;
    --fn-text:           #1F2328;
    --fn-text-muted:     #6B7280;
    --fn-tertiary-bg:    #EEF0F3;
    --fn-shadow:         rgba(0,0,0,.06);
}
[data-bs-theme="dark"] {
    --fn-body-bg:        #1a1d21;
    --fn-card-bg:        #23272C;
    --fn-card-border:    #2E343B;
    --fn-text:           #E6E8EB;
    --fn-text-muted:     #9099A4;
    --fn-tertiary-bg:    #2A2F35;
    --fn-shadow:         rgba(0,0,0,.3);
}

* { -webkit-tap-highlight-color: transparent; }

html, body {
    margin: 0;
    background: var(--fn-body-bg);
    color: var(--fn-text);
    font-family: system-ui, -apple-system, 'Segoe UI', Roboto, sans-serif;
    -webkit-font-smoothing: antialiased;
}

body {
    /* Floating hero needs ~5rem total room: 0.45rem chrome offset +
       hero height (mobile 4.5rem from index.css = 1.2 pad + 2.1 content
       + 1.2 pad) + 0.5rem breathing = ~5.45rem. Round to 5.5rem.
       If the main app's hero height changes in index.css, this value
       must be updated to match. */
    padding-bottom: calc(var(--fn-safe-bottom) + 1rem);
}

/* Lock page scroll while the modal is up — same pattern as history.php
   so the sheet feels native and the page underneath doesn't scroll
   behind the dimmed backdrop. */
body.fn-modal-open { overflow: hidden; }

.fn-page-back-link {
    display: inline-flex;
    align-items: center;
    gap: .15rem;
    color: var(--fn-text-muted);
    background: transparent;
    border: 0;
    padding: .35rem .25rem;
    margin: 0 0 .65rem -.25rem;
    font-weight: 700;
    font-size: .9rem;
    text-decoration: none;
    cursor: pointer;
    line-height: 1;
}
.fn-page-back-link:hover, .fn-page-back-link:active {
    color: var(--fn-text);
}
.fn-page-back-link .mdi {
    font-size: 1.2rem;
}

.fn-admin-container {
    max-width: 720px;
    margin: 0 auto;
    padding: .85rem 1rem 1rem;
}

/* ── Error/info banner (success messages suppressed) ───────── */
.fn-msg {
    position: relative;
    padding: .65rem 2.5rem .65rem .85rem;
    border-radius: .55rem;
    margin-bottom: .75rem;
    font-size: .88rem;
    font-weight: 600;
}
.fn-msg.danger  { background: rgba(220,53,69,.12);  color: #842029; border: 1px solid rgba(220,53,69,.4); }
.fn-msg.info    { background: rgba(13,110,253,.10); color: #084298; border: 1px solid rgba(13,110,253,.3); }

[data-bs-theme="dark"] .fn-msg.danger { color: #ea868f; }
[data-bs-theme="dark"] .fn-msg.info   { color: #6ea8fe; }

.fn-msg-close {
    position: absolute;
    top: 50%;
    right: .4rem;
    transform: translateY(-50%);
    background: transparent;
    border: 0;
    color: currentColor;
    opacity: .55;
    width: 1.8rem; height: 1.8rem;
    border-radius: 50%;
    display: inline-flex;
    align-items: center; justify-content: center;
    cursor: pointer;
    padding: 0;
    transition: opacity .12s, background .12s, transform .08s;
}
.fn-msg-close:hover  { opacity: 1; background: rgba(0,0,0,.08); }
.fn-msg-close:active { transform: translateY(-50%) scale(.9); }
.fn-msg-close .mdi { font-size: 1.1rem; line-height: 1; }
[data-bs-theme="dark"] .fn-msg-close:hover { background: rgba(255,255,255,.08); }

/* ── Access code reveal panel ──────────────────────────────── */
.fn-code-reveal {
    position: relative;
    background: var(--fn-accent);
    color: #fff;
    padding: 1rem 1.25rem;
    border-radius: .8rem;
    margin-bottom: .85rem;
    text-align: center;
    box-shadow: 0 4px 14px rgba(176,58,46,.25);
}
.fn-code-reveal-close {
    position: absolute;
    top: .5rem;
    right: .5rem;
    width: 2rem;
    height: 2rem;
    border-radius: 50%;
    background: rgba(255, 255, 255, .18);
    border: 0;
    color: #fff;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    cursor: pointer;
    padding: 0;
    line-height: 1;
    transition: background .12s, transform .08s;
}
.fn-code-reveal-close:hover  { background: rgba(255, 255, 255, .28); }
.fn-code-reveal-close:active { transform: scale(.92); }
.fn-code-reveal-close .mdi {
    font-size: 1.2rem;
    line-height: 1;
}
.fn-code-reveal .label {
    font-size: .72rem; font-weight: 700; text-transform: uppercase;
    letter-spacing: .05em; opacity: .8;
}
.fn-code-reveal .code {
    font-family: 'SF Mono','Monaco','Menlo','Consolas',monospace;
    font-size: 2rem; font-weight: 800; letter-spacing: .25em;
    margin: .3rem 0 .15rem;
}
.fn-code-reveal .who { font-size: .85rem; opacity: .9; }
.fn-code-reveal .copy-btn {
    margin-top: .55rem; background: rgba(255,255,255,.18);
    color: #fff; border: 0; border-radius: 999px;
    padding: .35rem .85rem; font-weight: 700; font-size: .8rem; cursor: pointer;
}
.fn-code-reveal .note {
    font-size: .72rem; margin-top: .5rem; opacity: .85; line-height: 1.4;
}
.fn-code-actions {
    display: flex;
    gap: .4rem;
    justify-content: center;
    flex-wrap: wrap;
    margin-top: .55rem;
}
.fn-code-reveal .fn-code-actions .copy-btn { margin-top: 0; }
.fn-code-reveal .fn-code-actions .copy-btn .mdi {
    font-size: 1rem;
    line-height: 1;
    margin-right: .15rem;
    vertical-align: -2px;
}

/* ── Add-user trigger button (was a <details>, now opens modal) */
.fn-add-trigger {
    width: 100%;
    background: var(--fn-card-bg);
    border: 1px solid var(--fn-card-border);
    border-radius: .65rem;
    padding: .85rem 1rem;
    margin-bottom: 1rem;
    display: flex;
    align-items: center;
    gap: .6rem;
    cursor: pointer;
    color: var(--fn-text);
    font-weight: 700;
    font-size: 1rem;
    text-align: left;
    font-family: inherit;
    transition: background .12s, border-color .12s, transform .08s;
}
.fn-add-trigger:hover  { border-color: var(--fn-brand); }
.fn-add-trigger:active { transform: scale(.995); background: var(--fn-tertiary-bg); }
.fn-add-trigger .mdi-account-plus-outline {
    font-size: 1.4rem;
    color: var(--fn-brand);
}
.fn-add-trigger .fn-add-trigger-plus {
    margin-left: auto;
    font-size: 1.4rem;
    color: var(--fn-text-muted);
    opacity: .55;
}

/* ── Search box ────────────────────────────────────────────── */
.fn-search {
    position: relative;
    margin-bottom: .75rem;
}
.fn-search input {
    width: 100%;
    box-sizing: border-box;
    padding: .65rem .75rem .65rem 2.25rem;
    border-radius: .55rem;
    border: 1px solid var(--fn-card-border);
    background: var(--fn-card-bg);
    color: var(--fn-text);
    font-size: .95rem;
    font-family: inherit;
}
.fn-search input:focus {
    outline: none;
    border-color: var(--fn-brand);
    background: var(--fn-body-bg);
}
.fn-search .mdi-magnify {
    position: absolute;
    left: .65rem;
    top: 50%;
    transform: translateY(-50%);
    color: var(--fn-text-muted);
    font-size: 1.15rem;
    pointer-events: none;
}
.fn-search-clear {
    position: absolute;
    right: .35rem;
    top: 50%;
    transform: translateY(-50%);
    background: var(--fn-tertiary-bg);
    border: 0;
    width: 1.7rem; height: 1.7rem;
    border-radius: 50%;
    color: var(--fn-text-muted);
    display: none;
    align-items: center; justify-content: center;
    cursor: pointer;
    padding: 0;
}
.fn-search-clear.is-visible { display: inline-flex; }
.fn-search-clear .mdi { font-size: 1rem; line-height: 1; }

.fn-empty-state {
    text-align: center;
    padding: 1.5rem;
    color: var(--fn-text-muted);
    font-size: .9rem;
}

/* ── Add-user modal (bottom-sheet on mobile, centered on desktop) */
.fn-modal-overlay {
    position: fixed;
    inset: 0;
    z-index: 200;
    background: rgba(0, 0, 0, .55);
    opacity: 0;
    pointer-events: none;
    transition: opacity .2s ease;
    display: flex;
    align-items: flex-end;
    justify-content: center;
}
.fn-modal-overlay.is-open {
    opacity: 1;
    pointer-events: auto;
}
.fn-modal {
    background: var(--fn-body-bg);
    color: var(--fn-text);
    width: 100%;
    max-width: 600px;
    /* Tall sheet — long station lists need room, and the segmented
       role row + four input fields can push past 50vh easily. dvh
       handles the iOS address-bar resize correctly. */
    height: 90vh;
    height: 90dvh;
    border-radius: 1rem 1rem 0 0;
    box-shadow: 0 -8px 32px rgba(0, 0, 0, .25);
    transform: translateY(100%);
    transition: transform .25s cubic-bezier(.2,.85,.3,1);
    display: flex;
    flex-direction: column;
    overflow: hidden;
    position: relative;
}
.fn-modal-overlay.is-open .fn-modal {
    transform: translateY(0);
}
.fn-modal-handle {
    position: absolute;
    top: .35rem;
    left: 50%;
    transform: translateX(-50%);
    width: 2.4rem;
    height: .3rem;
    border-radius: 999px;
    background: var(--fn-text-muted);
    opacity: .3;
    pointer-events: none;
}
.fn-modal-header {
    flex-shrink: 0;
    display: flex;
    align-items: center;
    gap: .5rem;
    padding: 1.15rem 1rem .65rem;
    border-bottom: 1px solid var(--fn-card-border);
    background: var(--fn-body-bg);
}
.fn-modal-title {
    flex: 1;
    font-weight: 800;
    font-size: 1.05rem;
    color: var(--fn-text);
    line-height: 1.25;
}
.fn-modal-close {
    background: var(--fn-tertiary-bg);
    border: 0;
    width: 2.1rem;
    height: 2.1rem;
    border-radius: 50%;
    color: var(--fn-text);
    cursor: pointer;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    font-size: 1.3rem;
    padding: 0;
    flex-shrink: 0;
}
.fn-modal-close .mdi { line-height: 1; }
.fn-modal-close:active { transform: scale(.92); }
.fn-modal-body {
    /* flex: 1 + min-height: 0 is the iOS scroll fix. .fn-modal is a
       flex column with overflow:hidden; without these two, the
       default min-height:auto on flex items keeps this container
       at its content's intrinsic height. On iPhone the form is
       taller than 90dvh (especially with the virtual keyboard up),
       the parent clips the overflow, and the user can't scroll
       because the scroll container itself is never constrained
       below its content. flex:1 makes it claim the leftover space;
       min-height:0 lets it actually shrink to fit. */
    flex: 1;
    min-height: 0;
    overflow-y: auto;
    -webkit-overflow-scrolling: touch;
    overscroll-behavior: contain;
    padding: 1rem;
    padding-bottom: calc(2.75rem + env(safe-area-inset-bottom, 0px));
}

@media (min-width: 600px) {
    .fn-modal-overlay {
        align-items: center;
        padding: 1rem;
    }
    .fn-modal {
        border-radius: 1rem;
        height: auto;
        min-height: 50vh;
        max-height: 82vh;
        transform: translateY(2rem);
    }
    .fn-modal-overlay.is-open .fn-modal { transform: translateY(0); }
    .fn-modal-handle { display: none; }
    .fn-modal-header { padding-top: .9rem; }
}

/* ── Add-form fields (inside modal body) ───────────────────── */
.fn-add-form-section { margin-bottom: 1rem; }
.fn-add-form-section:last-child { margin-bottom: 0; }
.fn-add-form-label {
    font-size: .68rem;
    font-weight: 800;
    text-transform: uppercase;
    letter-spacing: .05em;
    color: var(--fn-text-muted);
    margin-bottom: .4rem;
    display: block;
}
.fn-add-form input,
.fn-add-form select {
    width: 100%;
    box-sizing: border-box;
    padding: .65rem .75rem;
    border-radius: .5rem;
    border: 1px solid var(--fn-card-border);
    background: var(--fn-body-bg);
    color: var(--fn-text);
    font-size: .95rem;
    font-family: inherit;
}
.fn-add-form input:focus,
.fn-add-form select:focus {
    outline: none;
    border-color: var(--fn-brand);
}
.fn-add-form .form-grid {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: .55rem;
}
.fn-add-form .form-grid .full { grid-column: 1 / -1; }
.fn-add-form .station-help {
    font-size: .75rem; color: var(--fn-text-muted);
    margin-top: .4rem; line-height: 1.4;
}
.fn-add-form .station-help code {
    background: var(--fn-tertiary-bg);
    padding: .05rem .3rem;
    border-radius: .25rem;
    font-size: .85em;
}

/* Role-specific field visibility. The form has three optional
   field groups; only one shows at a time based on the chosen
   role (set on the form's data-role attribute by the JS below).
     - User / Admin   →  show firefighter fields (FF#, first, last)
     - Dashboard      →  show nothing (station alone is enough)
     - Apparatus      →  show apparatus-name field only
*/
form#fnAddUserForm:not([data-role="User"]):not([data-role="Admin"]) .fields-firefighter {
    display: none;
}
form#fnAddUserForm:not([data-role="Apparatus"]) .fields-apparatus {
    display: none;
}

.fn-role-help {
    font-size: .8rem;
    color: var(--fn-text);
    background: var(--fn-tertiary-bg);
    border-radius: .5rem;
    padding: .65rem .8rem;
    line-height: 1.4;
    margin-top: .55rem;
}
.fn-role-help strong { color: var(--fn-text); }

.fn-add-submit {
    background: var(--fn-brand);
    color: #fff;
    border: 0;
    border-radius: .55rem;
    padding: .75rem 1rem;
    font-weight: 800;
    font-size: .95rem;
    cursor: pointer;
    width: 100%;
    margin-top: 1.25rem;
    font-family: inherit;
    transition: background .12s, transform .08s;
}
.fn-add-submit:active { transform: scale(.99); }

/* ── Segmented role chooser ────────────────────────────────── */
/* This is only for the Accounts Admin role chooser. Keep it scoped so it
   does not override the Settings page segmented controls. */
#fnRoleSegmented.fn-segmented {
    display: flex;
    width: 100%;
    background: var(--fn-tertiary-bg);
    border: 1px solid var(--fn-card-border);
    border-radius: .75rem;
    padding: .25rem;
    gap: .2rem;
}
#fnRoleSegmented.fn-segmented button {
    flex: 1 1 0;
    min-width: 0;
    background: transparent;
    border: 0;
    border-radius: .55rem;
    padding: .55rem .25rem;
    font-size: .82rem;
    font-weight: 700;
    color: var(--fn-text-muted);
    cursor: pointer;
    font-family: inherit;
    display: flex;
    align-items: center;
    justify-content: center;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    transition: background .15s, color .15s, box-shadow .15s, transform .08s;
}
#fnRoleSegmented.fn-segmented button:active { transform: scale(.97); }
#fnRoleSegmented.fn-segmented button.active {
    background: var(--fn-body-bg);
    color: var(--fn-text);
    box-shadow: 0 1px 3px rgba(0,0,0,.08);
}


/* ── User list rows (two-line layout) ──────────────────────── */
/* Line 1: full-width name with FF# / station inline as muted suffix.
   Line 2: role badge on the left, action controls (Code btn + role
   dropdown) pushed to the right with margin-left:auto. */
.fn-user-row {
    background: var(--fn-card-bg);
    border: 1px solid var(--fn-card-border);
    border-radius: .65rem;
    padding: .7rem .85rem;
    margin-bottom: .4rem;
    display: flex; flex-direction: column; gap: .5rem;
}
.fn-user-row.disabled { opacity: .55; }

.fn-user-line-1 {
    line-height: 1.3;
    word-break: break-word;
}
.fn-user-name {
    font-weight: 700;
    font-size: .95rem;
    color: var(--fn-text);
}
.fn-user-meta-inline {
    font-size: .8rem;
    color: var(--fn-text-muted);
    font-weight: 500;
}

.fn-user-line-2 {
    display: flex;
    align-items: center;
    gap: .4rem;
}
.fn-user-line-2 .fn-user-actions { margin-left: auto; }

.fn-user-actions { display: flex; gap: .35rem; align-items: center; }
.fn-user-actions form { margin: 0; }
.fn-user-actions button {
    background: var(--fn-tertiary-bg);
    border: 1px solid var(--fn-card-border);
    border-radius: .4rem;
    padding: .35rem .55rem;
    font-size: .75rem; font-weight: 700;
    color: var(--fn-text); cursor: pointer;
    display: inline-flex; align-items: center; gap: .25rem;
    font-family: inherit;
}
.fn-user-actions button:hover { border-color: var(--fn-brand); }
.fn-user-actions select {
    border: 1px solid var(--fn-card-border);
    border-radius: .4rem; padding: .3rem .4rem;
    font-size: .75rem;
    background: var(--fn-body-bg); color: var(--fn-text);
    font-weight: 700;
    font-family: inherit;
}

.fn-role-pill {
    font-size: .65rem; font-weight: 800;
    text-transform: uppercase; letter-spacing: .05em;
    padding: .15rem .45rem;
    border-radius: 999px;
    color: #fff;
    display: inline-block;
}
.fn-role-pill.Admin     { background: var(--fn-accent); }
.fn-role-pill.User      { background: #6c757d; }
.fn-role-pill.Disabled  { background: #343a40; }
.fn-role-pill.Dashboard { background: #0d6efd; }
.fn-role-pill.Apparatus { background: #198754; }



/* ==========================================================================
   Source: inline <style id="fn-fontsize-rules"> in responses-config.php
   ========================================================================== */

html { font-size: 18.4px !important; }
html[data-fn-fontsize="standard"] { font-size: 18.4px !important; }
html[data-fn-fontsize="large"]    { font-size: 20px !important; }
html[data-fn-fontsize="xlarge"]   { font-size: 22px !important; }
body { font-size: 1rem !important; }



/* ==========================================================================
   Source: inline <style> in responses-config.php
   ========================================================================== */

/* Admin-page-specific tweaks. The hero/.fn-top-chrome rules + safe-area
   gradient now come from liquid-glass.css and index.css via the link
   tags in the <head>; this file no longer duplicates them. */
body {
    /* Floating hero needs ~5rem total room: 0.45rem chrome offset +
       hero height (mobile 4.5rem from index.css = 1.2 pad + 2.1 content
       + 1.2 pad) + 0.5rem breathing = ~5.45rem. Round to 5.5rem.
       If the main app's hero height changes in index.css, this value
       must be updated to match. */

    padding-bottom: calc(var(--fn-safe-bottom) + 1rem);
}



/* ==========================================================================
   Source: inline <style> in pages/address.php
   ========================================================================== */

/* ── what3words auto-detected chip ─────────────────────────
   The chip renders only when render() found a /// address in
   the call data. It's an <a> tag pointing at what3words.com —
   tapping opens the installed w3w app on iOS via Universal
   Links, or the web page in Safari as a fallback. No API call
   from our side, no quota cost.

   Move to assets/css/address.css whenever convenient — inline
   here so the feature is one self-contained file to deploy. */
#fnAddrRoot .fn-w3w-chip {
    /* Same sizing rules as .fn-hydrants-info / .fn-map-btn so
       the chip + hydrants chip + map buttons read as one
       coherent action stack. The parent .fn-addr-stage already
       supplies horizontal padding and gap: .5rem between
       children, so the chip just fills the row — no margin
       of its own, no manual width math. */
    flex: 0 0 auto;
    display: flex;
    align-items: center;
    gap: .55rem;
    width: 100%;
    box-sizing: border-box;
    min-height: 2.5rem;
    padding: .5rem .85rem;
    background: rgba(225, 31, 38, .07);
    border: 1px solid rgba(225, 31, 38, .22);
    border-radius: .55rem;
    color: inherit;
    text-decoration: none;
    font-family: inherit;
    text-align: left;
    -webkit-tap-highlight-color: transparent;
}
#fnAddrRoot .fn-w3w-chip:active {
    transform: scale(0.99);
    background: rgba(225, 31, 38, .12);
}
#fnAddrRoot .fn-w3w-chip .fn-w3w-prefix {
    color: #E11F26;
    font-weight: 800;
    letter-spacing: -1px;
    font-size: 1rem;
    line-height: 1;
    flex-shrink: 0;
}
#fnAddrRoot .fn-w3w-chip .fn-w3w-words {
    flex: 1;
    font-weight: 700;
    font-size: .92rem;
    word-break: break-word;
    line-height: 1.25;
}
#fnAddrRoot .fn-w3w-chip-icon {
    color: var(--fn-text-muted, #5d6b78);
    flex-shrink: 0;
    font-size: 1.05rem;
}
[data-bs-theme="dark"] #fnAddrRoot .fn-w3w-chip {
    background: rgba(225, 31, 38, .14);
    border-color: rgba(225, 31, 38, .35);
}



/* ==========================================================================
   Source: inline <style> in pages/preplan.php
   ========================================================================== */

/* ── Page layout ──────────────────────────────────────────── */
/* When 'preplan' is in FN_FULL_PAGES, the parent .fn-page is a
   flex column with a fixed viewport-derived height. This makes
   the inner root a flex column too so the controls + status
   stay pinned at the top while the results list owns its own
   scroll. The user keeps the search bar in view at all times,
   even after scrolling through dozens of preplan cards. */
.fn-page--full #fnPreplanRoot {
    flex: 1 1 auto;
    min-height: 0;
    display: flex;
    flex-direction: column;
    /* Defensive — flex children need this so wide content
       doesn't blow out the column width on narrow screens. */
    min-width: 0;
    /* width: 100% + box-sizing: border-box pairs with the same
       defensive declaration on .fn-page-inner. Safari on iPadOS was
       resolving fnPreplanRoot's cross-axis width to content size
       (not stretching) when results re-rendered, leaving the search
       fields visibly narrower than the no-results state. Forcing
       width to 100% guarantees the same width in both states. */
    width: 100%;
    box-sizing: border-box;
}

/* ── Empty-state layout override ─────────────────────────────
   When the results area has nothing in it (idle / no-results),
   we don't WANT the page to behave as a fixed-height flex column.
   The flex layout is only there to give a scrollable list of
   result cards a pinned-controls + scrollable-results split;
   without a list, all it does is stretch fn-preplan-results
   into a huge flex item, which makes the small empty-state
   block float in the middle of an enormous void.

   When renderEmpty() runs it adds .fn-preplan-no-results to
   the section element. These overrides collapse the layout
   back to plain block flow for that one state, so the empty
   message sits right below the Reset button — same visual
   relationship a single result card would have. The moment a
   real search returns rows, renderResults() removes the class
   and the original flex layout takes over again. */
.fn-page.fn-page--full.active.fn-preplan-no-results {
    display: block;
    height: auto;
}
.fn-page--full.fn-preplan-no-results #fnPreplanRoot {
    display: block;
    flex: none;
}
.fn-page--full.fn-preplan-no-results .fn-preplan-results {
    flex: none;
    overflow: visible;
}

/* ── Collapsible controls ─────────────────────────────────────
   "Manual Search" header stays locked at the top of the page
   regardless of the collapse state — tapping it toggles
   .collapsed on the wrapper, which hides the inputs / range /
   reset below. Default state on first render is COLLAPSED so
   the preplan list dominates the screen on iPhone; the user
   pops it open only when they need to change the search.

   Visually, the whole wrapper is ringed by a brand-colored
   border so the toggle button and the body below feel like
   ONE dropdown component, not two stacked cards. When
   collapsed the border is invisible against the brand-
   colored button; when expanded the border continues around
   the white body. */
.fn-preplan-controls {
    border: 2px solid var(--fn-brand);
    border-radius: .8rem;
    overflow: hidden;
    transition: box-shadow .15s ease;
}
.fn-preplan-controls:not(.collapsed) {
    box-shadow: 0 4px 16px rgba(0, 0, 0, .08);
}

.fn-preplan-controls-toggle {
    display: flex;
    align-items: center;
    gap: .55rem;
    width: 100%;
    background: var(--fn-brand);
    border: 0;
    /* Wrapper owns the rounded corners now — toggle stays
       square and clips to the wrapper's overflow:hidden. */
    border-radius: 0;
    padding: .75rem .9rem;
    color: #fff;
    font-family: inherit;
    font-size: .9rem;
    text-align: left;
    cursor: pointer;
    transition: filter .12s ease, transform .08s ease;
    /* Stay anchored — never shrink/grow with the page below. */
    flex: 0 0 auto;
}
.fn-preplan-controls-toggle:active {
    filter: brightness(.92);
    transform: scale(.99);
}
.fn-preplan-controls-toggle-icon {
    flex-shrink: 0;
    font-size: 1.25rem;
    color: #fff;
    opacity: .85;
}
.fn-preplan-controls-toggle-label {
    flex-shrink: 0;
    font-weight: 800;
    font-size: .82rem;
    text-transform: uppercase;
    letter-spacing: .06em;
    color: #fff;
}
.fn-preplan-controls-toggle-status {
    flex: 1;
    min-width: 0;
    font-weight: 600;
    font-size: .78rem;
    color: rgba(255, 255, 255, .78);
    text-align: right;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    padding-left: .4rem;
}
.fn-preplan-controls-toggle-status:empty { display: none; }
/* Chevron sits inside a subtly inset circle to read as a
   distinct affordance rather than a passive decoration. */
.fn-preplan-controls-chevron {
    flex-shrink: 0;
    font-size: 1.35rem;
    color: #fff;
    background: rgba(255, 255, 255, .14);
    border-radius: 50%;
    width: 1.75rem;
    height: 1.75rem;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    transition: transform .18s ease, background .12s ease;
}
.fn-preplan-controls-toggle:active .fn-preplan-controls-chevron {
    background: rgba(255, 255, 255, .22);
}
/* Chevron points DOWN when expanded, LEFT when collapsed
   (default), so the icon reads as "tap to open / tap to
   close" rather than just decoration. */
.fn-preplan-controls.collapsed .fn-preplan-controls-chevron {
    transform: rotate(-90deg);
}

/* Body is the mode tabs + active input row + range + reset
   stack. Inside the brand-colored wrapper, with white body
   background so the inputs read clearly against the surround. */
.fn-preplan-controls-body {
    display: flex;
    flex-direction: column;
    gap: .65rem;
    padding: .85rem .8rem;
    background: var(--fn-body-bg);
}
.fn-preplan-controls.collapsed .fn-preplan-controls-body {
    display: none;
}

/* ── Mode tabs (Address vs Name) ──────────────────────────────
   iOS-style segmented control. Picking a tab is mutually
   exclusive — switching modes wipes the OTHER mode's input
   value and search state so the two never combine into a
   stale "address + name + radius" filter. */
.fn-preplan-mode-tabs {
    display: flex;
    gap: .25rem;
    background: var(--fn-tertiary-bg);
    border-radius: .55rem;
    padding: .25rem;
    box-sizing: border-box;
}
.fn-preplan-mode-btn {
    flex: 1 1 0;
    min-width: 0;
    background: transparent;
    border: 0;
    /* Inactive tabs are clearly muted — lighter color and a touch
       of dimming so the active tab pops by contrast. */
    color: var(--fn-text-muted);
    opacity: .72;
    font-family: inherit;
    font-size: .85rem;
    font-weight: 700;
    padding: .55rem .65rem;
    border-radius: .4rem;
    cursor: pointer;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: .3rem;
    transition: background .14s ease, color .14s ease, opacity .14s ease,
                box-shadow .14s ease, transform .08s ease;
}
.fn-preplan-mode-btn:active {
    transform: scale(.97);
}
.fn-preplan-mode-btn .mdi { font-size: 1.05rem; line-height: 1; }
/* Active tab matches the "Manual Search" button above — solid
   brand background with white text and a tiny drop shadow.
   Strong contrast against the muted inactive tab so it's
   obvious at a glance which mode you're in. */
.fn-preplan-mode-btn.active {
    background: var(--fn-brand);
    color: #fff;
    opacity: 1;
    box-shadow: 0 1px 4px rgba(0, 0, 0, .18);
}
.fn-preplan-mode-btn.active .mdi {
    color: #fff;
}

/* Mode-specific row visibility. The body holds rows for BOTH
   modes; CSS shows only the one matching the wrapper's current
   data-mode. Switching modes is a single attribute flip — no
   DOM teardown. */
.fn-preplan-controls[data-mode="address"] .mode-row--name,
.fn-preplan-controls[data-mode="name"]    .mode-row--address {
    display: none;
}

.fn-preplan-controls {
    display: flex;
    flex-direction: column;
    /* No gap — toggle button and body should sit flush against
       each other inside the brand-colored border. The original
       .65rem gap was for the legacy stacked-cards layout that
       this wrapper no longer contains directly. */
    gap: 0;
    margin-bottom: .65rem;
    /* Stay locked in place — never grow or shrink. */
    flex: 0 0 auto;
}

/* Each search input is wrapped in a "field" with a small label above */
.fn-preplan-field {
    display: flex;
    flex-direction: column;
    gap: .3rem;
    width: 100%;
    box-sizing: border-box;
}

/* Top search fields must stay full width like the range/results cards */
.fn-preplan-controls > .fn-preplan-field {
    padding: 0;
    border-bottom: 0;
    width: 100%;
    max-width: 100%;
    box-sizing: border-box;
}

.fn-preplan-field-head {
    display: inline-flex;
    align-items: center;
    gap: .35rem;
    font-size: .72rem;
    font-weight: 800;
    text-transform: uppercase;
    letter-spacing: .04em;
    color: var(--fn-text-muted);
    padding-left: .15rem;
}

.fn-preplan-field-head .mdi {
    font-size: .9rem;
}

/* Confirms the currently-active Google search anchor. Spans the
   full width of the field so it lines up with the input above
   and the range card below — visually clearer as a "this is the
   active address" banner than as a small floating pill. */
.fn-preplan-google-anchor {
    display: flex;
    align-items: center;
    gap: .4rem;
    width: 100%;
    box-sizing: border-box;
    font-size: .78rem;
    font-weight: 700;
    color: #0a4d6a;
    background: rgba(13, 202, 240, .18);
    border: 1px solid rgba(13, 202, 240, .45);
    padding: .45rem .7rem;
    border-radius: .55rem;
    line-height: 1.3;
    /* Long addresses ellipsis-truncate rather than wrap to two
       lines — keeps the banner height predictable and avoids
       pushing the range card down on narrow phones. */
    min-width: 0;
}
.fn-preplan-google-anchor > span {
    flex: 1;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.fn-preplan-google-anchor[hidden] {
    display: none;
}

.fn-preplan-google-anchor .mdi {
    font-size: .85rem;
    flex-shrink: 0;
}

[data-bs-theme="dark"] .fn-preplan-google-anchor {
    color: #7ee0f5;
    background: rgba(13, 202, 240, .12);
    border-color: rgba(13, 202, 240, .35);
}

.fn-preplan-search-row {
    position: relative;
    display: block;
    width: 100%;
    max-width: 100%;
    box-sizing: border-box;
}

.fn-preplan-search-icon {
    position: absolute;
    left: .65rem;
    top: 50%;
    transform: translateY(-50%);
    color: var(--fn-text-muted);
    font-size: 1.15rem;
    pointer-events: none;
}

.fn-preplan-search {
    display: block;
    width: 100%;
    max-width: 100%;
    box-sizing: border-box;
    margin: 0;
    padding: .65rem 2.4rem .65rem 2.3rem;
    border-radius: .55rem;
    border: 1px solid var(--fn-card-border);
    background: var(--fn-card-bg);
    color: var(--fn-text);
    font-family: inherit;
    font-size: .95rem;
    line-height: 1;
    -webkit-appearance: none;
    appearance: none;
    -webkit-box-sizing: border-box;
}

.fn-preplan-search:focus {
    outline: none;
    border-color: var(--fn-brand);
    box-shadow: 0 0 0 3px var(--fn-brand-soft);
}

.fn-preplan-search-clear {
    position: absolute;
    right: .35rem;
    top: 50%;
    transform: translateY(-50%);
    background: transparent;
    border: 0;
    color: var(--fn-text-muted);
    font-size: 1.3rem;
    line-height: 1;
    cursor: pointer;
    padding: .35rem;
    display: flex;
    align-items: center;
    justify-content: center;
}

.fn-preplan-search-clear[hidden] {
    display: none;
}

.fn-preplan-range {
    background: var(--fn-card-bg);
    border: 1px solid var(--fn-card-border);
    border-radius: .65rem;
    padding: .65rem .8rem .55rem;
    transition: opacity .2s;
    box-sizing: border-box;
    width: 100%;
}

.fn-preplan-range.disabled {
    opacity: .55;
}

.fn-preplan-range-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    margin-bottom: .35rem;
}

.fn-preplan-range-label {
    display: inline-flex;
    align-items: center;
    gap: .35rem;
    font-size: .8rem;
    font-weight: 800;
    text-transform: uppercase;
    letter-spacing: .04em;
    color: var(--fn-text-muted);
}

.fn-preplan-range-label .mdi {
    font-size: 1rem;
}

.fn-preplan-range-value {
    font-weight: 800;
    font-size: .95rem;
    color: var(--fn-brand);
    font-variant-numeric: tabular-nums;
}

[data-bs-theme="dark"] .fn-preplan-range-value {
    color: #c5d0db;
}

.fn-preplan-range-slider {
    width: 100%;
    margin: .15rem 0 .25rem;
    -webkit-appearance: none;
    appearance: none;
    height: .35rem;
    border-radius: 999px;
    background: var(--fn-tertiary-bg);
    cursor: pointer;
}

.fn-preplan-range-slider:disabled {
    cursor: not-allowed;
}

.fn-preplan-range-slider::-webkit-slider-thumb {
    -webkit-appearance: none;
    appearance: none;
    width: 1.4rem;
    height: 1.4rem;
    border-radius: 50%;
    background: var(--fn-brand);
    cursor: pointer;
    border: 2px solid #fff;
    box-shadow: 0 1px 4px rgba(0,0,0,.25);
}

.fn-preplan-range-slider::-moz-range-thumb {
    width: 1.4rem;
    height: 1.4rem;
    border-radius: 50%;
    background: var(--fn-brand);
    cursor: pointer;
    border: 2px solid #fff;
    box-shadow: 0 1px 4px rgba(0,0,0,.25);
}

.fn-preplan-range-bounds {
    display: flex;
    justify-content: space-between;
    font-size: .7rem;
    color: var(--fn-text-muted);
    margin-top: -.1rem;
}

.fn-preplan-range-note {
    margin-top: .35rem;
    font-size: .75rem;
    color: var(--fn-text-muted);
    font-style: italic;
}

.fn-preplan-range-note[hidden] {
    display: none;
}

.fn-preplan-status {
    /* Layout-wise this can hold EITHER plain text (loading /
       error / offline messages set via setStatus) OR a row of
       result-summary pill badges (set by renderResults via
       innerHTML). The flex+wrap layout handles both — a single
       text node becomes one flex item, and the badges wrap
       naturally on narrow phones if the line gets long. */
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: .3rem;
    font-size: .8rem;
    color: var(--fn-text-muted);
    margin: .35rem 0 .55rem;
    min-height: 1.65rem;
    /* Stay locked in place between controls and results. */
    flex: 0 0 auto;
}

/* ── Result-summary banner ────────────────────────────────────
   ONE full-width pill containing the count plus any filter
   qualifiers, all in a single visually-unified block. Sits in
   the same slot as the plain-text status messages (loading,
   errors) — the banner is rendered via innerHTML from
   renderResults; plain-text setStatus() calls overwrite it
   when the status is something other than a result summary. */
.fn-preplan-status-banner {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    width: 100%;
    box-sizing: border-box;
    gap: .55rem;
    background: var(--fn-brand);
    color: #fff;
    border-radius: .6rem;
    padding: .5rem .85rem;
    font-size: .78rem;
    font-weight: 700;
    line-height: 1.3;
    letter-spacing: .015em;
    box-shadow: 0 1px 3px rgba(0, 0, 0, .12);
}
/* Count is the headline — slightly larger and heavier so it
   reads first at a glance. */
.fn-preplan-status-banner .count {
    font-size: .85rem;
    font-weight: 800;
    flex-shrink: 0;
}
/* Middot separators between count and each filter qualifier.
   Faded so they're visible but recede behind the actual text. */
.fn-preplan-status-banner .sep {
    opacity: .4;
    font-weight: 400;
    flex-shrink: 0;
}
/* Each filter qualifier (proximity scope, name-match). Slightly
   lighter weight than the count so the hierarchy is "answer →
   how we got that answer". */
.fn-preplan-status-banner .filter {
    display: inline-flex;
    align-items: center;
    gap: .3rem;
    font-weight: 600;
    color: rgba(255, 255, 255, .92);
    /* Long Google addresses + long search queries should ellipsis
       rather than blow the banner off-screen. */
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.fn-preplan-status-banner .filter .mdi {
    font-size: .95rem;
    opacity: .85;
    flex-shrink: 0;
}

/* Compact outlined "Reset" button. Sits at the bottom of the
   pinned controls so it's always reachable, but visually subtle
   so it doesn't compete with the active search inputs. Tapping
   restores the page to whatever the call's defaults would show. */
.fn-preplan-reset-btn {
    appearance: none;
    -webkit-appearance: none;
    align-self: flex-end;
    display: inline-flex;
    align-items: center;
    gap: .35rem;
    padding: .45rem .75rem;
    background: transparent;
    color: var(--fn-text-muted);
    border: 1px solid var(--fn-card-border);
    /* Was .55rem. Bumped to 1rem to match other preplan buttons. */
    border-radius: 1rem;
    font-family: inherit;
    font-size: .78rem;
    font-weight: 700;
    letter-spacing: .03em;
    text-transform: uppercase;
    cursor: pointer;
    width: 100%;
    transition: background .15s, color .15s, border-color .15s, transform .1s;
}
.fn-preplan-reset-btn:active {
    transform: scale(.96);
    background: var(--fn-tertiary-bg);
    color: var(--fn-text);
}
.fn-preplan-reset-btn .mdi {
    font-size: 1rem;
    line-height: 1;
}

.fn-preplan-results {
    display: flex;
    flex-direction: column;
    gap: .55rem;
    /* This region owns the scroll. Controls and status above
       stay pinned; this is the only thing that moves when the
       user has more results than fit on screen. */
    flex: 1 1 auto;
    min-height: 0;
    overflow-y: auto;
    -webkit-overflow-scrolling: touch;
    /* Prevent scroll chaining so a flick at the bottom of the
       list doesn't bubble up to the page-host scroller and
       trigger pull-to-refresh behavior. */
    overscroll-behavior: contain;
    /* A bit of bottom padding so the last card has breathing
       room above the tab bar shadow when scrolled to the end. */
    padding-bottom: .5rem;
}
/* Slim, unobtrusive scrollbar on platforms that show one. */
.fn-preplan-results::-webkit-scrollbar { width: 4px; }
.fn-preplan-results::-webkit-scrollbar-thumb {
    background: var(--fn-card-border);
    border-radius: 2px;
}

.fn-preplan-card {
    background: var(--fn-card-bg);
    border: 1px solid var(--fn-card-border);
    border-radius: .75rem;
    padding: .75rem .85rem;
    box-shadow: 0 1px 3px rgba(0,0,0,.04);
    display: flex;
    flex-direction: column;
    gap: .55rem;
}

.fn-preplan-card-head {
    display: flex;
    flex-direction: column;
    gap: .15rem;
}

.fn-preplan-card-name {
    font-weight: 800;
    font-size: 1.02rem;
    color: var(--fn-text);
    line-height: 1.2;
    word-wrap: break-word;
}

.fn-preplan-card-addr {
    font-size: .85rem;
    color: var(--fn-text-muted);
    line-height: 1.3;
    word-wrap: break-word;
}

.fn-preplan-card-distance {
    display: inline-flex;
    align-items: center;
    gap: .3rem;
    align-self: flex-start;
    font-size: .72rem;
    font-weight: 800;
    color: #fff;
    background: var(--fn-brand);
    text-transform: uppercase;
    letter-spacing: .04em;
    padding: .25rem .6rem .28rem;
    border-radius: 999px;
    margin-top: .25rem;
    line-height: 1.2;
    box-shadow: 0 1px 2px rgba(0,0,0,.12);
}

.fn-preplan-card-distance .mdi {
    font-size: .9rem;
}

.fn-preplan-card-actions {
    display: flex;
    flex-wrap: wrap;
    gap: .35rem;
}

.fn-preplan-action-btn {
    flex: 1 1 auto;
    min-width: 0;
    border: 0;
    /* Was .5rem. Bumped to 1rem to match the home response buttons. */
    border-radius: 1rem;
    padding: .55rem .65rem;
    font-family: inherit;
    font-weight: 800;
    font-size: .72rem;
    text-transform: uppercase;
    letter-spacing: .02em;
    line-height: 1.05;
    cursor: pointer;
    color: #fff;
    background: var(--fn-brand);
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: .3rem;
    box-shadow: 0 1px 3px rgba(0,0,0,.12);
    transition: filter .12s, transform .1s;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.fn-preplan-action-btn:active {
    transform: scale(.96);
    filter: brightness(.92);
}

.fn-preplan-action-btn .mdi {
    font-size: .95rem;
}

/* Hazards: same red as other "warning/danger" buttons across the app */
.fn-preplan-action-btn.hazards {
    background: var(--fn-accent);
    color: #fff;
}

/* Secure: bootstrap-info-feel cyan. Bright background needs dark text
   for readable contrast (white on cyan fails WCAG). */
.fn-preplan-action-btn.secure {
    background: #0dcaf0;
    color: #fff;
}

.fn-preplan-action-btn.full {
    background: var(--fn-brand);
    color: #fff;
}

.fn-preplan-empty {
    text-align: center;
    /* Tight padding so the empty state sits right below the
       Reset-to-call-defaults button instead of floating in a
       big padded zone. The results container above us is
       flex:1 1 auto and fills whatever vertical room is left
       on the page, so a short empty-state block here just
       leaves blank scroll space below — same as a list with
       one short result card would. The original 2.5rem on
       top + bottom made the empty state itself feel oversized
       and read as "padded big time" against the controls. */
    padding: .85rem 1rem 1.25rem;
    color: var(--fn-text-muted);
}

.fn-preplan-empty .mdi {
    /* Slightly smaller and tighter to the title text below.
       2.8rem was visually heavier than the empty state needs;
       2.1rem still reads as an icon at a glance without
       dominating the band. */
    font-size: 2.1rem;
    opacity: .3;
    color: var(--fn-text);
    display: block;
    margin-bottom: .15rem;
}

.fn-preplan-empty-title {
    font-weight: 800;
    color: var(--fn-text);
    margin-bottom: .25rem;
}

.fn-preplan-empty-sub {
    font-size: .85rem;
    line-height: 1.45;
}

/* ── Modal ──────────────────────────────────────────────────
   Modal sits BETWEEN the FN top chrome and the tab bar so the
   header is fully visible AND the navigation tabs stay
   visible/tappable below it. */
.fn-preplan-modal {
    position: fixed;
    /* Backdrop covers the WHOLE screen except the tabbar:
         - top: 0 — extends over the safe-area dark strip and the
           floating top chrome, so the entire app surface is frosted
         - bottom: ends right at the tabbar's top edge (tabbar floats
           at safe-bottom + 0.45rem) — tabbar stays visible/tappable */
    top: 0;
    left: 0;
    right: 0;
    bottom: calc(var(--fn-tabbar-h) + var(--fn-safe-bottom) + 0.45rem);

    /* Glass backdrop instead of the prior charcoal rgba(0,0,0,.55).
       Light translucent tint + strong blur on light mode; deeper
       tint + same blur on dark. Reads as frosted glass dimming the
       background rather than a flat dim layer. */
    background-color: rgba(255, 255, 255, 0.30);
    backdrop-filter: blur(28px) saturate(180%);
    -webkit-backdrop-filter: blur(28px) saturate(180%);

    z-index: 250;
    display: flex;
    align-items: stretch;
    justify-content: center;
    /* Padding pushes the modal CARD down to below the floating chrome
       (top), and keeps standard breathing on the sides + bottom. */
    padding: calc(var(--fn-safe-top) + 0.45rem + var(--fn-top-chrome-h) + 0.25rem)
             0.6rem 0.6rem;
    box-sizing: border-box;
    opacity: 0;
    pointer-events: none;
    transition: opacity .2s ease;
}
[data-bs-theme="dark"] .fn-preplan-modal {
    background-color: rgba(15, 17, 21, 0.45);
}

.fn-preplan-modal[hidden] {
    display: none;
}

.fn-preplan-modal.active {
    opacity: 1;
    pointer-events: auto;
}

.fn-preplan-modal-card {
    position: relative;
    background: var(--fn-body-bg);
    color: var(--fn-text);
    width: 100%;
    max-width: 640px;
    border-radius: .85rem;
    overflow: hidden;
    display: flex;
    flex-direction: column;
    box-shadow: 0 16px 50px rgba(0,0,0,.4);
    transform: scale(.96) translateY(.5rem);
    transition: transform .22s cubic-bezier(.2,.8,.2,1);
    box-sizing: border-box;
}

.fn-preplan-modal.active .fn-preplan-modal-card {
    transform: scale(1) translateY(0);
}

.fn-preplan-modal-head {
    display: flex;
    align-items: center;
    gap: .65rem;
    padding: .85rem .95rem;
    border-bottom: 1px solid var(--fn-card-border);
    background: var(--fn-card-bg);
    flex-shrink: 0;
    transition: background .2s;
}

/* Themed modal headers — match the action button colors so the modal
   carries the same visual identity as whichever button opened it.
   Colors are theme-independent so dark mode just works. */
.fn-preplan-modal-card.theme-hazards .fn-preplan-modal-head {
    background: var(--fn-accent);
    border-bottom-color: rgba(0,0,0,.18);
}

.fn-preplan-modal-card.theme-secure .fn-preplan-modal-head {
    background: #0dcaf0;
    border-bottom-color: rgba(0,0,0,.18);
}

.fn-preplan-modal-card.theme-full .fn-preplan-modal-head {
    background: var(--fn-brand);
    border-bottom-color: rgba(0,0,0,.25);
}

/* Title/sub text colors per theme — white on red & navy, dark on cyan
   (cyan needs dark text for contrast). */
.fn-preplan-modal-card.theme-hazards .fn-preplan-modal-title,
.fn-preplan-modal-card.theme-full .fn-preplan-modal-title {
    color: #fff;
}

.fn-preplan-modal-card.theme-hazards .fn-preplan-modal-sub,
.fn-preplan-modal-card.theme-full .fn-preplan-modal-sub {
    color: rgba(255,255,255,.85);
}

.fn-preplan-modal-card.theme-secure .fn-preplan-modal-title {
    color: #fff;
}

.fn-preplan-modal-card.theme-secure .fn-preplan-modal-sub {
    color: rgba(255, 255, 255, .85);
}

.fn-preplan-modal-title-wrap {
    flex: 1;
    min-width: 0;
}

.fn-preplan-modal-title {
    font-weight: 800;
    font-size: 1.1rem;
    line-height: 1.2;
    color: var(--fn-text);
    overflow: hidden;
    text-overflow: ellipsis;
}

.fn-preplan-modal-sub {
    font-size: .8rem;
    color: var(--fn-text-muted);
    line-height: 1.3;
    margin-top: .15rem;
    overflow: hidden;
    text-overflow: ellipsis;
}

.fn-preplan-modal-filter {
    position: relative;
    padding: .55rem .85rem;
    border-bottom: 1px solid var(--fn-card-border);
    flex-shrink: 0;
    display: flex;
    align-items: center;
    gap: .4rem;
}

.fn-preplan-modal-filter[hidden] {
    display: none;
}

.fn-preplan-modal-filter .mdi {
    color: var(--fn-text-muted);
    font-size: 1.1rem;
}

.fn-preplan-modal-filter-input {
    flex: 1;
    padding: .45rem .55rem;
    border-radius: .5rem;
    border: 1px solid var(--fn-card-border);
    background: var(--fn-card-bg);
    color: var(--fn-text);
    font-family: inherit;
    font-size: .9rem;
    -webkit-appearance: none;
    appearance: none;
}

.fn-preplan-modal-filter-input:focus {
    outline: none;
    border-color: var(--fn-brand);
    box-shadow: 0 0 0 2px var(--fn-brand-soft);
}

.fn-preplan-modal-body {
    overflow-y: auto;
    -webkit-overflow-scrolling: touch;
    flex: 1 1 0;
    min-height: 0;
    /* Bottom padding so the floating close FAB doesn't cover the
       last item when scrolled to the end */
    padding: .35rem 0 4rem;
}

/* Modal detail rows only.
   This was previously using .fn-preplan-field globally, which also
   affected the two search inputs at the top and made them appear narrower. */
#fnPreplanModalBody .fn-preplan-field {
    padding: .55rem .95rem .6rem;
    border-bottom: 1px solid var(--fn-card-border);
}

#fnPreplanModalBody .fn-preplan-field:last-child {
    border-bottom: 0;
}

#fnPreplanModalBody .fn-preplan-field[hidden] {
    display: none;
}

.fn-preplan-field-label {
    font-size: .68rem;
    font-weight: 800;
    text-transform: uppercase;
    letter-spacing: .04em;
    color: var(--fn-text-muted);
    margin-bottom: .15rem;
    display: inline-flex;
    align-items: center;
    gap: .25rem;
}

.fn-preplan-field-label::before {
    content: '';
    width: 3px;
    height: 10px;
    background: var(--fn-brand);
    border-radius: 2px;
}

.fn-preplan-field-value {
    font-size: .95rem;
    line-height: 1.45;
    color: var(--fn-text);
    word-break: break-word;
    white-space: pre-wrap;
}

.fn-preplan-modal-prose {
    padding: 1rem 1rem 4rem;   /* extra bottom for the FAB */
    font-size: 1rem;
    line-height: 1.55;
    color: var(--fn-text);
    white-space: pre-wrap;
    word-break: break-word;
}

/* Google Places Autocomplete dropdown — lift above the FN tab bar
   (z-index 100) but stay below our modal (z-index 250). Theme for
   dark mode so it doesn't look like a foreign white box. */
.pac-container {
    z-index: 200 !important;
    border-radius: .5rem;
    box-shadow: 0 8px 24px rgba(0,0,0,.18), 0 1px 4px rgba(0,0,0,.08);
    margin-top: .25rem;
    font-family: inherit;
}

[data-bs-theme="dark"] .pac-container {
    background: var(--fn-card-bg);
    border: 1px solid var(--fn-card-border);
}

[data-bs-theme="dark"] .pac-item {
    background: var(--fn-card-bg);
    color: var(--fn-text);
    border-top-color: var(--fn-card-border);
}

[data-bs-theme="dark"] .pac-item:hover,
[data-bs-theme="dark"] .pac-item-selected {
    background: var(--fn-tertiary-bg);
}

[data-bs-theme="dark"] .pac-item-query,
[data-bs-theme="dark"] .pac-matched {
    color: var(--fn-text);
}

/* Persistent bottom-right close FAB — sits over the modal body
   so it's always reachable regardless of scroll position. */
.fn-preplan-modal-fab-close {
    position: absolute;
    right: .85rem;
    bottom: .85rem;
    width: 3.2rem;
    height: 3.2rem;
    border-radius: 50%;
    background: var(--fn-brand);
    color: #fff;
    border: 0;
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 0;
    box-shadow: 0 4px 14px rgba(0,0,0,.3), 0 1px 4px rgba(0,0,0,.18);
    z-index: 5;
    transition: transform .12s, filter .12s;
}

.fn-preplan-modal-fab-close:active {
    transform: scale(.93);
    filter: brightness(.9);
}

.fn-preplan-modal-fab-close .mdi {
    font-size: 1.55rem;
    line-height: 1;
}

/* FAB color follows the modal theme so it matches the header.
   Cyan needs a dark icon for contrast (same rule as the button). */
.fn-preplan-modal-card.theme-hazards .fn-preplan-modal-fab-close {
    background: var(--fn-accent);
    color: #fff;
}

.fn-preplan-modal-card.theme-secure .fn-preplan-modal-fab-close {
    background: #0dcaf0;
    color: #fff;
}

.fn-preplan-modal-card.theme-full .fn-preplan-modal-fab-close {
    background: var(--fn-brand);
    color: #fff;
}

/* Desktop / wide-viewport — pin the modal inside the same boxed
   app layout the chrome and page-host live in. 1rem gutter on
   every side; with --fn-tabbar-h overridden to 0 in the desktop
   media query in index.php, the bottom calc just becomes 1rem.
   The result: modal sits flush inside the bottom-rounded
   page-host area on desktop, never extending past it. */
/* Desktop only — fixes preplan modal spacing on computer screens.
   Mobile and iPad keep the existing app-style modal behaviour. */
@media (hover: hover) and (pointer: fine) {
    .fn-preplan-modal {
        /* Let the blurred overlay cover the entire browser window */
        top: 0;
        bottom: 0;
        left: 0;
        right: 0;

        width: auto;
        max-width: none;

        padding: 1rem 1rem 1.75rem;
        transform: none;

        align-items: stretch;
        justify-content: center;
    }

    .fn-preplan-modal-card {
        width: min(1180px, calc(100vw - 2rem));
        max-width: calc(100vw - 2rem);
        height: 100%;
        max-height: calc(100vh - 2.75rem);
        border-radius: .85rem;
    }
}


/* ==========================================================================
   Layout safety patch — shared fn chrome must stack above content
   ==========================================================================
   After consolidation, page-specific CSS now shares one cascade. These rules
   keep the main Priority4 chrome in normal top-to-bottom order, even if a
   page-level/vendor rule tries to turn the body into a side-by-side layout. */
body.fn-chrome-page {
    display: block !important;
    min-height: 100dvh;
    width: 100%;
    overflow-x: hidden;
}

body.fn-chrome-page .fn-top-chrome {
    display: block !important;
    float: none !important;
    clear: both !important;
}

body.fn-chrome-page .fn-page-host,
body.fn-chrome-page .fn-admin-container {
    display: block !important;
    float: none !important;
    clear: both !important;
}

@media (hover: hover) and (pointer: fine) {
    body.fn-chrome-page .fn-top-chrome {
        position: sticky;
        top: 1rem;
        left: auto !important;
        right: auto !important;
        width: calc(100% - 2rem);
        max-width: 1180px;
        margin: 1rem auto 0 auto;
    }

    body.fn-chrome-page .fn-page-host,
    body.fn-chrome-page .fn-admin-container {
        width: calc(100% - 2rem);
        max-width: 1180px;
        margin-left: auto !important;
        margin-right: auto !important;
    }
}

@media (hover: none) and (pointer: coarse) {
    body.fn-admin-page {
        padding-top: calc(var(--fn-safe-top) + 0.45rem + var(--fn-top-chrome-h) + 0.15rem);
    }

    body.fn-admin-page .fn-admin-container {
        padding-top: 0.25rem;
    }
}


/* ==========================================================================
   App background restore — keep Liquid Glass backdrop after CSS consolidation
   ==========================================================================
   dashboard.css contains global body/body::before rules for the wall display.
   Once all CSS was merged into priority4.css, those dashboard rules were able
   to override the normal app backdrop and leave app/admin pages plain white.
   These rules restore the shared subtle gradient for the main chrome pages. */
body.fn-chrome-page {
    color: var(--fn-text) !important;
    background-color: var(--fn-body-bg) !important;

    background-image:
        linear-gradient(
            135deg,
            rgba(120, 145, 195, 0.22) 0%,
            rgba(120, 145, 195, 0.10) 32%,
            rgba(220, 130, 110, 0.08) 68%,
            rgba(220, 130, 110, 0.18) 100%
        ) !important;

    background-attachment: fixed !important;
    background-repeat: no-repeat !important;
    background-size: 100% 100% !important;

    animation: fn-bg-pulse 16s ease-in-out infinite;
    isolation: auto !important;
}

[data-bs-theme="dark"] body.fn-chrome-page {
    background-color: var(--fn-body-bg) !important;

    background-image:
        radial-gradient(
            ellipse 110% 90% at -10% -10%,
            rgba(42, 62, 110, 0.55),
            rgba(42, 62, 110, 0.28) 35%,
            transparent 72%
        ),
        radial-gradient(
            ellipse 115% 95% at 115% 115%,
            rgba(110, 38, 32, 0.42),
            rgba(110, 38, 32, 0.20) 38%,
            transparent 74%
        ) !important;
}

[data-bs-theme="dark"] body.fn-chrome-page {
    background-color: var(--fn-body-bg) !important;

    background-image:
        radial-gradient(
            ellipse 110% 90% at -10% -10%,
            rgba(42, 62, 110, 0.55),
            rgba(42, 62, 110, 0.28) 35%,
            transparent 72%
        ),
        radial-gradient(
            ellipse 115% 95% at 115% 115%,
            rgba(110, 38, 32, 0.42),
            rgba(110, 38, 32, 0.20) 38%,
            transparent 74%
        ) !important;
}

body.fn-chrome-page::before {
    content: "" !important;
    position: fixed !important;
    top: 0 !important;
    left: 0 !important;
    right: 0 !important;
    height: calc(var(--fn-safe-top) + 1.25rem) !important;
    z-index: 1 !important;
    pointer-events: none !important;

    background:
        linear-gradient(to bottom,
            rgba(15, 17, 21, 0.42) 0%,
            rgba(15, 17, 21, 0.18) 45%,
            transparent 100%
        ) !important;

    animation: none !important;
}

body.fn-chrome-page::after {
    display: none !important;
    content: none !important;
}


/* ==========================================================================
   Admin page spacing
   ========================================================================== */
body.fn-admin-page .fn-admin-container {
    padding-top: 0.25rem;
}

@media (hover: hover) and (pointer: fine) {
    body.fn-admin-page .fn-admin-container {
        padding-top: 0.75rem;
    }
}

/* ==========================================================================
   Apparatus page dark-mode restore — original apparatus theme logic
   ==========================================================================
   apparatus.php uses its own data-theme attribute and --ap-* variables. The
   shared fn-chrome-page background restore later in the consolidated CSS only
   watched data-bs-theme, so apparatus could stay on the light app backdrop.
   These rules intentionally support BOTH:
     - html[data-theme="dark"]       original apparatus.php toggle/session
     - html[data-bs-theme="dark"]    shared Priority4/Bootstrap theme
   ========================================================================== */

html[data-theme="dark"],
html[data-bs-theme="dark"] {
    --ap-bg-base:        #0a0d12;
    --ap-bg-mid:         #11151c;
    --ap-surface:        rgba(255, 255, 255, 0.04);
    --ap-surface-2:      rgba(255, 255, 255, 0.075);
    --ap-surface-3:      rgba(255, 255, 255, 0.12);
    --ap-surface-hover:  rgba(255, 255, 255, 0.10);
    --ap-border:         rgba(255, 255, 255, 0.08);
    --ap-border-strong:  rgba(255, 255, 255, 0.18);
    --ap-text:           #e8eaed;
    --ap-text-muted:     #95a0ae;
    --ap-text-dim:       #5a6371;
    --ap-brand-soft:     rgba(192, 40, 45, 0.18);
    --ap-accent:         #f59e0b;
    --ap-accent-soft:    rgba(245, 158, 11, 0.16);
    --ap-success:        #10b981;
    --ap-success-soft:   rgba(16, 185, 129, 0.16);
    --ap-info:           #3b82f6;
    --ap-info-soft:      rgba(59, 130, 246, 0.14);
    --ap-hazard:         #f87171;
    --ap-hazard-bg:      linear-gradient(135deg, rgba(220, 38, 38, 0.30) 0%, rgba(185, 28, 28, 0.40) 100%);
    --ap-hazard-border:  rgba(248, 113, 113, 0.55);
    --ap-hazard-text:    #fecaca;
    --ap-shadow-card:
        0 12px 30px rgba(0, 0, 0, 0.36),
        0 4px 10px  rgba(0, 0, 0, 0.20),
        inset 0 1px 0 rgba(255, 255, 255, 0.06);
    --ap-shadow-topbar:
        0 12px 32px rgba(192, 40, 45, 0.30),
        inset 0 1px 0 rgba(255, 255, 255, 0.12);
}

/* Apparatus must not use the shared app/admin chrome backdrop. */
body.fn-chrome-page.fn-apparatus-page {
    overflow: hidden;
    background-color: var(--ap-bg-base) !important;
    background-image: none !important;
    background-attachment: initial !important;
    background-repeat: initial !important;
    background-size: initial !important;
    color: var(--ap-text) !important;
    isolation: isolate !important;
}

body.fn-chrome-page.fn-apparatus-page::before {
    content: "" !important;
    position: fixed !important;
    inset: 0 !important;
    width: auto !important;
    height: auto !important;
    z-index: -2 !important;
    pointer-events: none !important;
    background:
        radial-gradient(ellipse 70% 60% at 50% 0%, var(--ap-brand-soft) 0%, transparent 55%),
        var(--ap-bg-base) !important;
    animation: none !important;
}

body.fn-chrome-page.fn-apparatus-page::after {
    display: none !important;
    content: none !important;
}

html[data-theme="dark"] body.fn-chrome-page.fn-apparatus-page,
html[data-bs-theme="dark"] body.fn-chrome-page.fn-apparatus-page {
    background-color: #0a0d12 !important;
    background-image: none !important;
    color: var(--ap-text) !important;
}

html[data-theme="dark"] body.fn-chrome-page.fn-apparatus-page::before,
html[data-bs-theme="dark"] body.fn-chrome-page.fn-apparatus-page::before {
    content: "" !important;
    position: fixed !important;
    inset: 0 !important;
    width: auto !important;
    height: auto !important;
    z-index: -2 !important;
    pointer-events: none !important;
    background:
        radial-gradient(ellipse 70% 60% at 50% 0%, rgba(192, 40, 45, 0.18) 0%, transparent 55%),
        linear-gradient(180deg, #11151c 0%, #0a0d12 100%) !important;
    animation: none !important;
}

html[data-theme="dark"] body.fn-chrome-page.fn-apparatus-page::after,
html[data-bs-theme="dark"] body.fn-chrome-page.fn-apparatus-page::after {
    display: block !important;
    content: "" !important;
    position: fixed !important;
    inset: -10% !important;
    z-index: -1 !important;
    pointer-events: none !important;
    background:
        radial-gradient(circle at 30% 40%, rgba(192, 40, 45, 0.06) 0%, transparent 40%),
        radial-gradient(circle at 70% 60%, rgba(192, 40, 45, 0.04) 0%, transparent 40%) !important;
    animation: apEmberDrift 90s linear infinite !important;
}

/* Calls tab / apparatus shell: reduce the boxed-in spacing without affecting admin pages. */
body.fn-apparatus-page .ap-shell {
    padding-left: max(0.5rem, env(safe-area-inset-left));
    padding-right: max(0.5rem, env(safe-area-inset-right));
}

body.fn-apparatus-page .ap-main,
body.fn-apparatus-page .ap-panel,
body.fn-apparatus-page .ap-panel-call,
body.fn-apparatus-page .ap-call-layout {
    width: 100%;
    max-width: none;
}

@media (max-width: 1023px) {
    body.fn-apparatus-page .ap-shell {
        padding-left: max(0.35rem, env(safe-area-inset-left));
        padding-right: max(0.35rem, env(safe-area-inset-right));
    }

    body.fn-apparatus-page .ap-call-layout {
        gap: 0.45rem;
    }
}

/* Dark-mode surface reinforcement copied from the original apparatus look. */
html[data-theme="dark"] body.fn-apparatus-page .ap-card,
html[data-bs-theme="dark"] body.fn-apparatus-page .ap-card {
    background: var(--ap-surface) !important;
    border-color: var(--ap-border) !important;
    box-shadow: var(--ap-shadow-card) !important;
    color: var(--ap-text) !important;
    backdrop-filter: blur(24px) saturate(160%);
    -webkit-backdrop-filter: blur(24px) saturate(160%);
}

html[data-theme="dark"] body.fn-apparatus-page .ap-bottom-nav,
html[data-bs-theme="dark"] body.fn-apparatus-page .ap-bottom-nav {
    background: rgba(10, 13, 18, 0.78) !important;
    border-color: rgba(255, 255, 255, 0.10) !important;
}

html[data-theme="dark"] body.fn-apparatus-page .ap-map-btn.is-google,
html[data-bs-theme="dark"] body.fn-apparatus-page .ap-map-btn.is-google {
    background: #131314 !important;
    color: #e3e3e3 !important;
    border-color: #5f6368 !important;
    box-shadow: 0 1px 2px rgba(0, 0, 0, 0.3) !important;
}

html[data-theme="dark"] body.fn-apparatus-page .ap-map-btn.is-google:hover,
html[data-bs-theme="dark"] body.fn-apparatus-page .ap-map-btn.is-google:hover {
    background: #1c1c1d !important;
    border-color: #8e918f !important;
}

html[data-theme="dark"] body.fn-apparatus-page .ap-action-btn,
html[data-bs-theme="dark"] body.fn-apparatus-page .ap-action-btn {
    background: transparent;
    color: #fca5a5;
    border-color: #fca5a5;
}

html[data-theme="dark"] body.fn-apparatus-page .ap-action-btn:hover,
html[data-bs-theme="dark"] body.fn-apparatus-page .ap-action-btn:hover {
    background: var(--ap-brand);
    color: #fff;
    border-color: var(--ap-brand);
}

html[data-theme="dark"] body.fn-apparatus-page .ap-action-btn-secure,
html[data-bs-theme="dark"] body.fn-apparatus-page .ap-action-btn-secure {
    background: transparent;
    color: #e3e3e3;
    border-color: #8e918f;
}

html[data-theme="dark"] body.fn-apparatus-page .ap-action-btn-secure:hover,
html[data-bs-theme="dark"] body.fn-apparatus-page .ap-action-btn-secure:hover {
    background: rgba(255, 255, 255, 0.08);
    color: #fff;
    border-color: #e3e3e3;
}

html[data-theme="dark"] body.fn-apparatus-page .ap-action-btn[aria-disabled="true"],
html[data-bs-theme="dark"] body.fn-apparatus-page .ap-action-btn[aria-disabled="true"] {
    background: transparent;
    color: var(--ap-text-dim);
    border-color: #3a3d40;
}

html[data-theme="dark"] body.fn-apparatus-page .ap-hydrants-info,
html[data-bs-theme="dark"] body.fn-apparatus-page .ap-hydrants-info {
    background: rgba(220, 38, 38, 0.20);
    border-color: rgba(220, 38, 38, 0.42);
}

html[data-theme="dark"] body.fn-apparatus-page .ap-pp-modal,
html[data-bs-theme="dark"] body.fn-apparatus-page .ap-pp-modal {
    background: rgba(15, 17, 21, 0.55);
}

/* Address hydrant popup */
.fn-hydrant-popup {
    font-family: inherit;
    font-size: 1rem;
    line-height: 1.35;
    color: #1f2328;
    min-width: 220px;
    max-width: 300px;
}

/* Header row: title + custom X */
.fn-hydrant-popup-head {
    display: grid;
    grid-template-columns: minmax(0, 1fr) auto;
    align-items: start;
    column-gap: 0.6rem;

    padding-bottom: 0.35rem;
    margin-bottom: 0.45rem;

    border-bottom: 1px solid rgba(15, 23, 42, 0.16);
}

.fn-hydrant-popup-title {
    min-width: 0;

    font-weight: 800;
    font-size: 1.08rem;
    line-height: 1.1;
    color: #0f172a;

    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

/* Custom close button inline with title */
.fn-hydrant-popup-close {
    align-self: start;

    width: 1.55rem;
    height: 1.55rem;

    display: inline-flex;
    align-items: center;
    justify-content: center;

    padding: 0;
    margin: -0.18rem -0.15rem 0 0;

    border: 0;
    border-radius: 50%;
    background: transparent;

    color: #6b7280;
    font-size: 1.65rem;
    line-height: 1;
    cursor: pointer;
    font-family: inherit;
}

.fn-hydrant-popup-close:hover {
    background: #f3f4f6;
    color: #374151;
}

/* Body spacing */
.fn-hydrant-popup-body {
    display: grid;
    gap: 0.28rem;

    font-size: 1rem;
    line-height: 1.28;
    color: #374151;
}

.fn-hydrant-popup-body strong {
    color: #111827;
    font-weight: 800;
}

.fn-hydrant-popup-distance {
    color: #6b7280;
    font-size: 0.95rem;
    margin-top: 0.05rem;
}

.fn-hydrant-popup-oos {
    color: #b03a2e;
    font-weight: 800;
}

/* Hide Google's default InfoWindow X only when our custom close exists */
.gm-style .gm-style-iw-c:has(.fn-hydrant-popup-close) .gm-ui-hover-effect {
    display: none !important;
}

/* Reduce Google padding around the custom popup */
.gm-style .gm-style-iw-c:has(.fn-hydrant-popup-close) {
    padding: 8px 10px 10px 10px !important;
    border-radius: 0.75rem !important;
}

.gm-style .gm-style-iw-d:has(.fn-hydrant-popup-close) {
    overflow: hidden !important;
    padding: 0 !important;
    max-height: none !important;
}

/* Remove first-click blue focus ring on Google InfoWindow */
.gm-style .gm-style-iw-c,
.gm-style .gm-style-iw-d,
.gm-style .gm-style-iw-ch,
.gm-style .gm-style-iw-chr,
.gm-style .gm-ui-hover-effect,
.fn-hydrant-popup,
.fn-hydrant-popup * {
    outline: none;
    -webkit-tap-highlight-color: transparent;
}

.gm-style .gm-style-iw-c:focus,
.gm-style .gm-style-iw-c:focus-visible,
.gm-style .gm-style-iw-d:focus,
.gm-style .gm-style-iw-d:focus-visible,
.gm-style .gm-ui-hover-effect:focus,
.gm-style .gm-ui-hover-effect:focus-visible,
.fn-hydrant-popup:focus,
.fn-hydrant-popup:focus-visible {
    outline: none !important;
}