/* ========================================
   Eligtas — Command Center Layout
   Emergency management platform
   ======================================== */

/* Auth state visibility */
[data-show-when-logged-in] { display: none !important; }
body.logged-in [data-show-when-logged-in] { display: revert !important; }
body.logged-in [data-hide-when-logged-in] { display: none !important; }

/* Admin / moderator visibility */
[data-admin-only] { display: none !important; }
body.user-is-admin [data-admin-only] { display: inline-flex !important; }
[data-moderator-only] { display: none !important; }
body.user-is-moderator [data-moderator-only] { display: inline-flex !important; }

/* Nav avatar + user name */
.nav-user-dropdown { position: relative; }
.nav-avatar-btn {
  background: none !important;
  border: none !important;
  padding: 0 !important;
  cursor: pointer;
  box-shadow: none !important;
  display: flex;
  align-items: center;
  text-decoration: none;
  color: inherit;
}
.nav-avatar-btn:hover { transform: none; }
.nav-avatar {
  width: 26px;
  height: 26px;
  border-radius: 50%;
  object-fit: cover;
  border: 2px solid transparent;
  transition: border-color 0.2s;
}
.nav-avatar-btn:hover .nav-avatar { border-color: rgba(30, 64, 175, 0.4); }
.nav-user-name { font-size: 0.75rem; color: var(--text-2); font-weight: 500; margin-left: var(--sp-2); }

/* ========================================
   Map Page
   ======================================== */

.map-page { padding: 0; }

.map-container {
  position: relative;
  width: 100%;
  height: calc(100vh - 56px - 48px); /* viewport minus nav and footer */
  background: #080d1a;
  overflow: hidden;
}

#map-canvas {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 1;
}

#map-canvas svg {
  width: 100%;
  height: 100%;
}

.map-loading {
  color: var(--color-text-muted);
  font-size: var(--font-size-base);
  display: flex;
  align-items: center;
  gap: var(--spacing-2);
}
.map-loading i { font-size: 1.5rem; }

/* Map controls — top right overlay */
.map-controls {
  position: absolute;
  top: var(--spacing-4);
  right: var(--spacing-4);
  display: flex;
  flex-direction: column;
  gap: var(--spacing-1);
  z-index: var(--z-overlay);
}

.map-control-btn {
  width: 36px;
  height: 36px;
  display: flex;
  align-items: center;
  justify-content: center;
  background: var(--color-bg-raised);
  border: 1px solid var(--color-border-light);
  border-radius: var(--radius-md);
  color: var(--color-text-secondary);
  cursor: pointer;
  font-size: var(--font-size-base);
  transition: background var(--transition-fast), color var(--transition-fast);
}
.map-control-btn:hover {
  background: var(--color-bg-overlay);
  color: var(--color-text);
}

/* Unified map legend panel — top left overlay.
   Replaces .map-filters, .map-pin-filters, .map-incident-filter, .map-legend.
   Collapsed by default (only the chevron button is visible); `.open` on the
   panel reveals the body. Chevron rotation mirrors .alert-advanced-toggle. */
.map-legend-panel {
  position: absolute;
  top: var(--spacing-3);
  /* Sit to the right of Leaflet's top-left zoom control (~30px buttons +
     12px gap) instead of overlapping it on the same anchor (JOB-AUS1-00015d). */
  left: calc(var(--spacing-3) + 44px);
  background: rgba(8, 13, 26, 0.82);
  color: var(--color-text);
  border: 1px solid var(--color-border-light);
  border-radius: var(--radius-md);
  padding: var(--spacing-1);
  z-index: var(--z-overlay);
  display: flex;
  flex-direction: column;
  gap: var(--spacing-1);
  backdrop-filter: blur(4px);
}

.map-legend-toggle {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 24px;
  height: 24px;
  background: none;
  border: none;
  color: var(--color-text-muted);
  cursor: pointer;
  padding: 0;
  align-self: flex-start;
}

.map-legend-toggle:hover {
  color: var(--color-text-secondary);
}

.map-legend-toggle i {
  transition: transform var(--transition-fast);
}

.map-legend-panel.open .map-legend-toggle i {
  transform: rotate(90deg);
}

.map-legend-body {
  display: none;
  flex-direction: column;
  gap: 2px;
  padding: 0 var(--spacing-1) var(--spacing-1);
  min-width: 170px;
}

.map-legend-panel.open .map-legend-body {
  display: flex;
}

.legend-row {
  display: flex;
  align-items: center;
  gap: var(--spacing-1);
  font-size: var(--font-size-xs);
  color: var(--color-text-secondary);
  cursor: pointer;
  user-select: none;
  padding: 2px 0;
}

.legend-row input[type="checkbox"] {
  width: 14px;
  height: 14px;
  accent-color: rgb(var(--color-primary));
  flex-shrink: 0;
}

.legend-row .legend-label {
  flex: 1;
}

.legend-row .count {
  color: var(--color-text-muted);
  font-variant-numeric: tabular-nums;
  min-width: 1.5em;
  text-align: right;
}

.legend-row .count:empty {
  display: none;
}

.swatch {
  width: 10px;
  height: 10px;
  border-radius: 2px;
  display: inline-block;
  flex-shrink: 0;
}

.swatch-alert-active {
  background: rgb(var(--color-status-error));
}

.swatch-alert-acknowledged {
  background: rgb(var(--color-status-acknowledged));
}

.swatch-alert-draft {
  background: rgb(var(--color-status-muted));
}

.swatch-pins {
  background: rgb(var(--color-status-info));
}

.swatch-incidents {
  background: rgb(var(--color-status-error));
  box-shadow: 0 0 0 1px #fff inset;
}

.swatch-responders {
  background: rgb(var(--color-secondary));
}

.swatch-labels {
  background: transparent;
  border: 1px dashed var(--color-text-muted);
}

/* Nav location search (maps page) */
.nav-search {
  position: relative;
  flex: 0 1 260px;
  margin: 0 var(--spacing-4);
}

.nav-search i {
  position: absolute;
  left: 0.6rem;
  top: 50%;
  transform: translateY(-50%);
  color: var(--color-text-muted);
  font-size: var(--font-size-xs);
  pointer-events: none;
}

.nav-search input {
  width: 100%;
  padding: 0.35rem 0.6rem 0.35rem 1.8rem;
  background: var(--color-bg-raised);
  border: 1px solid var(--color-border-light);
  border-radius: var(--radius-md);
  color: var(--color-text);
  font-size: var(--font-size-xs);
  font-family: inherit;
  outline: none;
  transition: border-color var(--transition-fast);
}

.nav-search input:focus {
  border-color: rgb(var(--color-primary-light));
}

.nav-search input::placeholder {
  color: var(--color-text-muted);
}

.map-search-results {
  position: absolute;
  top: 100%;
  left: 0;
  right: 0;
  margin-top: 4px;
  background: rgba(8,13,26,0.95);
  border: 1px solid var(--color-border-light);
  border-radius: var(--radius-md);
  max-height: 300px;
  overflow-y: auto;
  z-index: 500;
}

.map-search-item {
  padding: 0.5rem 0.75rem;
  font-size: var(--font-size-xs);
  color: var(--color-text-secondary);
  cursor: pointer;
  border-bottom: 1px solid var(--color-border);
  transition: background var(--transition-fast);
}

.map-search-item:last-child {
  border-bottom: none;
}

.map-search-item:hover {
  background: var(--color-bg-overlay);
  color: var(--color-text);
}

.map-search-item-name {
  color: var(--color-text);
  font-weight: var(--font-weight-medium);
}

.map-search-item-type {
  color: var(--color-text-muted);
  font-size: 0.65rem;
  margin-left: 0.35rem;
}

/* Map detail sidebar */
.map-sidebar {
  position: absolute;
  top: 0;
  right: 0;
  width: 320px;
  height: 100%;
  background: rgba(8,13,26,0.95);
  border-left: 1px solid var(--color-border-light);
  z-index: 20;
  display: flex;
  flex-direction: column;
  overflow-y: auto;
}

.map-sidebar-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: var(--spacing-3) var(--spacing-4);
  border-bottom: 1px solid var(--color-border-light);
  flex-shrink: 0;
}

.map-sidebar-title {
  font-family: var(--font-family-display);
  font-size: var(--font-size-sm);
  font-weight: var(--font-weight-semibold);
  color: var(--color-text);
  text-transform: uppercase;
  letter-spacing: 0.05em;
}

.map-sidebar-close {
  background: transparent;
  border: none;
  color: var(--color-text-muted);
  cursor: pointer;
  font-size: 1rem;
  padding: 0.25rem;
  transition: color var(--transition-fast);
}

.map-sidebar-close:hover {
  color: var(--color-text);
}

.map-sidebar-body {
  padding: var(--spacing-4);
  flex: 1;
}

/* Pin tooltip */
.map-pin-tooltip {
  position: absolute;
  z-index: 20;
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  padding: var(--spacing-3);
  min-width: 180px;
  max-width: 260px;
  box-shadow: 0 4px 12px rgba(0,0,0,0.15);
}
.map-pin-tooltip-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--spacing-2);
}
.map-pin-tooltip-name {
  font-weight: var(--font-weight-semibold);
  font-size: var(--font-size-sm);
}
.map-pin-tooltip-close {
  background: none;
  border: none;
  cursor: pointer;
  color: var(--color-text-muted);
  padding: 0;
  font-size: var(--font-size-base);
  line-height: 1;
}
.map-pin-tooltip-close:hover { color: var(--color-text-primary); }
.map-pin-tooltip-type {
  font-size: var(--font-size-xs);
  color: var(--color-text-muted);
  text-transform: capitalize;
  margin-top: var(--spacing-1);
}
.map-pin-tooltip-coords {
  font-size: 0.65rem;
  color: var(--color-text-muted);
  font-family: monospace;
  margin-top: var(--spacing-1);
}

/* Focus pulse animation — applied to SVG elements highlighted by map_focus SSE event */
.map-focus-pulse {
  animation: map-focus-pulse-keyframes 1.5s ease-in-out 3;
}
@keyframes map-focus-pulse-keyframes {
  0%, 100% { opacity: 1; filter: none; }
  50% { opacity: 0.4; filter: drop-shadow(0 0 8px var(--color-primary)); }
}

/* Incident pin — larger, pulsing marker for active emergencies.
   The pulse ring expands outward beneath the teardrop marker; animation
   cadence is tied to alert level (RED fastest, GREEN slowest). */
.incident-pin-pulse {
  transform-box: fill-box;
  transform-origin: center;
  animation: incident-pin-pulse-keyframes 1.6s ease-out infinite;
}
.incident-pin-RED .incident-pin-pulse { animation-duration: 1.1s; }
.incident-pin-YELLOW .incident-pin-pulse { animation-duration: 1.6s; }
.incident-pin-GREEN .incident-pin-pulse { animation-duration: 2.4s; }

@keyframes incident-pin-pulse-keyframes {
  0%   { transform: scale(0.6); opacity: 0.55; }
  80%  { transform: scale(2.2); opacity: 0; }
  100% { transform: scale(2.2); opacity: 0; }
}

/* Respect reduced-motion preference */
@media (prefers-reduced-motion: reduce) {
  .incident-pin-pulse {
    animation: none;
    opacity: 0.35;
  }
}

.sidebar-field {
  margin-bottom: var(--spacing-3);
}

.sidebar-field-label {
  font-size: var(--font-size-xs);
  font-weight: var(--font-weight-semibold);
  color: var(--color-text-muted);
  text-transform: uppercase;
  letter-spacing: 0.05em;
  margin-bottom: var(--spacing-1);
}

.sidebar-field-value {
  font-size: var(--font-size-sm);
  color: var(--color-text);
  line-height: var(--line-height-relaxed);
}

/* Alert-form Area selector — the geofence name itself is the picker
   trigger. Looks like a borderless button that hovers up to an outline.
   The trailing pencil icon is a quiet hint that it's editable. */
.zone-picker-trigger {
  width: 100%;
  display: flex;
  align-items: center;
  gap: 0.5rem;
  padding: 0.5rem 0.75rem;
  background: transparent;
  border: 1px solid var(--color-border-light);
  border-radius: var(--radius-md);
  color: var(--color-text);
  font-size: var(--font-size-sm);
  font-family: inherit;
  text-align: left;
  cursor: pointer;
  transition: all var(--transition-fast);
}

.zone-picker-trigger:hover {
  border-color: rgb(var(--color-primary));
  background: var(--color-bg-overlay);
}

.zone-picker-trigger .zone-picker-edit {
  margin-left: auto;
  color: var(--color-text-muted);
  font-size: var(--font-size-xs);
}

.zone-picker-trigger:hover .zone-picker-edit {
  color: var(--color-text);
}

/* Tile loading state */
#map-canvas image[data-tile-loading] {
  opacity: 0.3;
}

/* SVG geofence hover states */
#map-canvas polygon[data-geofence-id]:hover {
  stroke-width: 3;
  filter: brightness(1.3);
}

/* SVG alert marker hover */
#map-canvas circle[data-alert-id]:hover {
  r: 8;
  stroke-width: 2;
}

/* ========================================
   Page Sections (Alerts, Events, Resources, About)
   ======================================== */

.page-section {
  padding: var(--spacing-12) 0;
}

.page-header {
  margin-bottom: var(--spacing-8);
}

.page-eyebrow {
  font-size: var(--font-size-xs);
  font-weight: var(--font-weight-semibold);
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: rgb(var(--color-primary-light));
  margin-bottom: var(--spacing-2);
  display: flex;
  align-items: center;
  gap: var(--spacing-2);
}

.page-header h1 {
  font-family: var(--font-family-display);
  font-size: var(--font-size-4xl);
  font-weight: var(--font-weight-bold);
  color: var(--color-text);
  margin: 0 0 var(--spacing-2) 0;
}

.page-desc {
  font-size: var(--font-size-lg);
  color: var(--color-text-secondary);
  max-width: 640px;
  line-height: var(--line-height-relaxed);
}

/* Empty state */
.empty-state {
  text-align: center;
  padding: var(--spacing-16) var(--spacing-4);
  color: var(--color-text-muted);
}

.empty-state i {
  font-size: 3rem;
  margin-bottom: var(--spacing-4);
  display: block;
  opacity: 0.4;
}

.empty-state h3 {
  font-family: var(--font-family-display);
  font-size: var(--font-size-xl);
  color: var(--color-text-secondary);
  margin: 0 0 var(--spacing-2) 0;
}

.empty-state p {
  font-size: var(--font-size-sm);
  max-width: 400px;
  margin: 0 auto;
  line-height: var(--line-height-relaxed);
}

/* About page */
.about-content {
  max-width: 720px;
}

.about-block {
  margin-bottom: var(--spacing-8);
}

.about-block h2 {
  font-family: var(--font-family-display);
  font-size: var(--font-size-xl);
  font-weight: var(--font-weight-semibold);
  color: var(--color-text);
  margin: 0 0 var(--spacing-3) 0;
}

.about-block p {
  font-size: var(--font-size-base);
  color: var(--color-text-secondary);
  line-height: var(--line-height-relaxed);
}

.about-list {
  list-style: none;
  padding: 0;
  margin: 0;
}

.about-list li {
  font-size: var(--font-size-base);
  color: var(--color-text-secondary);
  line-height: var(--line-height-relaxed);
  padding: var(--spacing-1) 0;
  padding-left: var(--spacing-4);
  position: relative;
}

.about-list li::before {
  content: '';
  position: absolute;
  left: 0;
  top: 0.75em;
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: rgb(var(--color-primary-light));
}

/* ========================================
   Data Table
   ======================================== */

.table-toolbar {
  display: flex;
  justify-content: flex-start;
  align-items: center;
  gap: var(--spacing-3);
  margin-bottom: var(--spacing-4);
  flex-wrap: wrap;
}
/* New-incident dropdown sits at the far right; search + view buttons hug the
   left edge next to each other. */
.table-actions {
  margin-left: auto;
}

/* Admin Teams view — one section per group_type (dispatch responder types +
   Custom), rendered by group/teams_sections.hbs. */
.group-type-section {
  margin-bottom: var(--spacing-5);
}

.group-type-label {
  margin: 0 0 var(--spacing-2);
  padding-bottom: var(--spacing-1);
  border-bottom: 1px solid var(--color-border);
  font-size: 0.85rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--color-text-muted);
}

/* List pager — server-driven prev/next for alerts + incidents tables.
   Empty nav has zero height; populated nav lays out prev | info | next.
   Initially hidden until rows arrive (no chrome shown for an empty page
   that hasn't loaded yet). */
.list-pager {
  display: flex;
  align-items: center;
  justify-content: flex-end;
  gap: var(--spacing-3);
  margin-bottom: var(--spacing-3);
  min-height: 0;
}
.list-pager:empty {
  display: none;
}
.pager-btn {
  display: inline-flex;
  align-items: center;
  gap: var(--spacing-1);
  padding: var(--spacing-1) var(--spacing-3);
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-sm);
  color: var(--color-text);
  font-size: var(--font-size-sm);
  cursor: pointer;
  transition: background 120ms ease, border-color 120ms ease;
}
.pager-btn:hover:not(:disabled) {
  background: rgba(var(--color-primary), 0.08);
  border-color: rgb(var(--color-primary));
  color: rgb(var(--color-primary));
}
.pager-btn:disabled {
  opacity: 0.4;
  cursor: not-allowed;
}
.pager-info {
  font-size: var(--font-size-sm);
  color: var(--color-text-muted);
}
.pager-info strong {
  color: var(--color-text);
  font-weight: 600;
}
.pager-total {
  margin-left: var(--spacing-2);
  color: var(--color-text-muted);
}

