/*
 * App design system — loaded after vendored Bootstrap 5.3 by the app shell
 * (partials/navbar.php) and the standalone auth pages. Restyles Bootstrap
 * through its CSS variables so page markup stays plain Bootstrap.
 *
 * Tokens live in :root (light) and [data-bs-theme="dark"]. The theme is
 * chosen in the top bar (light / dark / auto) and applied before first
 * paint by the inline script in navbar.php. To rebrand, change the
 * --app-accent* tokens (and the matching --bs-primary* values) below.
 */

/* ---- Tokens -------------------------------------------------------------- */
:root,
[data-bs-theme="light"] {
    --app-accent: #4f46e5;
    --app-accent-rgb: 79, 70, 229;
    --app-accent-text: #4338ca;
    --app-accent-subtle: #eef2ff;
    --app-btn: #4f46e5;
    --app-btn-hover: #4338ca;
    --app-bg: #f5f6f8;
    --app-surface: #ffffff;
    --app-surface-2: #f8f9fb;
    --app-border: #e6e8ec;
    --app-border-strong: #d4d8df;
    --app-text: #101828;
    --app-muted: #667085;
    --app-shadow: 0 1px 2px rgba(16, 24, 40, .04), 0 1px 3px rgba(16, 24, 40, .06);
    --app-shadow-lg: 0 12px 32px -8px rgba(16, 24, 40, .18);
    --app-radius: .75rem;

    --bs-primary: #4f46e5;
    --bs-primary-rgb: 79, 70, 229;
    --bs-primary-text-emphasis: #3730a3;
    --bs-primary-bg-subtle: #eef2ff;
    --bs-primary-border-subtle: #c7d2fe;
    --bs-link-color: #4f46e5;
    --bs-link-color-rgb: 79, 70, 229;
    --bs-link-hover-color: #3730a3;
    --bs-link-hover-color-rgb: 55, 48, 163;
    --bs-focus-ring-color: rgba(79, 70, 229, .22);
    --bs-body-bg: var(--app-bg);
    --bs-body-color: var(--app-text);
    --bs-border-color: var(--app-border);
    --bs-secondary-color: var(--app-muted);
    --bs-tertiary-bg: var(--app-surface-2);
    --bs-body-font-family: system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", sans-serif;
    --bs-body-font-size: .9375rem;
    --bs-border-radius: .5rem;
    --bs-border-radius-sm: .4rem;
    --bs-border-radius-lg: .75rem;
}

[data-bs-theme="dark"] {
    --app-accent: #818cf8;
    --app-accent-rgb: 129, 140, 248;
    --app-accent-text: #c7d2fe;
    --app-accent-subtle: rgba(129, 140, 248, .14);
    --app-btn: #6366f1;
    --app-btn-hover: #818cf8;
    --app-bg: #0b0d12;
    --app-surface: #13161d;
    --app-surface-2: #181c25;
    --app-border: #252a35;
    --app-border-strong: #313745;
    --app-text: #e6e8ec;
    --app-muted: #98a2b3;
    --app-shadow: 0 1px 2px rgba(0, 0, 0, .35);
    --app-shadow-lg: 0 16px 40px -8px rgba(0, 0, 0, .6);

    --bs-primary: #818cf8;
    --bs-primary-rgb: 129, 140, 248;
    --bs-primary-text-emphasis: #c7d2fe;
    --bs-primary-bg-subtle: rgba(129, 140, 248, .14);
    --bs-primary-border-subtle: rgba(129, 140, 248, .35);
    --bs-link-color: #a5b4fc;
    --bs-link-color-rgb: 165, 180, 252;
    --bs-link-hover-color: #c7d2fe;
    --bs-link-hover-color-rgb: 199, 210, 254;
    --bs-focus-ring-color: rgba(129, 140, 248, .3);
    --bs-body-bg: var(--app-bg);
    --bs-body-color: var(--app-text);
    --bs-border-color: var(--app-border);
    --bs-secondary-color: var(--app-muted);
    --bs-tertiary-bg: var(--app-surface-2);
}

/* ---- Base ---------------------------------------------------------------- */
body {
    background: var(--app-bg);
    color: var(--app-text);
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
    min-height: 100vh;
}
h1, h2, h3, h4, h5, h6, .h1, .h2, .h3, .h4, .h5, .h6 { font-weight: 650; letter-spacing: -.015em; color: var(--app-text); }
.app-main h1, .app-main h1.h3 { font-size: 1.5rem; }
.text-muted { color: var(--app-muted) !important; }
a { text-underline-offset: .15em; }
code { color: var(--app-accent-text); }
kbd { background: var(--app-surface-2); color: var(--app-text); border: 1px solid var(--app-border-strong); box-shadow: 0 1px 0 var(--app-border-strong); font-size: .75em; }
::selection { background: rgba(var(--app-accent-rgb), .2); }

