.incident-table tbody tr:hover {
    background-color: var(--sidebar-hover);
}

/* Filter toolbar */
.incident-filters {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.5rem;
}

.incident-filters .filter-search {
    flex: 1 1 16rem;
    min-width: 14rem;
    max-width: 24rem;
}

.incident-filters .filter-select {
    width: auto;
    min-width: 8rem;
    /* Cap width so a long option value (e.g. a mis-parsed incident type) can't
       blow out the toolbar; the closed control truncates, the dropdown shows full. */
    max-width: 14rem;
}

/* Multi-select checkbox dropdowns in the filter bar (status / agency / region / group /
   type). A button with a count badge opens a scrollable checkbox list; it stays open while
   ticking (data-bs-auto-close="outside") and submits the form on each change. */
.incident-filters .filter-dd-btn {
    white-space: nowrap;
}

.filter-dd-menu {
    max-height: 18rem;
    overflow-y: auto;
    min-width: 11rem;
}

.filter-dd-item {
    cursor: pointer;
    padding-top: 0.2rem;
    padding-bottom: 0.2rem;
    white-space: normal;
}

.filter-dd-item:hover {
    background-color: var(--bs-tertiary-bg);
}

/* Region heading inside the grouped (Group) filter dropdown — one per block of groups. */
.filter-dd-menu .filter-dd-header {
    font-size: 0.7rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.03em;
    color: var(--bs-secondary-color);
    padding: 0.3rem 0.5rem 0.1rem;
    margin: 0.2rem 0 0;
    border-top: 1px solid var(--bs-border-color);
}
.filter-dd-menu > li:first-child .filter-dd-header {
    border-top: 0;
    margin-top: 0;
}

/* Agency / Region / Group picker tree: one dropdown, a checkbox at each level, twist to expand,
   sticky search; parents roll up to indeterminate (the native checkbox dash). See _filter_macros.html. */
.org-menu {
    min-width: 15rem;
    max-height: 60vh;
}
.org-search {
    position: sticky;
    top: 0;
    z-index: 1;
}
.org-row {
    display: flex;
    align-items: center;
    gap: 0.3rem;
    padding: 0.12rem 0.2rem;
    border-radius: 0.25rem;
}
.org-row:hover {
    background-color: var(--bs-tertiary-bg);
}
.org-l1 { padding-left: 1.15rem; }
.org-l2 { padding-left: 2.3rem; }
.org-item {
    display: flex;
    align-items: center;
    gap: 0.4rem;
    margin: 0;
    flex: 1 1 auto;
    min-width: 0;
    cursor: pointer;
    font-size: 0.85rem;
}
.org-twist {
    background: none;
    border: 0;
    padding: 0 0.1rem;
    line-height: 1;
    color: var(--bs-secondary-color);
    cursor: pointer;
}
.org-twist i {
    font-size: 0.7rem;
    display: inline-block;
    transition: transform 0.12s ease;
}
.org-branch.open > .org-row > .org-twist i {
    transform: rotate(90deg);
}
.org-twist-spacer {
    display: inline-block;
    width: 0.95rem;
    flex: 0 0 auto;
}
.org-children {
    display: none;
}
.org-branch.open > .org-children {
    display: block;
}

/* "Clean canvas" disclosure — folds a rarely-needed / admin section out of the default view; one
   click reveals it. Native <details>, so it survives HTMX swaps (re-folds, fine for a seldom-used tool). */
.ft-tuck {
    border: 0.5px solid var(--bs-border-color);
    border-radius: 0.375rem;
}
.ft-tuck > summary {
    padding: 0.5rem 0.75rem;
    cursor: pointer;
    font-weight: 600;
    font-size: 0.9rem;
    color: var(--bs-secondary-color);
}
.ft-tuck > summary:hover {
    color: var(--bs-body-color);
}
.ft-tuck[open] > summary {
    border-bottom: 0.5px solid var(--bs-border-color);
}
.ft-tuck-body {
    padding: 0.75rem;
}