.table-search {
  position: relative;
  flex: 1;
  max-width: 320px;
}

.table-search i {
  position: absolute;
  left: 0.75rem;
  top: 50%;
  transform: translateY(-50%);
  color: var(--color-text-muted);
  font-size: var(--font-size-sm);
}

.table-search input {
  width: 100%;
  height: 34px;
  padding: 0 0.75rem 0 2rem;
  background: var(--color-bg-raised);
  border: 1px solid var(--color-border-light);
  border-radius: var(--radius-md);
  color: var(--color-text);
  font-size: var(--font-size-sm);
  font-family: inherit;
  outline: none;
  transition: border-color var(--transition-fast);
}

.table-search input:focus {
  border-color: rgb(var(--color-primary-light));
}

.table-search input::placeholder {
  color: var(--color-text-muted);
}

.table-filters {
  display: flex;
  gap: 3px;
  align-items: center;
}

/* Wrappers for the server-rendered toolbar buttons (status pills via
   incident.status_filters, saved-view buttons via incident.view_buttons),
   injected via OOB on sseReady. display:contents makes the wrapper visually
   transparent so the injected .filter-btn buttons lay out as direct flex items
   of the toolbar — identical to when they were static markup. */
.status-pills-slot,
.view-buttons-slot {
  display: contents;
}

/* Saved-view buttons read as the primary toolbar row — slightly heavier than
   the status quick-filter pills they sit beside. */
.view-btn.active {
  font-weight: 600;
}

.filter-btn {
  padding: 0.18rem 0.4rem;
  background: transparent;
  border: 1px solid var(--color-border-light);
  border-radius: var(--radius-md);
  color: var(--color-text-secondary);
  font-size: var(--font-size-xs);
  font-family: inherit;
  text-transform: uppercase;
  letter-spacing: 0.01em;
  cursor: pointer;
  display: flex;
  align-items: center;
  gap: 0.25rem;
  white-space: nowrap;
  transition: all var(--transition-fast);
}

/* Tighter dot inside a filter pill — the 8px base .level-dot is for
   sidebars; in the dense toolbar it reads better at 6px. */
.filter-btn .level-dot {
  width: 6px;
  height: 6px;
}

/* Category pulldown — replaces the per-category pills on the dispatch
   toolbar, where the full one-pill-per-status status row leaves no
   room for the category pills. Sized to match .filter-btn so it sits
   flush in the same row. */
.filter-category-select {
  padding: 0.18rem 0.4rem;
  background: transparent;
  border: 1px solid var(--color-border-light);
  border-radius: var(--radius-md);
  color: var(--color-text-secondary);
  font-size: var(--font-size-xs);
  font-family: inherit;
  text-transform: uppercase;
  letter-spacing: 0.01em;
  cursor: pointer;
  white-space: nowrap;
}

.filter-category-select:hover {
  border-color: var(--color-text-muted);
  color: var(--color-text);
}

/* Active (a real category chosen, not "all") — bold border to mirror
   the data-category pill's active treatment. */
.filter-category-select.active {
  border-color: rgb(var(--color-primary));
  color: var(--color-text);
  font-weight: 700;
}

.filter-btn:hover {
  border-color: var(--color-text-muted);
  color: var(--color-text);
}

.filter-btn.active {
  background: var(--color-bg-overlay);
  border-color: rgb(var(--color-primary));
  color: var(--color-text);
}

/* Category pills (data-category) live in the same row as status pills,
   separated by a |. Active state shows as bold rather than the filled
   background used for status, so the two filter dimensions read as
   distinct at a glance. */
.filter-btn[data-category].active {
  font-weight: 700;
  background: transparent;
  border-color: var(--color-border-light);
  color: var(--color-text);
}

.filter-sep {
  color: var(--color-text-muted);
  padding: 0 0.35rem;
  user-select: none;
  align-self: center;
}

/* New Incident dropdown — riffs on .kebab-dropdown but anchored under the
   primary button in the table toolbar. Toggled by .new-incident-trigger
   click handler in incidents.js. */
.new-incident-wrap {
  position: relative;
  display: inline-block;
}

.new-incident-menu {
  position: absolute;
  top: 100%;
  right: 0;
  margin-top: 4px;
  min-width: 180px;
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-sm, 4px);
  padding: 4px;
  box-shadow: 0 8px 24px rgba(0, 0, 0, 0.35);
  z-index: var(--z-dropdown, 100);
}

.new-incident-menu[hidden] { display: none; }

.new-incident-item {
  all: unset;
  display: block;
  width: 100%;
  padding: 6px 10px;
  font-size: var(--font-size-sm);
  color: var(--color-text);
  border-radius: var(--radius-sm, 4px);
  cursor: pointer;
  box-sizing: border-box;
}

.new-incident-item:hover:not(:disabled) {
  background: var(--color-surface-hover);
}

/* Section labels inside the New dropdown — non-interactive, smaller,
   muted; sits above each group of items and only renders if there are
   enough items to need scanning. */
.new-incident-heading {
  padding: 8px 10px 4px;
  font-size: var(--font-size-xs);
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--color-text-muted);
  font-weight: 600;
  user-select: none;
}

.new-incident-heading:first-child {
  padding-top: 4px;
}

/* Nested label under a heading (e.g. "Hazard Report" inside Non-Emergency).
   Same muted style as the group heading but indented and not uppercased. */
.new-incident-subheading {
  padding: 4px 10px 2px 18px;
  font-size: var(--font-size-xs);
  letter-spacing: 0.03em;
  color: var(--color-text-muted);
  font-weight: 600;
  user-select: none;
}

.new-incident-item:disabled {
  color: var(--color-text-muted);
  cursor: not-allowed;
  opacity: 0.55;
}

/* New Alert dropdown — same primitives as New Incident, scoped under
   a sibling class so the alerts page can opt in without inheriting
   incident-specific hooks from .new-incident-* selectors. Rules are
   aliased via comma-grouped selectors to keep one source of truth. */
.new-alert-wrap {
  position: relative;
  display: inline-block;
}
.new-alert-menu {
  position: absolute;
  top: 100%;
  right: 0;
  margin-top: 4px;
  min-width: 200px;
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-sm, 4px);
  padding: 4px;
  box-shadow: 0 8px 24px rgba(0, 0, 0, 0.35);
  z-index: var(--z-dropdown, 100);
}
.new-alert-menu[hidden] { display: none; }
.new-alert-item {
  all: unset;
  display: block;
  width: 100%;
  padding: 6px 10px;
  font-size: var(--font-size-sm);
  color: var(--color-text);
  border-radius: var(--radius-sm, 4px);
  cursor: pointer;
  box-sizing: border-box;
}
.new-alert-item:hover:not(:disabled) {
  background: var(--color-surface-hover);
}
.new-alert-heading {
  padding: 8px 10px 4px;
  font-size: var(--font-size-xs);
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--color-text-muted);
  font-weight: 600;
  user-select: none;
}
.new-alert-heading:first-child { padding-top: 4px; }

/* Mine/All filter toggle in alerts list toolbar. Borrows status-filter
   button styling for visual consistency. Active state managed by JS
   on click; default = All. */
.table-filters-mine .mine-filter-btn {
  padding: 0.3rem 0.65rem;
  background: transparent;
  border: 1px solid var(--color-border-light);
  border-radius: var(--radius-sm, 4px);
  color: var(--color-text-muted);
  font-size: var(--font-size-sm);
  cursor: pointer;
  margin-right: 4px;
}
.table-filters-mine .mine-filter-btn.active {
  background: var(--color-primary);
  color: white;
  border-color: var(--color-primary);
}

.status-filter-btn {
  padding: 0.3rem 0.65rem;
  background: transparent;
  border: 1px solid var(--color-border-light);
  border-radius: var(--radius-md);
  color: var(--color-text-muted);
  font-size: var(--font-size-xs);
  font-family: inherit;
  cursor: pointer;
  display: flex;
  align-items: center;
  gap: 0.35rem;
  transition: all var(--transition-fast);
}

.status-filter-btn:hover {
  border-color: var(--color-text-muted);
  color: var(--color-text);
}

.status-filter-btn.active {
  background: var(--color-bg-overlay);
  border-color: rgb(var(--color-primary));
  color: var(--color-text);
}

.level-dot {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  display: inline-block;
}

.table-wrap {
  overflow-x: auto;
  border: 1px solid var(--color-border-light);
  border-radius: var(--radius-lg);
  background: var(--color-bg-raised);
}

.data-table {
  width: 100%;
  border-collapse: collapse;
  font-size: var(--font-size-sm);
}

.data-table thead {
  background: var(--color-bg);
}

.data-table th {
  padding: 0.6rem 0.75rem;
  text-align: left;
  font-weight: var(--font-weight-semibold);
  font-size: var(--font-size-xs);
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--color-text-muted);
  border-bottom: 1px solid var(--color-border-light);
  white-space: nowrap;
  user-select: none;
}

.col-sortable {
  cursor: pointer;
  transition: color var(--transition-fast);
}

/* Generic ID column — monospace, muted, smaller font so the ID
   reads as a reference instead of competing with the row's content. */
.col-id {
  font-family: var(--font-family-mono);
  font-size: 0.72rem;
  color: var(--color-text-secondary);
  white-space: nowrap;
}

.col-sortable:hover {
  color: var(--color-text);
}

.col-sortable::after {
  content: '';
  display: inline-block;
  margin-left: 0.35rem;
  opacity: 0.3;
}

.col-sortable.sort-asc::after {
  content: '\2191';
  opacity: 1;
  color: rgb(var(--color-primary-light));
}

.col-sortable.sort-desc::after {
  content: '\2193';
  opacity: 1;
  color: rgb(var(--color-primary-light));
}

.data-table td {
  padding: 0.55rem 0.75rem;
  border-bottom: 1px solid var(--color-border);
  color: var(--color-text-secondary);
  vertical-align: middle;
}

.data-table tbody tr:hover {
  background: rgba(255,255,255,0.02);
}

.data-table tbody tr:last-child td {
  border-bottom: none;
}

.table-loading {
  text-align: center;
  padding: var(--spacing-8) !important;
  color: var(--color-text-muted);
}

.table-loading i {
  animation: spin 1s linear infinite;
  margin-right: var(--spacing-2);
}

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

/* Alert level badge — base shape only.
   Per-level colour rules live in components/alert-levels.css
   (lowercase classes matching level_badge.hbs / level_dot.hbs output). */
.level-badge {
  display: inline-flex;
  align-items: center;
  gap: 0.3rem;
  padding: 0.15rem 0.5rem;
  border-radius: var(--radius-full);
  font-size: var(--font-size-xs);
  font-weight: var(--font-weight-semibold);
  text-transform: uppercase;
  letter-spacing: 0.04em;
}

/* Status badge */
.status-badge {
  font-size: var(--font-size-xs);
  padding: 0.15rem 0.5rem;
  border-radius: var(--radius-full);
  background: rgba(148,163,184,0.1);
  color: var(--color-text-secondary);
}

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

.status-badge.status-dispatched {
  background: rgba(59,130,246,0.1);
  color: #3b82f6;
}

.status-badge.status-acknowledged {
  background: rgba(139,92,246,0.1);
  color: #8b5cf6;
}

.status-badge.status-new {
  background: rgba(59,130,246,0.15);
  color: #3b82f6;
}

.status-badge.status-triage {
  background: rgba(251,146,60,0.15);
  color: #fb923c;
}

.status-badge.status-locating {
  background: rgba(168,85,247,0.15);
  color: #a855f7;
}

/* `located` — first GPS fix landed. Greener than .status-resolved so the
   operator can tell "we have their location" from "call is closed" at a
   glance. `dispatched` stays reserved for the future "responders sent"
   transition (Dispatch tab). */
.status-badge.status-located {
  background: rgba(34,197,94,0.15);
  color: #22c55e;
}

.status-badge.status-responding {
  background: rgba(234,179,8,0.15);
  color: #eab308;
}

.status-badge.status-onscene {
  background: rgba(14,165,233,0.15);
  color: #0ea5e9;
}

.status-badge.status-resolved {
  background: rgba(34,197,94,0.15);
  color: #22c55e;
}

.status-badge.status-closed {
  background: rgba(148,163,184,0.1);
  color: var(--color-text-muted);
}

.status-badge.status-approved {
  background: rgba(13,148,136,0.18);
  color: #2dd4bf;
}

.status-badge.status-cancelled {
  background: rgba(148,163,184,0.1);
  color: var(--color-text-muted);
}

.status-badge.status-draft {
  background: rgba(var(--color-status-muted), 0.12);
  color: rgb(var(--color-status-muted));
}

.status-badge.status-expired {
  background: rgba(var(--color-status-muted), 0.18);
  color: var(--color-text-secondary);
}

.status-badge.status-escalated {
  background: rgba(220,38,38,0.18);
  color: #f87171;
}

/* Compact incident form header (partial: incidents/form_header.hbs) */
.inc-form-title {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  margin: 0;
  font-size: 1rem;
  font-weight: 600;
  color: var(--color-text);
}

.inc-form-title .status-badge {
  text-transform: capitalize;
}

.inc-form-created {
  margin-top: 2px;
  font-size: var(--font-size-xs);
  color: var(--color-text-muted);
}

/* Request Location section (partial: incidents/form_actions.hbs) */
.inc-request-location {
  margin-top: var(--spacing-3);
  padding-top: var(--spacing-3);
  border-top: 1px solid var(--color-border);
}

.inc-request-heading {
  margin: 0 0 var(--spacing-2);
  font-size: var(--font-size-sm);
  font-weight: 600;
  color: var(--color-text-secondary);
  text-transform: uppercase;
  letter-spacing: 0.03em;
}

.inc-request-outcome {
  margin-top: var(--spacing-2);
  min-height: 1.2em;
  font-size: var(--font-size-xs);
  color: var(--color-text-muted);
}

.inc-request-outcome:empty {
  display: none;
}

/* Incident location read-only display (partial: incidents/form.hbs).
   Used for the unified Edit Location field that the operator clicks
   to open the canvas. The canvas modes were unified
   (TASK-AUS1-0001oB), so the old .inc-area-field selector retired
   alongside .inc-area-empty. */
.inc-location-display {
  display: flex;
  align-items: center;
  gap: var(--spacing-2);
  padding: var(--spacing-2) var(--spacing-3);
  background: rgba(148,163,184,0.05);
  border-radius: var(--radius-sm);
  font-size: var(--font-size-sm);
  color: var(--color-text);
}

.inc-location-empty {
  color: var(--color-text-muted);
  font-style: italic;
}

/* De-emphasised geofence + location widget (Wh). The selector was moved
   below Concern to simplify the form; here it's visually quietened — muted
   smaller label, tighter top margin — so it reads as secondary, not a
   primary data-entry field. The clickable display row keeps its styling so
   it's still an obvious affordance when the operator does need it. */
.incident-form-body .form-group.inc-location-deemph {
  margin-top: var(--spacing-1);
  opacity: 0.85;
}
.incident-form-body .form-group.inc-location-deemph label {
  color: var(--color-text-muted);
}

/* Cluster Coordination — external-team checkbox chips. A horizontal wrap row
   sitting where the level pills were (between Concern and the Action buttons);
   each chip is a bordered pill with a checkbox + team name. Checked chips
   highlight via :has() so the selected state survives the hx-swap="none" toggle
   (the server persists state; there's no re-render of this row). */
.inc-cluster-chips {
  display: flex;
  flex-wrap: nowrap;
  gap: var(--spacing-1);
  /* Always one row; if the pane is too narrow for all chips, scroll rather
     than wrap (the pane is user-resizable — drag it wider). */
  overflow-x: auto;
}
.inc-cluster-chip {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  flex: 0 0 auto;
  padding: var(--spacing-1);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-sm);
  background: var(--color-primary-subtle);
  font-size: var(--font-size-xs);
  text-transform: uppercase;
  letter-spacing: 0.02em;
  white-space: nowrap;
  cursor: pointer;
  user-select: none;
}
.inc-cluster-chip input {
  width: 13px;
  height: 13px;
  cursor: pointer;
  margin: 0;
  flex: 0 0 auto;
}
.inc-cluster-chip:has(input:checked) {
  border-color: var(--color-primary);
  background: var(--color-primary);
  color: var(--color-text-on-primary);
}
.inc-cluster-empty {
  color: var(--color-text-muted);
  font-style: italic;
  font-size: var(--font-size-xs);
}

/* Transfer & Close (Wa) — revealed under the cluster chips once ≥1 external
   agency is assigned. The container (#inc-cluster-transfer-<incident_id>) is a
   persistent OOB target: the server fills it with the button when a cluster
   team is assigned and empties it when none are (incident.assign_team /
   incident.unassign_team). :empty collapses the top margin so there's no
   phantom gap below the chips when no agency is selected. The button reuses the
   .btn system (.btn .btn-primary) — this rule is layout only. */
.inc-cluster-transfer:not(:empty) {
  margin-top: var(--spacing-2);
}
.inc-cluster-transfer .btn {
  width: 100%;
}

/* Phone field pinned to the top of the form, above the call-type buttons (Wp —
   for CTI pre-population). Matches the call-type button row's horizontal pad. */