/* ---- Shell: top bar, sidebar, main -------------------------------------- */
.app-topbar {
    position: sticky; top: 0; z-index: 1030;
    height: 58px; display: flex; align-items: center; gap: .75rem; padding: 0 1rem 0 1.25rem;
    background: color-mix(in srgb, var(--app-surface) 88%, transparent);
    backdrop-filter: saturate(160%) blur(10px);
    border-bottom: 1px solid var(--app-border);
}
.app-brand { display: flex; align-items: center; gap: .6rem; color: var(--app-text); text-decoration: none; font-weight: 650; letter-spacing: -.01em; }
.app-brand:hover { color: var(--app-text); }
.app-brand img { max-height: 28px; max-width: 140px; object-fit: contain; }
.app-topbar .topbar-btn {
    display: inline-flex; align-items: center; gap: .45rem; height: 36px; padding: 0 .7rem;
    border: 1px solid var(--app-border); border-radius: .55rem; background: var(--app-surface);
    color: var(--app-text); font-size: .875rem; font-weight: 500; text-decoration: none;
}
.app-topbar .topbar-btn:hover { background: var(--app-surface-2); border-color: var(--app-border-strong); }
.app-topbar .topbar-btn.icon-only { width: 36px; justify-content: center; padding: 0; }
.app-topbar .topbar-btn .bi { color: var(--app-muted); }
.app-avatar {
    width: 30px; height: 30px; border-radius: 50%; display: inline-flex; align-items: center; justify-content: center;
    background: var(--app-accent-subtle); color: var(--app-accent-text); font-weight: 650; font-size: .8rem;
}
.tenant-switch-name { max-width: 200px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

.app-shell { display: flex; min-height: calc(100vh - 58px); }
.app-sidebar {
    width: 252px; flex-shrink: 0; position: sticky; top: 58px; height: calc(100vh - 58px); overflow-y: auto;
    background: var(--app-surface); border-right: 1px solid var(--app-border);
}
.app-main { flex: 1; min-width: 0; padding: 1.5rem 2rem 3.5rem; }
.app-main-inner { max-width: 1440px; margin: 0 auto; }
@media (max-width: 991.98px) {
    .app-main { padding: 1rem 1rem 3rem; }
    .app-topbar { padding: 0 .75rem; }
}

.side-nav { padding: .75rem .75rem 1.5rem; }
.side-nav .nav-section {
    font-size: .68rem; font-weight: 650; letter-spacing: .08em; text-transform: uppercase;
    color: var(--app-muted); padding: 1.1rem .75rem .4rem;
}
.side-nav .nav-section:first-child { padding-top: .35rem; }
.side-nav .nav-link {
    display: flex; align-items: center; gap: .7rem; padding: .45rem .75rem; margin-bottom: 1px;
    border-radius: .5rem; color: var(--app-text); font-size: .9rem; font-weight: 500;
}
.side-nav .nav-link .bi { font-size: 1.05rem; width: 1.15rem; color: var(--app-muted); }
.side-nav .nav-link:hover { background: var(--app-surface-2); color: var(--app-text); }
.side-nav .nav-link.active { background: var(--app-accent-subtle); color: var(--app-accent-text); }
.side-nav .nav-link.active .bi { color: var(--app-accent-text); }
.offcanvas { --bs-offcanvas-bg: var(--app-surface); --bs-offcanvas-width: 280px; }

/* ---- Page header + breadcrumbs ----------------------------------------- */
.app-breadcrumb { margin-bottom: .6rem; font-size: .8125rem; }
.app-breadcrumb .breadcrumb { --bs-breadcrumb-divider: "›"; --bs-breadcrumb-item-padding-x: .45rem; flex-wrap: wrap; }
.app-breadcrumb .breadcrumb-item + .breadcrumb-item::before { color: var(--app-border-strong); }
.app-breadcrumb a { color: var(--app-muted); text-decoration: none; }
.app-breadcrumb a:hover { color: var(--app-accent-text); }
.app-breadcrumb .breadcrumb-item.active { color: var(--app-text); font-weight: 500; }
.app-breadcrumb .bi-house-door { font-size: .9rem; }

/* ---- Cards ---------------------------------------------------------------- */
.card {
    --bs-card-bg: var(--app-surface);
    --bs-card-border-color: var(--app-border);
    --bs-card-border-radius: var(--app-radius);
    --bs-card-inner-border-radius: calc(var(--app-radius) - 1px);
    --bs-card-cap-bg: transparent;
    --bs-card-cap-padding-y: .85rem;
    --bs-card-cap-padding-x: 1.1rem;
    --bs-card-spacer-x: 1.1rem;
    box-shadow: var(--app-shadow);
}
.card-header { border-bottom-color: var(--app-border); }
.card-header strong { font-weight: 650; }
.card-footer { background: var(--app-surface-2); border-top-color: var(--app-border); }
.card.border-0 { box-shadow: var(--app-shadow); }

/* ---- Tables --------------------------------------------------------------- */
.table {
    --bs-table-bg: transparent;
    --bs-table-color: var(--app-text);
    --bs-table-border-color: var(--app-border);
    --bs-table-hover-bg: var(--app-surface-2);
    --bs-table-hover-color: var(--app-text);
    --bs-table-striped-bg: var(--app-surface-2);
}
.table > thead th,
.table > thead.table-light th {
    background: var(--app-surface-2) !important; color: var(--app-muted) !important;
    font-size: .72rem; font-weight: 650; letter-spacing: .05em; text-transform: uppercase;
    border-bottom: 1px solid var(--app-border); padding-top: .65rem; padding-bottom: .65rem; white-space: nowrap;
}
.table > :not(caption) > * > * { padding-top: .7rem; padding-bottom: .7rem; }
/* Sortable column headers (buttons) look exactly like plain headers. */
.table > thead th .btn-link {
    padding: 0; border: 0; color: inherit !important; font: inherit; letter-spacing: inherit;
    text-transform: inherit; text-decoration: none; vertical-align: baseline;
}
.table > thead th .btn-link:hover { color: var(--app-text) !important; }
.card .table:last-child > :last-child > tr:last-child > * { border-bottom-width: 0; }

/* ---- Buttons -------------------------------------------------------------- */
.btn { --bs-btn-font-weight: 500; --bs-btn-border-radius: .55rem; --bs-btn-focus-box-shadow: 0 0 0 .2rem rgba(var(--app-accent-rgb), .22); }
.btn-sm { --bs-btn-border-radius: .45rem; }
.btn-primary {
    --bs-btn-bg: var(--app-btn); --bs-btn-border-color: var(--app-btn);
    --bs-btn-hover-bg: var(--app-btn-hover); --bs-btn-hover-border-color: var(--app-btn-hover);
    --bs-btn-active-bg: var(--app-btn-hover); --bs-btn-active-border-color: var(--app-btn-hover);
    --bs-btn-disabled-bg: var(--app-btn); --bs-btn-disabled-border-color: var(--app-btn);
    --bs-btn-color: #fff; --bs-btn-hover-color: #fff; --bs-btn-active-color: #fff;
    box-shadow: 0 1px 2px rgba(16, 24, 40, .12);
}
.btn-outline-primary {
    --bs-btn-color: var(--app-accent-text); --bs-btn-border-color: rgba(var(--app-accent-rgb), .45);
    --bs-btn-hover-bg: var(--app-accent-subtle); --bs-btn-hover-color: var(--app-accent-text); --bs-btn-hover-border-color: var(--app-accent);
    --bs-btn-active-bg: var(--app-accent-subtle); --bs-btn-active-color: var(--app-accent-text); --bs-btn-active-border-color: var(--app-accent);
}
.btn-outline-secondary {
    --bs-btn-color: var(--app-text); --bs-btn-border-color: var(--app-border-strong); --bs-btn-bg: var(--app-surface);
    --bs-btn-hover-bg: var(--app-surface-2); --bs-btn-hover-color: var(--app-text); --bs-btn-hover-border-color: var(--app-border-strong);
    --bs-btn-active-bg: var(--app-surface-2); --bs-btn-active-color: var(--app-text); --bs-btn-active-border-color: var(--app-border-strong);
}
.btn-secondary {
    --bs-btn-bg: var(--app-surface-2); --bs-btn-color: var(--app-text); --bs-btn-border-color: var(--app-border-strong);
    --bs-btn-hover-bg: var(--app-border); --bs-btn-hover-color: var(--app-text); --bs-btn-hover-border-color: var(--app-border-strong);
    --bs-btn-active-bg: var(--app-border); --bs-btn-active-color: var(--app-text);
}
.btn-link { --bs-btn-color: var(--bs-link-color); --bs-btn-hover-color: var(--bs-link-hover-color); }

/* ---- Forms ---------------------------------------------------------------- */
.form-control, .form-select { border-color: var(--app-border-strong); background-color: var(--app-surface); color: var(--app-text); }
.form-control:focus, .form-select:focus { border-color: var(--app-accent); box-shadow: 0 0 0 .2rem rgba(var(--app-accent-rgb), .18); background-color: var(--app-surface); color: var(--app-text); }
.form-control::placeholder { color: var(--app-muted); opacity: .8; }
.form-control[readonly] { background-color: var(--app-surface-2); }
.form-label, .col-form-label { font-weight: 500; font-size: .875rem; }
.form-text { color: var(--app-muted); font-size: .8125rem; }
.form-check-input { border-color: var(--app-border-strong); }
.form-check-input:checked { background-color: var(--app-btn); border-color: var(--app-btn); }
.form-check-input:focus { border-color: var(--app-accent); box-shadow: 0 0 0 .2rem rgba(var(--app-accent-rgb), .18); }
.input-group-text { background: var(--app-surface-2); border-color: var(--app-border-strong); color: var(--app-muted); }

/* ---- Nav tabs (underline style) + pills ---------------------------------- */
.nav-tabs { border-bottom: 1px solid var(--app-border); gap: .25rem; }
.nav-tabs .nav-link {
    border: 0; border-bottom: 2px solid transparent; border-radius: 0; margin-bottom: -1px;
    color: var(--app-muted); font-weight: 500; padding: .6rem .85rem;
}
.nav-tabs .nav-link:hover { color: var(--app-text); border-bottom-color: var(--app-border-strong); }
.nav-tabs .nav-link.active { color: var(--app-accent-text); background: transparent; border-bottom-color: var(--app-accent); }
.nav-pills { --bs-nav-pills-link-active-bg: var(--app-accent-subtle); --bs-nav-pills-link-active-color: var(--app-accent-text); }

/* ---- Badges, alerts, modals, dropdowns, toasts --------------------------- */
.badge { font-weight: 600; letter-spacing: .01em; }
.alert { border-radius: .65rem; }
.modal { --bs-modal-bg: var(--app-surface); --bs-modal-border-color: var(--app-border); --bs-modal-border-radius: .9rem; --bs-modal-header-border-color: var(--app-border); --bs-modal-footer-border-color: var(--app-border); }
.modal-content { box-shadow: var(--app-shadow-lg); }
.dropdown-menu {
    --bs-dropdown-bg: var(--app-surface); --bs-dropdown-border-color: var(--app-border); --bs-dropdown-border-radius: .65rem;
    --bs-dropdown-link-hover-bg: var(--app-surface-2); --bs-dropdown-link-active-bg: var(--app-accent-subtle); --bs-dropdown-link-active-color: var(--app-accent-text);
    --bs-dropdown-font-size: .875rem; --bs-dropdown-item-padding-y: .4rem;
    box-shadow: var(--app-shadow-lg); padding: .35rem;
}
.dropdown-item { border-radius: .4rem; }
.dropdown-header { font-size: .7rem; letter-spacing: .06em; text-transform: uppercase; font-weight: 650; }
.toast { --bs-toast-bg: var(--app-surface); --bs-toast-border-color: var(--app-border); border-radius: .65rem; box-shadow: var(--app-shadow-lg); }
.list-group { --bs-list-group-bg: var(--app-surface); --bs-list-group-border-color: var(--app-border); }
.progress { --bs-progress-bg: var(--app-surface-2); }

/* Loading overlay for full-page form submits (partials/footer.php). */
#loadingOverlay {
    position: fixed; inset: 0; z-index: 2000; display: none; align-items: center; justify-content: center;
    background: color-mix(in srgb, var(--app-bg) 65%, transparent); backdrop-filter: blur(1px);
}

/* ---- Settings layout (tabs on the left on wide screens) ------------------ */
.settings-nav .nav-link { color: var(--app-muted); border-radius: .5rem; padding: .45rem .75rem; font-weight: 500; font-size: .9rem; }
.settings-nav .nav-link:hover { color: var(--app-text); background: var(--app-surface-2); }
.settings-nav .nav-link.active { color: var(--app-accent-text); background: var(--app-accent-subtle); }

/* ---- Dark-mode fixes for Bootstrap's light-only utilities ---------------- */
[data-bs-theme="dark"] .bg-light,
[data-bs-theme="dark"] .bg-white { background-color: var(--app-surface-2) !important; }
[data-bs-theme="dark"] .text-bg-light { background-color: var(--app-surface-2) !important; color: var(--app-text) !important; }
[data-bs-theme="dark"] .alert-light { --bs-alert-bg: var(--app-surface-2); --bs-alert-color: var(--app-text); --bs-alert-border-color: var(--app-border); }
[data-bs-theme="dark"] .table-light { --bs-table-bg: var(--app-surface-2); --bs-table-color: var(--app-text); }
[data-bs-theme="dark"] .btn-close { filter: var(--bs-btn-close-white-filter); }

