/* Intentional product-level overrides on top of the Silicon UI Kit. */

/* Product typography. */
:root {
    --bs-body-font-family: "Google Sans", sans-serif;
}
body {
    font-family: "Google Sans", sans-serif;
    font-optical-sizing: auto;
    font-variation-settings: "GRAD" 0;
}

/* Authentication surface. */
.authentication-bg {
    background-color: #f6f8fb;
    background-image: linear-gradient(135deg, #f6f8fb 0%, #eef2f7 100%);
}
.authentication-bg .card {
    border: 0;
    box-shadow: 0 0.5rem 1.5rem rgba(0, 0, 0, 0.06);
}

/* Bootstrap has no max-width utility; keep every login method in one visual column. */
.login-methods {
    width: 100%;
    max-width: 400px;
}

#workos-google-login-form {
    width: 100%;
}

/*
 * Google Identity control rendered with the portal's Silicon button
 * (btn btn-outline-secondary) so it shares the theme's typography, sizing,
 * radius, and interaction states with every other action on the page. Only
 * the official multi-color "G" mark keeps Google's brand colors; its sizing
 * and label spacing live here.
 */
.google-g {
    display: inline-flex;
    width: 1.125rem;
    height: 1.125rem;
    margin-right: 0.625rem;
}

.google-g svg {
    width: 100%;
    height: 100%;
    display: block;
}

/* Device overview cards follow the same borderless identity / metrics / action
   structure as Device Group cards and Dashboard cards. */
@media (min-width: 768px) {
    .device-card {
        min-height: 18rem;
    }
}
.device-card__serial {
    max-width: 15rem;
    overflow-wrap: anywhere;
    font-size: 0.72rem;
}
.device-card__components {
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 0.65rem 1rem;
}
.device-card__group-badge {
    max-width: 10rem;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* Dense telemetry matrix severity states. Pair Silicon's bg-faded-warning /
   bg-faded-danger utilities on the cell with these accents so the label,
   numeric value, and unit read as one coherent state. */
.device-matrix__value {
    font-variant-numeric: tabular-nums;
    color: var(--si-heading-color);
}
.device-matrix__unit {
    font-weight: 600;
    color: var(--si-gray-600);
}
.device-matrix__accent--warning {
    color: var(--si-warning);
}
.device-matrix__accent--danger {
    color: var(--si-danger);
}

/* Camera preview modal. The video keeps a stable 16:9 canvas while the
   placeholder explains the unconfigured template state. */
.camera-live-stage {
    position: relative;
    aspect-ratio: 16 / 9;
    min-height: 18rem;
    overflow: hidden;
    background:
        radial-gradient(circle at 50% 42%, rgba(99, 102, 241, 0.2), transparent 34%),
        #111827;
}
.camera-live-video {
    position: absolute;
    z-index: 2;
    inset: 0;
    width: 100%;
    height: 100%;
    object-fit: contain;
    background: transparent;
}
.camera-stream-placeholder {
    position: absolute;
    z-index: 1;
    inset: 0;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    padding: 2rem;
    text-align: center;
}
.camera-stream-placeholder.is-hidden {
    display: none;
}
.camera-placeholder-icon {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 4.5rem;
    height: 4.5rem;
    border: 1px solid rgba(255, 255, 255, 0.2);
    border-radius: 50%;
    color: #fff;
    background: rgba(255, 255, 255, 0.08);
}
.camera-live-meta {
    position: absolute;
    z-index: 3;
    top: 1rem;
    left: 1rem;
    border-radius: 0.4rem;
    padding: 0.4rem 0.65rem;
    color: #fff;
    background: rgba(15, 23, 42, 0.72);
    font-size: 0.7rem;
    font-weight: 700;
    letter-spacing: 0.04em;
    pointer-events: none;
    backdrop-filter: blur(6px);
}
.camera-live-indicator {
    display: inline-block;
    width: 0.45rem;
    height: 0.45rem;
    border-radius: 50%;
    background: #ef4444;
    box-shadow: 0 0 0 0 rgba(239, 68, 68, 0.5);
    animation: camera-live-pulse 1.8s ease-out infinite;
}

@keyframes camera-live-pulse {
    70%, 100% { box-shadow: 0 0 0 0.35rem rgba(239, 68, 68, 0); }
}

@media (max-width: 575.98px) {
    .camera-live-stage {
        min-height: 14rem;
    }
}

/* Camera movement (PTZ) overlay on the live stage. The panel floats over the
   stream with the same dark-glass treatment as the LIVE badge so both read as
   one chrome layer. Direction buttons are press-and-hold, so they disable
   touch scrolling while pressed. */
.camera-ptz {
    position: absolute;
    z-index: 4;
    top: 1rem;
    right: 1rem;
    width: 11.75rem;
    border: 1px solid rgba(255, 255, 255, 0.16);
    border-radius: 0.875rem;
    background: rgba(15, 23, 42, 0.72);
    box-shadow: 0 12px 32px rgba(15, 23, 42, 0.35);
    color: #fff;
    backdrop-filter: blur(6px);
}
.camera-ptz__header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 0.5rem;
    padding: 0.5rem 0.6rem 0.4rem 0.85rem;
}
.camera-ptz__title {
    display: inline-flex;
    align-items: center;
    font-size: 0.7rem;
    font-weight: 700;
    letter-spacing: 0.04em;
    text-transform: uppercase;
}
.camera-ptz__title i {
    font-size: 0.9rem;
}
.camera-ptz__toggle {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 1.5rem;
    height: 1.5rem;
    padding: 0;
    border: 0;
    border-radius: 0.4rem;
    background: rgba(255, 255, 255, 0.08);
    color: #fff;
    font-size: 1rem;
    line-height: 1;
}
.camera-ptz__toggle:hover {
    background: rgba(255, 255, 255, 0.18);
}
.camera-ptz__body {
    display: flex;
    gap: 0.45rem;
    padding: 0.15rem 0.85rem 0.85rem;
}
.camera-ptz.is-collapsed .camera-ptz__body {
    display: none;
}

/* Compact report timeline. Fixed marker geometry keeps every icon centered on
   one axis instead of inheriting Silicon's larger numbered-step rings. */

.device-cycle-timeline {
    display: grid;
    grid-template-columns: 1fr;
}

.device-cycle-event {
    position: relative;
    display: grid;
    grid-template-columns: 2.25rem minmax(0, 1fr);
    gap: 0.75rem;
    min-width: 0;
    padding-bottom: 1rem;
}