.inc-phone-top {
  padding: var(--spacing-3) var(--spacing-4) 0;
}

/* Call-type buttons (We) — Emergency / Patient Transport / Transfer segmented
   row atop the intake forms. Active = filled primary; inactive = outlined. Each
   posts incident.set_type, which re-renders the whole detail form. */
.inc-call-type-buttons {
  display: flex;
  gap: var(--spacing-2);
  padding: var(--spacing-3) var(--spacing-4) 0;
}
.inc-call-type-btn {
  flex: 1 1 0;
  padding: var(--spacing-2);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-sm);
  background: var(--color-surface);
  color: var(--color-text);
  font-size: var(--font-size-sm);
  font-weight: 600;
  line-height: 1.2;
  cursor: pointer;
  transition: background 0.12s ease, border-color 0.12s ease, color 0.12s ease;
}
.inc-call-type-btn:hover {
  background: var(--color-surface-hover);
}
/* Selected call-type — solid primary fill, matches the mockup. */
.inc-call-type-btn.is-active {
  background: var(--color-primary);
  border-color: var(--color-primary);
  color: var(--color-text-on-primary);
  box-shadow: 0 1px 4px rgba(0, 0, 0, 0.25);
}
.inc-call-type-btn.is-active:hover {
  background: var(--color-primary);
}

/* Call-Transfer extension directory — fills the middle column in place of the
   minimap. Clickable contact rows; clicking resolves the call (transfer_close). */
.inc-transfer-directory {
  padding: var(--spacing-4) var(--spacing-5);
}
.inc-transfer-header {
  margin-bottom: var(--spacing-3);
}
.inc-transfer-title {
  margin: 0;
  font-family: var(--font-family-display);
  font-size: var(--font-size-lg);
}
.inc-transfer-sub {
  margin: var(--spacing-1) 0 0;
  color: var(--color-text-muted);
  font-size: var(--font-size-sm);
}
.inc-transfer-list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: var(--spacing-2);
}
.inc-transfer-row {
  width: 100%;
  height: 100%;
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: var(--spacing-2);
  padding: var(--spacing-3) var(--spacing-4);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  background: var(--color-surface);
  color: var(--color-text);
  text-align: left;
  cursor: pointer;
  transition: background 0.12s ease, border-color 0.12s ease;
}
.inc-transfer-row:hover {
  background: var(--color-surface-hover);
  border-color: var(--color-primary);
}
.inc-transfer-row-main {
  display: flex;
  flex-direction: column;
  gap: 2px;
}
.inc-transfer-name {
  font-weight: 600;
}
.inc-transfer-number {
  color: var(--color-text-muted);
  font-size: var(--font-size-sm);
}
.inc-transfer-contact {
  color: var(--color-text-secondary);
  font-size: var(--font-size-sm);
}
.inc-transfer-empty {
  color: var(--color-text-muted);
  font-style: italic;
  font-size: var(--font-size-sm);
  padding: var(--spacing-3);
}

/* Geofence icon at the head of the location widget. Shape (icon glyph)
   encodes ownership bucket; the colour underneath is driven by the
   fence's own alert_level. See incident_renderer.rs:
     compute_geofence_ownership() — level / custom / team / user
     geofence_icon_name_for()      — geo-alt / pentagon / people / person
   The .inc-geofence-{ownership} class is reserved for ownership-specific
   styling if needed later (e.g. team tint). Glyph colour comes from the
   shared `.level-{name}` family used by .level-badge / .level-dot —
   single source of truth in alert-levels.css. */
.inc-geofence-icon {
  font-size: var(--font-size-md);
  color: var(--color-text-muted);
  flex-shrink: 0;
  cursor: help;
}
/* New 8-tier taxonomy */
.inc-geofence-icon.level-none     { color: rgb(var(--color-alert-level-none)); }
.inc-geofence-icon.level-normal   { color: rgb(var(--color-alert-level-normal)); }
.inc-geofence-icon.level-advisory { color: rgb(var(--color-alert-level-advisory)); }
.inc-geofence-icon.level-alert    { color: rgb(var(--color-alert-level-alert)); }
.inc-geofence-icon.level-warning  { color: rgb(var(--color-alert-level-warning)); }
.inc-geofence-icon.level-ics      { color: rgb(var(--color-alert-level-ics)); }
.inc-geofence-icon.level-dfa      { color: rgb(var(--color-alert-level-warning)); }
.inc-geofence-icon.level-major    { color: rgb(var(--color-alert-level-major)); }

/* Status dot at the head of the incident location widget. Shape comes
   from `.level-dot` (eligtas.css base) and the colour from the shared
   `.level-{green,yellow,red,pending}` family (alert-levels.css) — same
   classes used by alert-level pills, so the dot stays visually in lock-
   step with the rest of the level taxonomy. `cursor: help` is the only
   widget-specific tweak. */
.level-dot { cursor: help; }

/* ========================================
   Admin Geofence Tree (view=geofences)
   ======================================== */

.geofence-tree-wrapper {
  padding: var(--spacing-3);
}

.tree-toolbar {
  display: flex;
  align-items: center;
  gap: var(--spacing-2);
  padding-bottom: var(--spacing-2);
  margin-bottom: var(--spacing-2);
  border-bottom: 1px solid var(--color-border);
}

.tree-toolbar-label {
  font-size: var(--font-size-xs);
  color: var(--color-text-muted);
  text-transform: uppercase;
  letter-spacing: 0.05em;
}

.geofence-tree,
.tree-children {
  list-style: none;
  padding-left: 0;
  margin: 0;
}

.tree-children {
  padding-left: var(--spacing-4);
  display: none;
}

.tree-node.open > .tree-children {
  display: block;
}

.tree-node {
  position: relative;
}

.tree-row {
  display: flex;
  align-items: center;
  gap: var(--spacing-2);
  padding: var(--spacing-1) var(--spacing-2);
  border-radius: var(--radius-sm);
  font-size: var(--font-size-sm);
  color: var(--color-text);
}

.tree-row:hover {
  background: rgba(148,163,184,0.05);
}

.tree-chevron {
  width: 20px;
  height: 20px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  background: none;
  border: none;
  color: var(--color-text-muted);
  cursor: pointer;
  padding: 0;
  border-radius: var(--radius-sm);
}

.tree-chevron:hover {
  color: var(--color-text);
  background: rgba(148,163,184,0.08);
}

.tree-chevron i {
  transition: transform var(--transition-fast);
  font-size: 0.8rem;
}

.tree-node.open > .tree-row > .tree-chevron i {
  transform: rotate(90deg);
}

.tree-chevron-empty {
  display: inline-block;
  width: 20px;
  height: 20px;
}

.tree-icon {
  color: var(--color-text-secondary);
  font-size: 0.95rem;
}

.tree-label {
  flex: 1;
  min-width: 0;
  color: var(--color-text);
  text-decoration: none;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.tree-type {
  font-size: var(--font-size-xs);
  color: var(--color-text-muted);
  padding: 2px 6px;
  background: rgba(148,163,184,0.08);
  border-radius: var(--radius-sm);
  text-transform: lowercase;
  letter-spacing: 0.02em;
}

.tree-count {
  font-size: var(--font-size-xs);
  color: var(--color-text-muted);
  font-family: ui-monospace, monospace;
}

.tree-empty {
  padding-left: var(--spacing-4);
}

.tree-empty-label {
  font-size: var(--font-size-xs);
  color: var(--color-text-muted);
  font-style: italic;
}

/* ========================================
   Incident Layout — Three-column grid
   ======================================== */

/* Incident layout — flex (parallel to .alert-layout). Hidden columns
   collapse via .col-state sentinel + .alert-col display:none rule. */
.incident-layout {
  display: flex;
  min-height: calc(100vh - var(--nav-height) - 48px);
}

#incidents-col-chat {
  flex: 0 0 280px;
  border-right: 1px solid var(--color-border);
}

#incidents-col-list {
  flex: 1 1 0;
  min-width: 0;
  overflow-y: auto;
  padding: var(--spacing-4) var(--spacing-5);
}

#incidents-col-detail {
  flex: 0 0 380px;
  border-left: 1px solid var(--color-border);
  /* Anchor for the absolutely-positioned drag handle (detail-resize). */
  position: relative;
}

/* Draggable detail-pane width (detail-resize in incidents.js). A thin grip on
   the column's left edge; JS overrides flex-basis on drag and persists it to
   localStorage. Sits over the column's border-left. */
.detail-resize-handle {
  position: absolute;
  top: 0;
  left: -3px;
  width: 6px;
  height: 100%;
  cursor: col-resize;
  z-index: 5;
}
.detail-resize-handle:hover,
body.detail-resizing .detail-resize-handle {
  background: var(--color-primary);
  opacity: 0.4;
}
/* Kill text selection + keep the resize cursor while dragging. */
body.detail-resizing {
  cursor: col-resize;
  user-select: none;
}

/* Detail column collapses to no track when its body slot is empty —
   mirrors #bugs-detail-body:empty. Here the body is nested inside the
   .alert-col aside (not the column itself), so use :has(). Content lands
   via the OOB/SSE innerHTML swap; emptying the body collapses the column.
   dispatch.html reuses the incidents-col-* ids, so it's covered too. */
#incidents-col-detail:has(#incidents-col-detail-body:empty) {
  display: none;
}

.incident-panel-header {
  padding: var(--spacing-3) var(--spacing-4);
  border-bottom: 1px solid var(--color-border);
  font-family: var(--font-family-display);
  font-weight: var(--font-weight-semibold);
  font-size: var(--font-size-sm);
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--color-text-muted);
  flex-shrink: 0;
}

.incident-panel-body {
  flex: 1;
  padding: var(--spacing-4);
  overflow-y: auto;
}

.empty-state-sm {
  text-align: center;
  padding: var(--spacing-6) var(--spacing-4);
  color: var(--color-text-muted);
}

.empty-state-sm i {
  font-size: 2rem;
  display: block;
  margin-bottom: var(--spacing-3);
  opacity: 0.4;
}

.empty-state-sm p {
  font-size: var(--font-size-sm);
  line-height: var(--line-height-relaxed);
}

/* Incident form styles */
.incident-form-header {
  margin-bottom: var(--spacing-4);
}

.incident-form-body .form-group {
  margin-bottom: var(--spacing-3);
}

.incident-form-body .form-group label {
  font-size: var(--font-size-xs);
  margin-bottom: var(--spacing-1);
}

/* Compact caller fields — inline "Label: [input]" rows with right-aligned
   labels so the colons line up and the inputs share a left edge. */
.inc-caller-fields {
  margin-bottom: var(--spacing-3);
}

.form-field-inline {
  display: flex;
  align-items: center;
  gap: var(--spacing-2);
  margin-bottom: var(--spacing-1);
}

.form-field-inline > label {
  flex: 0 0 5.5rem;
  text-align: right;
  font-size: var(--font-size-xs);
  font-weight: var(--font-weight-medium);
  color: var(--color-text-secondary);
  margin: 0;
  white-space: nowrap;
}

.form-field-inline > label::after {
  content: ":";
}

/* Mirror the base .form-group input styling — these inputs sit in a
   .form-field-inline row, not a .form-group, so they don't inherit
   components/forms.css. Keep border/padding/focus in sync with it.
   `select` is included so inline pickers (alerts Duration / Assigned
   To) match the text inputs. */
.form-field-inline > input,
.form-field-inline > select {
  flex: 1 1 auto;
  min-width: 0;
  padding: var(--spacing-2) var(--spacing-3);
  font-family: var(--font-family-primary);
  font-size: var(--font-size-base);
  color: var(--color-text);
  background: var(--color-bg);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-lg);
  transition: border-color var(--transition-fast), box-shadow var(--transition-fast);
  outline: none;
}

.form-field-inline > input:focus,
.form-field-inline > select:focus {
  border-color: var(--color-border-focus);
  box-shadow: 0 0 0 3px rgba(var(--color-primary-light), 0.15);
}

.form-field-inline > input::placeholder {
  color: var(--color-text-muted);
}

/* Phone status hint sits under the inputs, aligned to the input column. */
.inc-caller-hint:empty {
  display: none;
}

.inc-caller-hint {
  margin-left: calc(5.5rem + var(--spacing-2));
}

/* Last-seen + Locate-with-Safe360 row uses the shared .form-field-inline
   geometry (5.5rem right-aligned label + colon), so the Safe360 button
   lines up under the edit boxes and is the same width. The button's
   wrapper is the "field"; strip the section border-top/spacing it carries
   by default — here it's an inline field, not a separate bordered section. */
.form-field-inline > .inc-request-location {
  flex: 1 1 auto;
  min-width: 0;
  margin-top: 0;
  padding-top: 0;
  border-top: none;
}

.inc-locate-full {
  display: block;
  width: 100%;
  justify-content: center;
}

/* The outcome message reserves height (min-height + margin-top) so the row
   doesn't jump when a Safe360 result arrives. The template's `:empty` collapse
   never matches (the rendered div holds a whitespace text node), so in this
   inline row the reserved space sits below the button, makes the wrapper
   taller than the button, and align-items:center drops the "Last seen" label
   to the button's base. Collapse it here — the label centres on the button;
   an incoming message just expands the row downward. */
.form-field-inline > .inc-request-location .inc-request-outcome {
  min-height: 0;
  margin-top: 0;
}

.form-divider {
  border: none;
  border-top: 1px solid var(--color-border);
  margin: var(--spacing-4) 0;
}

.form-hint {
  font-size: var(--font-size-xs);
  color: var(--color-text-muted);
  margin-top: var(--spacing-1);
}

/* Alert level selector */
.alert-level-selector {
  display: flex;
  gap: var(--spacing-1);
}

.alert-level-btn {
  flex: 1 1 0;
  min-width: 0;
  padding: var(--spacing-1) calc(var(--spacing-1) / 2);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  background: transparent;
  color: var(--color-text-muted);
  font-size: var(--font-size-2xs, 0.65rem);
  font-weight: var(--font-weight-semibold);
  letter-spacing: 0;
  text-transform: capitalize;
  cursor: pointer;
  font-family: inherit;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  transition: all var(--transition-fast);
}

.alert-level-btn.active,
.alert-level-btn:hover {
  color: white;
}

/* Per-level active/hover variants live in components/alert-levels.css
   alongside the matching badge + dot rules — single source of truth
   for the 5-tier alert-level palette. */

/* Incident status selector — 13-button CAD lifecycle palette.
   Mirrors .alert-level-selector / .alert-level-btn shape so a status
   pill row sits next to (or above) the alert-level row without
   visual jitter. Adds flex-wrap so the 13 buttons spill onto two
   rows naturally — single-row layout would crush each button below
   readability. Per-status colour rules live in
   components/incident-statuses.css. */
.status-selector {
  display: flex;
  flex-wrap: wrap;
  gap: var(--spacing-1);
}

.status-btn {
  flex: 1 1 calc(20% - var(--spacing-1));
  min-width: 0;
  padding: var(--spacing-1) calc(var(--spacing-1) / 2);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  background: transparent;
  color: var(--color-text-muted);
  font-size: var(--font-size-2xs, 0.65rem);
  font-weight: var(--font-weight-semibold);
  letter-spacing: 0;
  text-transform: capitalize;
  cursor: pointer;
  font-family: inherit;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  transition: all var(--transition-fast);
}

.status-btn.active,
.status-btn:hover {
  color: white;
}

/* Kebab menu (⋮ on owner-authored items — notes, comments, cards) */
.kebab-menu-wrap {
  position: relative;
  display: inline-block;
  margin-left: var(--spacing-1, 4px);
}

.kebab-btn {
  all: unset;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  color: var(--color-text-muted);
  font-size: 1.1rem;
  line-height: 1;
  cursor: pointer;
  padding: 0 6px;
  border-radius: var(--radius-sm, 4px);
  background: transparent;
}

.kebab-btn:hover {
  color: var(--color-text);
  background: var(--color-surface-hover);
}

.kebab-dropdown {
  position: absolute;
  top: 100%;
  right: 0;
  margin-top: 4px;
  min-width: 140px;
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-sm, 4px);
  padding: 4px;
  /* Status-gating moved the full incident status list into this menu
     (Change incident type + Change status + Panel ≈ 25 items), so cap
     the height and scroll rather than overflow the viewport. */
  max-height: 70vh;
  overflow-y: auto;
  box-shadow: 0 8px 24px rgba(0, 0, 0, 0.35);
  opacity: 0;
  visibility: hidden;
  transform: translateY(-4px);
  transition: opacity 0.15s, transform 0.15s, visibility 0.15s;
  z-index: 100;
}

.kebab-dropdown.show {
  opacity: 1;
  visibility: visible;
  transform: translateY(0);
}

.kebab-item {
  all: unset;
  display: block;
  width: 100%;
  padding: 6px 10px;
  font-size: 0.8rem;
  color: var(--color-text);
  border-radius: var(--radius-sm, 4px);
  cursor: pointer;
  font-family: var(--font-family-mono);
  box-sizing: border-box;
}

.kebab-item:hover {
  background: var(--color-surface-hover);
}

/* Current incident status in the "Change status" submenu — marked
   active server-side (form_header.hbs) so the operator sees where the
   incident sits in the list. */
.kebab-item.active {
  background: var(--color-surface-hover);
  font-weight: 600;
  color: var(--color-text);
}

.kebab-item .cmd-prefix {
  color: var(--color-text-muted);
  margin-right: 4px;
}