/* Sortable column headers */
.incident-table th.sortable {
    white-space: nowrap;
}

/* Column resize — every header is a positioning context with a grab strip on its right edge.
   Dragging the strip resizes the column (incident-filters.js); double-click resets it. */
.incident-table thead th { position: relative; }
.col-resize {
    position: absolute;
    top: 0;
    right: 0;
    width: 6px;
    height: 100%;
    cursor: col-resize;
    user-select: none;
    z-index: 2;
}
.col-resize:hover { background: var(--bs-primary); opacity: 0.35; }
body.col-resizing { cursor: col-resize; user-select: none; }
body.col-resizing * { cursor: col-resize !important; }

.incident-table th.sortable .sort-link {
    display: inline-flex;
    align-items: center;
    gap: 0.25rem;
    color: inherit;
    text-decoration: none;
    cursor: pointer;
}

.incident-table th.sortable .sort-link:hover {
    color: var(--bs-primary);
}

.incident-table th.sortable .sort-idle {
    opacity: 0.25;
}

.incident-table th.sorted .sort-link {
    color: var(--bs-primary);
    font-weight: 600;
}

/* Sort-tier badge ①②③ — the priority of this column in a multi-column sort (only shown when more
   than one tier is active). */
.incident-table th .sort-tier {
    font-size: 0.6rem;
    font-weight: 700;
    color: var(--bs-primary);
    margin-left: 1px;
}

.detail-label {
    font-size: 0.7rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    color: var(--bs-secondary-color);
    margin-bottom: 0.15rem;
}

.detail-value {
    font-size: 0.9rem;
}

.incident-map-container {
    border-radius: 0.375rem;
    overflow: hidden;
    border: 1px solid var(--bs-border-color);
}

.incident-map {
    width: 100%;
    height: 300px;
    border: none;
}

/* --- Event grouping (2026-06-15) ----------------------------------------------------
   Single-leg events sit FLUSH as a tight tinted list (agency tint + left spine + a hairline
   between rows) so the page stays decluttered. A MULTI-agency event is a contained rounded
   CARD — a neutral heading (.event-head-row) + a connector rail down to each agency leg
   (.agency-subrow) — set apart by a gap above/below so the cluster stands out against the
   flush singles. border-collapse: separate is REQUIRED for the rounded corners; the default
   per-cell borders are reset so only what we draw shows. Agency colour via --agency. */
.incident-table { border-collapse: separate; border-spacing: 0; }
.incident-table > tbody > tr > td { border: 0; }
.incident-table tbody.event-gap > tr > td { height: 8px; padding: 0; background: transparent; }

/* Single-leg events — flush tinted rows with an agency left spine + a hairline separator. */
.inc-single > td:first-child { border-left: 4px solid var(--agency, var(--bs-border-color)); }
.event-group:not(.is-multi) > tr > td { border-bottom: 0.5px solid var(--bs-border-color); }

/* Multi-agency events — a contained card (border + rounded corners). */
.event-group.is-multi > tr > td:first-child { border-left: 0.5px solid var(--bs-border-color); }
.event-group.is-multi > tr > td:last-child  { border-right: 0.5px solid var(--bs-border-color); }
.event-group.is-multi > tr:first-child > td { border-top: 0.5px solid var(--bs-border-color); }
.event-group.is-multi > tr:last-child > td  { border-bottom: 0.5px solid var(--bs-border-color); }
.event-group.is-multi > tr:first-child > td:first-child { border-top-left-radius: 0.5rem; }
.event-group.is-multi > tr:first-child > td:last-child  { border-top-right-radius: 0.5rem; }
.event-group.is-multi > tr:last-child > td:first-child  { border-bottom-left-radius: 0.5rem; }
.event-group.is-multi > tr:last-child > td:last-child   { border-bottom-right-radius: 0.5rem; }