/* ---- Page help: a one-line "How this works" toggle instead of an intro paragraph (renderPageHelp() in src/nav.php). */
.page-help-toggle { display:inline-flex; align-items:center; gap:.3rem; font-size:.8125rem; color:var(--app-muted); text-decoration:none; padding:0; border:0; background:none; }
.page-help-toggle:hover { color:var(--app-accent-text); }
.page-help-toggle .bi-chevron-down { transition:transform .15s; font-size:.7rem; }
.page-help-toggle[aria-expanded="true"] .bi-chevron-down { transform:rotate(180deg); }
.page-help { max-width:760px; font-size:.875rem; color:var(--app-muted); padding:.5rem .85rem; border-left:3px solid var(--app-border-strong); margin-bottom:1rem; }
.page-help p:last-child { margin-bottom:0; }

/* ---- Page header: title + one primary action + quiet extras / a "…" menu. */
.page-head { display:flex; justify-content:space-between; align-items:flex-start; gap:.75rem; flex-wrap:wrap; margin-bottom:1rem; }
.page-head .page-actions { display:flex; gap:.5rem; align-items:center; flex-wrap:wrap; }
.page-sub { color:var(--app-muted); font-size:.875rem; }
.page-sub .sep { margin:0 .35rem; color:var(--app-border-strong); }
/* System hub (system.php): the key badges strip under the title. */
.key-strip { display:flex; flex-wrap:wrap; gap:.35rem; align-items:center; }
.key-strip .badge { font-weight:500; }

/* ---- Quick picks under a datetime-local input (data-time-for / data-time in app.js): small chips that wrap on phones. */
.quick-picks { display:flex; flex-wrap:wrap; gap:.3rem; margin-top:.35rem; }
.quick-picks .btn { --bs-btn-padding-y:.15rem; --bs-btn-padding-x:.55rem; --bs-btn-font-size:.78rem; border-radius:999px; }

/* ---- Row menus ("…" per table row): the menu escapes .table-responsive via Popper's fixed strategy (data-bs-popper-config). */
.row-menu { border:0; background:transparent; color:var(--app-muted); width:32px; height:32px; border-radius:.45rem; display:inline-flex; align-items:center; justify-content:center; }
.row-menu:hover, .row-menu[aria-expanded="true"] { color:var(--app-text); background:var(--app-surface-2); }
.row-menu::after { display:none; }
.td-actions { width:1%; white-space:nowrap; }

/* ---- Stacked tables: a .table-stack renders each row as a card on phones; cells show their <th> text via data-label. */
@media (max-width: 767.98px) {
  .table-stack thead { display:none; }
  .table-stack, .table-stack tbody, .table-stack tr, .table-stack td { display:block; width:100%; }
  .table-stack tr { position:relative; padding:.75rem 1rem .75rem; border-bottom:1px solid var(--app-border); }
  .table-stack tr:last-child { border-bottom:0; }
  .table-stack td { border:0; padding:.15rem 0 !important; }
  .table-stack td.ps-3 { padding-left:0 !important; }
  .table-stack td[data-label]::before { content:attr(data-label); display:block; font-size:.68rem; font-weight:650; letter-spacing:.06em; text-transform:uppercase; color:var(--app-muted); margin-top:.35rem; }
  .table-stack td.td-primary { font-size:1rem; font-weight:600; padding-right:2.5rem !important; }
  .table-stack td.td-actions { position:absolute; top:.5rem; right:.5rem; width:auto; padding:0 !important; }
  .table-stack td.td-actions .d-flex { justify-content:flex-end; }
  .table-stack td.text-end { text-align:left !important; }
  .table-stack td:empty { display:none; }
  .table-stack .form-select-sm { max-width:240px; }
  .card .table-stack:last-child > :last-child > tr:last-child > * { border-bottom-width:0; }
}

/* ---- Standalone auth pages (login / magic link / installer) -------------- */
.auth-wrap { min-height: 100vh; display: flex; align-items: center; justify-content: center; padding: 2rem 1rem; }
.auth-card { width: 100%; max-width: 420px; }

.auth-card .card { box-shadow: var(--app-shadow-lg); }
.auth-card .brand-logo { max-height: 52px; }