/* Section heading inside a kebab dropdown — non-interactive, smaller,
   muted; mirrors the .new-incident-heading style so multi-group menus
   read consistently. */
.kebab-heading {
  padding: 8px 10px 4px;
  font-size: var(--font-size-xs);
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--color-text-muted);
  font-weight: 600;
  user-select: none;
}
.kebab-heading:first-child { padding-top: 4px; }

/* Alert form kebab pinned to the right of the header row. The header
   itself is flex; margin-left:auto pushes the kebab past the status
   badge without disturbing the chip ordering. */
.alert-form-kebab { margin-left: auto; }

/* Inline hint next to a form label — explains current mode at a glance
   (e.g. "(text-to-voice)" or "(disabled — using selected voice file)").
   Smaller and muted so it reads as metadata, not as the field name. */
.form-hint-inline {
  font-size: var(--font-size-xs);
  font-weight: 400;
  color: var(--color-text-muted);
  margin-left: 0.4em;
}

/* Incident notes (operator log entries) */
.incident-notes-list {
  display: flex;
  flex-direction: column;
  gap: var(--spacing-2);
  max-height: 18rem;
  overflow-y: auto;
  margin-bottom: var(--spacing-2);
}

.incident-note {
  border: 1px solid var(--color-border);
  border-left: 3px solid var(--color-primary, #3b82f6);
  border-radius: var(--radius-sm, 4px);
  padding: var(--spacing-2);
  background: var(--color-surface-alt, rgba(255, 255, 255, 0.02));
}

.incident-note-header {
  display: flex;
  align-items: center;
  gap: var(--spacing-2);
  font-size: 0.85em;
  margin-bottom: var(--spacing-1, 4px);
}

.incident-note-author {
  font-weight: 600;
}

.incident-note-role {
  color: var(--color-text-muted, #94a3b8);
  font-size: 0.9em;
}

.incident-note-time {
  margin-left: auto;
  font-size: 0.85em;
}

.incident-note-body {
  white-space: pre-wrap;
  word-wrap: break-word;
}

.incident-note-add textarea {
  width: 100%;
  margin-bottom: var(--spacing-1, 4px);
}

.incident-note-editing {
  border-left-color: var(--color-status-warning, #f59e0b);
}

.incident-note-edit textarea {
  width: 100%;
  margin-bottom: var(--spacing-1, 4px);
  font-family: inherit;
}

.incident-note-edit-actions {
  display: flex;
  gap: var(--spacing-1, 4px);
  justify-content: flex-end;
}

/* Incident form action buttons */
.incident-form-actions {
  display: flex;
  flex-wrap: wrap;
  gap: var(--spacing-2);
}

.incident-form-actions .btn {
  flex: 1;
  min-width: 120px;
}

/* Mobile: stack vertically, hide chat */
@media (max-width: 1024px) {
  .incident-layout {
    flex-direction: column;
  }
  #incidents-col-chat {
    display: none;
  }
  #incidents-col-detail {
    border-left: none;
    border-top: 1px solid var(--color-border);
  }
}

/* ── App canvas (four-column flex) ──
   Flex, not grid: hidden columns (display:none via .col-state sentinel
   or :empty rule) collapse without leaving an empty track. Widths are
   id-specific; the 1fr columns expand to fill. See
   declarative-column-builder-pattern.md.

   Originally `.alert-layout` / `.alert-col` (alerts.html) — promoted to
   the neutral `.app-*` names so admin/briefing/alerts share one
   primitive. Old class names retained as aliases until callers migrate. */
.app-layout,
.alert-layout {
  display: flex;
  min-height: calc(100vh - var(--nav-height) - 48px);
}

/* State-sentinel: invisible in layout, CSS-selectable to hide the
   next-sibling column. Server OOB-swaps just this ~80-byte element
   to toggle column visibility, preserving column children. */
.col-state {
  display: contents;
}
.col-state[data-state="hidden"] + .app-col,
.col-state[data-state="hidden"] + .alert-col {
  display: none;
}

.app-col,
.alert-col {
  background: var(--color-surface);
  display: flex;
  flex-direction: column;
  overflow-y: auto;
}

/* ----------------------------------------------------------------------
   List column-chooser (configurable-list-views C4j/C4s)
   - .list-cog: toolbar gear firing ui.view_editor_open
   - #list-col-editor: OOB-revealed pane column (the .col-state rules above
     collapse it while its sentinel is data-state="hidden")
   - .list-view-editor__*: the server form (templates/list/view_editor.hbs)
   ------------------------------------------------------------------- */
.list-cog {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 32px;
  height: 32px;
  margin-left: var(--spacing-2, 8px);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  background: var(--color-surface);
  color: var(--color-text-secondary);
  cursor: pointer;
}
.list-cog:hover {
  background: var(--color-surface-hover);
  color: var(--color-text);
}

#list-col-editor {
  flex: 0 0 420px;
}
.list-col-editor__header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--spacing-2, 8px);
  padding: var(--spacing-3, 12px);
  border-bottom: 1px solid var(--color-border);
  font-weight: 600;
}
.list-col-editor__close {
  border: none;
  background: none;
  color: var(--color-text-muted);
  cursor: pointer;
  font-size: var(--font-size-md);
}
.list-col-editor__close:hover {
  color: var(--color-text);
}

.list-view-editor {
  display: flex;
  flex-direction: column;
  gap: var(--spacing-3, 12px);
  padding: var(--spacing-3, 12px);
}
.list-view-editor__name {
  display: flex;
  flex-direction: column;
  gap: var(--spacing-1, 4px);
  font-size: var(--font-size-sm);
  color: var(--color-text-secondary);
}
.list-view-editor__name input {
  padding: var(--spacing-2, 8px);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  background: var(--color-surface);
  color: var(--color-text);
}
.list-view-editor__cols {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 2px;
}
.list-view-editor__col {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--spacing-2, 8px);
  padding: var(--spacing-2, 8px);
  border: 1px solid var(--color-border-light);
  border-radius: var(--radius-md);
  background: var(--color-surface-alt);
  cursor: grab;
}
.list-view-editor__col-label {
  display: flex;
  align-items: center;
  gap: var(--spacing-2, 8px);
  cursor: pointer;
}
.list-view-editor__grip {
  color: var(--color-text-muted);
  cursor: grab;
}
.list-view-editor__placement {
  display: flex;
  flex-direction: column;
  gap: var(--spacing-1, 4px);
  font-size: var(--font-size-sm);
  color: var(--color-text-secondary);
}
.list-view-editor__actions {
  display: flex;
  gap: var(--spacing-2, 8px);
}

/* Server-rendered toolbar (configurable-list-views C4k/C4v): the dynamic
   strip renders one pill per in-scope status, so the dispatch lifecycle
   (~14 stages) wraps rather than running off-screen. */
.list-toolbar {
  flex-wrap: wrap;
  gap: var(--spacing-2, 8px);
}
/* View buttons + the Views button match the search-bar height so the strip
   reads as one row of equal-height controls sitting next to the search. */
.list-toolbar .filter-btn {
  height: 34px;
  padding: 0 0.6rem;
}
.list-toolbar .list-views-btn {
  height: 34px;
  margin-left: 0;
}

/* Column-chooser (configurable-list-views C4j/C4s) --------------------
   Toolbar cog opens a canvas column (#list-col-editor) hosting the
   server-rendered pane (templates/list/view_editor.hbs). The column
   collapses via its .col-state sentinel like the other canvas columns. */
.list-cog {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 32px;
  height: 32px;
  margin-left: var(--spacing-2);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-sm);
  background: var(--color-surface);
  color: var(--color-text-muted);
  cursor: pointer;
}
.list-cog:hover {
  color: var(--color-text);
  border-color: var(--color-primary);
}

#list-col-editor {
  flex: 0 0 420px;
  border-left: 1px solid var(--color-border);
}
.list-col-editor__header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: var(--spacing-3);
  font-weight: 600;
  border-bottom: 1px solid var(--color-border);
}
.list-col-editor__close {
  border: none;
  background: none;
  color: var(--color-text-muted);
  cursor: pointer;
  font-size: 1rem;
}
.list-col-editor__close:hover { color: var(--color-text); }

.list-view-editor {
  display: flex;
  flex-direction: column;
  gap: var(--spacing-3);
  padding: var(--spacing-3);
}
.list-view-editor__name {
  display: flex;
  flex-direction: column;
  gap: var(--spacing-1);
  font-size: 0.85rem;
  font-weight: 600;
}
.list-view-editor__name input {
  padding: var(--spacing-2);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-sm);
  font-weight: 400;
}
.list-view-editor__cols {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 2px;
}
.list-view-editor__col {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--spacing-2);
  padding: var(--spacing-2);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-sm);
  background: var(--color-surface);
  cursor: grab;
}
.list-view-editor__col:active {
  cursor: grabbing;
}
.list-view-editor__col-label {
  display: flex;
  align-items: center;
  gap: var(--spacing-2);
  cursor: pointer;
}
.list-view-editor__grip {
  color: var(--color-text-muted);
  cursor: grab;
  user-select: none;
}
.list-view-editor__placement {
  display: flex;
  flex-direction: column;
  gap: var(--spacing-1);
  font-size: 0.85rem;
}
.list-view-editor__actions {
  display: flex;
  gap: var(--spacing-2);
  justify-content: flex-end;
}

/* Assistant drawer handle — thin always-visible rail at the layout's left
   edge. Toggles the chat column's col-state (main.js initAssistantToggle).
   Lives outside the column so it stays clickable when the column collapses.
   .is-open is set by JS to mirror the sentinel's data-state="visible". */
.assistant-rail {
  flex: 0 0 28px;
  align-self: stretch;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--spacing-2);
  padding: var(--spacing-3) 0;
  border: none;
  border-right: 1px solid var(--color-border);
  background: var(--color-surface);
  color: var(--color-text-muted);
  cursor: pointer;
}
.assistant-rail:hover {
  color: var(--color-text);
}
.assistant-rail .rail-chevron {
  transition: transform 0.15s ease;
}
.assistant-rail.is-open .rail-chevron {
  transform: rotate(180deg);
}
@media (max-width: 900px) {
  .assistant-rail {
    display: none;
  }
}

#alerts-col-chat {
  flex: 0 0 280px;
  border-right: 1px solid var(--color-border);
}

#alerts-col-list,
#alerts-col-search {
  flex: 1 1 0;
  min-width: 0;
}

#alerts-col-search {
  border-left: 1px solid var(--color-border);
}

#alerts-col-detail {
  flex: 0 0 380px;
  border-left: 1px solid var(--color-border);
  /* Anchor for the absolutely-positioned drag handle (detail-resize in
     alerts.js) — mirrors #incidents-col-detail. */
  position: relative;
}

/* :empty collapse — same as #incidents-col-detail above. */
#alerts-col-detail:has(#alerts-col-detail-body:empty) {
  display: none;
}

/* Briefing columns (three-col canvas, same .alert-col primitive). */
#briefing-col-selector {
  flex: 0 0 320px;
  border-right: 1px solid var(--color-border);
}

#briefing-col-center {
  flex: 1 1 0;
  min-width: 0;
}

#briefing-col-activity {
  flex: 0 0 320px;
  border-left: 1px solid var(--color-border);
}

.alert-list {
  overflow-y: auto;
  padding: var(--spacing-4) var(--spacing-5);
}

/* Row selection: the alerts.js click handler adds `.selected` to the
   clicked row (and clears it from siblings). Selection state is
   ephemeral — the next alert.list OOB push wipes the tbody so the
   class doesn't persist across re-renders. */
.alert-row.selected td {
  background: rgba(59, 130, 246, 0.12);
}
.alert-row.selected td:first-child {
  box-shadow: inset 3px 0 0 var(--color-primary, #3b82f6);
}

.alert-panel-header {
  padding: var(--spacing-3) var(--spacing-4);
  border-bottom: 1px solid var(--color-border);
  font-family: var(--font-family-display);
  font-weight: var(--font-weight-semibold);
  font-size: var(--font-size-sm);
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--color-text-muted);
  flex-shrink: 0;
}

.alert-panel-body {
  flex: 1;
  padding: var(--spacing-4);
  overflow-y: auto;
}

/* Alert form styles */
.alert-form-header {
  margin-bottom: var(--spacing-4);
}

.alert-form-title {
  display: flex;
  align-items: center;
  gap: var(--spacing-2);
  margin-bottom: var(--spacing-2);
}

.alert-form-id {
  font-family: monospace;
  font-size: var(--font-size-xs);
  color: var(--color-text-muted);
}

.alert-form-type-chip {
  padding: 2px 8px;
  font-size: var(--font-size-xs);
  background: var(--color-surface-hover);
  color: var(--color-text);
  border-radius: var(--radius-sm, 4px);
  letter-spacing: 0.02em;
}

/* Area picker breadcrumb — leaf (operator's actual zone) sits left in
   white, ancestors trail right in muted grey separated by `→`. Drops
   the static "Area" label that lived above the button; the breadcrumb
   IS the label now. */
.gf-breadcrumb {
  display: inline-flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 2px;
}
.gf-breadcrumb-leaf {
  color: var(--color-text);
  font-weight: 600;
}
.gf-breadcrumb-anc {
  color: var(--color-text-muted);
  font-weight: 400;
}
.gf-breadcrumb-sep {
  color: var(--color-text-muted);
  margin: 0 2px;
}
.gf-breadcrumb-empty {
  color: var(--color-text-muted);
  font-style: italic;
}

.alert-form-meta {
  display: flex;
  gap: var(--spacing-3);
  font-size: var(--font-size-xs);
  color: var(--color-text-muted);
}

.alert-form-meta i {
  margin-right: 0.25rem;
}

.alert-form-body .form-group {
  margin-bottom: var(--spacing-3);
}

.alert-form-body .form-group label {
  font-size: var(--font-size-xs);
  margin-bottom: var(--spacing-1);
}

.alert-form-actions {
  display: flex;
  flex-wrap: wrap;
  gap: var(--spacing-2);
  margin-top: var(--spacing-3);
}

/* Advanced options collapsible */
.alert-advanced-toggle {
  display: flex;
  align-items: center;
  gap: var(--spacing-2);
  padding: var(--spacing-2) 0;
  background: none;
  border: none;
  color: var(--color-text-muted);
  font-size: var(--font-size-xs);
  cursor: pointer;
  text-transform: uppercase;
  letter-spacing: 0.05em;
}

.alert-advanced-toggle:hover {
  color: var(--color-text-secondary);
}

.alert-advanced-toggle i {
  transition: transform var(--transition-fast);
}

.alert-advanced-toggle.open i {
  transform: rotate(90deg);
}

.alert-advanced-body {
  display: none;
}

.alert-advanced-body.open {
  display: block;
}

/* Headline character count */
.char-count {
  font-size: var(--font-size-xs);
  color: var(--color-text-muted);
  text-align: right;
  margin-top: var(--spacing-1);
}

.char-count.warn {
  color: var(--color-warning);
}

.char-count.over {
  color: var(--color-error);
}

/* Voice message picker */
.voice-picker-list {
  display: flex;
  flex-direction: column;
  gap: var(--spacing-2);
  max-height: 200px;
  overflow-y: auto;
}

.voice-picker-card {
  display: flex;
  align-items: center;
  gap: var(--spacing-2);
  padding: var(--spacing-2);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-sm);
  cursor: pointer;
  transition: border-color var(--transition-fast);
}

.voice-picker-card:hover {
  border-color: var(--color-secondary);
}

.voice-picker-card.selected {
  border-color: var(--color-secondary);
  background: rgba(13, 148, 136, 0.08);
}

.voice-picker-card .voice-name {
  flex: 1;
  font-size: var(--font-size-sm);
}

.voice-picker-card .voice-meta {
  font-size: var(--font-size-xs);
  color: var(--color-text-muted);
}

.voice-picker-card .lang-badge {
  font-size: var(--font-size-xs);
  padding: 0.1rem 0.4rem;
  border-radius: var(--radius-sm);
  background: var(--color-surface-overlay);
  color: var(--color-text-secondary);
  text-transform: uppercase;
}

/* Voice picker canvas — toolbar with Generate button on the right and
   a content area that toggles between list mode (search + picker) and
   generate mode (TTS form). Mode toggle is via [data-mode] on the
   .voice-canvas wrapper. */
.voice-canvas-toolbar {
  display: flex;
  align-items: center;
  gap: var(--spacing-2);
}

.voice-canvas-toolbar .inc-edit-title {
  flex: 1;
}

.voice-canvas-toolbar .voice-mode-generate {
  margin-left: auto;
}

/* Mode switching — only the active mode renders content. The
   authoring guide lives only in generate mode (alongside the form). */
.voice-canvas[data-mode="list"]      .voice-canvas-generate,
.voice-canvas[data-mode="list"]      .voice-gen-guide       { display: none; }
.voice-canvas[data-mode="generate"]  .voice-canvas-list     { display: none; }

/* Generate mode is a two-column split: form left, authoring guide
   right. The .voice-canvas-generate form keeps its existing column
   layout; .voice-gen-guide takes the right half and scrolls within
   itself so a long guide doesn't push the form down. Stacks under
   the form on canvases narrower than 900px (mobile / split panes). */
.voice-canvas[data-mode="generate"] {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  grid-template-rows: auto 1fr;
  column-gap: var(--spacing-4);
  align-items: start;
}