/* Agency colour on the row — a tint of the brand colour (CFS yellow / MFS red / SES orange),
   theme-tuned and deliberately stronger than a wash so the agency reads at a glance (user
   request 2026-06-14). The solid .agency-pill still carries the exact, always-legible label. */
.inc-single > td,
.agency-subrow > td {
    background-color: color-mix(in srgb, var(--agency) 22%, var(--bs-body-bg));
}
[data-bs-theme="dark"] .inc-single > td,
[data-bs-theme="dark"] .agency-subrow > td {
    background-color: color-mix(in srgb, var(--agency) 34%, var(--bs-body-bg));
}

/* Status-driven hierarchy: a COMPLETE leg recedes so active jobs carry the eye. The agency
   identity (bar + pill) stays legible; only the row content dims. */
.incident-row.is-complete > td,
.agency-subrow.is-complete > td,
.event-head-row.is-complete > td {
    opacity: 0.55;
}
.incident-row.is-complete:hover > td,
.agency-subrow.is-complete:hover > td,
.event-head-row.is-complete:hover > td {
    opacity: 1;
}

/* Where cell — suburb leads (bold), street sits muted beneath. */
.whr-sub { font-weight: 600; display: block; }
/* Bracketed geocoded locality shown beside the pager suburb when they disagree (neighbouring
   suburbs) — secondary weight/colour so the pager suburb still leads. */
.whr-alt { font-weight: 400; font-size: 0.82em; color: var(--bs-secondary-color); }
.whr-street {
    display: block;
    font-size: 0.78rem;
    color: var(--bs-secondary-color);
    max-width: 22rem;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* Inline Type editor — a dotted underline on hover hints the label is editable; the input sizes
   to the cell. */
.type-text { cursor: pointer; border-bottom: 1px dotted transparent; }
.type-text:hover { border-bottom-color: var(--bs-secondary-color); }
.type-input { display: inline-block; width: auto; min-width: 9rem; }

/* When cell — absolute date+time (primary) over the relative running/ago line. Compact folds them. */
.when-abs { display: block; }
.when-rel { display: block; font-size: 0.78rem; color: var(--bs-secondary-color); }
#incident-table-wrap[data-density="compact"] .when-abs,
#incident-table-wrap[data-density="compact"] .when-rel { display: inline; }
#incident-table-wrap[data-density="compact"] .when-rel::before { content: " · "; }

/* Description column — the operator's free-typed pager note. Wraps to at most TWO lines, then
   ellipsis (-webkit-line-clamp is honoured across modern browsers); full note on hover. Same clamp
   in both densities. */
.desc-col { max-width: 260px; }
.desc-text {
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
    white-space: normal;
    overflow-wrap: anywhere;
    font-size: 0.8rem;
    line-height: 1.2;
    color: var(--bs-secondary-color);
}

/* ID cell — DIN over the AIRS/CAD number; both kept, stacked to save width. */
.id-cell .id-din { display: block; }
.id-cell .id-airs { display: block; color: var(--bs-secondary-color); }

/* Escalation cell — the alarm + level pickers sit together with a small gap. */
.incident-table td .badge-pick + .badge-pick { margin-left: 0.2rem; }

/* Res/Air cell — the CAD resource (vehicle) count over the aircraft count, stacked. */
.units-cell { line-height: 1.15; }
.units-cell .u-veh,
.units-cell .u-air { display: block; white-space: nowrap; }
.units-cell .u-air { color: var(--bs-secondary-color); font-size: 0.85rem; }

/* Density — Compact tightens the row height + type, and folds the Where street onto the suburb
   line. data-density lives on #incident-table-wrap so it persists across result swaps. */
#incident-table-wrap[data-density="compact"] .incident-table > tbody > tr > td {
    padding-top: 0.1rem;
    padding-bottom: 0.1rem;
}
#incident-table-wrap[data-density="compact"] .incident-table { font-size: 0.82rem; }
#incident-table-wrap[data-density="compact"] .whr-street {
    display: inline;
    font-size: inherit;
}
#incident-table-wrap[data-density="compact"] .whr-street::before { content: " · "; }
#incident-table-wrap[data-density="compact"] .whr-sub { display: inline; }
#incident-table-wrap[data-density="compact"] .id-cell .id-airs { display: inline; margin-left: 0.3rem; }

