/* ============================================================================
   SulyEye Operations - console shell and data components
   ----------------------------------------------------------------------------
   Built on the same token layer as the public site (tokens.css). Nothing here
   introduces a new colour; everything resolves to --brand / --surface / --line
   so the console follows the theme and the language direction for free.

   As in the rest of the system: no `left`, no `right`. The sidebar, the table
   alignment and the chat bubbles all mirror themselves when dir="rtl".
   ========================================================================== */

@layer components {

  /* ============================================== department identity ==== */

  /* Vehicle type and reporting department share these four keys, so one set of
     tokens colours the map pins, the badges and the filter chips alike. */
  :root {
    --dept-police: #2563eb;
    --dept-ambulance: #e11d48;
    --dept-fire: #f97316;
    --dept-krsa: #10b981;
  }

  :root[data-theme="dark"],
  :root:not([data-theme="light"]) {
    --dept-police: #60a5fa;
    --dept-ambulance: #fb7185;
    --dept-fire: #fdba74;
    --dept-krsa: #34d399;
  }

  [data-dept="police"]    { --dept: var(--dept-police); }
  [data-dept="ambulance"] { --dept: var(--dept-ambulance); }
  [data-dept="fire"]      { --dept: var(--dept-fire); }
  [data-dept="krsa"]      { --dept: var(--dept-krsa); }

  /* ============================================================ shell ==== */

  .app {
    display: grid;
    grid-template-columns: var(--sidebar-w, 17rem) minmax(0, 1fr);
    min-block-size: 100svh;
  }

  .app[data-collapsed="true"] { --sidebar-w: 4.5rem; }

  @media (max-width: 64rem) {
    .app { grid-template-columns: minmax(0, 1fr); }
  }

  /* ---------------------------------------------------------- sidebar --- */

  .sidebar {
    position: sticky;
    inset-block-start: 0;
    block-size: 100svh;
    display: flex;
    flex-direction: column;
    gap: var(--space-s);
    padding: var(--space-s);
    background: var(--bg-sunken);
    border-inline-end: 1px solid var(--line);
    overflow-y: auto;
    overscroll-behavior: contain;
    z-index: var(--z-sticky);
  }

  @media (max-width: 64rem) {
    .sidebar {
      position: fixed;
      inset-block: 0;
      inset-inline-start: 0;
      inline-size: min(19rem, 84vw);
      transform: translateX(calc(-105% * var(--dir, 1)));
      transition: transform var(--dur-base) var(--ease-out-quart);
      box-shadow: var(--shadow-l);
    }

    .sidebar[data-open="true"] { transform: translateX(0); }

    .sidebar-scrim {
      position: fixed;
      inset: 0;
      z-index: calc(var(--z-sticky) - 1);
      background: color-mix(in oklab, #000 45%, transparent);
      backdrop-filter: blur(2px);
      opacity: 0;
      visibility: hidden;
      transition: opacity var(--dur-base) linear, visibility 0s linear var(--dur-base);
    }

    .sidebar-scrim[data-open="true"] {
      opacity: 1;
      visibility: visible;
      transition-delay: 0s;
    }
  }

  .sidebar__brand {
    display: flex;
    align-items: center;
    gap: 0.65rem;
    padding: 0.6rem 0.5rem;
    text-decoration: none;
    color: var(--text);
    font-family: var(--font-display);
    font-weight: 700;
    font-size: 1.05rem;
    letter-spacing: -0.02em;
  }

  .sidebar__brand svg { inline-size: 1.9rem; block-size: 1.9rem; flex-shrink: 0; }

  /* A little larger than the glyph it replaced: the eagle drawing carries much
     more line detail and needs the room. */
  .sidebar__mark {
    inline-size: 2.4rem;
    block-size: 2.4rem;
    flex-shrink: 0;
    background-color: var(--brand);
    -webkit-mask: url("/img/sulyeye-mark.png") center / contain no-repeat;
            mask: url("/img/sulyeye-mark.png") center / contain no-repeat;
  }
  .sidebar__brand b { color: var(--brand); font-weight: inherit; }

  /* ==========================================================================
     Development-only test-account list on the sign-in page. Delete this block
     together with Views/Operations/_TestAccounts.cshtml.
     Deliberately styled as a warning panel rather than as part of the design, so
     nobody mistakes it for a shipped feature.
     ========================================================================== */
  .test-accounts {
    margin-block-start: var(--space-s);
    padding: var(--space-s);
    border: 1px dashed color-mix(in oklab, var(--warn, #b8860b) 55%, transparent);
    border-radius: var(--radius-s);
    background: color-mix(in oklab, var(--warn, #b8860b) 8%, transparent);
    text-align: start;
  }

  .test-accounts__head {
    display: flex;
    align-items: center;
    gap: 0.4rem;
    font-size: var(--step--2);
  }

  .test-accounts__head svg {
    inline-size: 0.95rem;
    block-size: 0.95rem;
    flex-shrink: 0;
  }

  .test-accounts__env {
    margin-inline-start: auto;
    padding: 0.05rem 0.4rem;
    border-radius: 999px;
    background: color-mix(in oklab, var(--warn, #b8860b) 22%, transparent);
    font-size: var(--step--3, 0.7rem);
    text-transform: uppercase;
    letter-spacing: 0.04em;
  }

  .test-accounts__pw,
  .test-accounts__note {
    margin-block: 0.45rem 0.35rem;
    font-size: var(--step--2);
    color: var(--text-soft, inherit);
  }

  .test-accounts__pw code {
    padding: 0.05rem 0.3rem;
    border-radius: 4px;
    background: color-mix(in oklab, var(--text) 10%, transparent);
    font-family: var(--font-mono, monospace);
  }

  /* auto-fit rather than a fixed column count: the list grows with the number of
     stations and should not force the card wider. */
  .test-accounts__grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(11rem, 1fr));
    gap: 0.3rem;
    margin-block-start: 0.35rem;
  }

  .test-accounts__btn {
    display: flex;
    flex-direction: column;
    gap: 0.05rem;
    padding: 0.35rem 0.5rem;
    border: 1px solid var(--line);
    border-radius: var(--radius-s);
    background: var(--surface-raised);
    color: var(--text);
    font: inherit;
    text-align: start;
    cursor: pointer;
    transition: border-color .15s, background-color .15s;
  }

  .test-accounts__btn:hover {
    border-color: var(--brand);
    background: color-mix(in oklab, var(--brand) 10%, transparent);
  }

  .test-accounts__user {
    font-family: var(--font-mono, monospace);
    font-size: var(--step--2);
    font-weight: 600;
  }

  .test-accounts__meta {
    font-size: var(--step--3, 0.7rem);
    color: var(--text-muted);
    overflow-wrap: anywhere;
  }

  .test-accounts__drivers {
    margin-block-start: 0.5rem;
    font-size: var(--step--2);
  }

  .test-accounts__drivers summary {
    cursor: pointer;
  }

  /* Login hero: ring and logo stacked in one grid cell so they stay concentric
     at every width, with no absolute positioning to keep in sync. */
  .login-mark {
    display: grid;
    place-items: center;
    inline-size: min(20rem, 56vw);
    margin-inline: auto;
  }

  .login-mark > * { grid-area: 1 / 1; }

  .login-mark__ring { inline-size: 100%; block-size: auto; }

  /* Inset from the ring so the drawing sits inside it rather than touching. */
  .login-mark__logo {
    inline-size: 72%;
    block-size: auto;
    filter: drop-shadow(0 8px 24px rgb(0 0 0 / 0.45));
  }

  .sidebar__scope {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    padding: 0.5rem 0.7rem;
    margin-block-end: 0.25rem;
    border-radius: var(--radius-s);
    background: color-mix(in oklab, var(--dept, var(--brand)) 12%, transparent);
    border: 1px solid color-mix(in oklab, var(--dept, var(--brand)) 30%, transparent);
    font-size: var(--step--2);
    font-weight: 700;
    color: color-mix(in oklab, var(--dept, var(--brand)) 70%, var(--text));
  }

  .sidebar__group {
    margin-block-start: var(--space-s);
    padding-inline: 0.7rem;
    font-family: var(--font-mono);
    font-size: var(--step--2);
    letter-spacing: var(--tracking-wide);
    text-transform: uppercase;
    color: var(--text-muted);
  }

  :root[dir="rtl"] .sidebar__group {
    font-family: var(--font-sans);
    text-transform: none;
    letter-spacing: 0;
    font-weight: 700;
  }

  .sidebar__nav { display: grid; gap: 2px; }

  .sidebar__link {
    display: flex;
    align-items: center;
    gap: 0.7rem;
    padding: 0.62rem 0.7rem;
    border-radius: var(--radius-s);
    text-decoration: none;
    color: var(--text-soft);
    font-size: var(--step--1);
    font-weight: 600;
    position: relative;
    transition: background-color var(--dur-fast) var(--ease-out-soft),
                color var(--dur-fast) var(--ease-out-soft);
  }

  .sidebar__link svg {
    inline-size: 1.15rem;
    block-size: 1.15rem;
    flex-shrink: 0;
    opacity: 0.85;
  }

  .sidebar__link:hover {
    background: color-mix(in oklab, var(--brand) 8%, transparent);
    color: var(--text);
  }

  .sidebar__link[aria-current="page"] {
    background: color-mix(in oklab, var(--brand) 14%, transparent);
    color: var(--brand);
  }

  /* A lit rail on the leading edge marks the active section. */
  .sidebar__link[aria-current="page"]::before {
    content: "";
    position: absolute;
    inset-inline-start: 0;
    inset-block: 20%;
    inline-size: 3px;
    border-radius: var(--radius-pill);
    background: var(--brand);
  }

  .sidebar__count {
    margin-inline-start: auto;
    min-inline-size: 1.5rem;
    padding: 0.1rem 0.4rem;
    border-radius: var(--radius-pill);
    background: var(--accent);
    color: #fff;
    font-family: var(--font-mono);
    font-size: 0.68rem;
    font-weight: 700;
    text-align: center;
  }

  .sidebar__foot {
    margin-block-start: auto;
    padding-block-start: var(--space-s);
    border-block-start: 1px solid var(--line);
    display: grid;
    gap: 0.5rem;
  }

  .sidebar__user {
    display: flex;
    align-items: center;
    gap: 0.6rem;
    padding: 0.5rem;
    border-radius: var(--radius-s);
    font-size: var(--step--2);
  }

  .sidebar__user .avatar { inline-size: 2.1rem; block-size: 2.1rem; }
  .sidebar__user strong { display: block; font-size: var(--step--1); }
  .sidebar__user span { color: var(--text-muted); }

  /* ----------------------------------------------------------- topbar --- */

  .topbar {
    position: sticky;
    inset-block-start: 0;
    z-index: calc(var(--z-sticky) - 2);
    display: flex;
    align-items: center;
    gap: var(--space-s);
    padding: 0.75rem var(--space-m);
    background: var(--glass);
    backdrop-filter: blur(14px) saturate(150%);
    border-block-end: 1px solid var(--line);
  }

  .topbar__title {
    font-family: var(--font-display);
    font-size: var(--step-1);
    font-weight: 600;
    line-height: 1.2;
  }

  .topbar__tools {
    margin-inline-start: auto;
    display: flex;
    align-items: center;
    gap: 0.4rem;
  }

  .sidebar-toggle { display: none; }
  @media (max-width: 64rem) { .sidebar-toggle { display: grid; } }

  .console-main { min-inline-size: 0; display: flex; flex-direction: column; }

  .console-body {
    padding: var(--space-m);
    display: grid;
    gap: var(--space-m);
    align-content: start;
  }

  @media (min-width: 90rem) {
    .console-body { padding: var(--space-l) var(--space-xl); }
  }

  /* ============================================================ panel ==== */

  .panel {
    background: var(--surface);
    border: 1px solid var(--line);
    border-radius: var(--radius-l);
    box-shadow: var(--shadow-s);
    overflow: hidden;
  }

  .panel__head {
    display: flex;
    align-items: center;
    gap: var(--space-s);
    flex-wrap: wrap;
    padding: var(--space-s) var(--space-m);
    border-block-end: 1px solid var(--line);
  }

  .panel__title {
    font-family: var(--font-display);
    font-size: var(--step-1);
    font-weight: 600;
  }

  .panel__tools { margin-inline-start: auto; display: flex; gap: 0.4rem; align-items: center; }

  .panel__body { padding: var(--space-m); }
  .panel__body--flush { padding: 0; }

  /* ============================================================ stats ==== */

  /* auto-fit, not auto-fill: a department operator sees four tiles rather than
     six, and the empty tracks collapse so their row still fills the width. The
     min is tuned so all six fit on one row beside the sidebar. */
  .stat-grid {
    display: grid;
    gap: var(--space-s);
    grid-template-columns: repeat(auto-fit, minmax(min(9rem, 100%), 1fr));
  }

  .stat {
    position: relative;
    padding: var(--space-m);
    border-radius: var(--radius-l);
    border: 1px solid var(--line);
    background: var(--surface);
    display: grid;
    gap: 0.3rem;
    overflow: hidden;
    transition: transform var(--dur-base) var(--ease-out-quart),
                box-shadow var(--dur-base) var(--ease-out-quart);
  }

  .stat:hover { transform: translateY(-2px); box-shadow: var(--shadow-m); }

  /* A soft wash of the stat's own accent, so a row of tiles reads as a set
     rather than four identical boxes. */
  .stat::after {
    content: "";
    position: absolute;
    inset-block-start: -60%;
    inset-inline-end: -20%;
    inline-size: 10rem;
    block-size: 10rem;
    border-radius: 50%;
    background: radial-gradient(circle, color-mix(in oklab, var(--tone, var(--brand)) 22%, transparent), transparent 68%);
    pointer-events: none;
  }

  .stat[data-tone="accent"] { --tone: var(--accent); }
  .stat[data-tone="lumen"]  { --tone: var(--lumen); }
  .stat[data-tone="muted"]  { --tone: var(--text-muted); }

  .stat__label {
    font-size: var(--step--2);
    color: var(--text-muted);
    font-weight: 600;
    /* Clears the absolutely-positioned icon, which the label would otherwise
       run underneath once the tiles get narrow. */
    padding-inline-end: 1.9rem;
  }

  .stat__value {
    font-family: var(--font-display);
    font-size: var(--step-4);
    line-height: 1;
    letter-spacing: -0.03em;
    font-variant-numeric: tabular-nums;
  }

  .stat__note { font-size: var(--step--2); color: var(--text-muted); }

  .stat__icon {
    position: absolute;
    inset-block-start: var(--space-m);
    inset-inline-end: var(--space-m);
    inline-size: 1.4rem;
    block-size: 1.4rem;
    color: color-mix(in oklab, var(--tone, var(--brand)) 70%, var(--text-muted));
  }

  /* ============================================================ table ==== */

  .table-wrap {
    overflow-x: auto;
    overscroll-behavior-inline: contain;
  }

  .table {
    inline-size: 100%;
    border-collapse: collapse;
    font-size: var(--step--1);
  }

  .table th,
  .table td {
    padding: 0.7rem var(--space-s);
    text-align: start;
    vertical-align: middle;
    white-space: nowrap;
  }

  .table th {
    position: sticky;
    inset-block-start: 0;
    z-index: 1;
    background: var(--surface-2);
    font-size: var(--step--2);
    font-weight: 700;
    letter-spacing: 0.03em;
    color: var(--text-muted);
    border-block-end: 1px solid var(--line);
  }

  .table tbody tr {
    border-block-end: 1px solid var(--line-faint);
    transition: background-color var(--dur-fast) linear;
  }

  .table tbody tr:hover { background: color-mix(in oklab, var(--brand) 5%, transparent); }
  .table tbody tr:last-child { border-block-end: 0; }

  .table td.wrap { white-space: normal; min-inline-size: 18rem; }
  .table td.num { font-variant-numeric: tabular-nums; }

  .table a { color: var(--brand); text-decoration: none; font-weight: 600; }
  .table a:hover { text-decoration: underline; }

  /* ============================================================ badge ==== */

  .badge {
    display: inline-flex;
    align-items: center;
    gap: 0.35em;
    padding: 0.18em 0.6em;
    border-radius: var(--radius-pill);
    font-size: var(--step--2);
    font-weight: 700;
    line-height: 1.6;
    white-space: nowrap;
    background: color-mix(in oklab, var(--text-muted) 16%, transparent);
    color: var(--text-soft);
  }

  .badge--brand  { background: color-mix(in oklab, var(--brand) 16%, transparent);  color: var(--brand); }
  .badge--ok     { background: color-mix(in oklab, var(--dept-krsa) 18%, transparent); color: color-mix(in oklab, var(--dept-krsa) 75%, var(--text)); }
  .badge--warn   { background: color-mix(in oklab, var(--accent) 18%, transparent); color: var(--accent); }
  .badge--danger { background: color-mix(in oklab, var(--dept-ambulance) 20%, transparent); color: color-mix(in oklab, var(--dept-ambulance) 78%, var(--text)); }

  /* Department badge takes its colour from the [data-dept] on the same element. */
  .badge--dept {
    background: color-mix(in oklab, var(--dept, var(--brand)) 16%, transparent);
    color: color-mix(in oklab, var(--dept, var(--brand)) 72%, var(--text));
  }

  .dot {
    inline-size: 0.5rem;
    block-size: 0.5rem;
    border-radius: 50%;
    background: currentColor;
    flex-shrink: 0;
  }

  .dot--live {
    background: var(--dept-krsa);
    box-shadow: 0 0 0 0 color-mix(in oklab, var(--dept-krsa) 60%, transparent);
    animation: dot-ping 2s var(--ease-in-out-soft) infinite;
  }

  @keyframes dot-ping {
    0%, 100% { box-shadow: 0 0 0 0 color-mix(in oklab, var(--dept-krsa) 55%, transparent); }
    60%      { box-shadow: 0 0 0 7px transparent; }
  }

  /* =========================================================== filters === */

  .filters {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-2xs);
    align-items: end;
  }

  .filters .field { gap: 0.3rem; }
  .filters .field__control { padding: 0.55rem 0.75rem; }
  .filters .field__label { font-size: 0.68rem; }

  .chip-toggle {
    display: inline-flex;
    align-items: center;
    gap: 0.45rem;
    padding: 0.42rem 0.8rem;
    border-radius: var(--radius-pill);
    border: 1px solid var(--line);
    background: var(--surface);
    font-size: var(--step--2);
    font-weight: 600;
    cursor: pointer;
    user-select: none;
    transition: opacity var(--dur-fast) linear, border-color var(--dur-fast) linear;
  }

  .chip-toggle input { position: absolute; opacity: 0; pointer-events: none; }
  .chip-toggle .dot { background: var(--dept, var(--brand)); }
  .chip-toggle[data-off="true"] { opacity: 0.42; }
  .chip-toggle:hover { border-color: var(--line-strong); }

  /* ======================================================== empty state == */

  .empty {
    padding: var(--space-xl) var(--space-m);
    text-align: center;
    color: var(--text-muted);
    display: grid;
    gap: 0.5rem;
    justify-items: center;
  }

  .empty svg { inline-size: 2rem; block-size: 2rem; opacity: 0.5; }

  /* ======================================================== pagination === */

  .pager {
    display: flex;
    gap: 0.3rem;
    align-items: center;
    justify-content: center;
    padding: var(--space-s);
    flex-wrap: wrap;
  }

  .pager a,
  .pager span {
    min-inline-size: 2.2rem;
    padding: 0.35rem 0.6rem;
    border-radius: var(--radius-s);
    border: 1px solid var(--line);
    text-align: center;
    text-decoration: none;
    font-size: var(--step--2);
    font-weight: 600;
    color: var(--text-soft);
    font-variant-numeric: tabular-nums;
  }

  .pager a:hover { border-color: var(--brand); color: var(--brand); }
  .pager [aria-current="page"] { background: var(--brand); border-color: var(--brand); color: var(--text-on-brand); }
  .pager .is-disabled { opacity: 0.4; pointer-events: none; }

  /* ====================================================== key / value ==== */

  .kv {
    display: grid;
    grid-template-columns: minmax(8rem, auto) minmax(0, 1fr);
    gap: 0.5rem var(--space-m);
    margin: 0;
    font-size: var(--step--1);
  }

  .kv dt { color: var(--text-muted); font-size: var(--step--2); }
  .kv dd { margin: 0; font-weight: 600; overflow-wrap: anywhere; }

  @media (max-width: 34rem) {
    .kv { grid-template-columns: 1fr; gap: 0.15rem; }
    .kv dd { margin-block-end: 0.6rem; }
  }

  /* ============================================================= chat ==== */

  .chat {
    display: flex;
    flex-direction: column;
    gap: var(--space-s);
    padding: var(--space-m);
    max-block-size: 60vh;
    overflow-y: auto;
    overscroll-behavior: contain;
    background:
      radial-gradient(circle at 1px 1px, var(--line-faint) 1px, transparent 0) 0 0 / 22px 22px;
  }

  .msg {
    max-inline-size: min(46rem, 82%);
    padding: 0.7rem 0.95rem;
    border-radius: var(--radius-m);
    font-size: var(--step--1);
    line-height: 1.55;
    box-shadow: var(--shadow-s);
    overflow-wrap: anywhere;
  }

  /* The citizen sits on the leading edge, staff on the trailing edge - which
     swaps automatically with the document direction. */
  .msg--citizen {
    align-self: flex-start;
    background: var(--surface);
    border: 1px solid var(--line);
    border-start-start-radius: var(--radius-xs);
  }

  .msg--staff {
    align-self: flex-end;
    background: color-mix(in oklab, var(--brand) 90%, var(--surface));
    color: var(--text-on-brand);
    border-start-end-radius: var(--radius-xs);
  }

  .msg__meta {
    display: flex;
    gap: 0.5rem;
    align-items: baseline;
    margin-block-end: 0.2rem;
    font-size: 0.7rem;
    opacity: 0.75;
    font-variant-numeric: tabular-nums;
  }

  .msg__meta strong { font-weight: 700; }

  .chat-compose {
    display: grid;
    grid-template-columns: minmax(0, 1fr) auto;
    gap: var(--space-2xs);
    padding: var(--space-s) var(--space-m);
    border-block-start: 1px solid var(--line);
    align-items: end;
  }

  @media (max-width: 34rem) {
    .chat-compose { grid-template-columns: 1fr; }
  }

  /* ======================================================== attachments == */

  .attach-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(9rem, 1fr));
    gap: var(--space-2xs);
  }

  .attach {
    position: relative;
    display: block;
    aspect-ratio: 4 / 3;
    border-radius: var(--radius-s);
    overflow: hidden;
    border: 1px solid var(--line);
    background: var(--surface-2);
  }

  .attach img,
  .attach video {
    inline-size: 100%;
    block-size: 100%;
    object-fit: cover;
    transition: transform var(--dur-slow) var(--ease-out-quart);
  }

  .attach:hover img { transform: scale(1.05); }

  .attach__type {
    position: absolute;
    inset-block-end: 0.35rem;
    inset-inline-start: 0.35rem;
    padding: 0.1rem 0.45rem;
    border-radius: var(--radius-pill);
    background: color-mix(in oklab, #000 60%, transparent);
    color: #fff;
    font-size: 0.65rem;
    font-weight: 700;
  }

  /* =============================================================== map === */

  .map-shell {
    inline-size: 100%;
    block-size: clamp(26rem, 70vh, 46rem);
    border-radius: var(--radius-m);
    overflow: hidden;
    border: 1px solid var(--line);
    background: var(--surface-2);
  }

  /* Leaflet paints its own white chrome; tint it to the theme instead. */
  .leaflet-container { background: var(--surface-2); font-family: var(--font-sans); }

  .leaflet-popup-content-wrapper,
  .leaflet-popup-tip {
    background: var(--surface);
    color: var(--text);
    box-shadow: var(--shadow-m);
  }

  .leaflet-popup-content-wrapper { border-radius: var(--radius-m); }
  .leaflet-popup-content { margin: 0.75rem 0.9rem; font-size: var(--step--1); }
  .leaflet-bar a { background: var(--surface); color: var(--text); border-color: var(--line); }
  .leaflet-bar a:hover { background: var(--surface-2); }

  /* Dark mode: OSM tiles are drawn for light UIs, so they are dimmed rather
     than left glowing against a petrol shell. */
  :root[data-theme="dark"] .leaflet-tile-pane,
  :root:not([data-theme="light"]) .leaflet-tile-pane {
    filter: invert(1) hue-rotate(180deg) brightness(0.86) contrast(0.92) saturate(0.7);
  }

  /* Markers are built by js/map-pins.js as inline SVG; this only positions and
     animates them. Leaflet's own .leaflet-div-icon chrome is opted out of by
     passing our own className. */
  .pin {
    background: none;
    border: 0;
    filter: drop-shadow(0 2px 4px rgb(0 0 0 / 0.35));
  }

  .pin-vehicle,
  .pin-incident { display: block; overflow: visible; }

  .pin--offline { opacity: 0.45; filter: grayscale(0.7); }

  /* The halo scales from the dot's own centre and never affects its box, so the
     dot stays a clean circle at every frame. */
  .pin-incident__halo {
    transform-origin: 13px 13px;
    animation: pin-ping 1.9s var(--ease-out-quart) infinite;
  }

  .pin--selected .pin-incident__halo { animation-duration: 1.1s; }

  @keyframes pin-ping {
    0%   { transform: scale(1);   opacity: 0.75; }
    70%  { transform: scale(2.3); opacity: 0; }
    100% { transform: scale(2.3); opacity: 0; }
  }

  @media (prefers-reduced-motion: reduce) {
    .pin-incident__halo { animation: none; opacity: 0.5; }
  }

  .side-list {
    max-block-size: clamp(26rem, 70vh, 46rem);
    overflow-y: auto;
    overscroll-behavior: contain;
  }

  .side-item {
    inline-size: 100%;
    display: grid;
    gap: 0.25rem;
    padding: 0.8rem var(--space-s);
    border: 0;
    border-block-end: 1px solid var(--line-faint);
    background: none;
    text-align: start;
    cursor: pointer;
    color: inherit;
    font: inherit;
    transition: background-color var(--dur-fast) linear;
  }

  .side-item:hover { background: color-mix(in oklab, var(--brand) 7%, transparent); }
  .side-item[aria-selected="true"] { background: color-mix(in oklab, var(--brand) 12%, transparent); }

  /* ============================================================ modal ==== */

  /* Native <dialog>: focus trapping, Esc and inertness come from the platform. */
  dialog.modal {
    /* The base reset zeroes every margin, which also removes the UA's `margin:auto`
       on <dialog> and drops the modal into the top-left corner. Put it back. */
    margin: auto;
    inline-size: min(38rem, calc(100vw - 2rem));
    max-block-size: min(85vh, 50rem);
    padding: 0;
    border: 1px solid var(--line);
    border-radius: var(--radius-l);
    background: var(--surface);
    color: var(--text);
    box-shadow: var(--shadow-l);
    overflow: visible;
  }

  dialog.modal::backdrop {
    background: color-mix(in srgb, #000 55%, transparent);
    backdrop-filter: blur(3px);
  }

  dialog.modal[open] { animation: modal-in var(--dur-base) var(--ease-out-quart); }

  @keyframes modal-in {
    from { opacity: 0; transform: translateY(10px) scale(0.98); }
  }

  .modal__head {
    display: flex;
    align-items: center;
    gap: var(--space-s);
    padding: var(--space-s) var(--space-m);
    border-block-end: 1px solid var(--line);
  }

  .modal__title { font-family: var(--font-display); font-size: var(--step-1); font-weight: 600; }
  .modal__body { padding: var(--space-m); display: grid; gap: var(--space-s); max-block-size: 60vh; overflow-y: auto; }
  .modal__foot {
    display: flex;
    gap: var(--space-2xs);
    justify-content: flex-end;
    padding: var(--space-s) var(--space-m);
    border-block-start: 1px solid var(--line);
  }

  /* ============================================================ toasts === */

  .toast-stack {
    position: fixed;
    inset-block-start: var(--space-s);
    inset-inline-end: var(--space-s);
    z-index: var(--z-overlay);
    display: grid;
    gap: 0.5rem;
    max-inline-size: min(23rem, calc(100vw - 2rem));
  }

  .toast {
    display: flex;
    align-items: center;
    gap: 0.65rem;
    padding: 0.8rem 1rem;
    border-radius: var(--radius-m);
    background: var(--surface);
    border: 1px solid var(--line);
    border-inline-start: 3px solid var(--brand);
    box-shadow: var(--shadow-l);
    color: var(--text);
    text-decoration: none;
    animation: toast-in var(--dur-base) var(--ease-spring);
  }

  .toast[data-kind="sos"] {
    border-inline-start-color: var(--dept-ambulance);
    background: color-mix(in oklab, var(--dept-ambulance) 10%, var(--surface));
  }

  .toast svg { inline-size: 1.3rem; block-size: 1.3rem; flex-shrink: 0; color: var(--brand); }
  .toast[data-kind="sos"] svg { color: var(--dept-ambulance); }
  .toast strong { display: block; font-size: var(--step--1); }
  .toast small { color: var(--text-muted); }
  .toast button { margin-inline-start: auto; background: none; border: 0; color: var(--text-muted); cursor: pointer; }

  @keyframes toast-in {
    from { opacity: 0; transform: translateY(-10px); }
  }

  /* ========================================================= call desk === */
  /* In-app calls (Views/Shared/_CallDesk.cshtml, js/call-desk.js). Bottom-centre:
     toasts own the top corner and the mute button the bottom corner, and a
     ringing call must not hide behind either. --call-tint is the calling
     department's colour, set per card from the hub payload. The go/stop pair is
     the mobile app's success and danger, so a desk and a phone agree on what
     "answer" and "hang up" look like. */

  .call-desk {
    --call-go: #22c55e;
    --call-stop: #e5342f;
    position: fixed;
    inset-block-end: var(--space-m);
    inset-inline: 0;
    margin-inline: auto;
    z-index: calc(var(--z-overlay) + 1);
    display: grid;
    gap: 0.6rem;
    inline-size: min(27rem, calc(100vw - 2rem));
  }

  /* The site has no global [hidden] rule, and the display:grid above would beat
     the browser's own one - leaving an empty card on every page. Scoped here so
     nothing else on the site changes behaviour. */
  .call-desk[hidden],
  .call-desk [hidden] { display: none !important; }

  .call-desk__incoming { display: grid; gap: 0.6rem; }

  .call-card,
  .call-desk__active {
    --call-tint: var(--brand);
    display: grid;
    gap: 0.75rem;
    padding: 1rem 1.1rem;
    border-radius: var(--radius-l);
    background: color-mix(in oklab, var(--call-tint) 9%, var(--surface-raised));
    border: 1px solid color-mix(in oklab, var(--call-tint) 38%, var(--line));
    box-shadow: var(--shadow-l), 0 0 0 4px color-mix(in oklab, var(--call-tint) 14%, transparent);
    color: var(--text);
    animation: call-in var(--dur-base) var(--ease-spring);
  }

  .call-card__head,
  .call-active__head {
    display: flex;
    align-items: center;
    gap: 0.75rem;
  }

  .call-card__icon {
    display: grid;
    place-items: center;
    flex-shrink: 0;
    inline-size: 2.75rem;
    block-size: 2.75rem;
    border-radius: 50%;
    background: var(--call-tint);
    color: #fff;
  }

  .call-card__icon svg { inline-size: 1.25rem; block-size: 1.25rem; }

  /* The ringing card's icon pulses; a live call's holds still. */
  .call-card:not(.call-card--closed) .call-card__icon { animation: call-pulse 1.4s var(--ease-out-soft) infinite; }

  .call-card__heading { display: grid; gap: 0.1rem; min-inline-size: 0; flex: 1; }
  .call-card__kicker { font-size: var(--step--2); color: var(--text-muted); font-weight: 600; }
  .call-card__name {
    font-size: var(--step-0);
    font-weight: 800;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
  }

  .call-card__elapsed {
    font-family: var(--font-mono);
    font-size: var(--step--1);
    color: var(--text-soft);
    font-variant-numeric: tabular-nums;
  }

  .call-card__meta { display: flex; flex-wrap: wrap; gap: 0.4rem 0.9rem; }

  .call-card__fact {
    display: inline-flex;
    align-items: center;
    gap: 0.35rem;
    font-size: var(--step--1);
    color: var(--text-soft);
  }

  .call-card__fact svg { inline-size: 0.95rem; block-size: 0.95rem; flex-shrink: 0; }
  .call-card__fact--link { color: var(--brand); text-decoration: none; font-weight: 600; }
  .call-card__fact--link:hover { text-decoration: underline; }
  .call-card__fact--muted { color: var(--text-muted); }

  .call-card__actions { display: flex; align-items: center; gap: 0.5rem; }

  .call-btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 0.45rem;
    min-block-size: 2.6rem;
    padding: 0 1.1rem;
    border-radius: var(--radius-pill);
    border: 1px solid transparent;
    font: inherit;
    font-weight: 700;
    cursor: pointer;
    transition: transform var(--dur-fast) var(--ease-out-soft), filter var(--dur-fast);
  }

  .call-btn svg { inline-size: 1.05rem; block-size: 1.05rem; }
  .call-btn:hover:not(:disabled) { filter: brightness(1.08); }
  .call-btn:active:not(:disabled) { transform: scale(0.97); }
  .call-btn:disabled { opacity: 0.45; cursor: not-allowed; }
  .call-btn:focus-visible { outline: 2px solid var(--brand-ring); outline-offset: 2px; }

  .call-btn--go { flex: 1; background: var(--call-go); color: #fff; }
  .call-btn--stop { flex: 1; background: var(--call-stop); color: #fff; }
  /* The receiver glyph lies down for "hang up", the convention on every phone. */
  .call-btn--stop svg { transform: rotate(135deg); }
  .call-btn--quiet { background: transparent; border-color: var(--line-strong); color: var(--text-soft); }

  .call-btn--round {
    inline-size: 2.6rem;
    padding: 0;
    background: var(--surface-2);
    border-color: var(--line);
    color: var(--text-soft);
  }

  .call-btn--round.is-on { background: var(--text); color: var(--surface); }

  .call-active__status {
    font-size: var(--step--1);
    color: var(--text-soft);
    font-variant-numeric: tabular-nums;
  }

  .call-desk__active--live .call-active__status { color: var(--call-go); font-weight: 700; }

  .call-card__note,
  .call-active__ended {
    margin: 0;
    font-size: var(--step--1);
    color: var(--text-soft);
    font-weight: 600;
  }

  .call-card--closed { opacity: 0.72; }

  .call-desk__notice {
    margin: 0;
    padding: 0.75rem 1rem;
    border-radius: var(--radius-m);
    background: color-mix(in oklab, var(--call-stop) 12%, var(--surface-raised));
    border: 1px solid color-mix(in oklab, var(--call-stop) 40%, var(--line));
    color: var(--text);
    font-size: var(--step--1);
    box-shadow: var(--shadow-m);
  }

  @keyframes call-in {
    from { opacity: 0; transform: translateY(14px) scale(0.98); }
  }

  @keyframes call-pulse {
    0%   { box-shadow: 0 0 0 0 color-mix(in oklab, var(--call-tint) 55%, transparent); }
    100% { box-shadow: 0 0 0 14px color-mix(in oklab, var(--call-tint) 0%, transparent); }
  }

  @media (prefers-reduced-motion: reduce) {
    .call-card,
    .call-desk__active,
    .call-card__icon { animation: none !important; }
  }

  /* Inline status banner (TempData). */
  .flash {
    display: flex;
    align-items: center;
    gap: 0.6rem;
    padding: 0.7rem var(--space-s);
    border-radius: var(--radius-m);
    font-size: var(--step--1);
    font-weight: 600;
    border: 1px solid color-mix(in oklab, var(--brand) 30%, transparent);
    background: color-mix(in oklab, var(--brand) 10%, transparent);
    color: var(--brand-strong);
  }

  .flash--error {
    border-color: color-mix(in oklab, var(--accent) 40%, transparent);
    background: color-mix(in oklab, var(--accent) 12%, transparent);
    color: var(--accent);
  }

  .flash svg { inline-size: 1.1rem; block-size: 1.1rem; flex-shrink: 0; }

  /* ============================================================== misc === */

  .split {
    display: grid;
    grid-template-columns: minmax(0, 2fr) minmax(0, 1fr);
    gap: var(--space-m);
    align-items: start;
  }

  @media (max-width: 72rem) {
    .split { grid-template-columns: minmax(0, 1fr); }
  }

  .portrait {
    inline-size: 100%;
    aspect-ratio: 3 / 4;
    object-fit: cover;
    border-radius: var(--radius-m);
    border: 1px solid var(--line);
    background: var(--surface-2);
  }

  .verify {
    display: inline-flex;
    align-items: center;
    gap: 0.3rem;
    font-size: var(--step--2);
    font-weight: 700;
  }

  .verify[data-ok="true"]  { color: color-mix(in oklab, var(--dept-krsa) 75%, var(--text)); }
  .verify[data-ok="false"] { color: var(--text-muted); }

  .mute-btn {
    position: fixed;
    inset-block-end: var(--space-s);
    inset-inline-end: var(--space-s);
    z-index: var(--z-overlay);
    inline-size: 2.75rem;
    block-size: 2.75rem;
    border-radius: 50%;
    border: 1px solid var(--line);
    background: var(--surface);
    color: var(--brand);
    box-shadow: var(--shadow-m);
    cursor: pointer;
    display: grid;
    place-items: center;
  }

  .mute-btn[data-muted="true"] { opacity: 0.55; color: var(--text-muted); }
  .mute-btn svg { inline-size: 1.2rem; block-size: 1.2rem; }

  /* ============================================================= login === */

  .login-shell {
    min-block-size: 100svh;
    display: grid;
    grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
    align-items: stretch;
  }

  @media (max-width: 62rem) {
    .login-shell { grid-template-columns: 1fr; }
    .login-shell__art { display: none; }
  }

  .login-shell__art {
    position: relative;
    overflow: hidden;
    display: grid;
    place-items: center;
    padding: var(--space-2xl);
    background:
      radial-gradient(90% 120% at 20% 10%, color-mix(in oklab, var(--blue-500) 85%, transparent), transparent 60%),
      linear-gradient(140deg, var(--blue-800), var(--blue-900) 55%, var(--slate-900));
    color: var(--mist-50);
  }

  .login-shell__form {
    display: grid;
    place-items: center;
    padding: var(--space-xl) var(--gutter);
  }

  .login-card { inline-size: min(24rem, 100%); display: grid; gap: var(--space-m); }
}

@layer components {

  /* ======================================================= situation board */

  /* The dashboard is a board, not a page of tables: a live map carries the
     "where", the charts carry the "how much" and "which way". */
  .board {
    display: grid;
    gap: var(--space-m);
    grid-template-columns: minmax(0, 2fr) minmax(0, 1fr);
    align-items: start;
  }

  @media (max-width: 78rem) {
    .board { grid-template-columns: minmax(0, 1fr); }
  }

  .board__map { min-block-size: 26rem; }

  .map-shell--board { block-size: clamp(22rem, 46vh, 34rem); }

  /* ------------------------------------------------------------- charts -- */

  .chart {
    inline-size: 100%;
    block-size: auto;
    display: block;
    overflow: visible;
  }

  .chart__grid line {
    stroke: var(--line-faint);
    stroke-width: 1;
  }

  .chart__axis {
    font-family: var(--font-mono);
    font-size: 11px;
    fill: var(--text-muted);
  }

  :root[dir="rtl"] .chart__axis { font-family: var(--font-sans); }

  .chart__area { fill: url(#activityFill); }

  .chart__line {
    fill: none;
    stroke: var(--brand);
    stroke-width: 2.5;
    stroke-linecap: round;
    stroke-linejoin: round;
    /* Drawn in on load: the length is set inline by the view, because only the
       server knows how long the path is. */
    stroke-dasharray: var(--len);
    stroke-dashoffset: var(--len);
    animation: chart-draw 1.4s var(--ease-out-quart) forwards;
  }

  @keyframes chart-draw { to { stroke-dashoffset: 0; } }

  .chart__point {
    fill: var(--surface);
    stroke: var(--brand);
    stroke-width: 2.5;
    opacity: 0;
    animation: chart-pop var(--dur-base) var(--ease-spring) forwards;
    animation-delay: 1.2s;
  }

  @keyframes chart-pop { to { opacity: 1; } }

  /* A hit area per column: invisible, full height, so hovering anywhere in the
     column reveals that day rather than demanding the reader hit a 3px dot. */
  .chart__hit { fill: transparent; cursor: default; }
  .chart__hit:hover + .chart__marker,
  .chart__hit:focus-visible + .chart__marker { opacity: 1; }

  .chart__marker {
    opacity: 0;
    transition: opacity var(--dur-fast) linear;
    pointer-events: none;
  }

  .chart__marker line { stroke: var(--brand); stroke-width: 1; stroke-dasharray: 3 3; }
  .chart__marker circle { fill: var(--brand); }
  .chart__marker text {
    font-family: var(--font-mono);
    font-size: 11px;
    font-weight: 700;
    fill: var(--text);
    text-anchor: middle;
  }

  /* -------------------------------------------------------------- donut -- */

  .donut { display: block; inline-size: 100%; max-inline-size: 15rem; margin-inline: auto; }

  .donut__track { fill: none; stroke: var(--line); stroke-width: 14; }

  .donut__slice {
    fill: none;
    stroke-width: 14;
    stroke-linecap: butt;
    transform: rotate(-90deg);
    transform-origin: center;
    transition: stroke-width var(--dur-fast) var(--ease-out-soft);
    /* Each slice sweeps out from zero on load. */
    animation: donut-sweep 1s var(--ease-out-quart) backwards;
  }

  .donut__slice:hover { stroke-width: 18; }

  @keyframes donut-sweep { from { stroke-dasharray: 0 999; } }

  .donut__total {
    font-family: var(--font-display);
    font-size: 30px;
    font-weight: 600;
    fill: var(--text);
    text-anchor: middle;
  }

  .donut__caption {
    font-size: 10px;
    fill: var(--text-muted);
    text-anchor: middle;
    letter-spacing: 0.06em;
  }

  /* ------------------------------------------------------------- legend -- */

  .legend {
    display: grid;
    gap: 0.45rem;
    margin-block-start: var(--space-s);
  }

  .legend__row {
    display: grid;
    grid-template-columns: auto minmax(0, 1fr) auto;
    gap: 0.6rem;
    align-items: center;
    font-size: var(--step--2);
  }

  .legend__swatch {
    inline-size: 0.65rem;
    block-size: 0.65rem;
    border-radius: 3px;
    background: var(--swatch, var(--brand));
  }

  .legend__value { font-variant-numeric: tabular-nums; font-weight: 700; }

  /* ---------------------------------------------------------- bar rows --- */

  .bars { display: grid; gap: var(--space-s); }

  .bar-row { display: grid; gap: 0.3rem; }

  .bar-row__head {
    display: flex;
    justify-content: space-between;
    align-items: baseline;
    gap: 0.5rem;
    font-size: var(--step--2);
  }

  .bar-row__head b { font-variant-numeric: tabular-nums; font-size: var(--step--1); }

  .bar-row__track {
    block-size: 0.5rem;
    border-radius: var(--radius-pill);
    background: var(--line);
    overflow: hidden;
  }

  .bar-row__fill {
    display: block;
    block-size: 100%;
    border-radius: inherit;
    background: var(--swatch, var(--brand));
    inline-size: var(--pct, 0%);
    /* Grown from zero rather than faded in, so the eye reads the length. */
    animation: bar-grow 1s var(--ease-out-quart) backwards;
  }

  @keyframes bar-grow { from { inline-size: 0; } }

  @media (prefers-reduced-motion: reduce) {
    .chart__line { animation: none; stroke-dashoffset: 0; }
    .chart__point { animation: none; opacity: 1; }
    .donut__slice, .bar-row__fill { animation: none; }
  }

  /* --------------------------------------------------------- map legend -- */

  .map-key {
    display: flex;
    flex-wrap: wrap;
    gap: 0.4rem 0.9rem;
    padding: var(--space-s) var(--space-m);
    border-block-start: 1px solid var(--line);
    font-size: var(--step--2);
    color: var(--text-muted);
  }

  .map-key span { display: inline-flex; align-items: center; gap: 0.4rem; }
  .map-key i {
    inline-size: 0.6rem;
    block-size: 0.6rem;
    border-radius: 50%;
    background: var(--swatch, var(--brand));
  }
}

@layer components {

  /* ==================================================== station roster ==== */

  /* The operators of one station, inside a narrow card. Deliberately not a
     table: at a third of the page wide a table only scrolls sideways. */
  .roster {
    list-style: none;
    padding: 0;
    margin: 0;
    display: grid;
    gap: 1px;
    background: var(--line-faint);
    border: 1px solid var(--line-faint);
    border-radius: var(--radius-s);
    overflow: hidden;
  }

  .roster__row {
    display: grid;
    grid-template-columns: minmax(0, 1fr) auto auto;
    gap: 0.6rem;
    align-items: center;
    padding: 0.5rem 0.65rem;
    background: var(--surface);
  }

  .roster__who { display: grid; min-inline-size: 0; }
  .roster__who strong { font-size: var(--step--1); overflow-wrap: anywhere; }

  .roster__row .icon-btn {
    inline-size: 2rem;
    block-size: 2rem;
  }

  .roster__row .icon-btn svg { inline-size: 1rem; block-size: 1rem; }
}