.voice-canvas[data-mode="generate"] .voice-canvas-toolbar {
  grid-column: 1 / -1;
}

.voice-canvas[data-mode="generate"] .voice-canvas-generate {
  grid-column: 1;
  grid-row: 2;
}

.voice-canvas[data-mode="generate"] .voice-gen-guide {
  grid-column: 2;
  grid-row: 2;
}

@media (max-width: 900px) {
  .voice-canvas[data-mode="generate"] {
    grid-template-columns: 1fr;
  }
  .voice-canvas[data-mode="generate"] .voice-canvas-generate,
  .voice-canvas[data-mode="generate"] .voice-gen-guide {
    grid-column: 1;
    grid-row: auto;
  }
}

/* Toolbar Generate button hidden in generate mode (Cancel is in the
   form, so the toolbar one would be redundant). */
.voice-canvas[data-mode="generate"]  .voice-mode-generate   { display: none; }

/* Slim the search bar so it doesn't span the full canvas width — the
   picker rows are ~360px so cap the search width to match. */
.voice-search-bar {
  max-width: 360px;
}

/* TTS generate form — vertical stack of labelled fields with a
   two-column row for voice + category. Mirrors the alert form's
   field rhythm so the picker canvas feels native. */
.voice-canvas-generate {
  display: flex;
  flex-direction: column;
  gap: var(--spacing-3);
  padding-top: var(--spacing-2);
}

.voice-gen-title {
  margin: 0 0 var(--spacing-2) 0;
  font-size: var(--font-size-md);
  font-weight: 600;
  color: var(--color-text);
}

.voice-picker-row .voice-edit-btn {
  flex: 0 0 auto;
  color: var(--color-text-muted);
}

.voice-picker-row .voice-edit-btn:hover {
  color: var(--color-secondary, #0d9488);
}

.voice-canvas-generate .form-field {
  display: flex;
  flex-direction: column;
  gap: 0.25rem;
}

.voice-canvas-generate .form-label {
  font-size: var(--font-size-xs);
  color: var(--color-text-muted);
  text-transform: uppercase;
  letter-spacing: 0.04em;
}

.voice-canvas-generate input[type="text"],
.voice-canvas-generate textarea,
.voice-canvas-generate select {
  width: 100%;
  font-size: var(--font-size-sm);
  padding: 0.5rem 0.7rem;
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-sm);
  color: var(--color-text);
  font-family: inherit;
}

.voice-canvas-generate input[type="text"]:focus,
.voice-canvas-generate textarea:focus,
.voice-canvas-generate select:focus {
  outline: none;
  border-color: var(--color-secondary);
  box-shadow: 0 0 0 2px rgba(13, 148, 136, 0.15);
}

.voice-canvas-generate textarea {
  resize: vertical;
  min-height: 6rem;
  line-height: 1.4;
}

.voice-gen-row {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--spacing-3);
}

.voice-gen-row-3 {
  grid-template-columns: 1fr 1fr 1fr;
}

/* Voice picker row layout — single horizontal lane:
   [play] [Select] [main: name+desc / meta-line] [delete]
   Meta line wraps inline on a single row when space allows so
   language/duration/scope/owner/modified don't stack under buttons. */
.voice-picker-row {
  display: flex;
  align-items: center;
  gap: var(--spacing-2);
  padding: var(--spacing-2) var(--spacing-3);
}

.voice-picker-row .voice-row-main {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 0.2rem;
}

.voice-picker-row .voice-row-title {
  display: flex;
  align-items: baseline;
  gap: var(--spacing-2);
  flex-wrap: wrap;
}

.voice-picker-row .inc-result-name {
  font-weight: 600;
  font-size: var(--font-size-sm);
}

.voice-picker-row .voice-row-desc {
  font-size: var(--font-size-xs);
  color: var(--color-text-muted);
  font-style: italic;
}

.voice-picker-row .voice-row-meta {
  display: flex;
  align-items: center;
  gap: var(--spacing-2);
  flex-wrap: wrap;
  font-size: var(--font-size-xs);
  color: var(--color-text-muted);
}

.voice-picker-row .voice-row-meta .pill {
  margin: 0;
}

.voice-picker-row .voice-row-owner,
.voice-picker-row .voice-row-modified {
  display: inline-flex;
  align-items: center;
  gap: 0.25rem;
}

.voice-picker-row .voice-meta {
  font-variant-numeric: tabular-nums;
}

.voice-picker-row .voice-select-btn {
  flex: 0 0 auto;
  min-width: 5.5rem;
  text-align: center;
}

.voice-picker-row .voice-delete-btn {
  flex: 0 0 auto;
  color: var(--color-text-muted);
}

.voice-picker-row .voice-delete-btn:hover {
  color: var(--color-error, #dc2626);
}

/* Voice play button — distinct from the geofence tree chevron. Bigger
   filled play/pause icon with a hit area sized for finger tap. Toggles
   to bi-pause-circle-fill while audio plays (set inline by the row's
   onclick handler). */
.voice-picker-row .voice-play-btn {
  flex: 0 0 auto;
  width: 2.5rem;
  height: 2.5rem;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  background: transparent;
  border: 0;
  padding: 0;
  cursor: pointer;
  color: var(--color-secondary, #0d9488);
  font-size: 1.85rem;
  line-height: 1;
  border-radius: 50%;
  transition: transform var(--transition-fast), color var(--transition-fast);
}

.voice-picker-row .voice-play-btn:hover {
  transform: scale(1.08);
  color: var(--color-secondary-hover, #0f766e);
}

.voice-picker-row .voice-play-btn:active {
  transform: scale(0.96);
}

.voice-picker-row .voice-play-btn i {
  display: block;
}

/* Source-text line — what was spoken. Tucks below the meta row,
   muted and italic, single-line ellipsis with hover for full text. */
.voice-picker-row .voice-row-source {
  font-size: var(--font-size-xs);
  color: var(--color-text-secondary);
  font-style: italic;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  margin-top: 0.15rem;
}

.voice-picker-row .voice-row-source i {
  margin-right: 0.25rem;
  opacity: 0.6;
}

/* Selected state — the row that's currently attached to the alert.
   Stronger treatment than the legacy voice-picker-card.selected: a
   teal accent bar, deeper tint, the leading "Selected for alert"
   pill, and a button that's locked to "Selected" so the operator
   can scan-find the active file. */
.voice-picker-row.is-selected {
  background: rgba(13, 148, 136, 0.12);
  border-left: 4px solid var(--color-secondary);
  padding-left: calc(var(--spacing-3) - 4px);
}

.voice-picker-row.is-selected .inc-result-name {
  color: var(--color-secondary, #0d9488);
}

.voice-picker-row .voice-row-selected-pill {
  display: inline-flex;
  align-items: center;
  gap: 0.25rem;
  font-weight: 600;
  letter-spacing: 0.02em;
}

.voice-picker-row .voice-row-selected-pill i {
  font-size: 0.95em;
}

/* The Select button picks up a "Selected" treatment when this row is
   the active voice for the alert. Stays clickable on purpose — a
   click on the already-selected row fires the idempotent
   set_voice_message + closes the picker (same close path as the
   Back button), which is the natural way to dismiss the panel after
   confirming the choice. */
.voice-picker-row.is-selected .voice-select-btn {
  background: var(--color-secondary, #0d9488);
  color: var(--color-text-on-primary, #fff);
  border-color: var(--color-secondary, #0d9488);
  opacity: 1;
}

.voice-picker-row.is-selected .voice-select-btn:hover {
  background: var(--color-secondary-hover, #0f766e);
  border-color: var(--color-secondary-hover, #0f766e);
}

/* Close X — top-right corner of the voice canvas, hovers over the
   toolbar so it's the conventional dismiss affordance regardless of
   which mode (list or generate) the canvas is showing. Same close
   action as the Back button: hide the search col-state, restore the
   list col-state, empty the search body. */
.voice-canvas {
  position: relative;
}

/* Close X — sits at the far right of the voice-canvas toolbar after
   the Generate-new button so they don't overlap. Sized to match the
   other btn-sm controls in the toolbar. */
.voice-canvas-close {
  flex: 0 0 auto;
  width: 2rem;
  height: 2rem;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  background: transparent;
  border: 0;
  padding: 0;
  margin-left: var(--spacing-1);
  cursor: pointer;
  color: var(--color-text-muted);
  font-size: 1.1rem;
  border-radius: 50%;
  transition: background var(--transition-fast), color var(--transition-fast);
}

.voice-canvas-close:hover {
  background: var(--color-surface-overlay, rgba(0, 0, 0, 0.06));
  color: var(--color-error, #dc2626);
}

.voice-gen-actions {
  display: flex;
  align-items: center;
  gap: var(--spacing-2);
  padding-top: var(--spacing-1);
  flex-wrap: wrap;
}

.voice-gen-actions .form-hint {
  margin-left: auto;
}

.voice-gen-actions .voice-preview-btn {
  background: var(--color-surface-overlay, rgba(13, 148, 136, 0.12));
  color: var(--color-secondary, #0d9488);
  border: 1px solid var(--color-secondary, #0d9488);
}

.voice-gen-actions .voice-preview-btn:hover:not(:disabled) {
  background: var(--color-secondary, #0d9488);
  color: var(--color-text-on-primary, #fff);
}

.voice-gen-actions .voice-preview-btn:disabled {
  opacity: 0.6;
  cursor: progress;
}

.voice-gen-actions .voice-preview-audio {
  flex: 1 1 100%;
  min-width: 0;
  margin-top: var(--spacing-2);
  height: 2.25rem;
}

/* Authoring guide — right-hand panel in generate mode. */
.voice-gen-guide {
  background: var(--color-surface-overlay, rgba(0, 0, 0, 0.02));
  border: 1px solid var(--color-border-light, rgba(0, 0, 0, 0.08));
  border-radius: var(--radius-md);
  padding: var(--spacing-3) var(--spacing-4);
  max-height: calc(100vh - 240px);
  overflow-y: auto;
  font-size: var(--font-size-sm);
  line-height: 1.5;
}

.voice-gen-guide details {
  margin: 0;
}

.voice-gen-guide details > summary {
  cursor: pointer;
  list-style: none;
  font-weight: 600;
  font-size: var(--font-size-md);
  margin-bottom: var(--spacing-2);
  display: flex;
  align-items: center;
  gap: var(--spacing-2);
}

.voice-gen-guide details > summary::-webkit-details-marker { display: none; }

.voice-gen-guide details > summary::after {
  content: "▾";
  margin-left: auto;
  transition: transform var(--transition-fast);
}

.voice-gen-guide details:not([open]) > summary::after {
  transform: rotate(-90deg);
}

.voice-gen-guide section {
  margin: var(--spacing-3) 0;
  padding-bottom: var(--spacing-3);
  border-bottom: 1px solid var(--color-border-light, rgba(0, 0, 0, 0.06));
}

.voice-gen-guide section:last-child {
  border-bottom: 0;
  padding-bottom: 0;
}

.voice-gen-guide h4 {
  margin: 0 0 var(--spacing-2) 0;
  font-size: var(--font-size-sm);
  font-weight: 600;
  color: var(--color-text);
  text-transform: uppercase;
  letter-spacing: 0.04em;
}

.voice-gen-guide p { margin: 0 0 var(--spacing-2) 0; }
.voice-gen-guide ul, .voice-gen-guide ol { margin: 0 0 var(--spacing-2) 1.25rem; padding: 0; }
.voice-gen-guide li { margin-bottom: 0.35rem; }

.voice-gen-guide code {
  background: var(--color-surface-overlay, rgba(0, 0, 0, 0.05));
  padding: 0.05rem 0.3rem;
  border-radius: 3px;
  font-size: 0.85em;
}

.voice-guide-table {
  width: 100%;
  border-collapse: collapse;
  font-size: var(--font-size-xs);
  margin: 0 0 var(--spacing-2) 0;
}

.voice-guide-table th,
.voice-guide-table td {
  text-align: left;
  padding: 0.3rem 0.5rem;
  border-bottom: 1px solid var(--color-border-light, rgba(0, 0, 0, 0.05));
}

.voice-guide-table th {
  font-weight: 600;
  color: var(--color-text-muted);
}

.voice-guide-tip {
  background: var(--color-surface);
  border-left: 3px solid var(--color-secondary);
  padding: var(--spacing-2);
  border-radius: 0 var(--radius-sm) var(--radius-sm) 0;
}

@media (max-width: 1024px) {
  .alert-layout {
    flex-direction: column;
  }
  #alerts-col-chat,
  #briefing-col-selector {
    display: none;
  }
  #alerts-col-detail,
  #briefing-col-activity {
    border-left: none;
    border-top: 1px solid var(--color-border);
  }
}

/* Action icons */
.row-actions {
  display: flex;
  gap: 0.25rem;
}

.action-btn {
  width: 28px;
  height: 28px;
  display: flex;
  align-items: center;
  justify-content: center;
  background: transparent;
  border: 1px solid transparent;
  border-radius: var(--radius-sm);
  color: var(--color-text-muted);
  cursor: pointer;
  font-size: 0.85rem;
  transition: all var(--transition-fast);
}

.action-btn:hover {
  background: var(--color-bg-overlay);
  border-color: var(--color-border-light);
  color: var(--color-text);
}

.action-btn.action-map:hover {
  color: rgb(var(--color-primary-light));
}

.action-btn.action-detail:hover {
  color: rgb(var(--color-secondary-light));
}

*, *::before, *::after { margin: 0; padding: 0; box-sizing: border-box; }
html { scroll-behavior: smooth; }

body {
  font-family: var(--font-family-primary);
  font-size: var(--font-size-base);
  line-height: var(--line-height-normal);
  color: var(--color-text);
  background: var(--color-bg);
  min-height: 100vh;
  display: flex;
  flex-direction: column;
  -webkit-font-smoothing: antialiased;
}

/* ---- Status Bar (top of page) ---- */
.status-bar {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  height: 3px;
  z-index: 999;
  background: linear-gradient(90deg,
    rgb(var(--color-status-success)) 0%,
    rgb(var(--color-secondary)) 30%,
    rgb(var(--color-primary)) 60%,
    rgb(var(--color-secondary)) 100%);
  background-size: 300% 100%;
  animation: statusSweep 8s ease infinite;
}
@keyframes statusSweep {
  0% { background-position: 0% 50%; }
  50% { background-position: 100% 50%; }
  100% { background-position: 0% 50%; }
}

/* ---- Topo Background ---- */
.topo-bg {
  position: fixed;
  inset: 0;
  z-index: -1;
  opacity: 0.03;
  background-image:
    repeating-conic-gradient(
      rgba(96, 165, 250, 0.3) 0deg 1deg,
      transparent 1deg 90deg
    );
  background-size: 60px 60px;
}

/* Container */
.container {
  width: 100%;
  max-width: var(--container-max);
  margin: 0 auto;
  padding: 0 var(--spacing-6);
}

/* ---- Navigation ---- */
.nav {
  position: fixed;
  top: 3px;
  left: 0;
  right: 0;
  height: var(--nav-height);
  background: var(--nav-bg);
  backdrop-filter: blur(20px);
  -webkit-backdrop-filter: blur(20px);
  border-bottom: 1px solid var(--nav-border);
  /* Above Leaflet controls (800) so .user-dropdown-menu (z-index 1000),
     trapped inside this nav's stacking context, can render above the
     minimap mounted in the alert edit panel (JOB-AUS1-00014x). */
  z-index: 1000;
  transition: box-shadow var(--transition-base);
}
.nav.scrolled {
  box-shadow: 0 8px 32px rgba(0, 0, 0, 0.4);
}

.nav-inner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  height: 100%;
}

.brand {
  display: flex;
  align-items: center;
  gap: var(--spacing-3);
  text-decoration: none;
  color: var(--color-text);
}
.brand-icon {
  width: 28px;
  height: 28px;
  flex-shrink: 0;
}
.brand-name {
  font-family: var(--font-family-display);
  font-weight: var(--font-weight-bold);
  font-size: var(--font-size-lg);
  letter-spacing: 0.08em;
  text-transform: uppercase;
}
.brand-tag {
  font-size: 0.6rem;
  font-weight: var(--font-weight-medium);
  color: var(--color-text-muted);
  letter-spacing: 0.15em;
  text-transform: uppercase;
  margin-left: var(--spacing-3);
  padding-left: var(--spacing-3);
  border-left: 1px solid var(--color-border-light);
}

.nav-links {
  display: flex;
  align-items: center;
  gap: var(--spacing-1);
  list-style: none;
}

.tab {
  padding: var(--spacing-2) var(--spacing-3);
  font-size: 0.8rem;
  font-weight: var(--font-weight-medium);
  color: var(--color-text-secondary);
  text-decoration: none;
  border-radius: var(--radius-md);
  transition: all var(--transition-fast);
  letter-spacing: 0.04em;
  text-transform: uppercase;
}
.tab:hover {
  color: var(--color-text);
  background: rgba(255, 255, 255, 0.04);
}
.tab.active {
  color: rgb(var(--color-secondary-light));
  background: rgba(var(--color-secondary), 0.08);
}
.tab-login {
  color: rgb(var(--color-primary-light));
  border: 1px solid rgba(var(--color-primary-light), 0.2);
  margin-left: var(--spacing-2);
}
.tab-login:hover {
  background: rgba(var(--color-primary), 0.12);
  color: rgb(var(--color-primary-light));
  border-color: rgba(var(--color-primary-light), 0.4);
}
.tab-avatar {
  display: none;
  align-items: center;
  gap: var(--spacing-2);
}
.tab-avatar-img {
  width: 26px;
  height: 26px;
  border-radius: var(--radius-full);
  object-fit: cover;
  border: 1px solid var(--color-border-light);
}

.mobile-menu-toggle {
  display: none;
  background: none;
  border: none;
  color: var(--color-text);
  font-size: var(--font-size-xl);
  cursor: pointer;
  padding: var(--spacing-2);
}

/* ---- Main Content ---- */
main {
  flex: 1;
  margin-top: calc(var(--nav-height) + 3px);
}

/* ---- Hero ---- */
.hero {
  position: relative;
  padding: var(--spacing-32) 0 var(--spacing-20);
  overflow: hidden;
}

.hero-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--spacing-16);
  align-items: center;
}

.hero-content {
  position: relative;
  z-index: 2;
}

.hero-eyebrow {
  display: inline-flex;
  align-items: center;
  gap: var(--spacing-2);
  font-size: 0.7rem;
  font-weight: var(--font-weight-semibold);
  color: rgb(var(--color-secondary-light));
  letter-spacing: 0.2em;
  text-transform: uppercase;
  margin-bottom: var(--spacing-6);
  opacity: 0;
  animation: fadeUp 0.6s ease 0.2s forwards;
}
.hero-eyebrow .dot {
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: rgb(var(--color-status-success));
  animation: pulse 2s ease infinite;
}

.hero h1 {
  font-family: var(--font-family-display);
  font-size: clamp(2.5rem, 5vw, 4rem);
  font-weight: var(--font-weight-bold);
  line-height: 1.1;
  margin-bottom: var(--spacing-6);
  opacity: 0;
  animation: fadeUp 0.6s ease 0.35s forwards;
}
.hero h1 .text-gradient {
  background: var(--gradient-brand-light);
  -webkit-background-clip: text;
  -webkit-text-fill-color: transparent;
  background-clip: text;
}
.hero h1 .text-dim {
  color: var(--color-text-muted);
  font-weight: var(--font-weight-normal);
  font-size: 0.55em;
  display: block;
  margin-top: var(--spacing-2);
  font-style: italic;
}

.hero-desc {
  font-size: var(--font-size-lg);
  color: var(--color-text-secondary);
  line-height: var(--line-height-relaxed);
  max-width: 480px;
  margin-bottom: var(--spacing-8);
  opacity: 0;
  animation: fadeUp 0.6s ease 0.5s forwards;
}

.hero-actions {
  display: flex;
  gap: var(--spacing-4);
  opacity: 0;
  animation: fadeUp 0.6s ease 0.65s forwards;
}

/* Hero visual — Philippine sun radar */
.hero-visual {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
  opacity: 0;
  animation: fadeIn 1s ease 0.4s forwards;
}
.hero-sun {
  width: 360px;
  height: 360px;
  opacity: 0.12;
  filter: blur(0.5px);
  animation: slowSpin 120s linear infinite;
}
.radar-ring {
  position: absolute;
  border-radius: 50%;
  border: 1px solid rgba(var(--color-secondary), 0.08);
}
.radar-ring:nth-child(2) { width: 200px; height: 200px; }
.radar-ring:nth-child(3) { width: 300px; height: 300px; }
.radar-ring:nth-child(4) { width: 400px; height: 400px; }
.radar-sweep {
  position: absolute;
  width: 180px;
  height: 180px;
  background: conic-gradient(
    from 0deg,
    transparent 0deg,
    rgba(var(--color-secondary), 0.06) 40deg,
    transparent 80deg
  );
  border-radius: 50%;
  animation: radarSweep 4s linear infinite;
}

/* ---- Ops Panels ---- */
.ops-section {
  padding: var(--spacing-20) 0;
}
.ops-section-header {
  margin-bottom: var(--spacing-10);
}
.ops-label {
  font-size: 0.65rem;
  font-weight: var(--font-weight-semibold);
  color: var(--color-text-muted);
  letter-spacing: 0.2em;
  text-transform: uppercase;
  margin-bottom: var(--spacing-2);
}
.ops-title {
  font-family: var(--font-family-display);
  font-size: var(--font-size-3xl);
  font-weight: var(--font-weight-bold);
}

.ops-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: var(--spacing-4);
}

.ops-card {
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-lg);
  padding: var(--spacing-6);
  position: relative;
  overflow: hidden;
  transition: all var(--transition-base);
  opacity: 0;
  transform: translateY(20px);
}
.ops-card.visible {
  opacity: 1;
  transform: translateY(0);
  transition: opacity 0.5s ease, transform 0.5s ease;
}
.ops-card:hover {
  border-color: var(--color-border-light);
  box-shadow: var(--glow-primary);
  transform: translateY(-2px);
}

/* Severity stripe */
.ops-card::before {
  content: '';
  position: absolute;
  top: 0;
  left: 0;
  width: 3px;
  height: 100%;
  background: var(--card-accent, rgb(var(--color-primary)));
  opacity: 0.6;
  transition: opacity var(--transition-fast);
}
.ops-card:hover::before { opacity: 1; }

.ops-card-icon {
  width: 40px;
  height: 40px;
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: var(--radius-lg);
  font-size: var(--font-size-lg);
  margin-bottom: var(--spacing-4);
  background: rgba(var(--color-primary), 0.08);
  color: rgb(var(--color-primary-light));
}
.ops-card[data-accent="critical"] { --card-accent: rgb(var(--color-status-error)); }
.ops-card[data-accent="critical"] .ops-card-icon {
  background: rgba(var(--color-status-error), 0.08);
  color: rgb(var(--color-status-error));
}
.ops-card[data-accent="teal"] { --card-accent: rgb(var(--color-secondary)); }
.ops-card[data-accent="teal"] .ops-card-icon {
  background: rgba(var(--color-secondary), 0.08);
  color: rgb(var(--color-secondary-light));
}
.ops-card[data-accent="blue"] { --card-accent: rgb(var(--color-primary)); }

.ops-card h3 {
  font-family: var(--font-family-display);
  font-size: var(--font-size-base);
  font-weight: var(--font-weight-semibold);
  margin-bottom: var(--spacing-2);
}
.ops-card p {
  font-size: var(--font-size-sm);
  color: var(--color-text-secondary);
  line-height: var(--line-height-relaxed);
}

/* ---- Stats Row ---- */
.stats-row {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: var(--spacing-4);
  padding: var(--spacing-12) 0;
  border-top: 1px solid var(--color-border);
  border-bottom: 1px solid var(--color-border);
  margin: var(--spacing-8) 0;
}
.stat-item {
  text-align: center;
}
.stat-value {
  font-family: var(--font-family-display);
  font-size: var(--font-size-3xl);
  font-weight: var(--font-weight-bold);
  background: var(--gradient-brand-light);
  -webkit-background-clip: text;
  -webkit-text-fill-color: transparent;
  background-clip: text;
}
.stat-label {
  font-size: 0.7rem;
  color: var(--color-text-muted);
  letter-spacing: 0.12em;
  text-transform: uppercase;
  margin-top: var(--spacing-1);
}

/* ---- CTA Section ---- */
.cta-section {
  padding: var(--spacing-20) 0;
  text-align: center;
}
.cta-box {
  max-width: 600px;
  margin: 0 auto;
  padding: var(--spacing-12);
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-xl);
  position: relative;
  overflow: hidden;
}
.cta-box::before {
  content: '';
  position: absolute;
  inset: 0;
  background: var(--gradient-brand);
  opacity: 0.03;
}
.cta-box h2 {
  font-family: var(--font-family-display);
  font-size: var(--font-size-2xl);
  font-weight: var(--font-weight-bold);
  margin-bottom: var(--spacing-3);
  position: relative;
}
.cta-box p {
  color: var(--color-text-secondary);
  margin-bottom: var(--spacing-6);
  position: relative;
}

/* ---- Footer ---- */
.footer {
  border-top: 1px solid var(--color-border);
  background: var(--color-bg);
  padding: var(--spacing-3) 0;
}
.footer-inner {
  display: flex;
  justify-content: space-between;
  align-items: center;
}
.footer-text {
  font-size: var(--font-size-sm);
  color: var(--color-text-muted);
}
.footer-links {
  display: flex;
  gap: var(--spacing-6);
}
.footer-links a {
  font-size: 0.75rem;
  color: var(--color-text-muted);
  text-decoration: none;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  transition: color var(--transition-fast);
}
.footer-links a:hover {
  color: var(--color-text-secondary);
}

/* ---- Auth Page ---- */
.auth-page {
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: calc(100vh - var(--nav-height) - 3px);
  padding: var(--spacing-8) var(--spacing-4);
}
.auth-card {
  width: 100%;
  max-width: 400px;
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-xl);
  padding: var(--spacing-8);
  position: relative;
  overflow: hidden;
}
.auth-card::before {
  content: '';
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  height: 3px;
  background: var(--gradient-brand);
}
.auth-card h1 {
  font-family: var(--font-family-display);
  font-size: var(--font-size-xl);
  font-weight: var(--font-weight-bold);
  margin-bottom: var(--spacing-1);
  letter-spacing: 0.02em;
}
.auth-card .subtitle {
  color: var(--color-text-muted);
  font-size: var(--font-size-sm);
  margin-bottom: var(--spacing-6);
}
.auth-submit {
  width: 100%;
  padding: var(--spacing-3);
  font-family: var(--font-family-primary);
  font-size: var(--font-size-sm);
  font-weight: var(--font-weight-semibold);
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: #fff;
  background: var(--gradient-brand);
  border: none;
  border-radius: var(--radius-md);
  cursor: pointer;
  transition: all var(--transition-fast);
}
.auth-submit:hover {
  box-shadow: var(--glow-primary);
  transform: translateY(-1px);
}
.auth-links {
  text-align: center;
  margin-top: var(--spacing-4);
}
.auth-links a {
  font-size: var(--font-size-xs);
  color: var(--color-text-muted);
  text-decoration: none;
  letter-spacing: 0.04em;
}
.auth-links a:hover { color: var(--color-text-secondary); }

/* Password toggle inside form inputs */
.password-toggle {
  position: absolute;
  right: var(--spacing-3);
  top: 50%;
  transform: translateY(20%);
  background: none;
  border: none;
  color: var(--color-text-muted);
  cursor: pointer;
  padding: var(--spacing-1);
  font-size: var(--font-size-sm);
  line-height: 1;
}
.password-toggle:hover { color: var(--color-text-secondary); }

/* Checkbox group for auth forms */
.checkbox-group { margin-bottom: var(--spacing-4); }
.checkbox-label {
  display: flex;
  align-items: flex-start;
  gap: var(--spacing-2);
  font-size: var(--font-size-xs);
  color: var(--color-text-muted);
  cursor: pointer;
}
.checkbox-label input[type="checkbox"] {
  accent-color: var(--color-primary);
  margin-top: 2px;
  flex-shrink: 0;
}

/* ========================================
   Admin Layout — 2-column sidebar + content
   ======================================== */

/* Admin column widths — 5 slots in the .app-layout canvas:
   menu (250px, visible) | chat (280px, hidden) | search (1fr, hidden)
   | list (1fr, visible, hosts #admin-content) | detail (420px, :empty-collapsing).
   chat / search slots are reserved for the future LLM assistant + per-view
   filter UI; col-state sentinels keep them hidden until a server-side
   toggle reveals them (DPAT-AUS1-000DLu). */
#admin-col-menu {
  flex: 0 0 250px;
  border-right: 1px solid var(--color-border);
  padding: var(--spacing-4) 0;
}
#admin-col-chat {
  flex: 0 0 280px;
  border-right: 1px solid var(--color-border);
}
#admin-col-search {
  flex: 1 1 0;
  min-width: 0;
  border-right: 1px solid var(--color-border);
}
#admin-col-list {
  flex: 1 1 0;
  min-width: 0;
}
/* The detail column IS the bug.view OOB target (`#bugs-detail-body`) —
   one element serves as both the column primitive and the swap slot, so
   `:empty` cleanly drives the column's collapse. The handler pushes
   `<div id="bugs-detail-body" hx-swap-oob="innerHTML">…</div>` and the
   column shows; the X button clears innerHTML and the column collapses. */
#bugs-detail-body {
  flex: 0 0 420px;
  border-left: 1px solid var(--color-border);
  padding: 1rem;
}
#bugs-detail-body:empty {
  display: none;
}
@media (max-width: 900px) {
  #bugs-detail-body { flex: 0 0 100vw; }
}