/* The list view-toggles (density segmented control + Resources switch) in the toolbar. */
.list-view-toggles { display: inline-flex; align-items: center; gap: 0.75rem; }
.density-seg { display: inline-flex; border: 1px solid var(--bs-border-color); border-radius: 0.375rem; overflow: hidden; }
.density-seg button {
    border: 0; background: transparent; padding: 0.15rem 0.6rem;
    font-size: 0.78rem; color: var(--bs-secondary-color); cursor: pointer;
}
.density-seg button.active { background: var(--bs-secondary-bg); color: var(--bs-body-color); font-weight: 600; }

.agency-pill {
    display: inline-block;
    font-size: 0.62rem;
    font-weight: 700;
    line-height: 1;
    letter-spacing: 0.02em;
    padding: 0.15rem 0.34rem;
    border-radius: 0.25rem;
    background: var(--agency, var(--bs-secondary));
    color: var(--agency-fg, #fff);
    vertical-align: middle;
}
/* "Also responding" chip — an agency present on the event but hidden by the agency-only filter.
   Outlined (not solid) so it reads as secondary to the row's own agency pill. */
.agency-pill.ghost {
    background: transparent;
    color: var(--agency, var(--bs-secondary));
    border: 1px solid color-mix(in srgb, var(--agency) 60%, transparent);
    font-weight: 600;
    opacity: 0.85;
}

/* Connector rail — a left spine from the heading down through each agency leg, with a tick into
   each. The last leg's spine stops at its tick (so it reads as a corner, not a continuing line).
   Drawn in the leg's first cell; the agency tint + pill carry the per-leg identity. */
.is-multi > .agency-subrow > td:first-child { position: relative; padding-left: 2rem; }
.is-multi > .agency-subrow > td:first-child::before {
    content: ""; position: absolute; left: 0.85rem; top: 0; bottom: 0;
    border-left: 1.5px solid var(--bs-border-color);
}
.is-multi > .agency-subrow:last-child > td:first-child::before { bottom: 50%; }
.is-multi > .agency-subrow > td:first-child::after {
    content: ""; position: absolute; left: 0.85rem; top: 50%; width: 0.6rem;
    border-top: 1.5px solid var(--bs-border-color);
}

.event-head-row > td {
    background-color: var(--bs-tertiary-bg);
    font-weight: 500;
}

/* Keep the hover highlight visible over the tinted cells (a td background would
   otherwise win over the row-level hover rule above). */
.incident-table tbody tr:hover > td {
    background-color: var(--sidebar-hover);
}

/* Per-agency incident cards on the detail page — same agency identity colour as the
   list (left bar + faint header tint), via the --agency custom property. */
.agency-card {
    border-left: 4px solid var(--agency, var(--bs-border-color));
}

/* Agency identity on the detail card = the left bar + the agency pill in the header; no
   colour wash on the header (keeps it legible on both themes). */

/* Unified incident activity timeline — one chronological feed (newest first) replacing the
   separate paged/vehicle/alarm/control lists. A left rail with a per-kind coloured icon. */
.incident-timeline {
    list-style: none;
    margin: 0;
    padding: 0;
    position: relative;
}

.incident-timeline::before {
    content: "";
    position: absolute;
    left: 0.45rem;
    top: 0.3rem;
    bottom: 0.3rem;
    width: 2px;
    background: var(--bs-border-color);
}

.incident-timeline > li {
    position: relative;
    display: flex;
    align-items: baseline;
    gap: 0.4rem;
    padding: 0.15rem 0 0.15rem 1.6rem;
    font-size: 0.85rem;
}

.incident-timeline .tl-icon {
    position: absolute;
    left: 0;
    top: 0.15rem;
    font-size: 0.8rem;
    line-height: 1;
    color: var(--bs-secondary);
    background: var(--bs-body-bg);   /* mask the rail behind the icon */
    padding: 0.1rem 0;
}

.incident-timeline .tl-text {
    font-weight: 500;
}
/* A linked timeline entry (e.g. a STOP stand-down → its pager row) reads like the text, not a link. */
.incident-timeline a.tl-text { color: inherit; text-decoration: none; }
.incident-timeline a.tl-text:hover { text-decoration: underline; }
/* Briefly highlight a pager row jumped to from a timeline link. */
.pager-row-flash { animation: pager-flash 2s ease-out 1; }
@keyframes pager-flash { from { background: var(--bs-warning-bg-subtle, #fff3cd); } to { background: transparent; } }

.incident-timeline .tl-time {
    margin-left: auto;
    white-space: nowrap;
}

.tl-alarm .tl-icon { color: var(--bs-danger); }
.tl-dispatch .tl-icon { color: var(--bs-primary); }
.tl-arrived .tl-icon { color: var(--bs-success); }
.tl-released .tl-icon { color: var(--bs-secondary); }
.tl-stopped .tl-icon { color: var(--bs-danger); }
.tl-defaulted .tl-icon { color: var(--bs-warning); }
.tl-control .tl-icon { color: #6f42c1; }
.tl-paged .tl-icon { color: #0aa2c0; }
.tl-note .tl-icon { color: #20c997; }
.tl-reported .tl-icon { color: var(--bs-emphasis-color, var(--bs-dark)); }

/* Operator status override on each detail card header — compact inline picker beside the
   status badge. */
.status-select {
    width: auto;
    min-width: 7rem;
    display: inline-block;
    font-size: 0.78rem;
    padding: 0.1rem 1.5rem 0.1rem 0.5rem;
    vertical-align: middle;
}

/* Incident lock — lives in the Stale column, mutually exclusive with the countdown. A faint
   open padlock to lock; a solid LOCKED badge to unlock. */
.lock-btn {
    border: none;
    background: none;
    padding: 0;
    margin-left: 0.3rem;
    cursor: pointer;
    line-height: 1;
    vertical-align: middle;
}

.lock-btn.lock-off {
    color: var(--bs-secondary-color);
    opacity: 0.45;
    font-size: 0.85rem;
}

.lock-btn.lock-off:hover {
    opacity: 1;
    color: var(--bs-body-color);
}

.lock-btn.lock-on {
    margin-left: 0;
    color: #fff;
    background: var(--bs-dark);
    border-radius: 0.25rem;
    padding: 0.05rem 0.4rem;
    font-size: 0.66rem;
    font-weight: 700;
    letter-spacing: 0.03em;
}

/* Clickable-badge editor (Status / Alarm / Level / Control). The current badge toggles a
   stacked list of option badges inline — no overlay, so the scrollable table never clips it. */
.badge-pick {
    display: inline-block;
}

.badge-pick-current {
    cursor: pointer;
}

.badge-pick-options {
    display: none;
}

/* Open: a fixed-positioned floating menu (JS sets top/left under the badge) so the table's
   horizontal scroll can't clip it, and nothing in the row is pushed down. */
.badge-pick.open .badge-pick-options {
    display: flex;
    flex-direction: column;
    gap: 0.25rem;
    align-items: flex-start;
    position: fixed;
    z-index: 1060;
    background: var(--bs-body-bg);
    border: 1px solid var(--bs-border-color);
    border-radius: 0.375rem;
    padding: 0.35rem;
    box-shadow: 0 0.25rem 0.75rem rgba(0, 0, 0, 0.2);
}

.badge-pick-item {
    border: none;
    background: none;
    padding: 0;
    cursor: pointer;
}

.badge-pick-item:hover {
    filter: brightness(1.08);
}

/* (Event-group separation is now the card frame + the .event-gap spacer tbody — see the
   'Event grouping as cards' block above. The old hairline-rule approach was removed.) */