/* ---- Crew client (comms.php / assets/comms.js) ---------------------------- */
/* The intercom is an operating surface: no text selection, no long-press callouts, no double-tap zoom (pinch is also refused in comms.js). comms.php sets body.is-comms so the shell around it (top bar, breadcrumbs) cannot be highlighted by a double tap either. Inputs and the health readout stay selectable. */
body.is-comms, .comms { user-select:none; -webkit-user-select:none; -webkit-touch-callout:none; }
.comms { touch-action:manipulation; }
body.is-comms input, body.is-comms select, body.is-comms textarea, body.is-comms pre { user-select:text; -webkit-user-select:text; }
.comms.no-latch .comms-talk.latched { box-shadow:none; }
.comms-bar { display:flex; justify-content:space-between; align-items:center; gap:.75rem; flex-wrap:wrap; margin-bottom:.75rem; }
.comms-controls { display:flex; gap:.5rem; align-items:center; }
.comms-status.is-ok { color:var(--bs-success); } .comms-status.is-bad { color:var(--bs-danger); } .comms-status.is-busy { color:var(--bs-warning); }
.comms-microw { display:grid; grid-template-columns:auto 1fr auto auto; gap:.75rem; align-items:center; margin-bottom:.75rem; padding:.25rem .5rem; margin-left:-.5rem; margin-right:-.5rem; border-radius:6px; }
/* Something is latched: the mic row turns into the "you are latched" bar with Release latches (held keys are never touched). */
.comms-microw.is-latched { background:rgba(var(--bs-warning-rgb), .18); }
.comms-microw.is-latched [data-comms="sending"] { color:var(--app-text); font-weight:600; }
.comms-release[hidden] { display:none; }
.comms-release { white-space:nowrap; }
.comms-key-hold { font-size:.6rem; font-weight:700; letter-spacing:.04em; text-transform:uppercase; color:var(--app-muted); border:1px solid var(--app-border-strong); border-radius:3px; padding:0 .3em; margin-left:.35em; }
@media (max-width: 575.98px) { .comms-release span { display:none; } }
.comms-meter { height:8px; background:var(--app-surface-2); border:1px solid var(--app-border); border-radius:4px; overflow:hidden; min-width:60px; }
.comms-meter > div { height:100%; width:0; background:linear-gradient(90deg, var(--bs-success), var(--bs-warning) 70%, var(--bs-danger)); transition:width .08s linear; }
.comms-grid { display:grid; grid-template-columns:repeat(auto-fill, minmax(230px, 1fr)); gap:.75rem; }
.comms-key { background:var(--app-surface); border:1px solid var(--app-border); border-radius:var(--app-radius); padding:.6rem .75rem; box-shadow:var(--app-shadow); transition:background .15s, border-color .15s; }
.comms-key.is-rx { border-color:var(--bs-success); background:rgba(var(--bs-success-rgb), .08); }
.comms-key.is-talking { border-color:var(--bs-danger); background:rgba(var(--bs-danger-rgb), .10); }
.comms-key-head { display:flex; justify-content:space-between; align-items:baseline; margin-bottom:.4rem; }
.comms-key-name { font-weight:700; font-size:1.05rem; letter-spacing:.02em; }
.comms-key-kind { font-size:.7rem; color:var(--app-muted); text-transform:uppercase; }
.comms-key-body { display:grid; grid-template-columns:56px 1fr 56px; gap:.6rem; align-items:center; }
.comms-key-mid { min-width:0; } .comms-who { min-height:1.2em; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
.comms-spacer { display:block; width:56px; height:56px; }
.comms-listen, .comms-talk { width:56px; height:56px; border-radius:50%; border:2px solid var(--app-border-strong); background:var(--app-surface-2); color:var(--app-text); font-size:1.4rem; display:inline-flex; align-items:center; justify-content:center; user-select:none; -webkit-user-select:none; touch-action:none; cursor:pointer; }
.comms-listen { border-color:var(--bs-success); color:var(--bs-success); }
.comms-listen.on { background:var(--bs-success); color:#fff; }
.comms-talk { border-color:var(--bs-danger); color:var(--bs-danger); }
.comms-talk.on, .comms-ptalk.on { background:var(--bs-danger); color:#fff; box-shadow:0 0 0 4px rgba(var(--bs-danger-rgb), .25); }
.comms-talk.latched:not(.on) { box-shadow:inset 0 0 0 3px rgba(var(--bs-danger-rgb), .35); }
.comms-talk:disabled, .comms-direct:disabled { opacity:.35; cursor:default; }
.comms-key.is-paused { border-style:dashed; }
/* Group keys: the person's own "several lines with one key"; talk only, an accent bar tells them apart from channels. */
.comms-key.is-group { border-top:3px solid var(--app-accent); }
.comms-group-members { line-height:1.3; }
.comms-group-edit { width:56px; height:56px; border-radius:50%; border:2px solid var(--app-border); background:transparent; color:var(--app-muted); font-size:1.1rem; display:inline-flex; align-items:center; justify-content:center; cursor:pointer; }
.comms-group-edit:hover { color:var(--app-text); border-color:var(--app-border-strong); }
.comms-group-add { display:flex; flex-direction:column; align-items:center; justify-content:center; gap:.15rem; min-height:118px; border:2px dashed var(--app-border-strong); border-radius:var(--app-radius); background:transparent; color:var(--app-muted); cursor:pointer; font-weight:600; }
.comms-group-add i { font-size:1.4rem; } .comms-group-add small { font-weight:400; }
.comms-group-add:hover { color:var(--app-text); border-color:var(--app-accent); }
.comms:not(.is-connected) .comms-group-add { display:none; }
.comms-group-chips { display:flex; flex-wrap:wrap; gap:.5rem; }
.comms-group-chip { padding:.7rem 1.1rem; font-size:1.05rem; font-weight:600; border-radius:999px; min-width:5.5rem; }
.comms-key.is-paused .comms-talk { background:rgba(var(--bs-warning-rgb), .25); color:var(--bs-warning); border-color:var(--bs-warning); }
.comms-direct { width:48px; height:48px; border-radius:50%; border:2px solid var(--app-border-strong); background:var(--app-surface-2); color:var(--app-text); font-size:1.15rem; display:inline-flex; align-items:center; justify-content:center; user-select:none; -webkit-user-select:none; touch-action:none; cursor:pointer; flex:0 0 auto; }
.comms-direct.is-opening { background:rgba(var(--bs-warning-rgb), .35); border-color:var(--bs-warning); color:var(--bs-warning); }
.comms-direct.on { background:var(--bs-danger); border-color:var(--bs-danger); color:#fff; box-shadow:0 0 0 4px rgba(var(--bs-danger-rgb), .25); }
.comms-direct.is-incoming:not(.on) { border-color:var(--bs-success); color:var(--bs-success); animation:comms-pulse 1.2s ease-in-out infinite; }
.comms-reply { display:inline-flex; align-items:center; gap:.4rem; height:38px; padding:0 .9rem; border-radius:19px; min-width:44px; border:2px solid var(--bs-danger); background:var(--app-surface-2); color:var(--bs-danger); font-weight:600; user-select:none; -webkit-user-select:none; touch-action:none; cursor:pointer; max-width:12rem; }
.comms-reply-name { overflow:hidden; text-overflow:ellipsis; white-space:nowrap; max-width:9rem; }
.comms-reply-initials { display:none; font-size:.8rem; letter-spacing:.04em; }
.comms-people-btn { position:relative; }
.comms-people-count { position:absolute; top:-6px; right:-6px; min-width:18px; height:18px; padding:0 5px; border-radius:9px; background:var(--app-muted); color:#fff; font-size:.7rem; line-height:18px; text-align:center; }
.comms-people-count:empty { display:none; }
.comms-people-btn.is-incoming { border-color:var(--bs-success); color:var(--bs-success); animation:comms-pulse 1.2s ease-in-out infinite; }
.comms-people-btn.is-incoming .comms-people-count { background:var(--bs-success); }
.comms-notice { min-height:1.6em; margin:-.25rem 0 .5rem; color:var(--app-muted); white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }
.comms-notice .comms-incoming { display:inline-block; background:none; border:0; padding:0; margin:0; color:var(--bs-success); font-weight:600; }
.comms-people-panel { --bs-offcanvas-width: 360px; }
/* ≥ lg: the People panel is a card beside the key grid (offcanvas-lg renders inline there). */
@media (min-width: 992px) {
  /* The intercom fills the viewport below the top bar; the key grid and the People card each scroll on their own. */
  .comms { --comms-chrome: 11.5rem; /* top bar 58px + main padding + breadcrumb row */ display:flex; flex-direction:column; height:calc(100dvh - var(--comms-chrome)); min-height:420px; }
  .comms.is-connected { --comms-chrome: 9.5rem; /* breadcrumbs hidden, title one line */ }
  .comms-main { display:grid; grid-template-columns:minmax(0, 1fr) 320px; gap:1rem; align-items:stretch; flex:1 1 auto; min-height:0; }
  .comms:not(.is-connected) .comms-main { grid-template-columns:minmax(0, 1fr); }
  .comms:not(.is-connected) .comms-people-panel { display:none; }
  .comms-grid { overflow-y:auto; align-content:start; padding-right:.25rem; min-height:0; }
  .comms-people-panel { background:var(--app-surface); border:1px solid var(--app-border); border-radius:var(--app-radius); box-shadow:var(--app-shadow); display:flex; flex-direction:column; min-height:0; }
  .comms-people-panel .offcanvas-header { display:flex; padding:.6rem .9rem; flex:0 0 auto; } /* Bootstrap hides offcanvas-lg headers inline; the People title + online count is worth the row */
  .comms-people-panel .offcanvas-body { display:block; padding:.6rem .75rem; overflow-y:auto; flex:1 1 auto; min-height:0; }
  .comms-people-panel .comms-people-list { grid-template-columns:1fr; gap:.35rem; }
  .comms-people-panel .comms-person { padding:.4rem .6rem; border-radius:calc(var(--app-radius) - 2px); }
  .comms-people-panel .comms-person .fw-semibold { font-size:.92rem; }
  .comms-people-panel .comms-direct { width:40px; height:40px; font-size:1rem; }
}
@media (min-width: 1400px) { .comms.is-connected .comms-main { grid-template-columns:minmax(0, 1fr) 360px; } }
.comms-people-head { font-size:.75rem; text-transform:uppercase; letter-spacing:.04em; color:var(--app-muted); margin:.75rem 0 .4rem; }
.comms-people-head:first-child { margin-top:0; }
.comms-reply:disabled { opacity:.35; cursor:default; }
.comms-reply.is-opening { background:rgba(var(--bs-warning-rgb), .35); border-color:var(--bs-warning); color:var(--bs-warning); }
.comms-reply.on { background:var(--bs-danger); color:#fff; box-shadow:0 0 0 4px rgba(var(--bs-danger-rgb), .25); }
.comms-reply.is-incoming:not(.on):not(:disabled) { border-color:var(--bs-success); color:var(--bs-success); animation:comms-pulse 1.2s ease-in-out infinite; }
.comms.is-ducked .comms-key.is-listening .comms-listen.on { opacity:.6; }
.comms-layout { display:flex; flex-direction:column; gap:.25rem; max-width:420px; }
.comms-layout-row { display:flex; align-items:center; gap:.4rem; padding:.25rem .5rem; border:1px solid var(--app-border); border-radius:var(--app-radius); background:var(--app-surface); }
.comms-layout-row.is-hidden { opacity:.55; }
.comms-layout-row .name { flex:1 1 auto; min-width:0; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; font-weight:600; }
.comms-layout-row .btn { padding:.1rem .45rem; }
.comms-layout-row .comms-drag { flex:0 0 auto; width:2rem; height:2rem; display:flex; align-items:center; justify-content:center; color:var(--app-text-muted); cursor:grab; touch-action:none; user-select:none; border-radius:var(--app-radius); }
.comms-layout-row .comms-drag:active { cursor:grabbing; }
.comms-layout-row.is-dragging { opacity:.92; box-shadow:0 6px 18px rgba(0,0,0,.25); position:relative; z-index:2; background:var(--app-surface-2); }
.comms-layout-row.is-group .name { color:var(--app-accent); }
.comms-more > summary { cursor:pointer; color:var(--app-text-muted); list-style:none; }
.comms-more > summary::before { content:'▸'; display:inline-block; width:1em; transition:transform .15s; }
.comms-more[open] > summary::before { transform:rotate(90deg); }
.comms-more > summary::-webkit-details-marker { display:none; }
.comms-health { white-space:pre-wrap; background:var(--app-surface-2); border:1px solid var(--app-border); border-radius:var(--app-radius); padding:.4rem .6rem; font-size:.8rem; }
.comms-person.is-offline { opacity:.5; } .comms-person.is-incoming { border-color:var(--bs-success); }
@keyframes comms-pulse { 0%, 100% { box-shadow:0 0 0 0 rgba(var(--bs-success-rgb), .5); } 50% { box-shadow:0 0 0 6px rgba(var(--bs-success-rgb), 0); } }
.comms-level { width:100%; margin-top:.4rem; accent-color:var(--bs-success); }
.comms-people-list { display:grid; grid-template-columns:repeat(auto-fill, minmax(260px, 1fr)); gap:.5rem; }
.comms-person { display:flex; justify-content:space-between; align-items:center; gap:.5rem; background:var(--app-surface); border:1px solid var(--app-border); border-radius:var(--app-radius); padding:.5rem .75rem; }
.comms-person.is-selected { border-color:var(--bs-danger); }
.comms-person-actions { display:flex; align-items:center; gap:.5rem; }
.comms-incoming { background:rgba(var(--bs-danger-rgb), .10); border:1px solid var(--bs-danger); border-radius:var(--app-radius); padding:.5rem .75rem; margin-bottom:.5rem; }
@media (max-width: 575.98px) {
  .comms-grid { grid-template-columns:1fr; } .comms-key-body { grid-template-columns:64px 1fr 64px; } .comms-listen, .comms-talk, .comms-spacer { width:64px; height:64px; }
  /* One thumb: the bar (Connect / Mute / Reply) sticks to the top while the key grid scrolls; person keys and the Reply key grow. */
  .comms-bar { position:sticky; top:0; z-index:5; background:var(--app-bg); padding:.5rem 0; margin:0 0 .5rem; }
  .comms-controls { width:100%; justify-content:space-between; }
  .comms.is-connected .comms-title .comms-org { display:none; }
  .comms.is-connected .comms-bar { margin-bottom:.25rem; }
  .comms-reply { height:48px; width:72px; border-radius:24px; justify-content:center; flex:0 0 auto; }
  .comms-reply-name { display:none; } .comms-reply-initials { display:inline; }
  .comms-people-panel { --bs-offcanvas-width: 88vw; }
  .comms-direct { width:60px; height:60px; font-size:1.4rem; }
  .comms-person { padding:.65rem .75rem; }
  .comms-people-list { grid-template-columns:1fr; }
}
@media (display-mode: standalone) { .comms-bar { padding-top:max(.5rem, env(safe-area-inset-top)); } }

/* Before connecting: one Connect card instead of an empty grid and an empty People panel; the mic meter and notice line only once live. */
.comms-start { max-width:520px; margin:0 auto 1rem; }
.comms-start-icon { font-size:2.4rem; color:var(--app-accent); }
.comms.is-connected .comms-start, .comms.is-connecting .comms-start { display:none; }
.comms.is-connecting .comms-grid::before { content:'Connecting…'; display:block; color:var(--app-muted); padding:2rem 0; text-align:center; grid-column:1 / -1; }
.comms:not(.is-connected) .comms-microw, .comms:not(.is-connected) .comms-notice { display:none; }
.comms:not(.is-connected) .comms-people-btn { display:none !important; }
/* While live the shell steps back: no breadcrumbs, a one-line title with the status beside it (phones especially — the chrome was 200 px before the first key). */
body.comms-connected .app-breadcrumb { display:none; }
.comms.is-connected .comms-title { display:flex; align-items:baseline; gap:.5rem; flex-wrap:wrap; }
.comms.is-connected .comms-title .h4 { font-size:1.05rem; margin:0; }
.comms.is-connected .comms-title .small { font-size:.8rem; }
/* ---- Setup matrix (system_setup.php, assets/setup.js) --------------------- */
/* Columns are CLOSED by default: narrow, vertical name, each cell a two-half L|T pill (still clickable). .is-open on the <th>/<td> of a column widens it to full buttons. */
.kg-toolbar { display:flex; gap:.5rem; align-items:center; flex-wrap:wrap; margin-bottom:.75rem; }
.kg-actions { flex:0 0 auto; }
.kg-count { display:inline-block; min-width:1.6em; margin-left:.4em; vertical-align:baseline; visibility:hidden; }
.kg-filter { max-width:300px; }
.kg-swatch { display:inline-block; min-width:1.4em; text-align:center; font-size:.75rem; font-weight:700; border-radius:4px; padding:0 .25em; line-height:1.4; }
.kg-swatch-l { background:var(--bs-success); color:#fff; } .kg-swatch-t { background:var(--bs-danger); color:#fff; }
/* Hold-only talk key (can_latch 0): striped red T on Setup, "hold" tag on key badges. Read-only indicators; the switch is on the person / template page. */
.kg-swatch-hold, .kg-cell:has(input[data-kg-h]:checked:not(:disabled)) .btn-check:checked + .kg-btn-t { background-image:repeating-linear-gradient(135deg, rgba(255,255,255,.35) 0 3px, transparent 3px 7px); }
/* The H toggle (hold only) of an open cell: lit = striped T; disabled while the cell has no T. Hidden in a closed cell — the stripes say it. */
.kg-cell:not(.is-open) .kg-btn-h { display:none; }
.btn-check:checked + .kg-btn-h { background:var(--bs-warning); border-color:var(--bs-warning); color:#1a1a1a; }
.btn-check:disabled + .kg-btn-h { opacity:.35; cursor:not-allowed; }
.kg-swatch-h { background:var(--bs-warning); color:#1a1a1a; }
.key-hold { display:inline-block; margin-left:.25em; padding:0 .3em; border-radius:3px; font-size:.65em; font-weight:700; letter-spacing:.03em; text-transform:uppercase; vertical-align:middle; background:var(--app-surface-2); border:1px solid var(--app-border-strong); color:var(--app-muted); }
.kg-scroll { overflow:auto; max-height:calc(100dvh - 17rem); }
.kg-table { border-collapse:separate; border-spacing:0; width:auto; min-width:100%; }
.kg-table th, .kg-table td { border-bottom:1px solid var(--app-border); vertical-align:middle; }
/* Bootstrap paints table cells with --bs-table-bg: set that, not background, or sticky cells turn transparent over scrolled content. */
.kg-table thead th { position:sticky; top:0; z-index:3; --bs-table-bg:var(--bs-tertiary-bg); vertical-align:bottom; }
.kg-table tbody tr:nth-child(even) > * { --bs-table-bg:var(--app-surface-2); }
.kg-table tbody tr:nth-child(even) > .kg-person { --bs-table-bg:var(--app-surface-2); }
.kg-person-head, .kg-person { position:sticky; left:0; z-index:2; --bs-table-bg:var(--app-surface); min-width:220px; max-width:280px; border-right:1px solid var(--app-border); }
.kg-table thead .kg-person-head { z-index:4; --bs-table-bg:var(--bs-tertiary-bg); }
.kg-table tr.is-menu-open > *, .kg-table th.is-menu-open { z-index:6 !important; }
.kg-view-people tr[data-kg-kind="template"], .kg-view-templates tr[data-kg-kind="person"] { display:none; }
.kg-hint { font-size:.72rem; color:var(--app-muted); font-weight:400; }
.kg-person-name { font-weight:600; } .kg-person-sub { font-size:.75rem; color:var(--app-muted); }
.kg-row-off .kg-person-name { opacity:.6; }
.kg-row-menu { border:0; background:transparent; color:var(--app-muted); padding:0 .2rem; line-height:1; border-radius:4px; } .kg-row-menu:hover { color:var(--app-text); background:var(--app-surface-2); }
.kg-menu { min-width:16rem; }
/* column header */
.kg-col { text-align:center; padding:.25rem .15rem !important; width:34px; min-width:34px; max-width:34px; transition:width .15s; }
.kg-col-toggle { border:0; background:transparent; color:var(--app-text); padding:.2rem 0; cursor:pointer; display:flex; flex-direction:column; align-items:center; width:100%; border-radius:4px; }
.kg-col-toggle:hover { background:var(--app-surface); }
.kg-col.is-open .kg-col-toggle { color:var(--bs-primary); }
.kg-col-name { writing-mode:vertical-rl; transform:rotate(180deg); font-weight:700; font-size:.78rem; letter-spacing:.02em; max-height:120px; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; line-height:1.1; }
.kg-col-tools { display:none; justify-content:center; gap:.2rem; margin-top:.25rem; }
.kg-col.is-open { width:118px; min-width:118px; max-width:118px; }
.kg-col.is-open .kg-col-name { writing-mode:horizontal-tb; transform:none; max-height:none; max-width:110px; }
.kg-col.is-open .kg-col-tools { display:flex; }
.kg-col-pc { width:44px; min-width:44px; max-width:none; border-left:1px solid var(--app-border); }
.kg-col-name-fixed { writing-mode:horizontal-tb; transform:none; font-size:.7rem; }
.kg-all { border:1px dashed var(--app-border-strong); background:transparent; color:var(--app-muted); font-size:.7rem; font-weight:700; width:1.6rem; height:1.3rem; border-radius:4px; line-height:1; padding:0; cursor:pointer; }
.kg-all-l:hover { border-color:var(--bs-success); color:var(--bs-success); } .kg-all-t:hover { border-color:var(--bs-danger); color:var(--bs-danger); }
/* cells */
.kg-cell { text-align:center; white-space:nowrap; padding:.25rem .15rem !important; }
.kg-cell.is-changed { --bs-table-bg:rgba(var(--bs-warning-rgb), .15); }
.kg-btn { display:inline-flex; align-items:center; justify-content:center; border:1px solid var(--app-border-strong); background:var(--app-surface-2); color:var(--app-muted); font-weight:700; cursor:pointer; user-select:none; vertical-align:middle; }
/* closed: a pill of two halves, 12 px each, no text */
.kg-cell:not(.is-open) .kg-btn { width:11px; height:20px; margin:0; font-size:0; border-color:var(--app-border); background:transparent; cursor:zoom-in; }
.kg-cell:not(.is-open) .kg-btn:hover { border-color:var(--app-border); color:inherit; }
.kg-cell:not(.is-open) .kg-btn-l { border-radius:10px 0 0 10px; border-right-width:0; }
.kg-cell:not(.is-open) .kg-btn-t { border-radius:0 10px 10px 0; }
.kg-cell:not(.is-open) .btn-check:checked + .kg-btn-l { background:var(--bs-success); border-color:var(--bs-success); }
.kg-cell:not(.is-open) .btn-check:checked + .kg-btn-t { background:var(--bs-danger); border-color:var(--bs-danger); }
/* open: full buttons with letters */
.kg-cell.is-open .kg-btn { width:2rem; height:2rem; border-radius:6px; font-size:.8rem; margin:0 1px; }
.kg-btn:hover { border-color:var(--app-text); color:var(--app-text); }
.btn-check:checked + .kg-btn-l { background:var(--bs-success); border-color:var(--bs-success); color:#fff; }
.btn-check:checked + .kg-btn-t { background:var(--bs-danger); border-color:var(--bs-danger); color:#fff; }
.btn-check:checked + .kg-btn-pc { background:var(--bs-primary); border-color:var(--bs-primary); color:#fff; }
.btn-check:focus-visible + .kg-btn { outline:2px solid var(--bs-primary); outline-offset:1px; }
.kg-cell-pc { border-left:1px solid var(--app-border); } .kg-cell-pc .kg-btn { width:2rem; height:2rem; border-radius:6px; font-size:.8rem; }
@media (max-width: 575.98px) { .kg-person-head, .kg-person { min-width:160px; max-width:180px; } }

/* ---- Live now (system.php, assets/system_live.js) -------------------------- */
.live-channels { display:grid; grid-template-columns:repeat(auto-fill, minmax(180px, 1fr)); gap:.5rem; }
.live-channel { border:1px solid var(--app-border); border-radius:var(--app-radius); padding:.4rem .6rem; background:var(--app-surface); }
.live-channel.is-active { border-color:var(--bs-danger); background:rgba(var(--bs-danger-rgb), .08); }
.live-channel .name { font-weight:700; font-size:.9rem; } .live-channel .who { font-size:.8rem; min-height:1.2em; }
.live-channel .who:empty::before { content:'quiet'; color:var(--app-muted); }
.live-channel .count { font-size:.75rem; color:var(--app-muted); }

/* ---- flatpickr (assets/vendor/flatpickr) on the app's tokens, light and dark. The visible field is the altInput (a normal .form-control). ---- */
.flatpickr-calendar { background:var(--app-surface); color:var(--app-text); border:1px solid var(--app-border); box-shadow:0 .5rem 1.5rem rgba(0,0,0,.18); border-radius:8px; }
.flatpickr-calendar.arrowTop:before { border-bottom-color:var(--app-border); } .flatpickr-calendar.arrowTop:after { border-bottom-color:var(--app-surface); }
.flatpickr-calendar.arrowBottom:before { border-top-color:var(--app-border); } .flatpickr-calendar.arrowBottom:after { border-top-color:var(--app-surface); }
.flatpickr-months .flatpickr-month, .flatpickr-current-month, .flatpickr-weekdays, span.flatpickr-weekday { color:var(--app-text); fill:var(--app-text); background:transparent; }
.flatpickr-months .flatpickr-prev-month, .flatpickr-months .flatpickr-next-month { color:var(--app-text); fill:var(--app-text); }
.flatpickr-months .flatpickr-prev-month svg, .flatpickr-months .flatpickr-next-month svg { fill:var(--app-text); }
.flatpickr-current-month .flatpickr-monthDropdown-months, .flatpickr-current-month input.cur-year { background:var(--app-surface); color:var(--app-text); }
.flatpickr-day { color:var(--app-text); }
.flatpickr-day.flatpickr-disabled, .flatpickr-day.flatpickr-disabled:hover, .flatpickr-day.prevMonthDay, .flatpickr-day.nextMonthDay { color:var(--app-muted); }
.flatpickr-day:hover, .flatpickr-day.prevMonthDay:hover, .flatpickr-day.nextMonthDay:hover, .flatpickr-day:focus { background:var(--app-surface-2); border-color:var(--app-border); }
.flatpickr-day.today { border-color:var(--bs-primary); }
.flatpickr-day.selected, .flatpickr-day.selected:hover, .flatpickr-day.selected:focus { background:var(--bs-primary); border-color:var(--bs-primary); color:#fff; }
.flatpickr-time { border-top:1px solid var(--app-border); }
.flatpickr-time input, .flatpickr-time .flatpickr-am-pm, .flatpickr-time .flatpickr-time-separator { background:var(--app-surface); color:var(--app-text); }
.flatpickr-time input:hover, .flatpickr-time .flatpickr-am-pm:hover, .flatpickr-time input:focus, .flatpickr-time .flatpickr-am-pm:focus { background:var(--app-surface-2); }
.flatpickr-time .numInputWrapper span.arrowUp:after { border-bottom-color:var(--app-muted); } .flatpickr-time .numInputWrapper span.arrowDown:after { border-top-color:var(--app-muted); }
.flatpickr-wrapper { display:block; }
.modal .flatpickr-calendar.static { box-shadow:0 .25rem 1rem rgba(0,0,0,.18); }

/* ---- Routing matrix (system_routing.php): sources down, destinations across; sticky headers; a cell is one patch. ---- */
.rt-links { display:grid; grid-template-columns:repeat(auto-fill, minmax(320px, 1fr)); gap:.75rem; }
.rt-link, .rt-link .card-body { min-width:0; }
.rt-link .small { overflow-wrap:anywhere; }
.rt-scroll { overflow:auto; max-height:70vh; }
.rt-table { border-collapse:separate; border-spacing:0; width:auto; min-width:100%; }
.rt-table th, .rt-table td { border-bottom:1px solid var(--app-border); }
.rt-corner { position:sticky; left:0; top:0; z-index:3; background:var(--app-surface); min-width:170px; font-size:.68rem; color:var(--app-muted); text-transform:uppercase; letter-spacing:.04em; vertical-align:bottom; }
.rt-corner-src { display:block; } .rt-corner-dst { display:block; text-align:right; }
.rt-col { position:sticky; top:0; z-index:2; background:var(--app-surface); text-align:center; min-width:66px; vertical-align:bottom; padding:.4rem .25rem !important; }
.rt-col-name, .rt-row-name { font-weight:700; font-size:.85rem; letter-spacing:.02em; white-space:nowrap; }
.rt-col-sub, .rt-row-sub { font-size:.66rem; color:var(--app-muted); text-transform:uppercase; letter-spacing:.03em; white-space:nowrap; }
.rt-col-link .rt-col-name, .rt-row-link .rt-row-name { color:var(--app-accent); }
.rt-col-pl .rt-col-name, .rt-row-pl .rt-row-name { color:var(--bs-success); }
.rt-col-pl, .rt-row-pl { background:rgba(var(--bs-success-rgb), .06); }
.rt-col-link, .rt-row-link { background:rgba(var(--bs-primary-rgb), .05); }
.rt-key { display:inline-block; padding:0 .4em; border-radius:4px; font-size:.75rem; font-weight:700; letter-spacing:.02em; border:1px solid var(--app-border); }
.rt-key-local { color:var(--app-text); } .rt-key-pl { color:var(--bs-success); background:rgba(var(--bs-success-rgb), .08); } .rt-key-link { color:var(--app-accent); background:rgba(var(--bs-primary-rgb), .06); }
.rt-row { position:sticky; left:0; z-index:1; background:var(--app-surface); min-width:170px; padding:.35rem .6rem !important; vertical-align:middle; }
.rt-cell-td { text-align:center; padding:.2rem !important; vertical-align:middle; }
.rt-cell { position:relative; display:inline-flex; align-items:center; justify-content:center; width:44px; height:36px; border-radius:6px; border:1px solid var(--app-border-strong); background:var(--app-surface-2); color:#fff; font-size:.78rem; font-weight:700; cursor:pointer; vertical-align:middle; }
.rt-cell:hover { border-color:var(--app-accent); }
.rt-cell.is-on { background:var(--app-accent); border-color:var(--app-accent); }
.rt-cell.is-on.is-muted { background:var(--app-muted); border-color:var(--app-muted); background-image:repeating-linear-gradient(135deg, rgba(255,255,255,.25) 0 3px, transparent 3px 7px); }
.rt-cell.has-end::after { content:''; position:absolute; top:3px; right:3px; width:6px; height:6px; border-radius:50%; background:var(--bs-warning); }
.rt-cell.is-locked, .rt-cell.is-blocked { cursor:default; background:transparent; border-color:transparent; color:var(--app-muted); font-size:.7rem; }
.rt-cell.is-blocked { color:var(--bs-danger); opacity:.55; font-size:1rem; }
.rt-trim { border:0; background:transparent; color:var(--app-muted); font-size:.66rem; padding:0 .2em; cursor:pointer; text-transform:none; letter-spacing:0; }
.rt-trim:hover { color:var(--app-text); }
.rt-swatch { display:inline-flex; width:1.6em; height:1.2em; border-radius:3px; vertical-align:middle; border:1px solid var(--app-border-strong); background:var(--app-surface-2); align-items:center; justify-content:center; font-size:.6rem; color:var(--app-muted); }
.rt-swatch.is-on { background:var(--app-accent); border-color:var(--app-accent); }
.rt-swatch.is-on.is-muted { background:var(--app-muted); border-color:var(--app-muted); background-image:repeating-linear-gradient(135deg, rgba(255,255,255,.25) 0 3px, transparent 3px 7px); }
.rt-swatch.is-locked, .rt-swatch.is-blocked { background:transparent; border-color:transparent; }
.rt-swatch.is-blocked { color:var(--bs-danger); font-size:.8rem; }
/* Intercom: a channel that also carries routed audio (other channels or systems) */
.comms-key.is-linked .comms-key-kind::before { content:'⇄ '; color:var(--app-accent); font-weight:700; }
/* Party line cards: member chips, host's boot button */
.rt-pl { border-left:3px solid var(--app-accent); }
.rt-pl-members { display:flex; flex-wrap:wrap; gap:.35rem; }
.rt-pl-member { display:inline-flex; align-items:center; gap:.3rem; padding:.15rem .55rem; border-radius:999px; background:var(--app-surface-2); border:1px solid var(--app-border); font-size:.8rem; }
.rt-pl-member.is-invited { border-style:dashed; }
.rt-pl-member.is-bridged { background:transparent; border-style:dotted; }
.rt-pl-boot { border:0; background:transparent; color:var(--app-muted); padding:0 .1rem; line-height:1; cursor:pointer; font-size:.75rem; }
.rt-pl-boot:hover { color:var(--bs-danger); }
.rt-cell.is-na { background:transparent; border-color:transparent; cursor:default; }

/* ---- Tally (Decisions 2026-10-22) ---- */
.tally-dot { display:inline-block; width:12px; height:12px; border-radius:50%; background:var(--app-border-strong); vertical-align:middle; }
.tally-dot.is-pgm { background:#e5102e; box-shadow:0 0 6px #e5102e; } .tally-dot.is-pvw { background:#19a84b; } .tally-dot.is-aux { background:#e8a317; } .tally-dot.is-online { background:var(--bs-success); }
/* The third colour ("aux", amber): built in everywhere, off by default (Global settings → Tally), 2026-10-26. */
/* Intercom page: the op's camera bar + a glow around the viewport. Inset so the keys stay readable; a short pulse on change. */
.comms-tally { display:flex; align-items:center; gap:.6rem; padding:.5rem .75rem; margin-bottom:.6rem; border-radius:var(--app-radius); border:1px solid var(--app-border); background:var(--app-surface); color:var(--app-text); text-decoration:none; font-weight:600; }
.comms-tally:hover { color:var(--app-text); border-color:var(--app-border-strong); }
.comms-tally-dot { width:14px; height:14px; border-radius:50%; background:var(--app-border-strong); flex:0 0 auto; }
.comms-tally.is-pgm { background:#e5102e; border-color:#e5102e; color:#fff; } .comms-tally.is-pgm .comms-tally-dot { background:#fff; }
.comms-tally.is-pvw { background:#19a84b; border-color:#19a84b; color:#fff; } .comms-tally.is-pvw .comms-tally-dot { background:#fff; }
.comms-tally.is-aux { background:#e8a317; border-color:#e8a317; color:#1a1300; } .comms-tally.is-aux .comms-tally-dot { background:#1a1300; }
.comms-tally.is-offline { border-style:dashed; color:var(--app-muted); }
.comms-tally-state { font-weight:400; opacity:.9; text-transform:uppercase; font-size:.8rem; letter-spacing:.05em; }
.comms-tally { cursor:pointer; text-align:left; font:inherit; }
.comms-tally-view { position:fixed; inset:0; z-index:1075; border-radius:0; min-height:100dvh; }
.comms-tally-view .btn-outline-light { --bs-btn-color:#fff; --bs-btn-border-color:rgba(255,255,255,.5); }
body.comms-tally-open::after { display:none; } /* the view is the tally; no glow on top of it */
body.tally-pgm::after, body.tally-pvw::after { content:''; position:fixed; inset:0; pointer-events:none; z-index:1080; box-shadow:inset 0 0 0 6px #e5102e, inset 0 0 40px 10px rgba(229,16,46,.45); animation:tally-pulse .6s ease-out 1; }
body.tally-pvw::after { box-shadow:inset 0 0 0 6px #19a84b, inset 0 0 40px 10px rgba(25,168,75,.4); }
body.tally-aux::after { content:''; position:fixed; inset:0; pointer-events:none; z-index:1080; box-shadow:inset 0 0 0 6px #e8a317, inset 0 0 40px 10px rgba(232,163,23,.4); animation:tally-pulse .6s ease-out 1; }
@keyframes tally-pulse { 0% { box-shadow:inset 0 0 0 14px #fff; } 100% { } }
/* Tally view: own camera = the whole screen. */
body.is-tally main, body.is-tally .app-main { padding-bottom:0; }
.tally { display:flex; flex-direction:column; min-height:calc(100dvh - 7rem); border-radius:var(--app-radius); overflow:hidden; background:#101214; color:#fff; }
.tally-bar { display:flex; align-items:center; justify-content:space-between; gap:.75rem; padding:.5rem .75rem; background:rgba(255,255,255,.06); }
.tally-bar .text-muted { color:rgba(255,255,255,.6) !important; }
.tally-mine { flex:1 1 auto; display:flex; flex-direction:column; align-items:center; justify-content:center; text-align:center; padding:1rem; transition:background .15s; }
.tally-mine-name { font-size:clamp(2.5rem, 12vw, 7rem); font-weight:800; letter-spacing:.02em; line-height:1; }
.tally-mine-state { font-size:clamp(1.1rem, 4vw, 2rem); text-transform:uppercase; letter-spacing:.12em; opacity:.85; margin-top:.75rem; }
.tally.is-pgm .tally-mine { background:#e5102e; } .tally.is-pvw .tally-mine { background:#19a84b; } .tally.is-aux .tally-mine { background:#e8a317; color:#1a1300; }
.tally.is-offline .tally-mine { background:repeating-linear-gradient(135deg, #1a1d21 0 14px, #23272c 14px 28px); color:rgba(255,255,255,.6); }
.tally-board { flex:1 1 auto; display:grid; grid-template-columns:repeat(auto-fill, minmax(150px, 1fr)); gap:.5rem; padding:.6rem; align-content:start; }
.tally-cell { border-radius:8px; padding:.6rem .7rem; background:#1d2024; border:2px solid transparent; min-height:84px; display:flex; flex-direction:column; justify-content:space-between; }
.tally-cell.is-pgm { background:#e5102e; } .tally-cell.is-pvw { background:#19a84b; } .tally-cell.is-aux { background:#e8a317; color:#1a1300; } .tally-cell.is-mine { border-color:#fff; }
.tally-cell-no { font-size:.8rem; opacity:.7; } .tally-cell-name { font-size:1.25rem; font-weight:700; line-height:1.1; }
.tally-note { padding:.4rem .75rem; min-height:1.8em; color:rgba(255,255,255,.65) !important; }

/* Setup grid: the "Audio bridges" group row (gateway.php, 2026-10-28) */
.kg-table tr.kg-group th, .kg-table tr.kg-group td { background:rgba(var(--bs-secondary-rgb), .07); border-bottom:1px solid var(--app-border); }

/* Program feeds (2026-10-29): the Setup column tag and the crew client's feed card */
.kg-col-kind { display:block; font-size:.6rem; text-transform:uppercase; letter-spacing:.04em; color:var(--app-accent); font-weight:600; line-height:1; margin-top:.15rem; }
.comms-key.is-program .comms-key-kind { color:var(--app-accent); font-weight:600; }
.comms-key.is-program.is-dimmed .comms-key-kind::after { content:' · dimmed'; font-weight:400; color:var(--app-muted); }
.comms-person.is-away { opacity:.65; } /* every device of theirs lost its signalling socket and may resume (2026-10-29) */
.comms-tally.is-offline { opacity:.55; filter:grayscale(1); } /* the intercom's tally bar while the socket is down (review 2026-10-29) */

/* Knowledge base (/kb/, 2026-11-02): its own shell — header, contents, article typography, "on this page". Tokens only.
   Bootstrap's responsive offcanvas turns .offcanvas-body into a flex ROW at ≥ lg; the contents must stay a column. */
body.kb { background:var(--app-bg); }
.kb-top { position:sticky; top:0; z-index:1020; display:flex; align-items:center; gap:.75rem; padding:.55rem 1rem; background:color-mix(in srgb, var(--app-surface) 82%, transparent); backdrop-filter:saturate(1.4) blur(12px); -webkit-backdrop-filter:saturate(1.4) blur(12px); border-bottom:1px solid var(--app-border); }
.kb-top-inner { display:flex; align-items:center; gap:.75rem; width:100%; max-width:1280px; margin:0 auto; }
.kb-brand { display:flex; align-items:center; gap:.55rem; color:var(--app-text); text-decoration:none; font-weight:650; white-space:nowrap; }
.kb-brand img { height:26px; width:26px; border-radius:7px; }
.kb-brand-sub { display:inline-flex; align-items:center; padding:.1rem .5rem; border-radius:999px; background:var(--app-accent-subtle); color:var(--app-accent-text); font-size:.72rem; font-weight:600; letter-spacing:.04em; text-transform:uppercase; }
.kb-search { position:relative; flex:1 1 auto; max-width:380px; margin-left:auto; }
.kb-search .bi { position:absolute; left:.75rem; top:50%; transform:translateY(-50%); color:var(--app-muted); font-size:.85rem; pointer-events:none; }
.kb-search .form-control { padding-left:2.1rem; border-radius:999px; font-size:.9rem; background:var(--app-surface-2); }
.kb-search .form-control:focus { background:var(--app-surface); }
.kb-open { white-space:nowrap; border-radius:999px; }
.kb-wrap { display:grid; grid-template-columns:240px minmax(0, 1fr); gap:2.75rem; max-width:1280px; margin:0 auto; padding:2rem 1.25rem 5rem; }
.kb-wrap.has-toc { grid-template-columns:240px minmax(0, 1fr) 200px; }
.kb-nav { display:block; }
.kb-nav-body { display:block !important; flex-grow:0; position:sticky; top:4.25rem; max-height:calc(100vh - 5.5rem); overflow:auto; padding:0 .5rem 1rem 0 !important; scrollbar-width:thin; }
.kb-nav .nav-section { font-size:.68rem; text-transform:uppercase; letter-spacing:.08em; color:var(--app-muted); font-weight:650; margin:1.25rem 0 .35rem .65rem; }
.kb-nav .nav-section:first-child { margin-top:0; }
.kb-nav .nav-link { display:block; padding:.34rem .65rem; border-radius:.45rem; color:var(--app-text); font-size:.875rem; line-height:1.35; border-left:2px solid transparent; }
.kb-nav .nav-link:hover { background:var(--app-surface-2); color:var(--app-text); }
.kb-nav .nav-link.active { background:var(--app-accent-subtle); color:var(--app-accent-text); font-weight:600; border-left-color:var(--app-accent); border-radius:0 .45rem .45rem 0; }
.kb-main { min-width:0; }
.kb-crumbs { font-size:.8rem; color:var(--app-muted); margin-bottom:.9rem; }
.kb-crumbs a { color:inherit; text-decoration:none; } .kb-crumbs a:hover { color:var(--app-accent-text); }
.kb-crumbs .bi { font-size:.6rem; margin:0 .25rem; }
.kb-hero { position:relative; overflow:hidden; border-radius:1.1rem; padding:2.75rem 2.25rem; margin-bottom:2rem; background:linear-gradient(135deg, var(--app-accent-subtle), var(--app-surface) 70%); border:1px solid var(--app-border); }
.kb-hero::after { content:""; position:absolute; inset:auto -12% -55% auto; width:55%; aspect-ratio:1; border-radius:50%; background:radial-gradient(circle, rgba(var(--app-accent-rgb), .22), transparent 65%); pointer-events:none; }
.kb-hero h1 { font-size:2.35rem; font-weight:750; letter-spacing:-.02em; margin:0 0 .4rem; max-width:640px; position:relative; }
.kb-hero p { font-size:1.08rem; color:var(--app-muted); max-width:600px; margin:0 0 1.25rem; position:relative; }
.kb-hero .kb-search { max-width:520px; margin:0; position:relative; }
.kb-hero .kb-search .form-control { padding:.7rem 1rem .7rem 2.4rem; font-size:1rem; box-shadow:var(--app-shadow); }
.kb-start { display:grid; grid-template-columns:repeat(auto-fit, minmax(220px, 1fr)); gap:.85rem; margin:0 0 2.5rem; }
.kb-start-card { display:flex; gap:.85rem; align-items:flex-start; padding:1rem 1.1rem; background:var(--app-surface); border:1px solid var(--app-border); border-radius:.9rem; color:var(--app-text); text-decoration:none; box-shadow:var(--app-shadow); transition:transform .12s, border-color .12s, box-shadow .12s; }
.kb-start-card:hover { border-color:var(--app-accent); transform:translateY(-2px); box-shadow:var(--app-shadow-lg); color:var(--app-text); }
.kb-start-card .bi { font-size:1.25rem; color:var(--app-accent); line-height:1; padding:.55rem; border-radius:.6rem; background:var(--app-accent-subtle); }
.kb-start-card strong { display:block; font-weight:650; } .kb-start-card span { color:var(--app-muted); font-size:.875rem; }
.kb-section { margin-top:2rem; }
.kb-section-title { display:flex; align-items:center; gap:.6rem; font-size:1.05rem; font-weight:650; margin:0 0 .75rem; }
.kb-section-title .bi { color:var(--app-accent); font-size:1rem; }
.kb-cards { display:grid; grid-template-columns:repeat(auto-fill, minmax(230px, 1fr)); gap:.7rem; }
.kb-card { display:block; padding:.85rem 1rem; background:var(--app-surface); border:1px solid var(--app-border); border-radius:.75rem; color:var(--app-text); text-decoration:none; transition:border-color .12s, transform .12s; }
.kb-card:hover { border-color:var(--app-accent); transform:translateY(-1px); color:var(--app-text); }
.kb-card strong { display:block; font-size:.95rem; font-weight:650; } .kb-card span { display:block; color:var(--app-muted); font-size:.8125rem; margin-top:.2rem; line-height:1.45; }
.kb-article { max-width:720px; font-size:1rem; line-height:1.7; }
.kb-article h1 { font-size:2.1rem; font-weight:750; letter-spacing:-.02em; margin-bottom:.6rem; line-height:1.15; }
.kb-article h2 { font-size:1.3rem; font-weight:650; margin:2.4rem 0 .7rem; padding-top:1.4rem; border-top:1px solid var(--app-border); scroll-margin-top:5rem; letter-spacing:-.01em; }
.kb-article h3 { font-size:1.05rem; font-weight:650; margin:1.6rem 0 .45rem; scroll-margin-top:5rem; }
.kb-article .kb-lead { font-size:1.15rem; color:var(--app-muted); line-height:1.55; margin-bottom:1.5rem; }
.kb-article p, .kb-article ul, .kb-article ol { margin-bottom:1rem; }
.kb-article ul, .kb-article ol { padding-left:1.35rem; }
.kb-article li { margin-bottom:.4rem; padding-left:.15rem; }
.kb-article li::marker { color:var(--app-muted); }
.kb-article li > ul, .kb-article li > ol { margin-top:.35rem; margin-bottom:.35rem; }
.kb-article strong { font-weight:650; color:var(--app-text); }
.kb-article a { text-decoration-thickness:1px; text-underline-offset:.15em; }
.kb-article kbd { font-size:.8em; padding:.1em .45em; border-radius:.35em; }
.kb-article .kb-note { display:flex; gap:.7rem; align-items:flex-start; border:1px solid rgba(var(--app-accent-rgb), .35); background:var(--app-accent-subtle); padding:.8rem 1rem; border-radius:.75rem; margin:1.25rem 0; }
.kb-article .kb-note::before { content:"\F431"; font-family:"bootstrap-icons"; color:var(--app-accent-text); font-size:1.05rem; line-height:1.5; }
.kb-article .kb-note p:last-child { margin-bottom:0; }
.kb-article .kb-warn { border-color:rgba(var(--bs-warning-rgb), .45); background:rgba(var(--bs-warning-rgb), .12); }
.kb-article .kb-warn::before { content:"\F33B"; color:var(--bs-warning); }
.kb-article table { width:100%; border-collapse:separate; border-spacing:0; margin:0 0 1.25rem; font-size:.9rem; border:1px solid var(--app-border); border-radius:.6rem; overflow:hidden; }
.kb-article th, .kb-article td { padding:.55rem .75rem; border-bottom:1px solid var(--app-border); text-align:left; vertical-align:top; }
.kb-article tr:last-child td { border-bottom:0; }
.kb-article th { font-weight:650; color:var(--app-muted); font-size:.75rem; text-transform:uppercase; letter-spacing:.05em; background:var(--app-surface-2); }
.kb-article td strong { white-space:nowrap; }
.kb-toc { position:sticky; top:4.25rem; align-self:start; font-size:.8125rem; padding-left:1rem; border-left:1px solid var(--app-border); }
.kb-toc-title { font-size:.68rem; text-transform:uppercase; letter-spacing:.08em; color:var(--app-muted); font-weight:650; margin-bottom:.5rem; }
.kb-toc a { display:block; color:var(--app-muted); text-decoration:none; padding:.2rem 0; line-height:1.35; }
.kb-toc a:hover { color:var(--app-accent-text); }
.kb-pager { display:grid; grid-template-columns:1fr 1fr; gap:.75rem; margin-top:3rem; max-width:720px; }
.kb-pager a { display:flex; align-items:center; gap:.7rem; padding:.85rem 1rem; border:1px solid var(--app-border); border-radius:.75rem; background:var(--app-surface); color:var(--app-text); text-decoration:none; font-weight:600; transition:border-color .12s; }
.kb-pager a:hover { border-color:var(--app-accent); color:var(--app-accent-text); }
.kb-pager a .bi { color:var(--app-muted); }
.kb-pager-label { display:block; font-size:.68rem; font-weight:500; color:var(--app-muted); text-transform:uppercase; letter-spacing:.06em; margin-bottom:.1rem; }
.kb-pager-next { text-align:right; justify-content:flex-end; grid-column:2; }
.kb-title { font-size:2.1rem; font-weight:750; letter-spacing:-.02em; margin-bottom:.4rem; }
.kb-lead { font-size:1.08rem; color:var(--app-muted); max-width:720px; }
.kb-results { display:flex; flex-direction:column; gap:.6rem; max-width:720px; }
.kb-result { padding:.9rem 1.1rem; background:var(--app-surface); border:1px solid var(--app-border); border-radius:.75rem; }
.kb-result-title { font-weight:650; text-decoration:none; font-size:1.02rem; }
.kb-result-snippet { color:var(--app-muted); font-size:.9rem; margin-top:.2rem; line-height:1.5; }
mark.kb-hit { background:rgba(var(--app-accent-rgb), .22); color:inherit; padding:0 .1em; border-radius:.2em; }
@media (max-width: 1199.98px) { .kb-wrap.has-toc { grid-template-columns:240px minmax(0, 1fr); } .kb-toc { display:none; } }
@media (max-width: 991.98px) {
    .kb-wrap, .kb-wrap.has-toc { grid-template-columns:1fr; gap:1rem; padding:1.25rem 1rem 4rem; }
    .kb-nav-body { position:static; max-height:none; padding:1rem !important; }
    .kb-search { max-width:none; }
    .kb-hero { padding:1.75rem 1.25rem; } .kb-hero h1 { font-size:1.7rem; }
    .kb-title, .kb-article h1 { font-size:1.6rem; }
    .kb-pager { grid-template-columns:1fr; } .kb-pager-next { grid-column:auto; }
}
@media print { .kb-top, .kb-nav, .kb-pager, .kb-toc { display:none !important; } .kb-wrap { display:block; padding:0; } }