/* Legacy `.admin-sidebar` styles preserved for the menu's inner padding
   pattern. Outer width/border now lives on `#admin-col-menu`. */
.admin-sidebar {
  overflow-y: auto;
}

.admin-menu-section {
  margin-bottom: var(--spacing-4);
}
.admin-menu-section h3 {
  font-family: var(--font-family-display);
  font-size: var(--font-size-xs);
  font-weight: var(--font-weight-semibold);
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--color-text-muted);
  padding: var(--spacing-2) var(--spacing-4);
  margin: 0;
}

.admin-menu-link {
  display: flex;
  align-items: center;
  gap: var(--spacing-2);
  padding: var(--spacing-2) var(--spacing-4);
  font-size: var(--font-size-sm);
  color: var(--color-text-secondary);
  text-decoration: none;
  border: none;
  background: none;
  width: 100%;
  cursor: pointer;
  transition: all var(--transition-fast);
  font-family: var(--font-family-primary);
}
.admin-menu-link:hover {
  background: var(--color-surface-hover, rgba(0,0,0,0.05));
  color: var(--color-text-primary);
}
.admin-menu-link.active {
  background: var(--color-primary-subtle, rgba(30,64,175,0.08));
  color: var(--color-primary);
  font-weight: var(--font-weight-semibold);
  border-left: 3px solid var(--color-primary);
}
.admin-menu-link i {
  width: 18px;
  text-align: center;
  font-size: 1rem;
}

/* Legacy `.admin-content` wrapper (still on a few view fragments).
   The search column itself owns scrolling now via `.app-col` —
   leaving padding here so existing inner views don't reflow. */
.admin-content {
  padding: var(--spacing-6);
}

/* `#admin-content` lives inside `#admin-col-search` and acts as the
   canonical OOB target for `admin.switch_view`-rendered fragments.
   Flex it to fill the search column so view fragments that go
   full-height (bugs/features) can chain `flex: 1` down. */
#admin-content {
  flex: 1;
  min-height: 0;
  display: flex;
  flex-direction: column;
}
.admin-content h2 {
  font-family: var(--font-family-display);
  font-size: var(--font-size-lg);
  font-weight: var(--font-weight-bold);
  margin-bottom: var(--spacing-4);
}

/* Admin data table */
.admin-table {
  width: 100%;
  border-collapse: collapse;
  font-size: var(--font-size-sm);
}
.admin-table th,
.admin-table td {
  padding: var(--spacing-2) var(--spacing-3);
  text-align: left;
  border-bottom: 1px solid var(--color-border);
}
.admin-table th {
  font-weight: var(--font-weight-semibold);
  color: var(--color-text-muted);
  text-transform: uppercase;
  font-size: var(--font-size-xs);
  letter-spacing: 0.06em;
}
.admin-table tr:hover td {
  background: var(--color-surface-hover, rgba(0,0,0,0.02));
}

/* Mobile: stack menu above content. `.app-layout` switches to
   column flex; `#admin-col-menu` becomes a horizontal scroll-strip;
   the detail column collapses to full width when populated. */
@media (max-width: 768px) {
  .app-layout {
    flex-direction: column;
  }
  #admin-col-menu {
    flex: 0 0 auto;
    border-right: none;
    border-bottom: 1px solid var(--color-border);
    padding: var(--spacing-2) 0;
    display: flex;
    overflow-x: auto;
    gap: 0;
  }
  #admin-col-list {
    flex: 1 1 auto;
  }
  .admin-menu-section h3 {
    display: none;
  }
  .admin-menu-section {
    display: flex;
    margin-bottom: 0;
  }
  .admin-menu-link {
    white-space: nowrap;
    padding: var(--spacing-2) var(--spacing-3);
    font-size: var(--font-size-xs);
  }
  .admin-menu-link.active {
    border-left: none;
    border-bottom: 3px solid var(--color-primary);
  }
}

/* ---- Toast ---- */
.toast-container {
  position: fixed;
  top: calc(var(--nav-height) + var(--spacing-4) + 3px);
  right: var(--spacing-4);
  z-index: var(--z-toast);
  display: flex;
  flex-direction: column;
  gap: var(--spacing-2);
}
.toast {
  padding: var(--spacing-3) var(--spacing-4);
  border-radius: var(--radius-md);
  font-size: var(--font-size-sm);
  color: #fff;
  animation: slideIn var(--transition-base) ease;
}
.toast.error { background: rgb(var(--color-status-error)); }
.toast.warning { background: rgb(var(--color-status-warning)); color: var(--color-text-inverse); }
.toast.success { background: rgb(var(--color-status-success)); }
.toast.info { background: rgb(var(--color-status-info)); }

/* Error/success messages in forms */
.error-message {
  padding: var(--spacing-3);
  background: rgba(var(--color-status-error), 0.1);
  border: 1px solid rgba(var(--color-status-error), 0.2);
  border-radius: var(--radius-md);
  color: rgb(var(--color-status-error));
  font-size: var(--font-size-sm);
}
.success-message {
  padding: var(--spacing-3);
  background: rgba(var(--color-status-success), 0.1);
  border: 1px solid rgba(var(--color-status-success), 0.2);
  border-radius: var(--radius-md);
  color: rgb(var(--color-status-success));
  font-size: var(--font-size-sm);
}