.device-cycle-event:not(:last-child)::before {
    position: absolute;
    z-index: 0;
    top: 1.125rem;
    bottom: -1.125rem;
    left: 1.09375rem;
    width: 1px;
    background: var(--si-border-color, #d4d7e5);
    content: "";
}

.device-cycle-event__marker {
    position: relative;
    z-index: 1;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    box-sizing: border-box;
    width: 2.25rem;
    height: 2.25rem;
    padding: 0;
    border: 2px solid var(--si-border-color, #d4d7e5);
    border-radius: 50%;
    background: var(--si-body-bg, #fff);
    color: var(--si-body-color, #0b0f19);
    box-shadow: 0 0.25rem 0.75rem rgba(11, 15, 25, 0.08);
    font-size: 1rem;
    line-height: 1;
}

.device-cycle-event__marker > i {
    display: block;
    line-height: 1;
}

.device-cycle-event__body {
    min-width: 0;
    padding-top: 0.25rem;
}

.device-cycle-event__body .h6 {
    font-size: 0.875rem;
}

.device-cycle-event--complete .device-cycle-event__marker {
    border-color: var(--si-success, #14c38e);
    background: var(--si-success, #14c38e);
    color: #fff;
}

.device-cycle-event--active .device-cycle-event__marker {
    border-color: var(--si-primary, #6366f1);
    color: var(--si-primary, #6366f1);
}

.device-cycle-event--warning .device-cycle-event__marker {
    border-color: var(--si-warning, #f5a623);
    background: var(--si-warning, #f5a623);
    color: #fff;
}

.device-cycle-event--danger .device-cycle-event__marker {
    border-color: var(--si-danger, #ef4444);
    background: var(--si-danger, #ef4444);
    color: #fff;
}

.device-cycle-event--pending {
    opacity: 0.5;
}

.device-cycle-event--pending .device-cycle-event__marker {
    color: var(--si-secondary-color, #9397ad);
}

@media (min-width: 768px) {
    .device-cycle-timeline {
        grid-template-columns: repeat(var(--device-cycle-columns, 4), minmax(0, 1fr));
    }

    .device-cycle-event {
        display: block;
        padding: 0 0.75rem 0 0;
    }

    .device-cycle-event:not(:last-child)::before {
        top: 1.09375rem;
        right: -1.125rem;
        bottom: auto;
        left: 1.125rem;
        width: auto;
        height: 1px;
    }

    .device-cycle-event__body {
        padding-top: 0.75rem;
    }
}
.camera-ptz-dpad {
    display: grid;
    flex: 1 1 auto;
    grid-template-columns: repeat(3, 1fr);
    grid-auto-rows: 2.1rem;
    gap: 0.3rem;
}
.camera-ptz-zoom {
    display: flex;
    flex: 0 0 2.1rem;
    flex-direction: column;
    gap: 0.3rem;
}
.camera-ptz-btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 100%;
    height: 2.1rem;
    padding: 0;
    border: 1px solid rgba(255, 255, 255, 0.16);
    border-radius: 0.55rem;
    background: rgba(255, 255, 255, 0.08);
    color: #fff;
    font-size: 1.15rem;
    line-height: 1;
    user-select: none;
    touch-action: none;
    transition: background-color 0.15s ease, border-color 0.15s ease;
}
.camera-ptz-btn:hover {
    background: rgba(255, 255, 255, 0.18);
}
.camera-ptz-btn:focus-visible {
    outline: 2px solid #fff;
    outline-offset: 1px;
}
/* Held state, applied by device-details.js while the command is active. */
.camera-ptz-btn.is-active {
    border-color: transparent;
    background: #6366f1;
}
.camera-ptz-btn--home {
    background: rgba(255, 255, 255, 0.14);
}
/* Diagonals reuse the cardinal chevrons, rotated to their compass heading. */
.camera-ptz-btn--nw > i { transform: rotate(-45deg); }
.camera-ptz-btn--ne > i { transform: rotate(45deg); }
.camera-ptz-btn--sw > i { transform: rotate(45deg); }
.camera-ptz-btn--se > i { transform: rotate(-45deg); }

@media (max-width: 575.98px) {
    .camera-ptz {
        top: 0.75rem;
        right: 0.75rem;
        width: 9.25rem;
    }
    .camera-ptz__body {
        padding: 0.1rem 0.7rem 0.7rem;
    }
    .camera-ptz-dpad {
        grid-auto-rows: 1.85rem;
    }
    .camera-ptz-zoom {
        flex-basis: 1.85rem;
    }
    .camera-ptz-btn {
        height: 1.85rem;
        font-size: 1rem;
    }
}

@media (prefers-reduced-motion: reduce) {
    .camera-ptz-btn {
        transition: none;
    }
}

/* Search + sort toolbar follows the Users-page input-group idiom: fixed-width
   search (never a full row), sort controls pinned to the right edge. */
.search-toolbar__field {
    width: min(100%, 26rem);
}
/* Group cards carry identity, metrics and actions, so they run half the
   container width on desktop (col-6 style) instead of three-up. */
.group-overview-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(min(100%, 28rem), 1fr));
    gap: 1.5rem;
    align-items: stretch;
}
.group-overview-card {
    min-height: 18rem;
}
.group-overview-card__uuid {
    max-width: 19rem;
    overflow-wrap: anywhere;
    font-size: 0.72rem;
}
.group-overview-metrics {
    grid-template-columns: repeat(3, minmax(0, 1fr));
}
.group-overview-metrics > div + div {
    border-left: 1px solid var(--si-gray-300, #e2e5f1);
}
/* Wordy metric values ("Active", countdowns) share the strip with numerals;
   step them down so they stay on one line inside the three-column grid. */
.group-overview-metrics .metric-value-text {
    font-size: 1.05rem;
}

/* LiDAR operations dashboard. The structure intentionally composes Silicon's
   list groups, faded icon backgrounds, badges and thin progress bars. */
.dashboard-kpi-grid {
    display: grid;
    grid-template-columns: repeat(4, minmax(0, 1fr));
    gap: 1rem;
}
.dashboard-kpi {
    display: flex;
    align-items: center;
    gap: 0.75rem;
    height: 100%;
    min-width: 0;
    color: var(--si-body-color);
    text-decoration: none;
    transition: background-color 0.15s ease;
}
.dashboard-kpi:hover { background: rgba(var(--si-primary-rgb), 0.035); }
.dashboard-kpi small {
    display: block;
    color: var(--si-gray-600);
    font-size: 0.75rem;
    white-space: nowrap;
}
.dashboard-kpi strong {
    display: block;
    color: var(--si-heading-color);
    font-size: 1.5rem;
    line-height: 1.2;
}
.dashboard-icon,
.dashboard-result-card__icon {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    flex: 0 0 auto;
    border-radius: 0.75rem;
}
.dashboard-icon {
    width: 2.75rem;
    height: 2.75rem;
    font-size: 1.35rem;
}
.dashboard-empty-state {
    border: 1px dashed var(--si-gray-400, #d4d7e5);
    border-radius: 1rem;
    background: rgba(255, 255, 255, 0.65);
}
.dashboard-group-register {
    background: #fff;
}
/* Card headers use --si-card-spacer-x (1.5rem) while list-group items use
   1rem sides, so rows would sit wider than the header above them. Pin the
   dashboard lists to the same card gutter so left/right edges line up. */
.dashboard-group-register > .list-group-item {
    padding-left: var(--si-card-spacer-x, 1.5rem);
    padding-right: var(--si-card-spacer-x, 1.5rem);
}
.dashboard-group-row {
    display: grid;
    grid-template-columns: minmax(8rem, 1.15fr) minmax(8.5rem, 1fr) minmax(9rem, 1.1fr) minmax(8rem, 0.9fr) 1.5rem;
    gap: 1rem;
    align-items: center;
}
.dashboard-group-row__identity,
.dashboard-group-row__phase,
.dashboard-group-row__readiness,
.dashboard-group-row__schedule {
    min-width: 0;
}
.dashboard-group-row__open {
    color: var(--si-gray-500);
    font-size: 1.5rem;
    line-height: 1;
}
.dashboard-group-row:hover .dashboard-group-row__open { color: var(--si-primary); }
.dashboard-readiness-progress {
    height: 4px;
}
/* Recent scan results are standalone compact cards: a neutral icon tile and
   title row on the left, at-a-glance metric blocks on the right separated by
   dividers. The status pill carries the outcome color on its own so it is not
   repeated on the icon; non-successful runs get a colored accent edge. */
#recent-runs-list {
    display: flex;
    flex-direction: column;
    gap: 1rem;
    padding: 0 var(--si-card-spacer-x, 1.5rem) var(--si-card-spacer-x, 1.5rem);
}
.dashboard-result-card {
    display: grid;
    grid-template-columns: auto minmax(0, 1fr) auto auto;
    align-items: center;
    gap: 1.25rem;
    padding: 1rem 1.25rem;
    border: 1px solid var(--si-border-color, #e5e7eb);
    border-radius: var(--si-border-radius-lg, 0.75rem);
    color: var(--si-body-color);
    text-decoration: none;
    transition: box-shadow 0.15s ease;
}
.dashboard-result-card:hover {
    box-shadow: 0 0.5rem 1rem rgba(0, 0, 0, 0.08);
}
.dashboard-result-card:hover .dashboard-group-row__open { color: var(--si-primary); }
.dashboard-result-card--partial {
    border-left: 0.25rem solid var(--si-warning);
}
.dashboard-result-card--failed {
    border-left: 0.25rem solid var(--si-danger);
}
.dashboard-result-card__icon {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    flex: 0 0 auto;
    width: 2.75rem;
    height: 2.75rem;
    border-radius: 0.75rem;
    font-size: 1.35rem;
}
.dashboard-result-card__main {
    min-width: 0;
}
.dashboard-result-card__title {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    margin-bottom: 0.25rem;
}
.dashboard-result-card__title strong {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    font-size: 0.9375rem;
}
.dashboard-result-card__meta {
    margin: 0;
}
.dashboard-result-card__metrics {
    display: flex;
    align-items: stretch;
    gap: 1rem;
}
.dashboard-result-card__metric {
    text-align: right;
    white-space: nowrap;
}
.dashboard-result-card__metric-value {
    font-size: 1.25rem;
    font-weight: 700;
    line-height: 1.2;
    color: var(--si-heading-color);
}
.dashboard-result-card__metric-label {
    font-size: 0.6875rem;
    font-weight: 600;
    letter-spacing: 0.05em;
    text-transform: uppercase;
    color: var(--si-gray-600);
}
.dashboard-result-card__divider {
    width: 1px;
    background: var(--si-border-color, #e5e7eb);
}
/* Lifecycle strip along the foot of each result card: one dot + micro label
   per phase so a failed phase pops out without opening the report. */
.dashboard-result-card__phases {
    grid-column: 1 / -1;
    display: flex;
    flex-wrap: wrap;
    gap: 0.4rem 1rem;
    border-top: 1px solid var(--si-border-color, #e5e7eb);
    padding-top: 0.75rem;
}
.dashboard-result-phase {
    display: inline-flex;
    align-items: center;
    gap: 0.35rem;
}
.dashboard-result-phase__dot {
    width: 0.5rem;
    height: 0.5rem;
    border-radius: 50%;
    background: var(--si-gray-400, #d4d7e5);
    flex: 0 0 auto;
}
.dashboard-result-phase__label {
    font-size: 0.6875rem;
    font-weight: 600;
    letter-spacing: 0.04em;
    text-transform: uppercase;
    color: var(--si-gray-600);
}
.dashboard-result-phase--ok .dashboard-result-phase__dot { background: var(--si-success); }
.dashboard-result-phase--warn .dashboard-result-phase__dot { background: var(--si-warning); }
.dashboard-result-phase--warn .dashboard-result-phase__label { color: var(--si-warning); }
.dashboard-result-phase--bad .dashboard-result-phase__dot { background: var(--si-danger); }
.dashboard-result-phase--bad .dashboard-result-phase__label { color: var(--si-danger); }
.dashboard-result-phase--skip .dashboard-result-phase__dot {
    background: transparent;
    border: 1.5px solid var(--si-gray-400, #d4d7e5);
}
.dashboard-result-empty {
    display: flex;
    align-items: center;
    gap: 0.75rem;
    padding: 0.5rem 0;
}
.min-w-0 { min-width: 0; }

@media (max-width: 1199.98px) {
    .dashboard-group-row {
        grid-template-columns: minmax(9rem, 1.15fr) minmax(9rem, 1fr) minmax(10rem, 1fr) minmax(8rem, 0.9fr) 1.5rem;
    }
}

@media (max-width: 767.98px) {
    .dashboard-kpi-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
    .dashboard-group-row {
        grid-template-columns: minmax(0, 1fr) auto;
        gap: 0.85rem 1rem;
    }
    .dashboard-group-row__identity { grid-column: 1; }
    .dashboard-group-row__open { grid-column: 2; grid-row: 1; }
    .dashboard-group-row__phase { grid-column: 1 / -1; }
    .dashboard-group-row__readiness,
    .dashboard-group-row__schedule { grid-column: auto; }
}

@media (max-width: 575.98px) {
    .dashboard-kpi { gap: 0.55rem; }
    .dashboard-kpi .dashboard-icon { display: none; }
    .dashboard-group-row__readiness,
    .dashboard-group-row__schedule { grid-column: 1 / -1; }
    .dashboard-result-card {
        grid-template-columns: auto minmax(0, 1fr) auto;
        row-gap: 0.75rem;
    }
    .dashboard-result-card__metrics {
        grid-column: 2 / -1;
        justify-content: flex-start;
    }
    .dashboard-result-card__metric { text-align: left; }
}

@media (prefers-reduced-motion: reduce) {
    .dashboard-kpi { transition: none; }
}
/* Devices and Schedule cards share one height side by side; when either
   list outgrows the cap it scrolls inside its card instead of stretching
   the row and leaving dead space in the shorter card. */
@media (min-width: 1200px) {
    .group-panel-card {
        max-height: 38rem;
    }
}
.group-panel-scroll {
    flex: 1 1 auto;
    min-height: 0;
    overflow-y: auto;
}
.group-scan-progress {
    height: 0.375rem;
}

/* The active scan keeps its full three-cycle route visible. Only the current
   cycle carries emphasis; the other cycles remain readable context. */
.active-session-lifecycle {
    display: grid;
    grid-template-columns: repeat(3, minmax(0, 1fr));
    margin: 0;
    padding: 0;
    list-style: none;
}
.active-session-lifecycle__item {
    position: relative;
    display: flex;
    align-items: center;
    gap: 0.75rem;
    min-width: 0;
}
.active-session-lifecycle__item:not(:last-child)::after {
    position: absolute;
    top: 50%;
    right: 0.75rem;
    left: 3rem;
    height: 2px;
    background: var(--si-gray-300, #d4d7e5);
    content: "";
}
.active-session-lifecycle__marker,
.active-session-lifecycle__copy {
    position: relative;
    z-index: 1;
}
.active-session-lifecycle__marker {
    display: grid;
    flex: 0 0 2.25rem;
    width: 2.25rem;
    height: 2.25rem;
    place-items: center;
    border: 2px solid var(--si-gray-400, #b4b7c9);
    border-radius: 50%;
    background: var(--si-body-bg, #fff);
    font-size: 0.75rem;
    font-weight: 700;
}
.active-session-lifecycle__copy {
    padding-right: 1rem;
    background: var(--si-body-bg, #fff);
}
.active-session-lifecycle__copy strong {
    line-height: 1.25;
}
.active-session-lifecycle__item.is-current {
    color: var(--si-primary, #6366f1);
}
.active-session-lifecycle__item.is-current .active-session-lifecycle__marker {
    border-color: var(--si-primary, #6366f1);
    background: var(--si-primary, #6366f1);
    box-shadow: 0 0 0 0.3rem rgba(var(--si-primary-rgb, 99, 102, 241), 0.12);
    color: #fff;
}
.active-session-lifecycle__item.is-muted {
    color: var(--si-gray-500, #b4b7c9);
}

@media (max-width: 767.98px) {
    .active-session-lifecycle {
        grid-template-columns: 1fr;
    }
    .active-session-lifecycle__item {
        min-height: 4rem;
    }
    .active-session-lifecycle__item:not(:last-child)::after {
        top: calc(50% + 1rem);
        right: auto;
        bottom: -1rem;
        left: 1.0625rem;
        width: 2px;
        height: auto;
    }
}

/* Finished report cards use Silicon's card, badge and button primitives. The
   colored edge and compact result grid make terminal outcomes readable without
   repeating the live lifecycle or a meaningless 100% progress bar. */
.scan-report-card {
    --scan-report-muted: var(--si-gray-600, #9397ad);
    border-left: 0.25rem solid var(--si-success) !important;
}
.scan-report-card--partial {
    border-left-color: var(--si-warning) !important;
}
.scan-report-card--failed {
    border-left-color: var(--si-danger) !important;
}
.scan-report-card__body {
    padding: 1.35rem 1.5rem 1.5rem;
}
.scan-report-card__header {
    display: flex;
    align-items: flex-start;
    gap: 0.9rem;
}
.scan-report-card__outcome-icon {
    display: grid;
    flex: 0 0 2.35rem;
    width: 2.35rem;
    height: 2.35rem;
    place-items: center;
    border-radius: 50%;
    background: var(--si-success);
    color: #fff;
}
.scan-report-card--partial .scan-report-card__outcome-icon {
    background: var(--si-warning);
}
.scan-report-card--failed .scan-report-card__outcome-icon {
    background: var(--si-danger);
}
.scan-report-card__outcome-icon i {
    font-size: 1.2rem;
}
.scan-report-card__identity {
    min-width: 0;
    flex: 1 1 auto;
}
.scan-report-card__title-row {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.45rem;
    margin-bottom: 0.35rem;
}
.scan-report-card__title-row h3 {
    margin-right: 0.25rem;
}
.scan-report-card__outcome-badge {
    background: var(--si-success-bg-subtle, rgba(20, 195, 142, 0.12));
    color: var(--si-success);
}
.scan-report-card--partial .scan-report-card__outcome-badge {
    background: var(--si-warning-bg-subtle, rgba(245, 166, 35, 0.14));
    color: var(--si-warning);
}
.scan-report-card--failed .scan-report-card__outcome-badge {
    background: var(--si-danger-bg-subtle, rgba(239, 68, 68, 0.12));
    color: var(--si-danger);
}
.scan-report-card__summary {
    margin: 0 0 0.45rem;
    color: var(--si-gray-700, #565973);
    font-size: 0.875rem;
}
.scan-report-card__id {
    display: flex;
    align-items: baseline;
    min-width: 0;
    gap: 0.5rem;
    color: var(--si-gray-700, #565973);
    font-size: 0.75rem;
}
.scan-report-card__id-label {
    flex: 0 0 auto;
    color: var(--si-primary);
    font-size: 0.625rem;
    font-weight: 700;
    letter-spacing: 0.075em;
    text-transform: uppercase;
}
.scan-report-card__id strong {
    min-width: 0;
    overflow-wrap: anywhere;
}
.scan-report-card__results {
    display: grid;
    grid-template-columns: repeat(4, minmax(0, 1fr));
    gap: 0.75rem;
    margin-top: 1.15rem;
}
.scan-report-card__result {
    min-width: 0;
    padding: 0.8rem 0.9rem;
    border-radius: var(--si-border-radius-lg, 0.5rem);
}
.scan-report-card__result-heading {
    display: flex;
    align-items: center;
    gap: 0.35rem;
    color: var(--scan-report-muted);
}
.scan-report-card__result-heading i {
    font-size: 1rem;
}
.scan-report-card__result-label {
    font-size: 0.625rem;
    font-weight: 700;
    letter-spacing: 0.05em;
    text-transform: uppercase;
}
.scan-report-card__result-value,
.scan-report-card__result-detail {
    display: block;
    overflow-wrap: anywhere;
}
.scan-report-card__result-value {
    margin-top: 0.28rem;
    font-size: 1rem;
}
.scan-report-card__result-detail {
    margin-top: 0.12rem;
    color: var(--scan-report-muted);
    font-size: 0.7rem;
    line-height: 1.35;
}
.scan-report-card__result.is-success .scan-report-card__result-value {
    color: var(--si-success);
}
.scan-report-card__result.is-partial .scan-report-card__result-value {
    color: var(--si-warning);
}
.scan-report-card__result.is-failed .scan-report-card__result-value {
    color: var(--si-danger);
}
.scan-report-card__footer {
    display: grid;
    grid-template-columns: minmax(0, 1fr) auto;
    align-items: center;
    gap: 0.85rem 1.5rem;
    padding: 0.9rem 1.5rem;
}
.scan-report-card__meta {
    display: grid;
    grid-template-columns: repeat(4, auto);
    align-items: start;
    gap: 1rem 1.4rem;
}
.scan-report-card__timestamp > * {
    display: block;
}
.scan-report-card__timestamp-label {
    color: var(--scan-report-muted);
    font-size: 0.625rem;
    font-weight: 600;
    letter-spacing: 0.035em;
    text-transform: uppercase;
}
.scan-report-card__timestamp-absolute {
    margin-top: 0.12rem;
    font-size: 0.72rem;
    font-weight: 600;
    white-space: nowrap;
}
.scan-report-card__scan-ids > * {
    display: block;
}
.scan-report-card__scan-ids strong {
    font-size: 0.75rem;
}

@media (max-width: 1199.98px) {
    .scan-report-card__results {
        grid-template-columns: repeat(2, minmax(0, 1fr));
    }
}

@media (max-width: 991.98px) {
    .scan-report-card__meta {
        grid-template-columns: repeat(2, auto);
    }
}

@media (max-width: 575.98px) {
    .scan-report-card__body {
        padding: 1.1rem;
    }
    .scan-report-card__header {
        gap: 0.7rem;
    }
    .scan-report-card__results {
        grid-template-columns: 1fr;
    }
    .scan-report-card__footer {
        display: flex;
        align-items: flex-start;
        flex-direction: column;
        padding: 0.9rem 1.1rem;
    }
    .scan-report-card__meta {
        grid-template-columns: 1fr 1fr;
        width: 100%;
        gap: 0.85rem 1rem;
    }
    .scan-report-card__scan-ids {
        grid-column: 1 / -1;
    }
    .scan-report-card__footer > .btn {
        width: 100%;
    }
}
/* Bootstrap gives .card-body flex-grow; undo that so card headers stay
   pinned to the top and only the list region absorbs the shared height. */
.group-devices-card > .card-body {
    flex: 0 0 auto;
}
.group-schedule-card > .card-body {
    flex: 1 1 auto;
    min-height: 0;
}
.schedule-summary.is-paused .schedule-week-grid {
    opacity: 0.58;
}
.schedule-week-grid {
    display: grid;
    grid-template-columns: repeat(7, minmax(5rem, 1fr));
    gap: 0.5rem;
}
.schedule-day-summary {
    min-width: 0;
    padding: 0.75rem 0.625rem;
    border: 1px solid var(--si-gray-300, #e2e5f1);
    border-radius: 0.5rem;
    background: rgba(var(--si-primary-rgb), 0.025);
}
.schedule-day-summary.is-empty {
    background: var(--si-gray-100, #f3f6ff);
}
.schedule-day-summary__name {
    margin-bottom: 0.5rem;
    color: var(--si-gray-700, #565973);
    font-size: 0.75rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.035em;
}
.schedule-day-summary__times {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: 0.3rem;
}
.schedule-time-chip {
    width: 100%;
    padding: 0.35rem 0.4rem;
    font-size: 0.72rem;
    font-weight: 500;
    text-align: center;
}
.schedule-summary__footer {
    min-height: 2rem;
}
.schedule-days {
    border-bottom: 1px solid var(--si-gray-300, #e2e5f1);
}
.schedule-copy {
    width: 100%;
}
.schedule-copy-source {
    width: 9rem;
}
.schedule-copy-targets {
    display: flex;
    flex-wrap: wrap;
    gap: 0.25rem 1rem;
}
.schedule-copy-targets .form-check {
    min-width: 3.5rem;
    margin-bottom: 0;
}
.schedule-day-row {
    display: block;
}
.schedule-time-list {
    display: grid;
    grid-template-columns: repeat(6, minmax(0, 1fr));
    gap: 0.5rem;
}
.schedule-time-input {
    width: 100%;
    min-width: 0;
    flex-wrap: nowrap;
}
.schedule-time-input .form-control {
    min-width: 0;
}
.schedule-time-input .btn {
    flex: 0 0 auto;
}
.device-location-map-wrap {
    position: relative;
    min-height: 15rem;
    background: #eff2fc;
}
.device-location-map {
    position: absolute;
    inset: 0;
}
.device-location-map .leaflet-control-attribution {
    font-size: 0.625rem;
}
.device-location-empty {
    position: absolute;
    z-index: 500;
    inset: 0;
    pointer-events: none;
}
.device-location-empty[hidden] {
    display: none !important;
}
@media (max-width: 575.98px) {
    .schedule-copy,
    .schedule-copy-source {
        max-width: none;
        width: 100%;
    }
    .schedule-time-list {
        grid-template-columns: 1fr;
    }
}
@media (max-width: 767.98px) {
    .schedule-week-grid {
        grid-template-columns: repeat(2, minmax(0, 1fr));
    }
    .schedule-day-summary__times {
        flex-flow: row wrap;
    }
    .schedule-time-chip {
        width: auto;
        min-width: 4.25rem;
    }
}
@media (min-width: 576px) and (max-width: 767.98px) {
    .schedule-time-list {
        grid-template-columns: repeat(2, minmax(0, 1fr));
    }
}
@media (min-width: 768px) and (max-width: 1199.98px) {
    .schedule-time-list {
        grid-template-columns: repeat(3, minmax(0, 1fr));
    }
    .schedule-week-grid {
        grid-template-columns: repeat(4, minmax(0, 1fr));
    }
    .schedule-day-summary__times {
        flex-flow: row wrap;
    }
    .schedule-time-chip {
        width: auto;
        min-width: 4.25rem;
    }
}

/* Live device state: concentric signals keep the motion calm and purposeful. */
.device-live-card {
    background: linear-gradient(145deg, #fff 58%, rgba(var(--si-success-rgb), 0.08));
}
.device-status-visual {
    position: relative;
    width: 8.5rem;
    height: 8.5rem;
    margin-right: auto;
    margin-left: auto;
}
.device-status-ring,
.device-status-core {
    position: absolute;
    top: 50%;
    left: 50%;
    border-radius: 50%;
    transform: translate(-50%, -50%);
}
.device-status-ring {
    border: 1px solid rgba(var(--si-success-rgb), 0.38);
    animation: device-status-ripple 2.4s ease-out infinite;
}
.device-status-ring-inner {
    width: 5.4rem;
    height: 5.4rem;
}
.device-status-ring-outer {
    width: 8rem;
    height: 8rem;
    animation-delay: 0.8s;
}
.device-status-core {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 4rem;
    height: 4rem;
    font-size: 1.8rem;
    animation: device-status-glow 2.4s ease-in-out infinite;
}
.device-live-dot {
    display: inline-block;
    width: 0.45rem;
    height: 0.45rem;
    border-radius: 50%;
    background: currentColor;
    box-shadow: 0 0 0 rgba(var(--si-success-rgb), 0.4);
    animation: device-live-dot 1.8s ease-out infinite;
}

@keyframes device-status-ripple {
    0% { opacity: 0.8; transform: translate(-50%, -50%) scale(0.72); }
    75%, 100% { opacity: 0; transform: translate(-50%, -50%) scale(1.08); }
}
@keyframes device-status-glow {
    0%, 100% { transform: translate(-50%, -50%) scale(1); }
    50% { transform: translate(-50%, -50%) scale(1.06); }
}
@keyframes device-live-dot {
    0% { box-shadow: 0 0 0 0 rgba(var(--si-success-rgb), 0.4); }
    70%, 100% { box-shadow: 0 0 0 0.4rem rgba(var(--si-success-rgb), 0); }
}

/* The axis-free sparkline bleeds to the card edges inside a clipped, text-free
   plot band. Its data can change freely without crossing readable content. */
.device-trend-card {
    background: linear-gradient(180deg, #fff 0%, #fff 42%, rgba(var(--si-primary-rgb), 0.045) 100%);
}
.device-trend-reading {
    max-width: 18rem;
}
.device-trend-plot {
    min-height: 6.5rem;
    margin-right: -1.5rem;
    margin-left: -1.5rem;
    overflow: hidden;
}
.device-trend-chart {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    opacity: 0.78;
    pointer-events: none;
}
.device-trend-footer {
    position: relative;
    z-index: 2;
    background: rgba(255, 255, 255, 0.72);
}

/* Expanded device trend. The modal chart gets a stable host height so ECharts
   can calculate its canvas when Bootstrap finishes revealing the dialog. */
.device-detail-chart {
    width: 100%;
    height: 28rem;
    min-height: 28rem;
}

/* Leaflet is a decorative location layer on the compact card. The foreground
   gradient guarantees readable device details over every Positron tile. */
.device-map-background,
.device-map-scrim {
    position: absolute;
    inset: 0;
}
.device-map-background {
    z-index: 0;
    background: #eff2fc;
    pointer-events: none;
}
.device-map-background .leaflet-tile-pane {
    filter: grayscale(0.25) saturate(0.55);
    opacity: 0.72;
}
.device-map-scrim {
    z-index: 1;
    background: linear-gradient(
        180deg,
        rgba(255, 255, 255, 0.58) 0%,
        rgba(255, 255, 255, 0.12) 42%,
        rgba(255, 255, 255, 0.94) 72%,
        #fff 100%
    );
    pointer-events: none;
}
.device-map-card .leaflet-control-container {
    display: none;
}
.device-map-card .leaflet-marker-icon,
.device-map-card .leaflet-interactive {
    filter: none;
}
.device-map-attribution {
    color: var(--si-gray-600);
    font-size: 0.625rem;
    line-height: 1.2;
}
.device-map-attribution a {
    color: inherit;
}

/* Coordinate picker used by the device dialog. It exposes the application's
   standard GeoInfo/OpenStreetMap source switcher. */
.location-map-wrap {
    position: relative;
    height: 18rem;
    min-height: 18rem;
    background: #eff2fc;
}
.location-map {
    position: absolute;
    inset: 0;
}
.location-map .leaflet-control-attribution {
    font-size: 0.625rem;
}
.zone-map-wrap {
    position: relative;
    height: 22rem;
    min-height: 22rem;
    background: #eff2fc;
}
.zone-map {
    position: absolute;
    inset: 0;
}
.zone-map .leaflet-control-attribution {
    font-size: 0.625rem;
}
.location-dot {
    display: block;
    width: 1rem;
    height: 1rem;
    border: 3px solid #fff;
    border-radius: 50%;
    background: var(--si-primary);
    box-shadow: 0 0 0 2px rgba(var(--si-primary-rgb), 0.45), 0 0.25rem 0.75rem rgba(16, 24, 40, 0.3);
}
.location-marker {
    background: transparent;
    border: 0;
}
.location-marker:focus .location-dot {
    outline: 3px solid rgba(var(--si-primary-rgb), 0.35);
    outline-offset: 3px;
}

/* Full-screen route explorer for the map card. Desktop keeps the map and
   summary visible together; smaller screens stack them into a natural scroll. */
.device-route-body,
.device-route-layout,
.device-route-map-wrap {
    min-height: 0;
}
.device-route-map-wrap {
    min-height: 30rem;
}
.device-route-map {
    position: absolute;
    inset: 0;
    background: #eff2fc;
}
.device-route-actions {
    position: absolute;
    z-index: 520;
    bottom: 1rem;
    left: 1rem;
}
.device-route-loading {
    position: absolute;
    z-index: 550;
    inset: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    visibility: hidden;
    background: rgba(243, 246, 255, 0.78);
    opacity: 0;
    pointer-events: none;
    transition: opacity 0.2s ease, visibility 0.2s ease;
    backdrop-filter: blur(2px);
}
.device-route-loading.is-visible {
    visibility: visible;
    opacity: 1;
}
.device-route-sidebar {
    overflow-y: auto;
    scrollbar-width: thin;
}
.device-route-map .leaflet-control-attribution {
    font-size: 0.625rem;
}
.device-route-map .leaflet-popup-content {
    margin: 0.75rem 1rem;
    color: var(--si-body-color);
    font-family: "Google Sans", sans-serif;
    font-size: 0.75rem;
    line-height: 1.45;
}

@media (min-width: 992px) {
    .device-map-modal .modal-content {
        height: 100vh;
    }
    .device-route-body {
        overflow: hidden;
    }
    .device-route-layout {
        overflow: hidden;
    }
}

@media (max-width: 991.98px) {
    .device-route-body {
        overflow-y: auto;
    }
    .device-route-map-wrap {
        min-height: 55vh;
    }
    .device-route-sidebar {
        overflow: visible;
    }
}

@media (prefers-reduced-motion: reduce) {
    .device-route-loading {
        transition: none;
    }
}

/* Compact trend hosts for the device details weather history row; mirrors the
   dashboard chart scaffolding but sized to sit three-up in a card grid. */
.device-mini-chart {
    width: 100%;
    height: 13rem;
    min-height: 13rem;
}

/* Purpose-built weather and GPS tracker details templates. */
.device-page-icon,
.metric-icon {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    flex: 0 0 auto;
    border-radius: 0.75rem;
}
.device-page-icon {
    width: 4rem;
    height: 4rem;
    font-size: 2rem;
}
.metric-icon {
    width: 2.5rem;
    height: 2.5rem;
    font-size: 1.25rem;
}
.metric-icon-sm {
    width: 2rem;
    height: 2rem;
    font-size: 1rem;
    border-radius: 50%;
}

/* Weather station: current conditions panel */
.weather-hero-panel {
    background:
        radial-gradient(circle at 8% 0, rgba(14, 165, 233, 0.08), transparent 40%),
        linear-gradient(135deg, #fff 58%, #f4f7ff);
}
.weather-condition-icon {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 4rem;
    height: 4rem;
    border-radius: 50%;
    color: var(--si-info);
    background: rgba(var(--si-info-rgb), 0.1);
    font-size: 2rem;
    flex: 0 0 auto;
}
.weather-temperature {
    color: var(--si-heading-color);
    font-size: clamp(3.75rem, 7vw, 5.5rem);
    font-weight: 600;
    line-height: 0.85;
    letter-spacing: -0.06em;
}

/* Weather station: secondary readings */
.weather-readings {
    border-left: 1px solid var(--si-border-color);
    background: var(--si-body-bg);
}
.weather-reading {
    padding: 1.5rem 1.75rem;
    border-bottom: 1px solid var(--si-border-color);
}
.weather-reading:nth-child(-n+3) { border-bottom: 1px solid var(--si-border-color); }
.weather-reading:nth-child(3n+1) { border-left: 0; }
.weather-reading:nth-child(3n) { border-right: 0; }
.weather-reading dt {
    color: var(--si-gray-600);
    font-size: 1rem;
    font-weight: 500;
    margin-bottom: 0.5rem;
}
.weather-reading dt i { margin-right: 0.35rem; }
.weather-reading dd {
    color: var(--si-heading-color);
    font-size: 2rem;
    font-weight: 700;
    line-height: 1.1;
    margin: 0;
    font-variant-numeric: tabular-nums;
}
.weather-reading-unit {
    display: block;
    color: var(--si-gray-600);
    font-size: 1rem;
    font-weight: 500;
    margin-top: 0.35rem;
}

/* Weather station: daily summary */
.weather-summary-item {
    padding: 0.875rem 1rem;
    border-radius: 0.5rem;
    background: var(--si-gray-100);
    text-align: center;
}
.weather-summary-label {
    display: block;
    color: var(--si-gray-600);
    font-size: 0.75rem;
    margin-bottom: 0.25rem;
}
.weather-summary-value {
    display: block;
    color: var(--si-heading-color);
    font-size: 0.95rem;
    font-weight: 600;
}

/* Weather station: health list */
.weather-health-item {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 0.625rem 0;
    border-bottom: 1px solid var(--si-border-color);
}
.weather-health-item:last-child { border-bottom: 0; }
.weather-health-item dt { font-size: 0.8rem; }
.weather-health-item dd { font-size: 0.85rem; }

/* Sensor details: telemetry metric cards */
.sensor-metric-card {
    transition: transform 0.2s ease, box-shadow 0.2s ease;
}
.sensor-metric-card:hover {
    transform: translateY(-2px);
    box-shadow: 0 0.5rem 1.5rem rgba(0, 0, 0, 0.08) !important;
}
.sensor-metric-icon {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 2.75rem;
    height: 2.75rem;
    border-radius: 0.75rem;
    font-size: 1.35rem;
    flex: 0 0 auto;
}
.sensor-metric-progress {
    height: 6px;
    border-radius: 3px;
    background-color: var(--si-gray-200);
}
.sensor-metric-progress .progress-bar {
    border-radius: 3px;
}

.gps-route-map-wrap { min-height: 34rem; }
.gps-trip-summary dt { color: var(--si-gray-600); font-size: 0.7rem; font-weight: 400; margin-bottom: 0.3rem; }
.gps-trip-summary dd { color: var(--si-heading-color); font-size: 0.9rem; font-weight: 700; margin: 0; }
.gps-trip-summary > div + div { border-left: 1px solid var(--si-border-color); }
.gps-speed-panel {
    display: grid;
    grid-template-columns: 1fr auto;
    align-items: center;
    padding: 1.1rem 1.25rem;
    color: var(--si-primary);
    background: rgba(var(--si-primary-rgb), 0.08);
}
.gps-speed-panel > span { color: var(--si-gray-600); font-size: 0.75rem; }
.gps-speed-panel strong { grid-row: span 2; font-size: 2.25rem; line-height: 1; }
.gps-speed-panel strong small { font-size: 0.75rem; font-weight: 600; }
.gps-speed-panel em { color: var(--si-heading-color); font-size: 0.8rem; font-style: normal; font-weight: 600; }

@media (max-width: 991.98px) {
    .weather-readings {
        border-left: 0;
        border-top: 1px solid var(--si-border-color);
    }
}

@media (max-width: 767.98px) {
    .weather-reading { padding: 1rem 1.15rem; }
    .weather-reading dd { font-size: 1.25rem; }
    .gps-trip-summary > div:nth-child(3) { border-left: 0; }
    .gps-trip-summary > div:nth-child(-n + 2) { padding-bottom: 1rem; }
    .gps-trip-summary > div:nth-last-child(-n + 2) { padding-top: 1rem; border-top: 1px solid var(--si-border-color); }
}

@media (max-width: 575.98px) {
    .device-mini-chart {
        height: 10rem;
        min-height: 10rem;
    }

    /* The 55vh inline-route fallback is generous on phones; tighten it. */
    .device-route-map-wrap {
        min-height: 20rem;
    }
}

/* Compact device conversation. Messages remain inside a bounded log so user
   input cannot cause the card to grow and break the surrounding grid. */
.device-chat-card {
    background: linear-gradient(145deg, #fff 62%, rgba(var(--si-primary-rgb), 0.055));
}
.device-chat-log {
    min-height: 8.75rem;
    max-height: 8.75rem;
    overflow-y: auto;
    background: var(--si-gray-100);
    scrollbar-width: thin;
}
.device-chat-log.is-scrolled {
    -webkit-mask-image: linear-gradient(to bottom, transparent 0, #000 1.35rem, #000 100%);
    mask-image: linear-gradient(to bottom, transparent 0, #000 1.35rem, #000 100%);
}
.device-chat-message {
    width: fit-content;
    max-width: 88%;
    border-radius: 0.75rem;
    padding: 0.55rem 0.7rem;
    font-size: 0.75rem;
    line-height: 1.4;
}
.device-chat-message + .device-chat-message {
    margin-top: 0.55rem;
}
.device-chat-message-output {
    border: 1px solid var(--si-border-color);
    background: #fff;
    color: var(--si-body-color);
}
.device-chat-message-input {
    margin-left: auto;
    background: var(--si-primary);
    color: #fff;
}
.device-chat-speaker {
    display: block;
    margin-bottom: 0.15rem;
    font-size: 0.625rem;
    font-weight: 700;
    letter-spacing: 0.03em;
    opacity: 0.72;
    text-transform: uppercase;
}

/* Predictive health is deliberately glanceable: the conic ring communicates
   the score while the adjacent definition list carries exact diagnostics. */
.device-health-gauge {
    position: relative;
    width: 6.5rem;
    height: 6.5rem;
    border-radius: 50%;
    background: conic-gradient(var(--si-warning) 0 82%, var(--si-gray-200) 82% 100%);
}
.device-health-gauge::before {
    position: absolute;
    inset: 0.65rem;
    border-radius: 50%;
    background: #fff;
    box-shadow: inset 0 0 0 1px var(--si-border-color);
    content: "";
}
.device-health-gauge-value {
    position: absolute;
    z-index: 1;
    top: 50%;
    left: 50%;
    display: flex;
    align-items: baseline;
    transform: translate(-50%, -50%);
}
.device-health-gauge-value strong {
    color: var(--si-heading-color);
    font-size: 1.5rem;
    line-height: 1;
}
.device-health-gauge-value span {
    color: var(--si-gray-600);
    font-size: 0.625rem;
}

@media (prefers-reduced-motion: reduce) {
    .device-status-ring,
    .device-status-core,
    .device-live-dot {
        animation: none;
    }
    .device-status-ring-inner { opacity: 0.55; }
    .device-status-ring-outer { opacity: 0.28; }
}

/* Dashboard analytics. ECharts needs an explicit height on each host element. */
.dashboard-chart {
    width: 100%;
    height: 19rem;
    min-height: 19rem;
}
.dashboard-chart-lg {
    height: 22rem;
    min-height: 22rem;
}
.chart-icon {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 2.5rem;
    height: 2.5rem;
    flex: 0 0 2.5rem;
    border-radius: 0.75rem;
    font-size: 1.25rem;
}

@media (max-width: 575.98px) {
    .device-detail-chart {
        height: 21rem;
        min-height: 21rem;
    }
    .dashboard-chart,
    .dashboard-chart-lg {
        height: 17rem;
        min-height: 17rem;
    }
}

/* Device dashboard discovery toolbar. Search remains wider than sort while
   the sort and display controls stay anchored to the right on larger screens. */
.device-toolbar {
    display: flex;
    align-items: end;
    gap: 1rem;
    width: 100%;
}

.device-toolbar__search {
    flex: 1 1 36rem;
    max-width: 36rem;
}

.device-toolbar__controls {
    display: flex;
    align-items: end;
    gap: 1rem;
    flex: 0 0 auto;
    margin-left: auto;
}

.device-toolbar__sort {
    flex: 0 0 18rem;
    max-width: 18rem;
}

.device-toolbar__view {
    flex: 0 0 auto;
    min-width: 0;
}

.device-view-switch {
    display: inline-flex;
}

@media (max-width: 767.98px) {
    .device-toolbar {
        flex-direction: column;
        align-items: stretch;
    }

    .device-toolbar__search {
        flex-basis: auto;
        max-width: none;
    }

    .device-toolbar__controls {
        justify-content: space-between;
        width: 100%;
    }

    .device-toolbar__sort {
        flex: 1 1 auto;
        max-width: none;
    }
}

/* =========================================================================
   Combined map + telemetry card (production VMM dashboard reference).
   Reuses the `.device-map-*` map layer and scrim classes above so a
   decorative, non-interactive CARTO background stays the visual baseline;
   the classes below add the instrument foreground only.
   Source: VMMDashboard app/static/css/app.css and js/dashboard.js buildCard().
   ========================================================================= */

/* Combined card. The map host fills the card and the body floats over the
   white scrim so telemetry keeps strong foreground contrast over every tile. */
.vmm-card {
    min-height: 18rem;
}
.vmm-card__map {
    position: absolute;
    inset: 0;
    z-index: 0;
}
.vmm-card__scrim {
    /* Inherits the device-map-scrim gradient; keep it above the map tiles. */
    z-index: 1;
}
.vmm-card__body {
    position: relative;
    z-index: 2;
    /* Raise the body above the map so the lower metrics band always clears the
       marker, which is shifted into the upper visual third by dashboard.js. */
    justify-content: flex-end;
}
.vmm-card__name {
    font-weight: 600;
    line-height: 1.25;
}
.vmm-card__received {
    white-space: nowrap;
}

@media (max-width: 575.98px) {
    /* On phones, prioritize device information over the decorative map field. */
    .vmm-card {
        min-height: 0;
    }
    .vmm-card__body {
        justify-content: flex-start;
    }
}

/* Prominent electrical readings. Each value carries its own accent color so
   voltage/power/battery stay distinguishable in the muted map field. */
.vmm-card__metrics {
    margin-top: 0.75rem;
}
.vmm-metric {
    display: flex;
    flex-direction: column;
    gap: 0.15rem;
}
.vmm-metric__value {
    font-size: 1.35rem;
    font-weight: 700;
    font-variant-numeric: tabular-nums;
    line-height: 1.1;
    letter-spacing: -0.01em;
}
.vmm-metric__label {
    font-size: 0.6875rem;
    font-weight: 600;
    letter-spacing: 0.04em;
    text-transform: uppercase;
    color: var(--si-gray-600);
}

/* Neutral fallback when a device has no GPS coordinates: a calm electrical-grid
   texture instead of a broken/empty map pane. No glyph is injected here (a
   hardcoded icon codepoint would be unverifiable); the layered grid + soft
   instrument glows read as a deliberate, non-broken fallback surface. */
.vmm-card__map--neutral {
    background-color: #eef1f8;
    background-image:
        linear-gradient(0deg, rgba(99, 102, 241, 0.06) 1px, transparent 1px),
        linear-gradient(90deg, rgba(99, 102, 241, 0.06) 1px, transparent 1px),
        radial-gradient(circle at 30% 25%, rgba(99, 102, 241, 0.10), transparent 55%),
        radial-gradient(circle at 75% 80%, rgba(34, 197, 94, 0.08), transparent 60%);
    background-size: 26px 26px, 26px 26px, auto, auto;
}

/* Compact VMM list-view row. Identity is allowed to shrink so long names are
   truncated while the latest readings and action buttons remain aligned. */
.vmm-list-card__name {
    font-weight: 600;
    line-height: 1.25;
}

.vmm-list-card__status-dot {
    display: inline-block;
    flex-shrink: 0;
    width: 0.5rem;
    height: 0.5rem;
    border-radius: 50%;
}

.vmm-list-card__status-dot--online {
    background-color: var(--si-success, #22c55e);
}

.vmm-list-card__status-dot--offline {
    background-color: var(--si-danger, #ef4444);
}

.vmm-list-card__value {
    font-size: 1.1rem;
    font-weight: 700;
    font-variant-numeric: tabular-nums;
    line-height: 1.2;
    white-space: nowrap;
}

.vmm-list-card__reading {
    flex-shrink: 0;
}

.vmm-list-card__identity {
    min-width: 0;
}

/* Five compact-row concepts. Silicon's stock list-group, card-body, badge,
   button, border, background, spacing, and typography utilities provide the
   shared visual language; only the layouts without kit equivalents live here. */
.device-list > .list-group-item {
    min-height: 5.5rem;
}

/* A warning rail is not available as a one-sided Silicon border utility when
   the list-group item already owns a neutral border on all four sides. */
.device-list-alert {
    border-left-color: var(--si-warning, #ffba08) !important;
    border-left-width: 0.25rem !important;
}

.list-inline-reading {
    align-items: center;
    gap: 0.65rem;
    min-width: 8.5rem;
}

.list-inline-reading > i {
    font-size: 1.5rem;
}

.list-inline-reading strong,
.list-inline-reading span,
.list-primary-reading strong,
.list-primary-reading span,
.list-alert-reading strong,
.list-alert-reading span {
    display: block;
    white-space: nowrap;
}

.list-inline-reading strong {
    font-size: 0.9rem;
}

.list-inline-reading span,
.list-primary-reading span,
.list-alert-reading span {
    color: var(--si-gray-600, #9397ad);
    font-size: 0.6875rem;
    font-weight: 600;
    letter-spacing: 0.03em;
    text-transform: uppercase;
}

.list-metric-layout {
    display: grid;
    grid-template-columns: minmax(13rem, 1fr) auto auto;
    align-items: stretch;
}

.list-metric-identity {
    align-self: center;
    min-width: 0;
}

.list-metric-strip {
    display: grid;
    grid-template-columns: repeat(3, minmax(6rem, 1fr));
}

.list-metric-strip > div {
    display: flex;
    flex-direction: column-reverse;
    justify-content: center;
    min-width: 6rem;
    padding: 0.85rem 1rem;
    text-align: center;
}

.list-metric-strip dt {
    color: var(--si-gray-600, #9397ad);
    font-size: 0.6875rem;
    letter-spacing: 0.04em;
    text-transform: uppercase;
}

.list-metric-strip dd {
    margin: 0 0 0.15rem;
    font-size: 1rem;
    font-weight: 700;
    font-variant-numeric: tabular-nums;
    white-space: nowrap;
}

.list-metric-actions {
    display: flex;
    align-items: center;
    gap: 0.5rem;
}

.list-alert-reading strong,
.list-primary-reading strong {
    font-size: 1.1rem;
    font-variant-numeric: tabular-nums;
}

.list-primary-reading {
    min-width: 7.5rem;
}

@media (max-width: 767.98px) {
    .list-metric-layout {
        grid-template-columns: 1fr auto;
    }

    .list-metric-strip {
        grid-column: 1 / -1;
        grid-row: 2;
        border-left: 0 !important;
        border-top: 1px solid var(--si-gray-300, #e2e5f1);
    }

    .list-metric-actions {
        grid-column: 2;
        grid-row: 1;
    }
}

@media (max-width: 575.98px) {
    .device-list .card-body {
        gap: 0.75rem !important;
    }

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

    .list-metric-strip > div {
        min-width: 0;
        padding: 0.7rem 0.4rem;
    }

    .list-metric-strip dd {
        font-size: 0.875rem;
    }

}

/* Skeleton placeholders for a first load, if a live implementation reuses this
   card. The shimmer is disabled under prefers-reduced-motion (see below). */
.vmm-card--skeleton .card-body {
    pointer-events: none;
}
.vmm-skeleton-bar {
    position: relative;
    overflow: hidden;
    background: linear-gradient(100deg, #eef1f8 30%, #f7f8fc 50%, #eef1f8 70%);
    background-size: 200% 100%;
    animation: vmm-skeleton-shimmer 1.4s ease-in-out infinite;
}
@keyframes vmm-skeleton-shimmer {
    0% { background-position: 180% 0; }
    100% { background-position: -180% 0; }
}

@media (max-width: 575.98px) {
    .vmm-metric__value {
        font-size: 1.15rem;
    }
}

/* Respect reduced-motion across the combined card surface: stop the skeleton
   shimmer and any Leaflet decorative animation. Keep content fully legible. */
@media (prefers-reduced-motion: reduce) {
    .vmm-skeleton-bar {
        animation: none;
        background: #eef1f8;
    }
    .vmm-card,
    .vmm-card__map {
        transition: none;
    }
}

/* Silicon recolors its stock components from data-bs-theme. These application-
   specific surfaces use custom backgrounds, so give them equivalent dark-mode
   surfaces instead of leaving light panels behind white theme text. */
[data-bs-theme="dark"] .dashboard-empty-state,
[data-bs-theme="dark"] .device-route-loading {
    background: rgba(var(--si-body-bg-rgb), 0.78);
}

[data-bs-theme="dark"] .dashboard-group-register,
[data-bs-theme="dark"] .device-chat-message-output,
[data-bs-theme="dark"] .device-health-gauge::before {
    background: var(--si-body-bg);
}

[data-bs-theme="dark"] .device-live-card,
[data-bs-theme="dark"] .device-trend-card,
[data-bs-theme="dark"] .device-chat-card {
    background: linear-gradient(
        145deg,
        var(--si-body-bg) 58%,
        rgba(var(--si-primary-rgb), 0.1)
    );
}

[data-bs-theme="dark"] .device-trend-footer {
    background: rgba(var(--si-body-bg-rgb), 0.82);
}

[data-bs-theme="dark"] .weather-hero-panel {
    background:
        radial-gradient(circle at 8% 0, rgba(var(--si-info-rgb), 0.14), transparent 40%),
        linear-gradient(135deg, var(--si-body-bg) 58%, var(--si-secondary-bg));
}

[data-bs-theme="dark"] .weather-summary-item,
[data-bs-theme="dark"] .device-chat-log,
[data-bs-theme="dark"] .device-location-map-wrap,
[data-bs-theme="dark"] .device-map-background,
[data-bs-theme="dark"] .location-map-wrap,
[data-bs-theme="dark"] .zone-map-wrap,
[data-bs-theme="dark"] .device-route-map,
[data-bs-theme="dark"] .vmm-card__map--neutral {
    background-color: var(--si-secondary-bg);
}

[data-bs-theme="dark"] .device-map-scrim {
    background: linear-gradient(
        180deg,
        rgba(var(--si-body-bg-rgb), 0.5) 0%,
        rgba(var(--si-body-bg-rgb), 0.12) 42%,
        rgba(var(--si-body-bg-rgb), 0.92) 72%,
        var(--si-body-bg) 100%
    );
}

[data-bs-theme="dark"] .vmm-skeleton-bar {
    background: linear-gradient(
        100deg,
        var(--si-secondary-bg) 30%,
        rgba(var(--si-body-bg-rgb), 0.65) 50%,
        var(--si-secondary-bg) 70%
    );
}

/* github-markdown-css and Prism on the API reference are light-only assets.
   Scope their dark counterparts here so the page follows the shared mode. */
[data-bs-theme="dark"] .markdown-body {
    color: var(--si-body-color);
    background-color: transparent;
}

[data-bs-theme="dark"] .markdown-body h1,
[data-bs-theme="dark"] .markdown-body h2 {
    border-bottom-color: var(--si-border-color);
}

[data-bs-theme="dark"] .markdown-body blockquote {
    color: var(--si-secondary-color);
    border-left-color: var(--si-border-color);
}

[data-bs-theme="dark"] .markdown-body code,
[data-bs-theme="dark"] .markdown-body pre,
[data-bs-theme="dark"] .markdown-body table tr,
[data-bs-theme="dark"] .markdown-body table tr:nth-child(2n) {
    color: var(--si-body-color);
    background-color: var(--si-secondary-bg);
}

[data-bs-theme="dark"] .markdown-body table th,
[data-bs-theme="dark"] .markdown-body table td,
[data-bs-theme="dark"] .markdown-body hr {
    border-color: var(--si-border-color);
}

[data-bs-theme="dark"] .markdown-body .token.comment,
[data-bs-theme="dark"] .markdown-body .token.prolog,
[data-bs-theme="dark"] .markdown-body .token.doctype,
[data-bs-theme="dark"] .markdown-body .token.cdata {
    color: #8b949e;
}

[data-bs-theme="dark"] .markdown-body .token.property,
[data-bs-theme="dark"] .markdown-body .token.tag,
[data-bs-theme="dark"] .markdown-body .token.boolean,
[data-bs-theme="dark"] .markdown-body .token.number,
[data-bs-theme="dark"] .markdown-body .token.constant,
[data-bs-theme="dark"] .markdown-body .token.symbol {
    color: #79c0ff;
}

[data-bs-theme="dark"] .markdown-body .token.selector,
[data-bs-theme="dark"] .markdown-body .token.attr-name,
[data-bs-theme="dark"] .markdown-body .token.string,
[data-bs-theme="dark"] .markdown-body .token.char,
[data-bs-theme="dark"] .markdown-body .token.builtin {
    color: #a5d6ff;
}

[data-bs-theme="dark"] .markdown-body .token.operator,
[data-bs-theme="dark"] .markdown-body .token.entity,
[data-bs-theme="dark"] .markdown-body .token.url,
[data-bs-theme="dark"] .markdown-body .token.function,
[data-bs-theme="dark"] .markdown-body .token.class-name {
    color: #d2a8ff;
}

[data-bs-theme="dark"] .markdown-body .token.atrule,
[data-bs-theme="dark"] .markdown-body .token.attr-value,
[data-bs-theme="dark"] .markdown-body .token.keyword {
    color: #ff7b72;
}

[data-bs-theme="dark"] .markdown-body .token.regex,
[data-bs-theme="dark"] .markdown-body .token.important,
[data-bs-theme="dark"] .markdown-body .token.variable {
    color: #ffa657;
}

/* Lightweight direct LAS/LAZ preview. The fixed height gives deck.gl a stable
   WebGL viewport without introducing a viewer-specific page layout. */
#point-cloud-card {
    color-scheme: dark;
    color: #f1f5f9;
    background-color: #101418;
}

#point-cloud-card .text-muted {
    color: #9aa8b8 !important;
}

#point-cloud-viewport {
    position: relative;
    width: 100%;
    height: min(72vh, 760px);
    min-height: 420px;
    overflow: hidden;
    border-radius: 0.5rem;
    background: #101418;
}

#point-cloud-canvas {
    display: block;
    width: 100%;
    height: 100%;
}

#point-cloud-progress-fill {
    transition: width 150ms ease;
}

#point-cloud-card:fullscreen {
    height: 100vh;
    margin: 0;
    border-radius: 0;
    background-color: #101418;
}

#point-cloud-card:fullscreen .card-body {
    display: flex;
    flex-direction: column;
    height: 100%;
}

#point-cloud-card:fullscreen #point-cloud-viewport {
    flex: 1 1 auto;
    height: auto;
    max-height: none;
}
/* Shared breadcrumb shell; long identifiers and filenames must not overflow. */
.breadcrumb-nav {
    --bs-breadcrumb-divider: ">>";
}

.breadcrumb-nav .breadcrumb-item {
    max-width: 100%;
    overflow-wrap: anywhere;
}

/* The license warning takes up its normal space on arrival, then remains
   reachable at the viewport edge after the user scrolls past it. */
#license-status-banner {
    --bs-alert-color: #ffffff;
    --bs-alert-bg: #c62828;
    --bs-alert-border-color: #c62828;
    --bs-alert-link-color: #ffffff;
    position: sticky;
    top: 0;
    z-index: 1030;
    background-color: #c62828;
    color: #ffffff;
}

#license-status-banner .alert-link,
#license-status-banner .alert-link:hover {
    color: #ffffff;
    text-decoration: underline;
}

/* Live session state uses Silicon's faded pill badges. Motion is reserved for
   a verified SSE connection, so the pulse is connection truth rather than
   decorative activity. */
.live-update-badge {
    display: inline-flex;
    align-items: center;
    gap: 0.35rem;
}
.live-update-badge [data-live-indicator] {
    display: none;
    flex-shrink: 0;
}
.live-update-badge[data-live-state="connecting"] [data-live-indicator="connecting"],
.live-update-badge[data-live-state="paused"] [data-live-indicator="paused"] {
    display: inline-block;
}
.live-update-badge[data-live-state="live"] [data-live-indicator="live"] {
    display: inline-block;
}
.live-update-pulse {
    width: 0.45rem;
    height: 0.45rem;
    border-radius: 50%;
    background: currentColor;
    box-shadow: 0 0 0 0 rgba(var(--si-success-rgb), 0.4);
    animation: live-update-pulse 1.8s ease-out infinite;
}
@keyframes live-update-pulse {
    70%, 100% { box-shadow: 0 0 0 0.4rem rgba(var(--si-success-rgb), 0); }
}
@media (prefers-reduced-motion: reduce) {
    .live-update-badge .bx-spin,
    .live-update-pulse {
        animation: none;
    }
}
/* Display utilities (e.g. Bootstrap .d-block, set with !important) otherwise
   override the UA `[hidden] { display: none }` style and keep hidden preview,
   empty-state, and alert blocks visible (broken preview <img> + alt text next
   to the "no preview" notice). Force hidden to win. */
[hidden] {
    display: none !important;
}