/* ---- Animations ---- */
@keyframes fadeUp {
  from { opacity: 0; transform: translateY(16px); }
  to { opacity: 1; transform: translateY(0); }
}
@keyframes fadeIn {
  from { opacity: 0; }
  to { opacity: 1; }
}
@keyframes slowSpin {
  from { transform: rotate(0deg); }
  to { transform: rotate(360deg); }
}
@keyframes radarSweep {
  from { transform: rotate(0deg); }
  to { transform: rotate(360deg); }
}
@keyframes pulse {
  0%, 100% { opacity: 1; }
  50% { opacity: 0.4; }
}
@keyframes slideIn {
  from { transform: translateX(100%); opacity: 0; }
  to { transform: translateX(0); opacity: 1; }
}

/* ---- Utility ---- */
.gradient-text {
  background: var(--gradient-brand-light);
  -webkit-background-clip: text;
  -webkit-text-fill-color: transparent;
  background-clip: text;
}

/* ---- Responsive ---- */
@media (max-width: 900px) {
  .hero-grid { grid-template-columns: 1fr; text-align: center; }
  .hero-content { order: 2; }
  .hero-visual { order: 1; margin-bottom: var(--spacing-8); }
  .hero-sun { width: 240px; height: 240px; }
  .radar-ring:nth-child(2) { width: 140px; height: 140px; }
  .radar-ring:nth-child(3) { width: 200px; height: 200px; }
  .radar-ring:nth-child(4) { width: 280px; height: 280px; }
  .hero-desc { margin-left: auto; margin-right: auto; }
  .hero-actions { justify-content: center; }
  .ops-grid { grid-template-columns: 1fr; }
  .stats-row { grid-template-columns: repeat(2, 1fr); gap: var(--spacing-6); }
}
@media (max-width: 768px) {
  .mobile-menu-toggle { display: block; }
  .nav-links {
    display: none;
    position: absolute;
    top: var(--nav-height);
    left: 0;
    right: 0;
    background: var(--nav-bg);
    backdrop-filter: blur(20px);
    flex-direction: column;
    padding: var(--spacing-4);
    border-bottom: 1px solid var(--nav-border);
  }
  .nav-links.active { display: flex; }
  .brand-tag { display: none; }
  .hero { padding: var(--spacing-16) 0 var(--spacing-12); }
  .hero h1 { font-size: var(--font-size-3xl); }
  .hero-actions { flex-direction: column; align-items: center; }
  .footer-inner { flex-direction: column; gap: var(--spacing-4); text-align: center; }
  .stats-row { grid-template-columns: repeat(2, 1fr); }
}

/* ========================================
   Map Location Picker + Save Modal
   ======================================== */

.map-control-separator {
  width: 100%;
  height: 1px;
  background: var(--color-border, rgba(255,255,255,0.15));
  margin: var(--spacing-1, 4px) 0;
}

/* Location picker dropdown */
.map-location-picker {
  position: absolute;
  top: var(--spacing-4, 16px);
  left: calc(var(--spacing-4, 16px) + 48px);
  width: 260px;
  max-height: 400px;
  overflow-y: auto;
  background: var(--color-surface, #1e293b);
  border: 1px solid var(--color-border, rgba(255,255,255,0.1));
  border-radius: var(--radius-lg, 12px);
  box-shadow: 0 8px 32px rgba(0,0,0,0.4);
  z-index: 200;
}

.map-location-picker-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: var(--spacing-3, 12px) var(--spacing-4, 16px);
  border-bottom: 1px solid var(--color-border, rgba(255,255,255,0.1));
  font-weight: 600;
  font-size: var(--font-size-sm, 0.875rem);
}

.map-location-picker-close {
  background: none;
  border: none;
  color: var(--color-text-muted, #94a3b8);
  cursor: pointer;
  font-size: 1.1rem;
}

.map-location-picker-body {
  padding: var(--spacing-2, 8px);
}

.location-section h4 {
  font-size: var(--font-size-xs, 0.75rem);
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--color-text-muted, #94a3b8);
  padding: var(--spacing-2, 8px) var(--spacing-3, 12px) var(--spacing-1, 4px);
  margin: 0;
}

.location-section h4 i {
  margin-right: var(--spacing-1, 4px);
}

.location-item {
  display: flex;
  align-items: center;
  gap: var(--spacing-2, 8px);
  padding: var(--spacing-2, 8px) var(--spacing-3, 12px);
  border-radius: var(--radius-md, 8px);
  cursor: pointer;
  font-size: var(--font-size-sm, 0.875rem);
  color: var(--color-text, #e2e8f0);
  transition: background 0.15s;
}

.location-item:hover {
  background: var(--color-surface-hover, rgba(255,255,255,0.06));
}

.location-item i.bi-star-fill {
  color: #fbbf24;
  font-size: 0.7rem;
  margin-left: var(--spacing-1, 4px);
}

/* Save view modal */
.map-save-modal-overlay {
  position: absolute;
  inset: 0;
  background: rgba(0,0,0,0.5);
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 300;
}

.map-save-modal {
  background: var(--color-surface, #1e293b);
  border: 1px solid var(--color-border, rgba(255,255,255,0.1));
  border-radius: var(--radius-lg, 12px);
  width: 320px;
  box-shadow: 0 8px 32px rgba(0,0,0,0.5);
}

.map-save-modal-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: var(--spacing-3, 12px) var(--spacing-4, 16px);
  border-bottom: 1px solid var(--color-border, rgba(255,255,255,0.1));
  font-weight: 600;
}

.map-save-modal-close {
  background: none;
  border: none;
  color: var(--color-text-muted, #94a3b8);
  cursor: pointer;
}

.map-save-modal-body {
  padding: var(--spacing-4, 16px);
  display: flex;
  flex-direction: column;
  gap: var(--spacing-3, 12px);
}

.map-save-modal-body label {
  display: flex;
  flex-direction: column;
  gap: var(--spacing-1, 4px);
  font-size: var(--font-size-sm, 0.875rem);
  color: var(--color-text-muted, #94a3b8);
}

.map-save-modal-body label.checkbox-label {
  flex-direction: row;
  align-items: center;
  gap: var(--spacing-2, 8px);
}

.map-save-modal-body input[type="text"],
.map-save-modal-body select {
  padding: var(--spacing-2, 8px) var(--spacing-3, 12px);
  background: var(--color-bg, #0f172a);
  border: 1px solid var(--color-border, rgba(255,255,255,0.1));
  border-radius: var(--radius-md, 8px);
  color: var(--color-text, #e2e8f0);
  font-size: var(--font-size-sm, 0.875rem);
}

.map-save-modal-body .btn {
  margin-top: var(--spacing-2, 8px);
}

/* ---------------------------------------------------------------------------
   Draw-to-create geofence mode
   Cursor swap, draft polygon styling, vertex handles, status banner, and the
   save-form slot. layer-draw sits above layer-incidents in maps.html so the
   in-progress shape always paints on top.
   ------------------------------------------------------------------------- */

body.map-drawing,
body.map-drawing #map-canvas,
body.map-drawing #map-svg,
body.map-drawing #map,
body.map-drawing #map .leaflet-grab,
body.map-drawing #map .leaflet-interactive {
  cursor: crosshair;
}

#layer-draw polyline,
#layer-draw polygon {
  stroke: rgba(59, 130, 246, 0.85);
  stroke-width: 1.5;
  stroke-linejoin: round;
  pointer-events: none;
}

/* Open ring (still drawing) — dashed, no fill. */
#layer-draw polyline {
  fill: none;
  stroke-dasharray: 4, 3;
}

/* Closed ring — solid stroke + translucent accent fill. */
#layer-draw polygon {
  fill: rgba(59, 130, 246, 0.20);
  stroke-dasharray: none;
}

#layer-draw circle {
  fill: #fff;
  stroke: #3b82f6;
  stroke-width: 2;
  r: 5;
  cursor: grab;
}

#map-draw-banner {
  position: absolute;
  top: 10px;
  left: 50%;
  transform: translateX(-50%);
  background: rgba(59, 130, 246, 0.92);
  color: #fff;
  padding: 0.5rem 1rem;
  border-radius: 4px;
  font-size: 0.85rem;
  z-index: 10;
  box-shadow: 0 2px 6px rgba(0, 0, 0, 0.25);
  display: flex;
  align-items: center;
  gap: 0.5rem;
}

#map-draw-banner[hidden] { display: none; }

.map-draw-banner-count {
  font-variant-numeric: tabular-nums;
  font-weight: 600;
  background: rgba(255, 255, 255, 0.2);
  padding: 0.1rem 0.5rem;
  border-radius: 3px;
}

#map-draw-banner kbd {
  background: rgba(255, 255, 255, 0.2);
  padding: 0 0.35rem;
  border-radius: 3px;
  font-size: 0.75rem;
  font-family: inherit;
}

.map-geofence-form-slot {
  position: absolute;
  top: 60px;
  right: 10px;
  width: 300px;
  z-index: 10;
  background: var(--color-bg-panel, #0f172a);
  border: 1px solid var(--color-border, rgba(255, 255, 255, 0.1));
  border-radius: var(--radius-md, 8px);
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.35);
}

.map-geofence-form-slot[hidden] { display: none; }

.map-geofence-form {
  display: flex;
  flex-direction: column;
  gap: 0.65rem;
  padding: 0.85rem;
}

.map-geofence-form-header {
  font-weight: 600;
  font-size: 1rem;
  color: var(--color-text, #e2e8f0);
}

.map-geofence-form label {
  display: flex;
  flex-direction: column;
  gap: 0.25rem;
  font-size: 0.8rem;
  color: var(--color-text-muted, #94a3b8);
}

.map-geofence-form input,
.map-geofence-form select,
.map-geofence-form textarea {
  padding: 0.4rem 0.6rem;
  background: var(--color-bg, #0f172a);
  border: 1px solid var(--color-border, rgba(255, 255, 255, 0.1));
  border-radius: var(--radius-sm, 4px);
  color: var(--color-text, #e2e8f0);
  font-size: 0.85rem;
  font-family: inherit;
}

.map-geofence-form textarea {
  resize: vertical;
}

.map-geofence-form .muted {
  color: var(--color-text-muted, #64748b);
  font-weight: 400;
}

.map-geofence-form-meta {
  font-size: 0.75rem;
  color: var(--color-text-muted, #94a3b8);
}

.map-geofence-form-actions {
  display: flex;
  justify-content: flex-end;
  gap: 0.5rem;
  margin-top: 0.25rem;
}

.map-geofence-form-error {
  padding: 0.85rem;
  font-size: 0.85rem;
  color: #fca5a5;
}

/* ========================================
   Admin Pagination + generic .pill
   ======================================== */

.admin-pagination {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 4px;
  margin-top: 1.25rem;
  padding-top: 0.75rem;
  border-top: 1px solid var(--color-border, rgba(255,255,255,0.06));
}

/* When pagination follows the 2-col assistant/list grid, align it with the
   list column (right). Left column is minmax(220px, 280px) + 0.75rem gap. */
.admin-with-assistant + .admin-pagination {
  margin-left: calc(280px + 0.75rem);
}
@media (max-width: 900px) {
  /* Grid collapses to single column — drop the offset */
  .admin-with-assistant + .admin-pagination {
    margin-left: 0;
  }
}

.pill {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 30px;
  height: 28px;
  padding: 0 0.55rem;
  background: rgba(255,255,255,0.03);
  border: 1px solid var(--color-border, rgba(255,255,255,0.1));
  border-radius: 4px;
  color: var(--color-text-secondary, #cbd5e1);
  font-family: ui-monospace, monospace;
  font-size: 0.75rem;
  cursor: pointer;
  transition: background 0.12s ease, border-color 0.12s ease, color 0.12s ease;
}
.pill:hover {
  background: rgba(59,130,246,0.08);
  border-color: rgba(59,130,246,0.3);
  color: var(--color-text-primary, #e2e8f0);
}
.pill.active {
  background: rgba(59,130,246,0.18);
  border-color: rgba(59,130,246,0.5);
  color: #93c5fd;
  font-weight: 600;
  cursor: default;
}
.pill-nav { font-size: 1rem; line-height: 1; }
.pill-disabled {
  opacity: 0.35;
  cursor: not-allowed;
  pointer-events: none;
}
.pill-sep {
  display: inline-flex;
  align-items: center;
  min-width: 24px;
  color: var(--color-text-muted, #64748b);
  font-family: ui-monospace, monospace;
  font-size: 0.9rem;
}
.pill-info {
  margin-left: auto;
  font-size: 0.72rem;
  color: var(--color-text-muted, #94a3b8);
  font-family: ui-monospace, monospace;
}

/* ========================================
   Avatar Dropdown Menu
   ======================================== */

#nav-user-dropdown { position: relative; }

.user-dropdown-menu {
  position: absolute;
  top: calc(100% + 6px);
  right: 0;
  min-width: 180px;
  background: var(--color-bg-raised, #0f172a);
  border: 1px solid var(--color-border, rgba(255,255,255,0.1));
  border-radius: 6px;
  box-shadow: 0 8px 24px rgba(0,0,0,0.35);
  padding: 4px;
  display: none;
  z-index: 1000;
}
.user-dropdown-menu.open { display: block; }

.user-dropdown-menu a,
.user-dropdown-menu .user-dropdown-item {
  display: flex;
  align-items: center;
  gap: 8px;
  width: 100%;
  padding: 8px 12px;
  font-size: 0.85rem;
  color: var(--color-text-secondary, #cbd5e1);
  background: transparent;
  border: none;
  border-radius: 4px;
  cursor: pointer;
  text-align: left;
  text-decoration: none;
  font-family: inherit;
}
.user-dropdown-menu a:hover,
.user-dropdown-menu .user-dropdown-item:hover {
  background: rgba(59,130,246,0.12);
  color: var(--color-text-primary, #e2e8f0);
}
.user-dropdown-menu a i,
.user-dropdown-menu .user-dropdown-item i {
  width: 16px;
  text-align: center;
  color: var(--color-text-muted, #94a3b8);
}

/* ========================================
   Bug Report Modal
   ======================================== */

.bug-modal-backdrop {
  position: fixed;
  inset: 0;
  background: rgba(0,0,0,0.55);
  display: none;
  align-items: flex-start;
  justify-content: center;
  padding: 48px 16px;
  z-index: 1100;
}
.bug-modal-backdrop.open { display: flex; }

.bug-modal {
  width: 100%;
  max-width: 520px;
  background: var(--color-bg-raised, #0f172a);
  border: 1px solid var(--color-border, rgba(255,255,255,0.1));
  border-radius: 8px;
  box-shadow: 0 20px 50px rgba(0,0,0,0.5);
  overflow: hidden;
}

.bug-modal-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 14px 18px;
  border-bottom: 1px solid var(--color-border, rgba(255,255,255,0.08));
}
.bug-modal-header h2 {
  margin: 0;
  font-family: var(--font-family-display, inherit);
  font-size: 1.05rem;
  font-weight: 600;
  color: var(--color-text-primary, #e2e8f0);
  display: flex;
  align-items: center;
  gap: 8px;
}
.bug-modal-header h2 i { color: #f59e0b; }
.bug-modal-close {
  background: none;
  border: none;
  color: var(--color-text-muted, #94a3b8);
  font-size: 1.5rem;
  line-height: 1;
  cursor: pointer;
  padding: 0 4px;
}
.bug-modal-close:hover { color: var(--color-text-primary, #e2e8f0); }

.bug-modal-body {
  padding: 16px 18px 18px;
  display: flex;
  flex-direction: column;
  gap: 12px;
}

.bug-modal-body .form-field {
  display: flex;
  flex-direction: column;
  gap: 4px;
  font-size: 0.8rem;
  color: var(--color-text-secondary, #cbd5e1);
}
.bug-modal-body .form-field > span { font-weight: 500; }
.bug-modal-body input,
.bug-modal-body textarea,
.bug-modal-body select {
  padding: 8px 10px;
  background: rgba(255,255,255,0.02);
  border: 1px solid var(--color-border, rgba(255,255,255,0.1));
  border-radius: 4px;
  color: var(--color-text-primary, #e2e8f0);
  font-size: 0.88rem;
  font-family: inherit;
}
.bug-modal-body textarea { resize: vertical; min-height: 90px; }
.bug-modal-body input:focus,
.bug-modal-body textarea:focus,
.bug-modal-body select:focus {
  outline: none;
  border-color: rgba(59,130,246,0.5);
  background: rgba(59,130,246,0.05);
}

.bug-modal-result {
  min-height: 1.2em;
  font-size: 0.8rem;
}
.bug-modal-result .code-comment { margin: 0; }

.bug-modal-actions {
  display: flex;
  justify-content: flex-end;
  gap: 8px;
  margin-top: 4px;
}
.bug-modal-actions button {
  padding: 8px 16px;
  font-size: 0.85rem;
  font-family: inherit;
  border-radius: 4px;
  cursor: pointer;
  border: 1px solid transparent;
}
.bug-modal-actions .btn-secondary {
  background: transparent;
  border-color: var(--color-border, rgba(255,255,255,0.12));
  color: var(--color-text-secondary, #cbd5e1);
}
.bug-modal-actions .btn-secondary:hover {
  background: rgba(255,255,255,0.04);
  color: var(--color-text-primary, #e2e8f0);
}
.bug-modal-actions .btn-primary {
  background: var(--color-primary, #2563eb);
  color: white;
  font-weight: 500;
}
.bug-modal-actions .btn-primary:hover { background: #1d4ed8; }

/* =============================================================
   Home-page ops dashboard (Phase 1 scaffold)
   Components for #home-sse-root wrapper and nested tiles.
   ============================================================= */

/* LIVE pill in hero eyebrow */
.live-pill {
  display: inline-flex;
  align-items: center;
  gap: var(--spacing-1);
  padding: 2px var(--spacing-2);
  border-radius: var(--radius-full);
  background: rgba(var(--color-status-error), 0.12);
  color: rgb(var(--color-status-error));
  letter-spacing: 0.14em;
  font-weight: var(--font-weight-bold);
}
.live-pill .dot {
  width: 8px; height: 8px;
  border-radius: 50%;
  background: rgb(var(--color-status-error));
  box-shadow: 0 0 0 0 rgba(var(--color-status-error), 0.7);
  animation: live-pill-pulse 1.4s cubic-bezier(0.66, 0, 0, 1) infinite;
}
@keyframes live-pill-pulse {
  0%   { box-shadow: 0 0 0 0 rgba(var(--color-status-error), 0.7); transform: scale(1); }
  70%  { box-shadow: 0 0 0 10px rgba(var(--color-status-error), 0);   transform: scale(1.15); }
  100% { box-shadow: 0 0 0 0 rgba(var(--color-status-error), 0);      transform: scale(1); }
}
.eyebrow-sep {
  opacity: 0.35;
  margin: 0 var(--spacing-1);
}

/* Stats-row variants */
.stats-row-3 { grid-template-columns: repeat(3, 1fr); }
.stats-row-6 { grid-template-columns: repeat(6, 1fr); }
@media (max-width: 900px) {
  .stats-row-3 { grid-template-columns: repeat(1, 1fr); }
  .stats-row-6 { grid-template-columns: repeat(2, 1fr); }
}

/* Stat tile — severity-coded card variant of .stat-item. Recipe lifted
   from .ops-card (3px stripe via ::before + hover lift + glow). */
.stat-tile {
  position: relative;
  padding: var(--spacing-5);
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-lg);
  overflow: hidden;
  transition: all var(--transition-base);
  display: flex;
  flex-direction: column;
  gap: var(--spacing-2);
  min-height: 120px;
  text-align: left;
}
.stat-tile::before {
  content: '';
  position: absolute;
  top: 0; left: 0;
  width: 3px; height: 100%;
  background: var(--tile-accent, rgb(var(--color-primary)));
  opacity: 0.35;
  transition: opacity var(--transition-fast);
}
.stat-tile:hover {
  transform: translateY(-2px);
  border-color: var(--color-border-light);
  box-shadow: 0 8px 24px rgba(0,0,0,0.25);
}
.stat-tile:hover::before { opacity: 1; }
.stat-tile[data-severity="critical"] { --tile-accent: rgb(var(--color-status-error)); }
.stat-tile[data-severity="warning"]  { --tile-accent: rgb(var(--color-status-warning));  }
.stat-tile[data-severity="safe"]     { --tile-accent: rgb(var(--color-status-success));     }
.stat-tile .stat-value {
  font-size: var(--font-size-2xl);
  line-height: 1;
  text-align: left;
}
.stat-tile .stat-label {
  text-align: left;
  margin-top: 0;
}
.stat-tile-source {
  margin-top: auto;
  font-size: 0.65rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--color-text-muted);
}

/* Severity sub-bar under Open-Now tiles */
.sev-bar {
  display: flex;
  height: 4px;
  border-radius: 2px;
  overflow: hidden;
  background: var(--color-border);
}
.sev-bar > * { display: block; height: 100%; }
.sev-bar .sev-red   { background: rgb(var(--color-status-error)); }
.sev-bar .sev-amber { background: rgb(var(--color-status-warning));  }
.sev-bar .sev-green { background: rgb(var(--color-status-success));     }

/* Sparkline slot */
.spark-line {
  display: inline-block;
  width: 72px;
  height: 20px;
}
.spark-line svg { width: 100%; height: 100%; display: block; }
.spark-line polyline {
  fill: none;
  stroke: rgb(var(--color-primary-light));
  stroke-width: 1.5;
}

/* Live-ticker strip */
.live-ticker {
  background: var(--color-surface);
  border-top: 1px solid var(--color-border);
  border-bottom: 1px solid var(--color-border);
  border-left: 3px solid rgb(var(--color-status-info));
  padding: var(--spacing-3) 0;
  overflow: hidden;
}
#ticker-track {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: var(--spacing-2);
  max-height: 120px;
  overflow-y: auto;
}
.ticker-row {
  display: flex;
  align-items: center;
  gap: var(--spacing-3);
  font-size: var(--font-size-sm);
  animation: slideIn 0.4s ease;
}
.ticker-row time {
  color: var(--color-text-muted);
  min-width: 64px;
  font-variant-numeric: tabular-nums;
}
.ticker-row code {
  font-family: var(--font-family-mono);
  font-size: 0.8em;
  color: var(--color-text-secondary);
}
.ticker-row .sev-pill {
  padding: 2px 8px;
  border-radius: var(--radius-full);
  font-size: 0.65rem;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  font-weight: var(--font-weight-bold);
}
.ticker-row .sev-pill.level-RED   { background: rgba(var(--color-status-error), 0.15); color: rgb(var(--color-status-error)); }
.ticker-row .sev-pill.level-AMBER { background: rgba(var(--color-status-warning),  0.15); color: rgb(var(--color-status-warning));  }
.ticker-row .sev-pill.level-GREEN { background: rgba(var(--color-status-success),     0.15); color: rgb(var(--color-status-success));     }
.ticker-skeleton { opacity: 0.45; }

/* Mini-map preview — gradient placeholder until a real basemap asset is
   dropped in. Edge mask keeps pins fading out at the horizontal borders. */
.hero-map-preview {
  display: block;
  position: relative;
  height: 320px;
  border-radius: var(--radius-lg);
  overflow: hidden;
  background:
    radial-gradient(ellipse at 70% 40%, rgba(var(--color-primary), 0.25), transparent 55%),
    radial-gradient(ellipse at 20% 70%, rgba(var(--color-status-warning), 0.18), transparent 50%),
    linear-gradient(135deg, #0a1628, #152036);
  border: 1px solid var(--color-border);
  -webkit-mask-image: linear-gradient(to right, transparent 0, #000 5%, #000 95%, transparent 100%);
          mask-image: linear-gradient(to right, transparent 0, #000 5%, #000 95%, transparent 100%);
  text-decoration: none;
  color: inherit;
  transition: transform var(--transition-base);
}
.hero-map-preview:hover { transform: scale(1.01); }
.home-map-pin-layer {
  position: absolute;
  inset: 0;
  pointer-events: none;
}
.hero-map-label {
  position: absolute;
  bottom: var(--spacing-3);
  right: var(--spacing-4);
  font-size: var(--font-size-sm);
  color: var(--color-text-secondary);
  background: rgba(0,0,0,0.4);
  padding: 2px var(--spacing-2);
  border-radius: var(--radius-full);
}

/* Home-page pins — HTML (not SVG) so hx-swap-oob works. Pulse speed
   varies by severity, reusing the existing incident-pin-pulse-keyframes. */
.home-pin {
  position: absolute;
  width: 10px; height: 10px;
  margin-left: -5px; margin-top: -5px;
  border-radius: 50%;
  background: rgb(var(--color-status-error));
  color: rgb(var(--color-status-error));
  box-shadow: 0 0 0 2px rgba(0,0,0,0.35);
}
.home-pin::after {
  content: '';
  position: absolute;
  inset: -4px;
  border-radius: 50%;
  background: currentColor;
  opacity: 0.55;
  animation: incident-pin-pulse-keyframes 1.1s ease-out infinite;
}
.home-pin.level-RED   { background: rgb(var(--color-status-error)); color: rgb(var(--color-status-error)); }
.home-pin.level-AMBER { background: rgb(var(--color-status-warning));  color: rgb(var(--color-status-warning));  }
.home-pin.level-GREEN { background: rgb(var(--color-status-success));     color: rgb(var(--color-status-success));     }
.home-pin.level-AMBER::after { animation-duration: 1.6s; }
.home-pin.level-GREEN::after { animation-duration: 2.4s; }

/* ========================================
   Impersonation banner (JOB-AUS1-0001U3)
   Shown when an admin is impersonating another user. Visibility is gated by
   body.impersonating, set server-side by auth.state (Phase 3). Injected once
   as global chrome by main.js initImpersonationBanner().
   ======================================== */
.impersonation-banner { display: none; }
body.impersonating .impersonation-banner {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 0.75rem;
  position: fixed;
  top: 0; left: 0; right: 0;
  z-index: 2000;
  padding: 0.4rem 1rem;
  background: rgb(var(--color-status-warning));
  color: #1a1205;
  font-size: 0.85rem;
  font-weight: 600;
  box-shadow: 0 1px 6px rgba(0, 0, 0, 0.3);
}
body.impersonating .impersonation-banner .imp-stop {
  padding: 0.2rem 0.7rem;
  background: rgba(0, 0, 0, 0.18);
  border: 1px solid rgba(0, 0, 0, 0.28);
  border-radius: 4px;
  color: #1a1205;
  font-weight: 600;
  cursor: pointer;
}
body.impersonating .impersonation-banner .imp-stop:hover { background: rgba(0, 0, 0, 0.28); }
/* Push page content + the fixed status-bar/nav below the banner while
   impersonating. Without offsetting the fixed nav (top:3px) and status-bar
   (top:0), the banner (z-index 2000) overlays the menu bar and swallows its
   clicks — body padding alone moves flow content but not fixed elements. */
body.impersonating { padding-top: 2.1rem; }
body.impersonating .status-bar { top: 2.1rem; }
body.impersonating .nav { top: calc(2.1rem + 3px); }

/* ----------------------------------------------------------------------
   Views selector (configurable-list-views C4w).
   The toolbar "Views" button (server-rendered in list/toolbar.hbs) opens the
   #list-view-selector canvas column, which mirrors #list-col-editor's width and
   collapses via its .col-state sentinel like the other canvas columns. The
   server fills the body with templates/list/view_selector.hbs — a picklist of
   the user's show_in_selector saved views (pick → incident.list, pin →
   user.set_active_view).
   ------------------------------------------------------------------- */
.list-views-btn {
  display: inline-flex;
  align-items: center;
  gap: var(--spacing-1, 4px);
  height: 32px;
  padding: 0 var(--spacing-2, 8px);
  margin-left: var(--spacing-2, 8px);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  background: var(--color-surface);
  color: var(--color-text-secondary);
  cursor: pointer;
  font-size: var(--font-size-sm);
}
.list-views-btn:hover {
  background: var(--color-surface-hover);
  color: var(--color-text);
}

#list-view-selector {
  flex: 0 0 300px;
}
.list-view-selector__list {
  list-style: none;
  margin: 0;
  padding: var(--spacing-2, 8px);
  display: flex;
  flex-direction: column;
  gap: var(--spacing-1, 4px);
}
.list-view-selector__item {
  display: flex;
  align-items: stretch;
  gap: var(--spacing-1, 4px);
}
.list-view-selector__pick {
  flex: 1 1 auto;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--spacing-2, 8px);
  padding: var(--spacing-2, 8px);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  background: var(--color-surface);
  color: var(--color-text);
  cursor: pointer;
  text-align: left;
  font-size: var(--font-size-sm);
}
.list-view-selector__pick:hover {
  background: var(--color-surface-hover);
}
.list-view-selector__item.is-active .list-view-selector__pick {
  border-color: var(--color-status-info);
}
.list-view-selector__badge {
  font-size: var(--font-size-xs, 0.7rem);
  color: var(--color-status-info);
  text-transform: uppercase;
  letter-spacing: 0.03em;
}
.list-view-selector__default {
  flex: 0 0 auto;
  width: 32px;
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  background: var(--color-surface);
  color: var(--color-text-muted);
  cursor: pointer;
}
.list-view-selector__default:hover {
  background: var(--color-surface-hover);
  color: var(--color-text);
}
.list-view-selector__item.is-active .list-view-selector__default {
  color: var(--color-status-info);
}
.list-view-selector__empty {
  padding: var(--spacing-3, 12px);
  color: var(--color-text-muted);
  font-size: var(--font-size-sm);
}
/* Per-view reorder arrows — move a view up/down within its band. Mirrors
   __default; disabled at a band edge (can_up / can_down false). */
.list-view-selector__move {
  flex: 0 0 auto;
  width: 26px;
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  background: var(--color-surface);
  color: var(--color-text-muted);
  cursor: pointer;
}
.list-view-selector__move:hover:not(:disabled) {
  background: var(--color-surface-hover);
  color: var(--color-text);
}
.list-view-selector__move:disabled {
  opacity: 0.35;
  cursor: default;
}
/* Per-view Edit affordance — own (user-scope) views only. Mirrors __default. */
.list-view-selector__edit {
  flex: 0 0 auto;
  width: 32px;
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  background: var(--color-surface);
  color: var(--color-text-muted);
  cursor: pointer;
}
.list-view-selector__edit:hover {
  background: var(--color-surface-hover);
  color: var(--color-text);
}
/* Active default gets a filled highlighted star. */
.list-view-selector__default.is-default {
  color: var(--color-status-info);
}
/* Per-view Delete affordance — own views only. Mirrors __edit; danger on hover. */
.list-view-selector__delete {
  flex: 0 0 auto;
  width: 32px;
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  background: var(--color-surface);
  color: var(--color-text-muted);
  cursor: pointer;
}
.list-view-selector__delete:hover {
  background: var(--color-status-danger, #e5484d);
  border-color: var(--color-status-danger, #e5484d);
  color: #fff;
}
/* Create-a-view entry (replaces the removed toolbar cog). */
.list-view-selector__new {
  display: inline-flex;
  align-items: center;
  gap: var(--spacing-1, 4px);
  margin: var(--spacing-3, 12px);
  border: 1px dashed var(--color-border);
  border-radius: var(--radius-md);
  background: none;
  color: var(--color-text-secondary);
  padding: var(--spacing-2, 8px) var(--spacing-3, 12px);
  font-size: var(--font-size-sm);
  cursor: pointer;
}
.list-view-selector__new:hover {
  background: var(--color-surface-hover);
  color: var(--color-text);
}

/* Condition builder in the cog pane (configurable-list-views WS3): field/op/value
   rows the user adds. `head` (name + flags) sits up top so "Show as button" is
   always visible; `section` groups conditions + columns. */
.list-view-editor__head {
  display: flex;
  flex-direction: column;
  gap: var(--spacing-2, 8px);
  padding-bottom: var(--spacing-2, 8px);
  border-bottom: 1px solid var(--color-border-light);
}
.list-view-editor__flags {
  display: flex;
  flex-direction: column;
  gap: var(--spacing-1, 4px);
  font-size: var(--font-size-sm);
  color: var(--color-text-secondary);
}
.list-view-editor__flags label {
  display: inline-flex;
  align-items: center;
  gap: var(--spacing-2, 8px);
  cursor: pointer;
}
.list-view-editor__section {
  display: flex;
  flex-direction: column;
  gap: var(--spacing-2, 8px);
}
.list-view-editor__section-label {
  font-size: var(--font-size-xs, 0.7rem);
  text-transform: uppercase;
  letter-spacing: 0.03em;
  color: var(--color-text-muted);
}
.list-view-editor__conditions {
  display: flex;
  flex-direction: column;
  gap: var(--spacing-2, 8px);
}
.condition-row {
  display: flex;
  align-items: center;
  gap: var(--spacing-1, 4px);
}
.condition-row .condition-field {
  flex: 1 1 30%;
  min-width: 0;
}
.condition-row .condition-op {
  flex: 0 0 auto;
  width: 56px;
}
.condition-row .condition-value {
  flex: 1 1 40%;
  min-width: 0;
}
.condition-row select,
.condition-row input {
  font-size: var(--font-size-sm);
  padding: var(--spacing-1, 4px) var(--spacing-2, 8px);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  background: var(--color-surface);
  color: var(--color-text);
}
.condition-remove {
  flex: 0 0 auto;
  width: 28px;
  height: 28px;
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  background: var(--color-surface);
  color: var(--color-text-muted);
  cursor: pointer;
  line-height: 1;
}
.condition-remove:hover {
  background: var(--color-status-danger, #e5484d);
  color: #fff;
}
.list-view-editor__add-condition {
  align-self: flex-start;
  border: 1px dashed var(--color-border);
  border-radius: var(--radius-md);
  background: none;
  color: var(--color-text-secondary);
  padding: var(--spacing-1, 4px) var(--spacing-2, 8px);
  font-size: var(--font-size-sm);
  cursor: pointer;
}
.list-view-editor__add-condition:hover {
  background: var(--color-surface-hover);
  color: var(--color-text);
}
/* Per-column sort (None/Asc/Desc) in the column chooser row. */
.col-sort {
  flex: 0 0 auto;
  margin-left: auto;
  font-size: var(--font-size-xs, 0.7rem);
  padding: 2px var(--spacing-1, 4px);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-sm);
  background: var(--color-surface);
  color: var(--color-text);
}
