@font-face {
  font-family: "IBM Plex Mono";
  src: url("../fonts/IBM_Plex_Mono/IBMPlexMono-Regular.woff2") format("woff2");
  font-style: normal;
  font-weight: 400;
  font-display: swap;
}
@font-face {
  font-family: "IBM Plex Mono";
  src: url("../fonts/IBM_Plex_Mono/IBMPlexMono-Medium.woff2") format("woff2");
  font-style: normal;
  font-weight: 500;
  font-display: swap;
}
@font-face {
  font-family: "IBM Plex Mono";
  src: url("../fonts/IBM_Plex_Mono/IBMPlexMono-SemiBold.woff2") format("woff2");
  font-style: normal;
  font-weight: 600;
  font-display: swap;
}
@font-face {
  font-family: "IBM Plex Mono";
  src: url("../fonts/IBM_Plex_Mono/IBMPlexMono-Bold.woff2") format("woff2");
  font-style: normal;
  font-weight: 700;
  font-display: swap;
}

@font-face {
  font-family: "IBM Plex Mono";
  src: url("../fonts/IBM_Plex_Mono/IBMPlexMono-Italic.woff2") format("woff2");
  font-style: italic;
  font-weight: 400;
  font-display: swap;
}
@font-face {
  font-family: "IBM Plex Mono";
  src: url("../fonts/IBM_Plex_Mono/IBMPlexMono-MediumItalic.woff2") format("woff2");
  font-style: italic;
  font-weight: 500;
  font-display: swap;
}
@font-face {
  font-family: "IBM Plex Mono";
  src: url("../fonts/IBM_Plex_Mono/IBMPlexMono-SemiBoldItalic.woff2") format("woff2");
  font-style: italic;
  font-weight: 600;
  font-display: swap;
}
@font-face {
  font-family: "IBM Plex Mono";
  src: url("../fonts/IBM_Plex_Mono/IBMPlexMono-BoldItalic.woff2") format("woff2");
  font-style: italic;
  font-weight: 700;
  font-display: swap;
}


@font-face {
  font-family: "IBM Plex Sans";
  src: url("../fonts/IBM_Plex_Sans/IBMPlexSans-Regular.woff2") format("woff2");
  font-style: normal;
  font-weight: 400;
  font-display: swap;
}
@font-face {
  font-family: "IBM Plex Sans";
  src: url("../fonts/IBM_Plex_Sans/IBMPlexSans-Medium.woff2") format("woff2");
  font-style: normal;
  font-weight: 500;
  font-display: swap;
}
@font-face {
  font-family: "IBM Plex Sans";
  src: url("../fonts/IBM_Plex_Sans/IBMPlexSans-SemiBold.woff2") format("woff2");
  font-style: normal;
  font-weight: 600;
  font-display: swap;
}
@font-face {
  font-family: "IBM Plex Sans";
  src: url("../fonts/IBM_Plex_Sans/IBMPlexSans-Bold.woff2") format("woff2");
  font-style: normal;
  font-weight: 700;
  font-display: swap;
}

@font-face {
  font-family: "IBM Plex Sans";
  src: url("../fonts/IBM_Plex_Sans/IBMPlexSans-Italic.woff2") format("woff2");
  font-style: italic;
  font-weight: 400;
  font-display: swap;
}
@font-face {
  font-family: "IBM Plex Sans";
  src: url("../fonts/IBM_Plex_Sans/IBMPlexSans-MediumItalic.woff2") format("woff2");
  font-style: italic;
  font-weight: 500;
  font-display: swap;
}
@font-face {
  font-family: "IBM Plex Sans";
  src: url("../fonts/IBM_Plex_Sans/IBMPlexSans-SemiBoldItalic.woff2") format("woff2");
  font-style: italic;
  font-weight: 600;
  font-display: swap;
}
@font-face {
  font-family: "IBM Plex Sans";
  src: url("../fonts/IBM_Plex_Sans/IBMPlexSans-BoldItalic.woff2") format("woff2");
  font-style: italic;
  font-weight: 700;
  font-display: swap;
}





/* ============================================================
   VeraLab Console — Design System
   Option C (heritage blue nav). Single source of truth.
   Everything is tokenized; components are reusable classes.
   ============================================================ */

/* ---------- 1. TOKENS ---------- */
:root {
  /* Brand chrome (constant across themes) */
  --header-bg:   #22313d;
  --nav-bg:      #1f4e79;
  --nav-bg-hi:   #29618f;          /* nav hover */
  --nav-text:    #bcd2ea;          /* nav inactive */
  --nav-text-hi: #ffffff;          /* nav active */
  --on-dark:     #e9eef4;          /* text on header */
  --on-dark-dim: #9fb0c0;          /* muted text on header */

  /* Single accent ramp — the ONLY orange. Logo matches --accent. */
  --accent:        #e8820e;
  --accent-hover:  #cf7109;
  --accent-press:  #b56107;
  --accent-soft:   #fdf1e1;        /* tint bg (hover, badges) */
  --on-accent:     #ffffff;

  /* Accent FILLS THAT CARRY TEXT (buttons, selected day, active segment).
     --accent #e8820e is only 2.75:1 behind white text, so text-bearing fills use this
     darker ramp: white ink measures 5.00 / 6.66 / 8.21, and the button boundary is
     5.00:1 on the light page and 3.01:1 on dark --surface.
     Fills WITHOUT text (nav underline, KPI edge, dots, chart bars) keep --accent so the
     brand amber stays vivid — especially the underline on the dark blue nav. */
  --accent-fill:       #a85c07;
  --accent-fill-hover: #8c4c06;
  --accent-fill-press: #784105;

  /* Status */
  --ok:        #16a34a;
  --ok-soft:   #e7f4ee;
  --warn:      #c77b16;
  --warn-soft: #fbf1df;
  --danger:    #c8321f;
  --danger-soft: #fae8e3;
  --danger-fill: #c8321f;  /* red fill that carries white text (.btn-danger), 5.34:1; same in both themes */
  --info:      #2563eb;

  /* Status text foregrounds. Keep saturated hues for bars, borders and standalone
     icons; normal-size text, including numeric cells and text on *-soft tints,
     uses these pairs to clear WCAG AA 4.5:1. */
  --ok-text:     #0b6b32;
  --warn-text:   #7a4a0b;
  --danger-text: #9e1414;
  --accent-text: #8a4b06;

  /* File-type hues — the one decorative-looking colour that is actually semantic:
     users scan for "the green one" / "the red one" when exporting. */
  /* accent text on DARK CHROME (header, dark dropdowns, mobile drawer).
     Theme-independent: that chrome is dark in both themes. --accent is only 4.08:1
     on the drawer's darkened panel, so text there needs this lighter tone. */
  --accent-on-dark: #f2a85c;
  --file-excel: #1d7044;
  --file-pdf:   #c0392b;
  --file-csv:   #1d5fbf;

  /* Neutral surfaces (light theme) */
  --page:    #eef0f3;
  --surface: #ffffff;
  --raised:  #f8f9fb;              /* table head, footer, subtle fills */
  --zebra:   #fafbfc;
  --border:  #e3e5e9;
  --border-strong: #d3d7dd;        /* decorative dividers and chart axes */
  --control-border: #7d8590;       /* input boundaries, at least 3.27:1 */
  --hover:   #f4f5f7;

  /* Text (light theme) */
  --text:        #2b303a;
  --text-strong: #1b2027;
  --text-soft:   #3b424e;
  --muted:       #4e5764;
  --muted-2:     #626975;          /* secondary text, at least 4.84:1 */

  /* Spacing scale — 4px base. Use these, nothing else. */
  --space-1: 4px;
  --space-2: 8px;
  --space-3: 12px;
  --space-4: 16px;
  --space-5: 24px;
  --space-6: 32px;
  --space-7: 48px;

  /* Radius — one general radius; pill for badges; cell for heatmap. */
  --radius:      8px;
  --radius-pill: 999px;
  --radius-cell: 4px;

  /* Type scale */
  --font-sans: 'IBM Plex Sans', system-ui, -apple-system, Segoe UI, Roboto, sans-serif;
  --font-mono: 'IBM Plex Mono', ui-monospace, SFMono-Regular, Menlo, monospace;
  --text-xs:   12px;
  --text-2xs:  11px;   /* chart axes and micro labels only (from veralab-core) */
  --text-sm:   13px;
  --text-base: 14px;
  --text-md:   15px;
  --text-lg:   16px;
  --text-xl:   20px;
  --text-2xl:  23px;
  --text-3xl:  27px;

  /* Elevation */
  --shadow-1: 0 1px 2px rgba(16,24,40,.06);
  --shadow-2: 0 4px 12px rgba(16,24,40,.10);
  --shadow-pop: 0 14px 34px -10px rgba(20,24,32,.34);

  /* Control sizing */
  --control-h: 36px;
  --header-h:  52px;
  --nav-h:     40px;

  /* coverage charts */
  --coverage-covered-block-color:#DCF6DF;
  --coverage-covered-border-color:#ADE9B6;
  --coverage-uncovered-block-color:#FFECED;
  --coverage-uncovered-border-color:#FF8A8F;
  --coverage-block-color: var(--text);

  --tooltipster-text:#FFF;
  --tooltipster-bg: var(--header-bg);

  --admin-booking-tile-width:  120px;
  --admin-booking-del-cell-width:  20px;
  --admin-class-booking-tile-width:  120px;
  --admin-class-booking-del-cell-width:  20px;
  --booking-cell-width-12h: 170px;
  --booking-cell-width-24h: 150px;
  --booking-first-column-width: 80px;
  --stripped-table-header-color: var(--raised);
  --blue:  #59a5e9;
}

/* ---------- 2. DARK THEME ---------- */
[data-theme="dark"] {
  --page:    #0f1a22;
  --surface: #1a2832;
  --raised:  #16242e;
  --zebra:   #1f303b;
  --border:  #2c3d49;
  --border-strong: #3a4d5a;
  --control-border: #6f8594;       /* input boundaries, at least 3.21:1 */
  --hover:   #243743;

  --text:        #dde4ea;
  --text-strong: #f2f6f9;
  --text-soft:   #c9d1d8;
  --muted:       #acb7c2;
  --muted-2:     #96a3ae;          /* secondary text, at least 4.79:1 */

  --accent-soft: #3a2a16;
  --ok-soft:     #16302360;
  --warn-soft:   #3a2f1660;
  --danger-soft: #3a201c60;
  --danger:      #ff7a6b;          /* light #c8321f is 2.8:1 on dark surfaces; this is 4.8+ on all of them */

  --ok-text:     #7fe0a6;
  --warn-text:   #f3c473;
  --danger-text: #f5a29a;
  --accent-text: #f2a85c;

  --info:       #7fb0ff;
  --file-excel: #4ec98a;
  --file-pdf:   #f08a80;
  --file-csv:   #7fb0ff;

  --shadow-1: 0 1px 2px rgba(0,0,0,.4);
  --shadow-2: 0 4px 12px rgba(0,0,0,.45);
  --shadow-pop: 0 16px 40px -12px rgba(0,0,0,.6);

  --coverage-block-color: #ddd;
  --tooltipster-text: #cccccc;
  --tooltipster-bg: #151515;
}

@media (max-width: 767px) and (hover: none) and (pointer: coarse) {
  :root {
    --space-1: 4px;
    --space-2: 6px;
    --space-3: 8px;
    --space-4: 12px;
    --space-5: 16px;
    --space-6: 24px;
    --space-7: 32px;

    --radius: 6px;
    --radius-cell: 3px;
  }
}

/* ---------- 3. RESET / BASE ---------- */
* { box-sizing: border-box; }
html, body { margin: 0; }
body {
  font-family: var(--font-sans);
  font-size: var(--text-base);
  color: var(--text);
  background: var(--page);
  -webkit-font-smoothing: antialiased;
}
h1, h2, h3, p { margin: 0; }
a { color: inherit; text-decoration: none; }
button { font: inherit; cursor: pointer; }
/* Form controls do not inherit the page font by default, so every input, select
   and textarea rendered in the browser's face while the text around it was the
   app's. .btn needs it too: it is applied to <a> and <input> as well as <button>,
   and only <button> is covered by the rule above. */
input, select, textarea, .btn { font-family: inherit; }
/* A disabled control has to read as disabled. Left to the browser a disabled
   select dims itself while a disabled text input beside it keeps full contrast,
   so one row disagreed with itself. */
.form-control:disabled, .select:disabled, .input:disabled {
  background: var(--raised); color: var(--muted); opacity: 1; cursor: not-allowed;
}
.cal-btn:disabled { background: var(--raised); color: var(--muted-2); cursor: not-allowed; }
table { border-collapse: collapse; width: 100%; }
code { font-family: var(--font-mono); font-size: .92em; }
.mono { font-family: var(--font-mono); }

/* ---------- 4. APP LAYOUT ---------- */
.app {
  min-height: 100vh;
  min-width: var(--app-nav-min-width, 0);
  display: flex;
  flex-direction: column;
}

.app-header {
  height: var(--header-h);
  background: var(--header-bg);
  display: flex; align-items: center;
  gap: var(--space-4);
  padding: 0 var(--space-5) 0 12px;
  position: relative; z-index: 60;
}
.app-logo { display: block; margin-left:20px;}
.header-center { margin: 0 auto; display: flex; align-items: center; gap: var(--space-3); }
.header-label { font-size: var(--text-sm); color: var(--on-dark-dim); }
.header-right { display: flex; align-items: center; gap: var(--space-4); }
.header-welcome { font-size: var(--text-sm); color: var(--on-dark-dim); }
.header-welcome b { color: var(--accent-on-dark); font-weight: 600; }

/* pill control on dark header */
.dept-pill {
  display: inline-flex; align-items: center; gap: var(--space-2);
  font-size: var(--text-sm); font-weight: 600; color: var(--on-dark);
  padding: 6px var(--space-3);
  border: 1px solid #41566a; border-radius: var(--radius);
  background: transparent;
}
.dept-pill .caret { color: var(--on-dark-dim); font-size: 11px; }

.avatar {
  width: 32px; height: 32px; border-radius: var(--radius);
  background: #34465a; color: #cfd9e3;
  display: flex; align-items: center; justify-content: center;
  font-size: var(--text-sm); font-weight: 600; border: none;
}
.burger { display: flex; flex-direction: column; gap: 3px; background: none; border: none; padding: 4px; }
.burger span { width: 18px; height: 2px; background: var(--on-dark-dim); border-radius: 2px; }

/* nav (heritage blue) */
.app-nav {
  height: var(--nav-h);
  background: var(--nav-bg);
  display: flex; align-items: stretch;
  padding: 0 var(--space-4);
  position: relative; z-index: 30;
}
.app-nav-utility { display: none; }
.nav-item {
  display: flex; align-items: center; gap: 6px;
  padding: 0 var(--space-4);
  font-size: var(--text-base); font-weight: 600;
  color: var(--nav-text);
  background: none; border: none;
  box-shadow: inset 0 0 0 transparent;
  white-space: nowrap;
}
.nav-item:hover { color: #fff; background: var(--nav-bg-hi); }
.nav-item .caret { font-size: 10px; opacity: .75; }
.nav-item-active {
  color: var(--nav-text-hi);
  box-shadow: inset 0 -3px 0 var(--accent);
}

.app-main { flex: 1; min-width: 0; }
.app-footer {
  background: var(--raised);
  border-top: 1px solid var(--border);
  padding: var(--space-4);
  text-align: center;
  font-size: var(--text-xs); color: var(--muted);
}

/* page container — fluid + capped, consistent gutters */
.page { padding: var(--space-5) var(--space-6); display: flex; flex-direction: column; gap: var(--space-5); }
.page-warning { padding: var(--space-6) var(--space-5) 0 var(--space-5); display: flex; flex-direction: column; gap: var(--space-5); }
.page-narrow { max-width: 1000px; }
.page-title { font-size: var(--text-2xl); font-weight: 700; letter-spacing: -.01em; color: var(--text-strong); }
.page-subtitle { font-size: var(--text-sm); color: var(--muted); margin-top: var(--space-1); }
.section { display: flex; flex-direction: column; gap: var(--space-4); }
.eyebrow { font-size: 10.5px; font-weight: 600; text-transform: uppercase; letter-spacing: .12em; color: var(--muted); }

/* ---------- 5. DROPDOWN MENUS ---------- */
.menu-wrap { position: relative; display: flex; }
.menu {
  position: absolute; top: 100%; left: 0; min-width: 210px;
  background: var(--surface); border: 1px solid var(--border);
  border-radius: var(--radius); box-shadow: var(--shadow-pop);
  padding: var(--space-2); z-index: 50;
  display: none; flex-direction: column;
}
.menu.is-open { display: flex; }
.menu.menu-align-right { left: auto; right: 0; }
.menu-item {
  padding: 9px var(--space-3); border-radius: 6px;
  font-size: var(--text-sm); color: var(--text); text-align: left;
  background: none; border: none; cursor: pointer;
}
.menu-item:hover { background: var(--hover); }
.menu-item-primary { color: var(--accent-text); font-weight: 600; }
.menu-item-primary:hover { background: var(--accent-soft); }
.menu-divider { height: 1px; background: var(--border); margin: var(--space-2) 6px; }
.menu-badge {
  font-size: 9px; font-weight: 600; letter-spacing: .08em;
  color: var(--accent-text); background: var(--accent-soft);
  padding: 1px 5px; border-radius: 4px; margin-left: 6px;
}

/* header (dark) dropdown variant */
.menu-dark {
  background: var(--header-bg); border-color: #34465a;
}
.menu-dark .menu-item { color: #dbe3ec; }
.menu-dark .menu-item:hover { background: #2c3e4c; }
.menu-dark .menu-item-primary { color: var(--accent-on-dark); }
.menu-dark .menu-item-primary:hover { background: #2c3e4c; }
.menu-dark .menu-divider { background: #34465a; }

.menu-overlay { position: fixed; inset: 0; z-index: 20; display: none; }
.menu-overlay.is-open { display: block; }

/* ---------- 6. BUTTONS (one definition each) ---------- */
.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: var(--space-2);
  height: var(--control-h); padding: 0 var(--space-5);
  font-size: var(--text-sm); font-weight: 600;
  border-radius: var(--radius); border: 1px solid transparent;
  white-space: nowrap; transition: background .12s, border-color .12s;
  cursor: pointer;
}
.btn-primary { background: var(--accent-fill); color: var(--on-accent); }
.btn-primary:hover { background: var(--accent-fill-hover);color: var(--on-accent);text-decoration: none; }
.btn-primary:active { background: var(--accent-fill-press); }
.btn-default { background: var(--surface); color: var(--text-soft); border-color: var(--border-strong); }
.btn-default:hover { background: var(--hover); }
.btn--sm { height: 30px; padding: 0 var(--space-3); }

/* Filter buttons, shared with the design system. */
.filter-chip {
  border: 1px solid var(--border-strong); background: var(--surface);
  border-radius: 6px; padding: 0 11px; height: var(--control-h);
  font: inherit; font-size: var(--text-sm); color: var(--text-soft);
  display: inline-flex; align-items: center; white-space: nowrap;
}
.filter-chip:hover { background: var(--hover); }
.filter-chip.is-on { border-color: var(--accent); background: var(--accent-soft); color: var(--accent-text); font-weight: 600; }
.filter-chip-count { margin-left: 6px; font-variant-numeric: tabular-nums; color: var(--muted); font-weight: 400; }
.filter-chip.is-on .filter-chip-count { color: inherit; }
.filter-chip[disabled] { opacity: .45; cursor: not-allowed; }
.filter-chip[disabled]:hover { background: var(--surface); }

/* text action ("+ Add Employee", action links) — one definition */
a, .action-link {
  display: inline-flex; align-items: center; gap: 7px;
  font-size: var(--text-sm); font-weight: 600; color: var(--accent-text);
  background: none; border: none; padding: 0;
}
a:hover, .action-link:hover { color: var(--accent-text); text-decoration: underline; }
a .ic, .action-link .ic { width: 15px; height: 15px; }

/* icon button (table actions: edit, delete, duplicate, upload) — one definition */
.icon-btn {
  width: 30px; height: 30px; display: inline-flex; align-items: center; justify-content: center;
  border-radius: 6px; border: none; background: none; color: var(--muted);
}
.icon-btn:hover { background: var(--hover); color: var(--text); }
.icon-btn-accent { color: var(--accent-hover); }
.icon-btn-accent:hover { background: var(--accent-soft); color: var(--accent-hover); }
.icon-btn-danger:hover { background: var(--danger-soft); color: var(--danger); }
.icon-btn-super-danger {color: var(--danger);}
.icon-btn-info:hover { background: var(--ok-soft); color: var(--info); }
.icon-btn .ic { width: 16px; height: 16px; }

/* ---------- 7. FORM FIELDS ---------- */
.toolbar, .form-inline { display: flex; flex-wrap: wrap; gap: var(--space-4); align-items: flex-end; }
.field { display: flex; flex-direction: column; gap: 6px; }
.field-row { flex-direction: row; align-items: center; gap: var(--space-3); }
.field-label { font-size: var(--text-xs); font-weight: 600; color: var(--muted); }
.field-row .field-label { width: 84px; }
:where(.form-inline) .field { min-width: 0; max-width: 100%; }
:where(.form-inline) .field:has(> .select-wrapper > select) {
  max-width: min(250px, 100%);
}
:where(.form-inline) .select-wrapper {
  display: block;
  width: min(250px, 100%);
  min-width: min(150px, 100%);
  max-width: 100%;
}
:where(.form-inline) .select-wrapper > select.form-control,
:where(.form-inline) .select-wrapper > .jcf-select {
  width: 100%;
  max-width: 100%;
}

.form-control[type='password'], .form-control[type='text'], select.form-control, .select, .input {
  height: var(--control-h); padding: 0 11px;
}

.form-control, .select, .input {
  font-size: var(--text-sm); color: var(--text-strong);
  background: var(--surface);
  border: 1px solid var(--control-border); border-radius: var(--radius);
  outline: none; min-width: 0;
}
.form-control:focus, .select:focus, .input:focus { border-color: var(--accent-hover); }
.form-control::placeholder, .input::placeholder,
.textarea::placeholder, .code-block::placeholder { color: var(--muted-2); opacity: 1; }

/* File pickers had no definition of their own, so they inherited .input's control
   box: a full-width bordered rectangle with the browser's unstyled button loose at
   one end, reading as a stray second border inside the card. Full-width because
   .form-group is a column flex container and stretches its items - which is why
   width:auto alone does nothing here, and align-self is what actually sizes it.
   Applies to all eight file inputs in the console, which all had this. */
input[type="file"] {
  align-self: start; width: auto; max-width: 100%;
  height: auto; min-height: var(--control-h);
  padding: 4px 8px; line-height: 28px;
  color: var(--text-soft);
}
input[type="file"]::file-selector-button {
  height: 28px; padding: 0 var(--space-4); margin-right: var(--space-3);
  font: inherit; font-weight: 600; font-size: var(--text-sm);
  color: var(--text-soft); background: var(--surface);
  border: 1px solid var(--border-strong); border-radius: var(--radius);
  cursor: pointer;
}
input[type="file"]::file-selector-button:hover { background: var(--hover); }

select.form-control[multiple],
select.form-control[size]:not([size='1']) {
  min-height: 130px;
  padding-top: var(--space-2);
  padding-bottom: var(--space-2);
  line-height: 1.55;
}
select.form-control[multiple] option,
select.form-control[size]:not([size='1']) option {
  padding-top: 3px;
  padding-bottom: 3px;
  line-height: 1.55;
}

/* ---------- 8. CARD ---------- */
.card {
  background: var(--surface); border: 1px solid var(--border);
  border-radius: var(--radius); box-shadow: var(--shadow-1);
}
.card-pad { padding: var(--space-5); }
.card-header {
  display: flex; align-items: center; gap: var(--space-2);
  padding: var(--space-3) var(--space-4);
  border-bottom: 1px solid var(--border);
  font-size: var(--text-base); font-weight: 600; color: var(--text-strong);
}
.card-header .dot { width: 6px; height: 6px; border-radius: 2px; background: var(--accent); }
.card-header .meta { margin-left: auto; font-size: var(--text-xs); color: var(--muted); font-weight: 500; }
.card-subtitle {
  padding: var(--space-3) var(--space-4);
  font-size: var(--text-sm); color: var(--text-soft);
}
.card-title { font-size: var(--text-lg); font-weight: 700; color: var(--text-strong); }

/* ---------- 9. KPI / SCORECARD ---------- */
.kpi-grid { display: grid; grid-template-columns: repeat(4, 1fr); gap: var(--space-4); }
.kpi {
  background: var(--surface); border: 1px solid var(--border);
  border-radius: var(--radius); padding: var(--space-4) var(--space-4);
  border-left: 3px solid var(--accent);
}
.kpi-label { font-size: var(--text-xs); color: var(--muted); font-weight: 600; text-transform: uppercase; letter-spacing: .05em; }
.kpi-value { font-family: var(--font-mono); font-size: 26px; font-weight: 700; letter-spacing: -.02em; color: var(--text-strong); margin-top: 6px; }
.kpi-value .unit { font-family: var(--font-sans); font-size: var(--text-sm); color: var(--muted); font-weight: 500; letter-spacing: 0; }
.kpi-note { font-size: var(--text-xs); color: var(--muted); margin-top: var(--space-1); display: flex; align-items: center; gap: 6px; }
.kpi-ok    { border-left-color: var(--ok); }
.kpi-ok    .kpi-value { color: var(--ok); }
.kpi-danger{ border-left-color: var(--danger); }
.kpi-danger .kpi-value { color: var(--danger); }
.kpi-info  { border-left-color: var(--info); }
.kpi-warn { border-left-color: var(--warn); }
.kpi-muted { border-left-color: var(--muted); }
.kpi-text { border-left-color: var(--text); }

/* ---------- 10. BADGE / PILL ---------- */
.badge {
  display: inline-flex; align-items: center;
  font-size: 11px; font-weight: 600;
  /*padding: 2px 9px;*/ border-radius: var(--radius-pill);
  color: var(--muted); background: var(--zebra);
}
/* .badge-muted is used in veralab-core's markup but never defined there, so it
   falls through to the .badge base. Stated explicitly here so the neutral tone
   is a deliberate choice rather than an undefined class. */
.badge-muted  { color: var(--muted);       background: var(--zebra); }
.badge-ok     { color: var(--ok-text);     background: var(--ok-soft); }
.badge-warn   { color: var(--warn-text);   background: var(--warn-soft); }
.badge-danger { color: var(--danger-text); background: var(--danger-soft); }
.tag {
  display: inline-flex; align-items: center;
  font-size: 10px; font-weight: 600;
  padding: 1px 7px; border-radius: 5px;
}
.tag-ok     { color: var(--ok-text);     background: var(--ok-soft); }
.tag-danger { color: var(--danger-text); background: var(--danger-soft); }

/* ---------- 11. TABLE (consistent padding everywhere) ---------- */
.table-scroll { overflow-x: auto; }
.table th, .table td {
  padding: var(--space-3) var(--space-4);
  text-align: left; vertical-align: top;
}
.table thead th, .table tfoot tr, .srkListHeaderLink {
  background: var(--raised); color: var(--muted);
  font-size: var(--text-xs); font-weight: 600;
  white-space: nowrap;
}
/* A totals row is a conclusion, not a heading. Without this it inherited the
   `.table thead th, .table tfoot tr` rule above and rendered muted, 600 and
   small - indistinguishable from a column header and lighter than the rows it
   sums. The rule is the design system's, but its line is 1px, not the design
   system's 2px: Dev's call (9e7fee68b, b1984103d). Keep it 1px when syncing
   from veralab-core. */
.table tfoot td {
  border-top: 1px solid var(--border-strong);
  font-weight: 700; color: var(--text-strong); background: var(--raised);
}
.srkListHeaderLink {text-decoration: underline;}
.srkListHeaderLink:hover {color: var(--muted); text-decoration: none; }
.table tbody td { border-top: 1px solid var(--border); color: var(--text-soft); font-size: var(--text-sm); }
.table tbody tr:first-child td { border-top: none; }
.table-zebra tbody tr:nth-child(even) td { background: var(--zebra); }
.table .num { text-align: right; font-family: var(--font-mono); }
/* mono is for the figures, not their column names */
.table thead th.num { font-family: var(--font-sans); }
.table .center { text-align: center; }

/* Legacy presentational alignment. The srk: tag library still emits align="…"
   on table cells (63 of them across six pages alone, including every Edit /
   Delete header and the numeric columns). Author CSS beats presentational
   attributes, so `.table th, .table td { text-align: left }` above silently
   overrode all of them when the new table styling landed. Honour the attribute
   until that markup migrates to .center / .num. */
.table th[align="center"], .table td[align="center"] { text-align: center; }
.table th[align="right"],  .table td[align="right"]  { text-align: right; }
.table th[align="left"],   .table td[align="left"]   { text-align: left; }
.table .name { color: var(--text-strong); font-weight: 600; }
.table .accent { color: var(--accent-text); font-weight: 600; }

table.app-table  tbody td { vertical-align: middle; }
/* clickable identifier inside a table cell (station name, report name) */
.cell-link {
  background: none; border: none; padding: 0;
  font: inherit; color: var(--accent-text); font-weight: 600;
  text-align: left; cursor: pointer;
}
.cell-link:hover { text-decoration: underline; }
/* Focus keeps the base --accent-text colour (already 6.56-7.56:1) and adds two cues:
   a theme-aware ring and an underline. No fill-ramp tokens here - see README. */
.cell-link:focus-visible {
  text-decoration: underline;
  outline: 2px solid var(--accent-text); outline-offset: 2px; border-radius: 3px;
}

.table .report-action-heading,
.table .report-action-cell {
  width: 1%;
  white-space: nowrap;
}

/* two- or three-line cell: primary value + muted detail lines */
.stacked { display: flex; flex-direction: column; gap: 1px; }
.col-ok { color: var(--ok-text); }
.col-danger { color: var(--danger); }
.col-accent { color: var(--accent-text); }

.station { display: inline-flex; align-items: center; gap: var(--space-2); }
.station .ic { width: 16px; height: 13px; }
.station-offline { color: var(--danger); }   /* monitor icon color = in use */
.station-not-registered { color: var(--muted-2); }
.station-online { color: var(--ok); }

/* ---------- 15q. PAGINATION ----------
   Rendered at the TOP and BOTTOM of every table. One component, so the two
   instances can never drift apart. */
.pager {
  display: flex; align-items: center; gap: var(--space-3);
  padding: var(--space-2) var(--space-4);
  font-size: var(--text-xs); color: var(--muted);
  flex-wrap: wrap;
}
.pager-top { border-bottom: 1px solid var(--border); }
.pager-bottom { border-top: 1px solid var(--border); }
.pager-range { font-variant-numeric: tabular-nums; }
.pager-spacer { margin-left: auto; }
.pager-size { display: flex; align-items: center; gap: var(--space-2); }
.pager-size .select { height: 28px; padding: 0 24px 0 8px; font-size: var(--text-xs); }
.pager-nav { display: flex; align-items: center; gap: 2px; }
.pager-btn {
  min-width: 30px; height: 30px; padding: 0 6px;
  display: inline-flex; align-items: center; justify-content: center;
  background: var(--surface); border: 1px solid var(--border-strong);
  border-radius: 6px; color: var(--text);
  font-size: var(--text-xs); font-weight: 600; font-variant-numeric: tabular-nums;
}
.pager-btn[aria-current="page"]:hover:not(:disabled) { background: var(--accent-fill-hover); border-color: var(--muted-2); }
.pager-btn[aria-current="page"] {
  background: var(--accent-fill); border-color: var(--accent-fill);
  color: var(--on-accent);
}
.pager-btn:disabled { opacity: .45; cursor: not-allowed; }
.pager-gap { padding: 0 4px; color: var(--muted-2); }


/* ---------- 12. CHART HELPERS ---------- */
.chart { padding: var(--space-4); }
.bars { display: flex; align-items: flex-end; gap: var(--space-5); height: 132px; border-bottom: 1px solid var(--border); }
.bars-col { flex: 1; display: flex; align-items: flex-end; justify-content: center; height: 100%; }
.bar { width: 42px; border-radius: var(--radius-cell) var(--radius-cell) 0 0; background: var(--accent); }
.bar-muted { background: var(--muted-2); }
.axis { display: flex; gap: var(--space-5); margin-top: var(--space-2); }
.axis span { flex: 1; text-align: center; font-size: var(--text-xs); color: var(--muted); }
.legend { display: flex; gap: var(--space-4); margin-top: var(--space-3); font-size: var(--text-xs); color: var(--muted); flex-wrap: wrap; }
.legend span { display: inline-flex; align-items: center; gap: 6px; }
.swatch { width: 9px; height: 9px; border-radius: 2px; }

/* donut */
.donut-row { display: flex; align-items: center; gap: var(--space-5); }
.donut { width: 104px; height: 104px; flex: none; border-radius: 50%; display: flex; align-items: center; justify-content: center; }
.donut::after { content: ""; width: 62px; height: 62px; border-radius: 50%; background: var(--surface); }
.legend-list { display: flex; flex-direction: column; gap: var(--space-2); font-size: var(--text-sm); }
.legend-list > div { display: flex; align-items: center; gap: 9px; }
.legend-list .pct { margin-left: auto; font-family: var(--font-mono); font-weight: 600; }

/* ---------- 13. AI INSIGHTS ---------- */
.insight { padding: var(--space-3) 0; border-bottom: 1px solid var(--border); }
.insight:last-child { border-bottom: none; }
.insight p { font-size: var(--text-sm); line-height: 1.5; color: var(--text); margin-bottom: var(--space-2); }
.insight strong { font-family: var(--font-mono); font-weight: 700; }
.source-chip {
  display: inline-flex; align-items: center; gap: 5px;
  font-size: 11px; font-weight: 600; color: var(--accent-text);
  background: var(--accent-soft); border: 1px solid var(--border);
  border-radius: 7px; padding: 3px 9px; border: none;
}
.card-note {
  font-size: var(--text-xs); color: var(--muted);
  padding: var(--space-3) var(--space-4);
  border-top: 1px solid var(--border); background: var(--raised);
  display: flex; align-items: center; gap: 7px;
}

/* ---------- 14. HEATMAP (bigger, readable numbers) ---------- */
.heatmap {
  display: grid; grid-template-columns: 52px repeat(13, 1fr);
  gap: var(--space-1);
}
.heatmap-corner {}
.heatmap-h { font-size: var(--text-xs); color: var(--muted); text-align: center; font-weight: 600; align-self: center; }
.heatmap-d { font-size: var(--text-xs); color: var(--muted); font-weight: 600; display: flex; align-items: center; justify-content: flex-end; padding-right: var(--space-2); }
.heat-cell {
  aspect-ratio: 1.4 / 1; min-height: 30px;
  border-radius: var(--radius-cell);
  display: flex; align-items: center; justify-content: center;
  font-family: var(--font-mono); font-size: var(--text-sm); font-weight: 600;
}

/* ---------- 15. UTILITIES ---------- */
.grid-2 { display: grid; grid-template-columns: 1.1fr .9fr; gap: var(--space-5); align-items: start; }
.grid-2-wide { grid-template-columns: 1.65fr 1fr; }
.stack { display: flex; flex-direction: column; gap: var(--space-5); }
.row { display: flex; align-items: center; gap: var(--space-3); }
.row-wrap { display: flex; flex-wrap: wrap; gap: var(--space-4); align-items: center; }
.spacer { margin-left: auto; }
[hidden] { display: none !important; }

/* search box (AI ask) */
.searchbox {
  display: flex; align-items: center; gap: 9px;
  background: var(--surface); border: 1px solid var(--control-border);
  border-radius: var(--radius); padding: 9px var(--space-3);
  width: 320px; color: var(--muted); font-size: var(--text-sm);
}
.searchbox .ic { width: 15px; height: 15px; }

/* ---------- 15b. LINK LISTS / GROUPS (Reports, Settings) ---------- */
.cols-3 { display: grid; grid-template-columns: repeat(3, 1fr); gap: var(--space-5); align-items: start; }
.cols-2 { display: grid; grid-template-columns: repeat(2, 1fr); gap: var(--space-5); align-items: start; }
.col-stack { display: flex; flex-direction: column; gap: var(--space-5); }
.subhead {
  font-size: var(--text-md); font-weight: 700; color: var(--text-strong);
  padding-bottom: var(--space-2); margin-bottom: var(--space-3);
  border-bottom: 2px solid var(--accent);
}
.link-list { display: flex; flex-direction: column; }
.list-link {
  display: flex; align-items: center; gap: var(--space-2);
  width: 100%; text-align: left;
  padding: 10px var(--space-4);
  font-size: var(--text-sm); color: var(--text);
  background: none; border: none; border-top: 1px solid var(--border);
}
.link-list .list-link:first-child { border-top: none; }
.list-link:hover { background: var(--accent-soft); color: var(--accent-text); }
.list-link .chev { margin-left: auto; color: var(--muted-2); }
.list-link .dot { width: 6px; height: 6px; border-radius: 2px; background: var(--accent); flex: none; }
.settings-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 2px; }
.settings-grid .list-link { border-top: none; border-radius: 6px; }

/* ---------- 15c. DEFINITION LIST (About) ---------- */
.deflist { display: grid; grid-template-columns: minmax(150px, 230px) 1fr; gap: var(--space-2) var(--space-4); font-size: var(--text-sm); }
.deflist .dt { color: var(--muted); font-weight: 600; }
.deflist .dd { color: var(--text); }
.deflist .dd a { color: var(--info); }

/* ---------- 15d. STATUS LINE / ACTION ROW ---------- */
.statusline { display: flex; align-items: center; gap: var(--space-3); font-size: var(--text-xs); color: var(--muted); flex-wrap: wrap; }
/* The middle-dot separator from veralab-core; the base rule was ported earlier
   without it, so the facts ran together with only a gap between them. */
/* The middle dot as a literal character rather than a CSS escape: written
   through a shell edit, the escape lost its backslash and shipped as visible
   text on every report status line. */
.statusline > span + span::before { content: "·"; margin-right: var(--space-3); color: var(--muted-2); }
.links-block, .links-toolbar { display: flex; flex-wrap: wrap; gap: var(--space-4) var(--space-5); align-items: center; }
.links-block .muted { color: var(--muted); font-weight: 400; }

/* ---------- 15e. ALERT / PAGE MESSAGES ---------- */
.alert {
  display: flex; align-items: flex-start; gap: var(--space-3);
  padding: var(--space-3) var(--space-4);
  border-radius: var(--radius);
  border: 1px solid transparent;
  font-size: var(--text-sm); line-height: 1.45;
}
.alert .ic { width: 17px; height: 17px; flex: none; margin-top: 1px; color: inherit; }
.alert-body { flex: 1; }
.alert-title { font-weight: 700; display: block; margin-bottom: 2px; }
.alert-close {
  background: none; border: none; color: currentColor; opacity: 1;
  font-size: 15px; line-height: 1; padding: 2px 4px; border-radius: 4px; margin: -2px -4px 0 0;
}
.alert-close:hover { background: rgba(0,0,0,.06); }
.alert-danger  { background: var(--danger-soft); border-color: color-mix(in srgb, var(--danger) 28%, transparent); color: var(--danger-text); }
.alert-success { background: var(--ok-soft);     border-color: color-mix(in srgb, var(--ok) 28%, transparent);     color: var(--ok-text); }
.alert-warning { background: var(--warn-soft);   border-color: color-mix(in srgb, var(--warn) 30%, transparent);   color: var(--warn-text); }
.alert-info    { background: color-mix(in srgb, var(--info) 8%, var(--surface)); border-color: color-mix(in srgb, var(--info) 28%, transparent); color: var(--info); }
.alert-multi { border-color: var(--border); background: var(--surface); }
.alert-danger-message  { border-color: color-mix(in srgb, var(--danger) 28%, transparent); color: var(--danger-text); }
.alert-success-message { border-color: color-mix(in srgb, var(--ok) 28%, transparent);     color: var(--ok-text); }
.alert-warning-message { border-color: color-mix(in srgb, var(--warn) 30%, transparent);   color: var(--warn-text); }

/* legacy plain-text variant (matches old UI: bare coloured line under the title) */
.msg { font-size: var(--text-sm); font-weight: 500; }
.msg-danger  { color: var(--danger); }
.msg-success { color: var(--ok-text); }
.msg-muted   { color: var(--muted); }

/* ---------- 15f. MODAL / DIALOG ----------
   Structure and class names match the production app exactly, so the same
   markup works under real Bootstrap 3 JS or under veralab.js:

     .modal > .modal-dialog > .modal-content > [.modal-header]
                                             > .scroll-wrap > .modal-body
                                             > [.modal-footer]

   .modal-header and .modal-footer are BOTH optional. A popup with no title
   omits the header entirely; a popup with no actions omits the footer. The
   footer holds 0, 1 or 2 buttons and needs no modifier for either case.

   SIZING — the fix for the double-scrollbar bug.

   Width is always explicit: a preset (.modal-sm/-md/-lg/-xl) or --modal-w.

   Height has two modes, and picking the wrong one was the original bug:

     AUTO (default — inline content)
       No height is set anywhere in the dialog. It is exactly as tall as its
       content, however long that content is. NOTHING inside it scrolls. When
       the content is taller than the window, .modal — the full-viewport
       layer — scrolls the whole dialog, header and footer included. This is
       Bootstrap 3's behaviour and it cannot produce two scrollbars, because
       there is only ever one scroll container.

     FIXED (.modal-fixed + --modal-h — set by showPopup's h argument)
       The dialog is exactly --modal-h tall. .scroll-wrap is the ONE scroller;
       header and footer stay pinned. .modal-body itself never scrolls, so a
       nested scroll area cannot occur. The height is clamped only when the
       window is genuinely shorter than the requested height — the dialog is
       NOT sized off the viewport otherwise.

   An iframe body always needs FIXED mode: an iframe has no intrinsic height,
   so auto mode has nothing to measure. In iframe mode the iframe does its own
   scrolling and .scroll-wrap does not — again, one scrollbar. */
body.modal-open { overflow: hidden; }
.modal-scrollbar-measure { position: absolute; top: -9999px; width: 50px; height: 50px; overflow: scroll; }

.modal-backdrop {
  position: fixed; inset: 0; z-index: 99;
  background: rgba(12,18,26,.55);
  opacity: 0;
}
.modal-backdrop.fade { transition: opacity .15s linear; }
.modal-backdrop.in { opacity: 1; }

.modal {
  position: fixed; inset: 0; z-index: 100;
  display: none; outline: 0;
  overflow-x: hidden; overflow-y: auto;
  -webkit-overflow-scrolling: touch;
}
.modal-dialog {
  position: relative;
  width: var(--modal-w, 460px);
  max-width: calc(100vw - var(--space-4) * 2);
  margin: var(--space-6) auto;
}
/* width presets — Bootstrap's vocabulary, no custom property needed */
.modal-sm { --modal-w: 380px; }
.modal-md { --modal-w: 560px; }
.modal-lg { --modal-w: 640px; }
.modal-xl { --modal-w: 980px; }

.modal.fade .modal-dialog { transform: translateY(-24px); transition: transform .3s ease-out; }
.modal.in   .modal-dialog { transform: none; }

.modal-content {
  position: relative;
  display: flex; flex-direction: column;
  background: var(--surface); color: var(--text);
  border: 1px solid var(--border);
  border-radius: 12px;
  /* one radius on the shell means no child needs corner-specific radii,
     so header/footer stay optional without any extra rules */
  overflow: hidden;
  box-shadow: 0 24px 60px -12px rgba(0,0,0,.45);
}

/* AUTO mode: the wrapper is inert — it must not clip or scroll. */
.scroll-wrap { overflow: visible; min-height: 0; }

/* FIXED mode. The second selector supports markup without a .scroll-wrap:
   .modal-body then becomes the scroller itself. Both structures work. */
.modal-fixed .modal-content {
  height: var(--modal-h, 600px);
  max-height: calc(100vh - var(--space-6) * 2);
}
.modal-fixed .scroll-wrap,
.modal-fixed .modal-content > .modal-body {
  flex: 1 1 auto; min-height: 0;
  overflow: auto; -webkit-overflow-scrolling: touch;
}
/* when a .scroll-wrap is present it owns the scrolling, never the body */
.modal-fixed .scroll-wrap > .modal-body { overflow: visible; }

/* backdrop:"static" — the dialog nudges instead of closing, so the click is
   acknowledged rather than silently swallowed (BS3 only re-focuses). */
@keyframes modal-nudge {
  0%,100% { transform: none; }
  25%     { transform: translateX(-6px); }
  75%     { transform: translateX(6px); }
}
.modal.in .modal-dialog.is-nudging { animation: modal-nudge .22s ease-in-out; }
@media (prefers-reduced-motion: reduce) {
  .modal.fade .modal-dialog, .modal-backdrop.fade { transition: none; }
  .modal.in .modal-dialog.is-nudging { animation: none; }
}

.modal-header {
  flex: none;
  padding: var(--space-4) var(--space-5) var(--space-2);
  display: flex; align-items: center; gap: var(--space-3);
}
.modal-title { font-size: var(--text-lg); font-weight: 700; color: var(--text-strong); }
.modal-body {
  padding: var(--space-4) var(--space-5);
  font-size: var(--text-sm); color: var(--text-soft); line-height: 1.5;
}
.modal-header + .scroll-wrap .modal-body,
.modal-header + .modal-body { padding-top: var(--space-2); }
.modal-footer {
  flex: none;
  display: flex; justify-content: flex-end; gap: var(--space-2);
  padding: var(--space-4) var(--space-5);
  border-top: 1px solid var(--border); background: var(--raised);
}
.modal-footer:empty { display: none; }

/* close button — sits in the header, or floats when there is no header */
.modal-close {
  margin-left: auto; background: none; border: none; color: var(--muted);
  padding: 4px; border-radius: 6px; display: inline-flex; cursor: pointer;
}
.modal-close:hover { background: var(--hover); color: var(--text); }
.modal-content > .modal-close {
  position: absolute; top: var(--space-2); right: var(--space-2);
  z-index: 2; margin-left: 0; background: var(--surface);
}

.modal-icon {
  width: 34px; height: 34px; border-radius: 50%; flex: none;
  display: flex; align-items: center; justify-content: center;
}
.modal-icon .ic { width: 18px; height: 18px; }
.modal-icon-danger { background: var(--danger-soft); color: var(--danger); }
.modal-icon-warning{ background: var(--warn-soft);   color: var(--warn); }
.modal-icon-info   { background: color-mix(in srgb, var(--info) 12%, transparent); color: var(--info); }
.btn-danger { background: var(--danger-fill); color: #fff; }
.btn-danger:hover { background: color-mix(in srgb, var(--danger-fill) 86%, #000); }

/* ---------- 15g. FORM CONTROLS (radio, checkbox, listbox, required) ---------- */
.req, .required { color: var(--danger); margin-left: 3px; }
.radio-row { display: flex; align-items: center; gap: var(--space-3); min-height: 34px; }
.radio-row > label { display: inline-flex; align-items: center; gap: var(--space-2); font-size: var(--text-sm); color: var(--text); }
input[type="radio"], input[type="checkbox"] { accent-color: var(--accent-fill); width: 15px; height: 15px; }
.radio-cards { display: grid; grid-auto-flow: column; grid-auto-columns: minmax(0, 1fr); gap: var(--space-3); }
.radio-card {
  display: flex; align-items: flex-start; gap: var(--space-3); min-width: 0;
  padding: var(--space-4); border: 1px solid var(--border-strong); border-radius: var(--radius);
  background: var(--surface); cursor: pointer;
}
.radio-card:hover { background: var(--hover); }
.radio-card:has(> input:checked) {
  border-color: var(--accent); background: var(--accent-soft); box-shadow: inset 0 0 0 1px var(--accent);
}
.radio-card:has(> input:focus-visible) { outline: 2px solid var(--accent); outline-offset: 2px; }
.radio-card > input { margin-top: 3px; flex: none; }
.radio-card > span { min-width: 0; }
.radio-card-title {
  display: flex; align-items: center; gap: var(--space-2); flex-wrap: wrap;
  font-size: var(--text-sm); font-weight: 700; color: var(--text-strong);
}
.radio-card-title .ic { width: 16px; height: 16px; flex: none; }
.radio-card-description {
  display: block; margin-top: 3px; font-size: var(--text-xs); color: var(--text-soft);
  line-height: 1.45; text-wrap: pretty; overflow-wrap: anywhere;
}
@media (max-width: 820px) {
  .radio-cards { grid-auto-flow: row; grid-template-columns: 1fr; }
}
.form-grid { display: grid; grid-template-columns: minmax(180px, 260px) 1fr; gap: var(--space-3) var(--space-4); align-items: center; }
.listbox {
  width: 100%; max-width: 380px; min-height: 108px;
  padding: var(--space-2);
  border: 1px solid var(--control-border); border-radius: var(--radius);
  background: var(--surface); color: var(--text); font-size: var(--text-sm);
}
.listbox option { padding: 3px 5px; border-radius: 4px; }
.input-group { display: flex; align-items: center; gap: var(--space-2); }

/* ---------- 15h. DATEPICKER SHELL ----------
   Positioning only. The calendar's own look lives in 15p (bootstrap-datepicker
   theme) so there is exactly ONE source of truth for the grid, footer and
   week-number column. Width is intrinsic — a fixed width clipped the week
   column when showWeek was enabled. */
.datepicker-wrap { position: relative; display: inline-flex; }
.datepicker {
  position: absolute; top: calc(100% + 6px); left: 0; z-index: 90;
  padding: var(--space-3);
  background: var(--surface); border: 1px solid var(--border);
  border-radius: var(--radius); box-shadow: var(--shadow-pop);
  display: none;
}
.datepicker.is-open { display: block; }

/* ---------- 15i. TOOLTIP ---------- */
.has-tip { position: relative; }
.vl-tooltip {
  position: fixed; width: max-content; max-width: min(320px, calc(100vw - 16px));
  background: var(--header-bg); color: #fff;
  font-size: 11px; font-weight: 500; white-space: normal; overflow-wrap: anywhere;
  padding: 4px 8px; border-radius: 5px; z-index: 95;
}
.vl-tooltip[hidden] { display: none; }
/* A transparent bridge keeps the six-pixel gap hoverable. */
.vl-tooltip::before { content: ''; position: absolute; inset: -6px; }
.has-tip:focus-visible {
  outline: none;
  box-shadow: 0 0 0 2px var(--accent-hover);
}
/* small inline row icons (old UI "Native" markers) */
.row-ic { display: inline-flex; align-items: center; gap: 4px; margin-left: 5px; vertical-align: middle; color: var(--muted); }
.row-ic .ic { width: 13px; height: 13px; }

/* ---------- 15j. REPORT OUTPUT ---------- */
.report-meta { font-size: var(--text-sm); color: var(--muted); line-height: 1.6; }
.report-toolbar {
  display: flex; flex-wrap: wrap; align-items: center;
  gap: var(--space-2) var(--space-4);
  padding: var(--space-2) 0;
}
.tool-link {
  display: inline-flex; align-items: center; gap: 6px;
  background: none; border: none; padding: 4px 2px;
  font-size: var(--text-sm); font-weight: 600; color: var(--accent-text);
  border-radius: 5px;
}
.tool-link:hover { color: var(--accent-text); text-decoration: underline; }
.tool-link .ic { width: 15px; height: 15px; }
.tool-link-plain { color: var(--text-soft); }
.tool-link-plain:hover { color: var(--accent-text); }
/* header cell with a leading icon */
.th-ic { display: inline-flex; align-items: center; gap: 6px; }
.th-ic .ic { color: var(--muted-2); flex: none; }

/* Icon colour utilities.
   Default is monochrome (currentColor). Apply a tint ONLY when the colour
   carries meaning: status, connection state, or file type. */
.ic-ok      { color: var(--ok); }
.ic-warn    { color: var(--warn); }
.ic-danger  { color: var(--danger); }
.ic-info    { color: var(--info); }
.ic-accent  { color: var(--accent-hover); }
.ic-muted   { color: var(--muted); }
.ic-excel   { color: var(--file-excel); }
.ic-pdf     { color: var(--file-pdf); }
.ic-csv     { color: var(--file-csv); }
.ic-add     { color: var(--ok); }

/* simple CSS bar chart for report output.
   .rchart-track wraps plot + labels so both share ONE identical width/padding track. */
.rchart { display: flex; gap: var(--space-4); padding: var(--space-4) 0; }
.rchart-y {
  display: flex; flex-direction: column-reverse; justify-content: space-between;
  font-size: 11px; color: var(--muted); text-align: right; width: 18px; height: 300px;
}
.rchart-track { flex: 1; max-width: 640px; min-width: 0; }
.rchart-plot {
  height: 300px;
  display: flex; align-items: flex-end; gap: var(--space-3);
  border-left: 1px solid var(--border-strong); border-bottom: 1px solid var(--border-strong);
  padding: 0 var(--space-3);
  background: repeating-linear-gradient(to top, transparent 0 calc(14.28% - 1px), var(--border) calc(14.28% - 1px) 14.28%);
}
.rchart-col { flex: 1; display: flex; flex-direction: column; justify-content: flex-end; align-items: center; height: 100%; gap: 0; }
.rchart-seg { width: 46px; max-width: 100%; }
/* identical geometry to .rchart-plot so labels sit under their bars */
.rchart-x { display: flex; gap: var(--space-3); padding: var(--space-2) var(--space-3) 0; }
.rchart-x span { flex: 1; text-align: center; font-size: 11px; color: var(--muted); }
.rchart-axis-label { font-size: var(--text-xs); color: var(--muted); text-align: center; font-weight: 600; margin-top: var(--space-2); }

/* ---------- 15k. FORM MODAL ---------- */
.modal-header-center { justify-content: center; padding-top: var(--space-5); }
.form-stack { display: flex; flex-direction: column; gap: var(--space-4); }
.form-stack .field { gap: var(--space-2); }
.textarea, textarea.form-control {
  width: 100%; min-height: 88px; padding: var(--space-2) 11px;
  font-family: inherit; font-size: var(--text-sm); color: var(--text-strong);
  background: var(--surface); border: 1px solid var(--control-border);
  border-radius: var(--radius); outline: none; resize: vertical;
}
.textarea:focus, textarea.form-control:focus { border-color: var(--accent-hover); }
.check-row { display: flex; flex-wrap: wrap; gap: var(--space-3) var(--space-4); }
.check-row label { display: inline-flex; align-items: center; gap: 7px; font-size: var(--text-sm); color: var(--text); }
.hint { font-size: var(--text-xs); color: var(--muted); }

/* ---------- 15l. ICON SYSTEM ---------- */
/* All icons are <svg class="ic"><use href="#i-NAME"/></svg> from the sprite.
   They inherit currentColor and scale with the box they sit in. */
.ic { width: 16px; height: 16px; flex: none; display: inline-block; vertical-align: middle; }
.ic-sm { width: 13px; height: 13px; }
.ic-lg { width: 20px; height: 20px; }
.ic-xl { width: 24px; height: 24px; }
.burger .ic, .avatar .ic, .drawer-close .ic { width: 19px; height: 19px; color: currentColor; }
.burger { color: var(--on-dark-dim); }
.burger:hover { color: #fff; }

/* ---------- 15m. FORM GROUP + VALIDATION (server/XSL + client friendly) ----------
   Structure (label and control share ONE container; add .has-error to it):
     <div class="form-group">
       <label class="control-label" for="x">Name</label>
       <input id="x" class="input">
       <span class="help-block" data-error></span>
     </div>
   JS: setFieldError('#x', 'msg') / clearFieldError('#x') / clearFormErrors(form)          */
.form-group { display: flex; flex-direction: column; gap: 6px; }
.form-group-row { flex-direction: row; align-items: center; gap: var(--space-3); flex-wrap: wrap; }
.control-label { font-size: var(--text-xs); font-weight: 600; color: var(--muted); }
.form-group-row .control-label { width: 84px; }
.help-block { display: none; font-size: var(--text-xs); color: var(--danger); }
.help-block:not(:empty) { display: block; }
.form-group-row .help-block { flex-basis: 100%; margin-left: calc(84px + var(--space-3)); }

.inline-check-list {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-3) var(--space-4);
}
.inline-check-item {
  display: inline-flex;
  flex-direction: column;
  gap: 6px;
  min-width: 0;
  margin: 0;
  vertical-align: middle;
}
.inline-check-item .check-row { gap: 0; }
.inline-check-item .frow-label { align-items: center; gap: 7px; }
.inline-check-item .error-wrapper { margin-top: 4px; }

.form-group.has-error .control-label { color: var(--danger); }
.form-group.has-error .form-control,
.form-group.has-error .input,
.form-group.has-error .select,
.form-group.has-error .textarea,
.form-group.has-error .listbox {
  border-color: var(--danger);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--danger) 14%, transparent);
}
.form-group.has-error .help-block { display: block; }
.form-group.has-success .form-control,
.form-group.has-success .select { border-color: var(--ok); }

.has-error .check-row > .frow-label {
  color: var(--danger);
}


/* ---------- 15m. RECORD EDITOR ----------
   Two-column property form (Edit Workstation, Edit User …).
   Labels sit left of their control on a shared grid track so every row
   aligns across BOTH columns — the legacy page used table cells, which
   drifted whenever a label wrapped. */
.app-form { display: grid; grid-template-columns: 1fr /*1fr*/; gap: var(--space-4) var(--space-7); align-items: start; }
.app-form-2col { display: grid; grid-template-columns: 1fr 1fr; gap: var(--space-4) var(--space-7); align-items: start; }
/* The actions row spans both columns of a two-column form. The narrow-screen
   reset below (span 1) already assumed this default existed, but it never did:
   five report screens each declared their own copy, three of them unscoped and
   so restyling .form-actions for the whole console. */
.app-form-2col .form-actions { grid-column: span 2; }
.app-form-col, .app-form-one-col { display: flex; flex-direction: column; gap: var(--space-3); }
.app-form-one-col {grid-column: span 2;}

/* A form inside a modal: a column of .frow rows with a label column narrow
   enough for a dialog. ldap_settings.xsl had this as .ldap-modal-form in an
   inline <style>; smtp_settings needs the same thing, so it is defined once
   here rather than copied into a second page. */
.modal-form { --label-w: 190px; display: flex; flex-direction: column; gap: var(--space-3); }
.modal-form .frow { margin-bottom: 0; }
.modal-body .modal-form { padding-bottom: 0; }

/* A standalone note or instruction paragraph outside a card - the main menu's
   help and note text. Replaces .srkMainPageInstructions, which no stylesheet
   defined, and an align="justify" attribute: justified text with no hyphenation
   opens rivers of whitespace at narrow widths, so this reads ragged-right and
   is capped at a comfortable measure instead. */
.page-note { max-width: 70ch; color: var(--text-soft); margin-bottom: var(--space-4); }

/* Verbatim third-party licence text on the Acknowledgements page. It is fixed
   pre-formatted content that cannot reflow, so it scrolls inside its own box
   rather than forcing the page to scroll sideways. */
.license-block { max-height: 320px; overflow: auto; background: var(--raised);
  border: 1px solid var(--border); border-radius: var(--radius);
  padding: var(--space-4); margin-bottom: var(--space-5); }
.license-block pre { margin: 0; font-size: var(--text-xs); white-space: pre-wrap; }

.frow {
  display: grid;
  /* The label track must be allowed to shrink: a fixed 240px inside a ~373px
     editor column left only ~122px for the control and clipped real values
     (room names, IPs, Device IDs). The control keeps a usable minimum instead. */
  grid-template-columns: minmax(120px, var(--label-w, 240px)) minmax(180px, 1fr);
  align-items: center; gap: var(--space-3);
}
.frow-label {
  font-size: var(--text-sm); color: var(--text); font-weight: 500;
  display: flex; align-items: baseline; gap: 4px;
}
.frow-top { align-items: start; }
.frow-top .frow-label { padding-top: 8px; }
/* error text spans the control column only */
.frow .help-block { grid-column: 2; }
.frow.has-error .frow-label { color: var(--danger); }

/* required marker: colour is not the only signal — it also has a title */
.req { color: var(--danger); font-weight: 700; cursor: help; }

/* section heading inside the editor */
.fieldset { display: flex; flex-direction: column; gap: var(--space-3); }
.fieldset-title {
  font-size: var(--text-lg); font-weight: 700; color: var(--text-strong);
  margin: var(--space-5) 0 var(--space-2); letter-spacing: -.01em;
}

/* input with a trailing calendar affordance */
.input-cal { display: flex; align-items: center; gap: 6px; }
.input-cal .form-control { flex: 1; }
.datetimepicker-fields {
  display: flex; align-items: center; flex-wrap: wrap; gap: 6px; min-width: 0;
}
.datetimepicker-fields > .datepicker-wrap { flex: 1 1 170px; min-width: 0; }
.datetimepicker-fields > .time-input { flex: 0 0 100px; max-width: 100px; }
.cal-btn {
  width: 32px; height: var(--control-h); flex: none;
  display: inline-flex; align-items: center; justify-content: center;
  background: var(--surface); border: 1px solid var(--border-strong);
  border-radius: var(--radius); color: var(--accent-hover);
}
.cal-btn:hover { background: var(--hover); }

.form-actions {
  display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-3);
  margin-top: var(--space-5); padding-top: var(--space-4);
  border-top: 1px solid var(--border);
}
.form-actions > .button-wrapper {
  display: inline-flex;
  min-width: 0;
  max-width: 100%;
}
.form-actions > .btn,
.form-actions > .button-wrapper > .btn {
  max-width: 100%;
}

/* breadcrumb above a record title */
.crumb { display: flex; align-items: center; gap: 6px; font-size: var(--text-xs); color: var(--muted); margin-bottom: 4px; }
.crumb a { color: var(--accent-text); text-decoration: none; }
.crumb a:hover { text-decoration: underline; }
.crumb-sep { color: var(--muted-2); }

/* Two editor columns need ~1200px before the label+control pair inside each one
   becomes cramped; below that a single column is more readable than a clipped grid. */
@media (max-width: 1200px) {
  .app-form-2col { grid-template-columns: 1fr; gap: var(--space-3); }
  .app-form, .app-form-2col { --label-w: 260px; }
  .form-actions, .app-form-one-col {grid-column: span 1!important;}
}
@media (max-width: 620px) {
  .frow { grid-template-columns: 1fr; gap: 6px; }
  .frow .help-block { grid-column: 1; }
  .frow-top .frow-label { padding-top: 0; }
}

/* ---------- 15n. POPUP TYPE 1 — page-local popover (e.g. the ? helper) ---------- */
.popover-host { position: relative; display: inline-flex; vertical-align: middle; }
.help-btn {
  width: 20px; height: 20px; padding: 0; border: none; border-radius: 50%;
  background: none; color: var(--muted); display: inline-flex; align-items: center; justify-content: center;
}
.help-btn:hover { color: var(--accent-text); background: var(--accent-soft); }
.popover {
  position: absolute; top: calc(100% + 8px); left: 50%; transform: translateX(-50%);
  width: 280px; z-index: 92;
  background: var(--surface); color: var(--text);
  border: 1px solid var(--border); border-radius: var(--radius);
  box-shadow: var(--shadow-pop);
  display: none;
}
.popover.is-open { display: block; }
.popover::before {                        /* arrow */
  content: ""; position: absolute; top: -6px; left: 50%; margin-left: -6px;
  width: 10px; height: 10px; background: var(--surface);
  border-left: 1px solid var(--border); border-top: 1px solid var(--border);
  transform: rotate(45deg);
}
.popover-right { left: auto; right: 0; transform: none; }
.popover-right::before { left: auto; right: 14px; margin-left: 0; }
.popover-header {
  display: flex; align-items: center; gap: var(--space-2);
  padding: var(--space-3) var(--space-4);
  border-bottom: 1px solid var(--border);
  font-size: var(--text-sm); font-weight: 700; color: var(--text-strong);
}
.popover-close { margin-left: auto; background: none; border: none; color: var(--muted); padding: 2px; border-radius: 4px; display: inline-flex; }
.popover-close:hover { background: var(--hover); color: var(--text); }
.popover-body { padding: var(--space-3) var(--space-4); font-size: var(--text-sm); line-height: 1.5; color: var(--text-soft); }

/* ---------- 15o. IFRAME POPUP — showPopup(url, w, h) ----------
   The single reusable #modalWindow. Always FIXED height: an iframe has no
   intrinsic height to grow to. The iframe scrolls its own document, so
   .scroll-wrap must NOT scroll here — that pairing was the double scrollbar. */
.iframe-dialog .scroll-wrap { overflow: hidden; display: flex; flex-direction: column; }
/* .scroll-wrap is in the selector so this outranks the header-adjacency
   padding rule in §15f — an iframe body is always flush, header or no header.
   position: relative makes this slot the loading overlay's containing block,
   not .modal-content — otherwise inset:0 covers the header and footer and
   swallows clicks on Close while the page is still loading. */
.iframe-dialog .scroll-wrap .modal-body,
.iframe-dialog .modal-content > .modal-body { padding: 0; display: flex; min-height: 0; flex: 1 1 auto; position: relative; }
.modal-frame {
  flex: 1 1 auto; width: 100%; height: 100%;
  border: 0; display: block; background: var(--page);
}
.iframe-dialog .modal-header { border-bottom: 1px solid var(--border); padding-bottom: var(--space-4); }
.modal-loading {
  position: absolute; inset: 0;
  display: flex; align-items: center; justify-content: center;
  font-size: var(--text-sm); color: var(--muted);
  background: var(--page);
}
.modal-frame.is-ready + .modal-loading, .modal-loading[hidden] { display: none; }
/* footer separator between the two buttons, as in the production markup */
.button-divider { display: inline-block; width: var(--space-2); }
/* a table number that opens an iframe popup */
.link-count { background: none; border: none; padding: 0; font: inherit; color: var(--accent-text); font-weight: 600; text-decoration: underline; }
.link-count:hover { color: var(--accent-text); }

/* ---------- 15p. BOOTSTRAP-DATEPICKER THEME ----------
   Themes the standard bootstrap-datepicker DOM (.datepicker > .datepicker-days >
   table > thead .prev/.datepicker-switch/.next/.dow, tbody td.day/.old/.new/.today/.active,
   tfoot .today/.clear). Our built-in picker emits the same markup, so either works. */
.datepicker { width: auto; min-width: 260px; padding: var(--space-3); }
.datepicker.dropdown-menu { margin: 0; }
.datepicker-dropdown { top: 0; left: 0; }
.datepicker-dropdown:before,
.datepicker-dropdown:after {
  content: ""; display: inline-block; position: absolute;
  border-left: 7px solid transparent; border-right: 7px solid transparent;
}
.datepicker-dropdown:before { border-bottom: 7px solid var(--border); }
.datepicker-dropdown:after { border-bottom: 6px solid var(--surface); }
.datepicker-dropdown.datepicker-orient-left:before { left: 10px; }
.datepicker-dropdown.datepicker-orient-left:after { left: 11px; }
.datepicker-dropdown.datepicker-orient-right:before { right: 10px; }
.datepicker-dropdown.datepicker-orient-right:after { right: 11px; }
.datepicker-dropdown.datepicker-orient-bottom:before { top: -7px; }
.datepicker-dropdown.datepicker-orient-bottom:after { top: -6px; }
.datepicker-dropdown.datepicker-orient-top:before {
  bottom: -7px; border-bottom: 0; border-top: 7px solid var(--border);
}
.datepicker-dropdown.datepicker-orient-top:after {
  bottom: -6px; border-bottom: 0; border-top: 6px solid var(--surface);
}
.datepicker table { width: 100%; border-collapse: separate; border-spacing: 2px; }
.datepicker thead th,
.datepicker tbody td { text-align: center; }
.datepicker .datepicker-switch {
  font-size: var(--text-sm); font-weight: 700; color: var(--text-strong);
  padding: 4px; border-radius: 6px; cursor: pointer;
}
.datepicker .datepicker-switch:hover,
.datepicker .prev:hover, .datepicker .next:hover { background: var(--hover); }
.datepicker .prev, .datepicker .next {
  width: 28px; height: 28px; border-radius: 6px;
  color: var(--muted); font-size: 15px; cursor: pointer; user-select: none;
}
.datepicker .dow { font-size: 11px; font-weight: 600; color: var(--muted); padding: 4px 0; }
.datepicker td.day {
  height: 30px; width: 32px; border-radius: 6px;
  font-size: var(--text-xs); color: var(--text); cursor: pointer;
}
.datepicker td.day:hover { background: var(--hover); }
.datepicker td.old, .datepicker td.new { color: var(--muted-2); }
.datepicker td.today { background: var(--accent-soft); color: var(--accent-text); font-weight: 700; }
.datepicker td.active,
.datepicker td.active:hover { background: var(--accent-fill); color: var(--on-accent); font-weight: 700; }
.datepicker td.disabled { color: var(--muted-2); cursor: not-allowed; }
.datepicker .datepicker-months tbody td,
.datepicker .datepicker-years tbody td,
.datepicker .datepicker-decades tbody td,
.datepicker .datepicker-centuries tbody td {
  width: 100%; padding: 4px;
}
.datepicker .datepicker-grid {
  display: grid; grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 4px; width: 100%; min-width: 228px;
}
.datepicker .datepicker-grid > span {
  min-width: 0; height: 44px; display: flex; align-items: center; justify-content: center;
  float: none; width: auto; margin: 0;
  border-radius: 6px; cursor: pointer; color: var(--text); font-size: var(--text-xs);
  line-height: 1.2; white-space: nowrap; box-sizing: border-box;
}
.datepicker .datepicker-grid > span:hover,
.datepicker .datepicker-grid > span.focused { background: var(--hover); }
.datepicker .datepicker-grid > span.disabled,
.datepicker .datepicker-grid > span.disabled:hover {
  background: none; color: var(--muted-2); cursor: not-allowed;
}
.datepicker .datepicker-grid > span.active,
.datepicker .datepicker-grid > span.active:hover {
  background: var(--accent-fill); color: var(--on-accent); font-weight: 700;
}
.datepicker tfoot th {
  padding: 6px; border-radius: 6px; cursor: pointer;
  font-size: var(--text-sm); font-weight: 600; color: var(--accent-text);
}
.datepicker tfoot th:hover { background: var(--accent-soft); }
.datepicker tfoot tr:first-child th { border-top: 1px solid var(--border); }
/* footer actions sit side by side so both stay visible without scrolling */
.datepicker tfoot .dp-actions th { border-top: 1px solid var(--border); padding-top: var(--space-2); }
.datepicker tfoot .dp-actions button {
  background: none; border: none; padding: 6px 10px; border-radius: 6px;
  font-size: var(--text-sm); font-weight: 600; color: var(--accent-text);
}
.datepicker tfoot .dp-actions button:hover { background: var(--accent-soft); }
.datepicker tfoot .dp-actions .row { justify-content: space-between; }
/* ISO week numbers */
.datepicker .cw {
  font-size: 10px; font-weight: 700; color: var(--muted-2);
  padding-right: 6px; border-right: 1px solid var(--border);
}
.datepicker thead .cw { color: var(--muted); }

/* menu entries and nav items are anchors — strip link defaults, keep the look */
.menu-item, .nav-item, .action-link { text-decoration: none; }
a.menu-item, a.nav-item { display: flex; align-items: center; }
a.nav-item { text-decoration: none; }
.menu-item.is-current { background: var(--accent-soft); }
.nav-item.is-current { box-shadow: inset 0 -3px 0 var(--accent); color: #fff; }
[data-stub] { opacity: .62; }
[data-stub]:hover { opacity: 1; }

/* page header row: title left, Print right */
.page-head {
  display: flex; align-items: flex-start; justify-content: space-between;
  gap: var(--space-4); flex-wrap: wrap;
}
.pager-filtered { color: var(--muted-2); }


/* Session expiry is material information: use normal-size, full-contrast text. */
.session-warning .modal-body { font-size: var(--text-base); color: var(--text); }
.session-warning .modal-title { margin: 0; }
.session-warning .modal-icon-warning { color: var(--warn-text); }
.session-warning .session-countdown {
  font-family: var(--font-mono); font-weight: 700; font-variant-numeric: tabular-nums;
  color: var(--text-strong); white-space: nowrap;
}
.session-warning .session-time-track {
  height: 4px; border-radius: var(--radius-pill); background: var(--raised);
  overflow: hidden; margin-top: var(--space-3);
}
.session-warning .session-time-fill { height: 100%; background: var(--warn); transition: width 1s linear; }
@media (prefers-reduced-motion: reduce) {
  .session-warning .session-time-fill { transition: none; }
}
.session-warning .session-feedback:empty { display: none; }
.session-warning .modal-footer { flex-wrap: wrap; }
.session-warning [hidden] { display: none !important; }
.session-warning [aria-disabled="true"] { opacity: .65; cursor: wait; }
/* ---------- 15s. LOGIN (sign-in gate) ----------
   Ported verbatim from veralab-core/veralab.css in the Claude Design project
   "Dashboard and admin files" — that file is upstream, this is the copy.
   Re-port from there when the design changes; do not diverge here. */
.login-shell {
  min-height: calc(100vh - var(--header-h));
  display: flex; flex-direction: column; align-items: center;
  gap: var(--space-5);
  padding: clamp(var(--space-5), 6vh, 72px) var(--space-4) var(--space-6);
  background: var(--page);
}
.gate { width: 100%; max-width: 440px; display: flex; flex-direction: column; gap: var(--space-4); }
.gate-card { padding: var(--space-6) var(--space-6) var(--space-5); }
.gate-title { font-size: var(--text-2xl); font-weight: 700; letter-spacing: -.01em; color: var(--text-strong); margin: 0; }
.gate-lede {
  margin: var(--space-2) 0 var(--space-2) 0; font-size: var(--text-sm); line-height: 1.55;
  color: var(--text-soft); text-wrap: pretty;
}
.gate-lede strong { color: var(--text-strong); font-weight: 600; }
.gate-form { display: flex; flex-direction: column; gap: var(--space-4); }

/* password field with a reveal toggle inside the control */
.pw-wrap { position: relative; display: flex; align-items: center; }
.pw-wrap .input, .pw-wrap .form-control { width: 100%; padding-right: 38px; }
.pw-toggle {
  position: absolute; right: 5px;
  display: inline-flex; padding: 5px; cursor: pointer;
  background: none; border: 0; border-radius: 5px; color: var(--muted);
}
.pw-toggle:hover { background: var(--hover); color: var(--text); }
.pw-toggle[aria-pressed="true"] { color: var(--accent-text); }
.pw-toggle .ic { width: 16px; height: 16px; }

.gate-caps {
  display: inline-flex; align-items: center; gap: 5px;
  font-size: var(--text-xs); font-weight: 600; color: var(--warn-text);
}
.gate-caps .ic { width: 13px; height: 13px; }

/* stacked full-width actions: one obvious primary, escape hatch below it */
.gate-actions { display: flex; flex-direction: column; gap: var(--space-2); }
.btn-block { width: 100%; justify-content: center; }
.btn-ghost { background: var(--surface); color: var(--text-soft); border-color: var(--border-strong); }
.btn-ghost:hover { background: var(--hover); }
.login-or {
  display: flex; align-items: center; gap: var(--space-3);
  font-size: 10px; font-weight: 700; letter-spacing: .12em;
  text-transform: uppercase; color: var(--muted-2);
}
.login-or::before, .login-or::after { content: ""; flex: 1; height: 1px; background: var(--border); }

.gate-foot {
  margin: var(--space-5) 0 0; padding-top: var(--space-4);
  border-top: 1px solid var(--border);
  font-size: var(--text-xs); color: var(--muted);
}
.gate-foot-sep { margin: 0 6px; }
.gate-foot strong { color: var(--text); font-variant-numeric: tabular-nums; }
.gate-aside {
  display: flex; gap: var(--space-2); margin: 0;
  font-size: var(--text-xs); line-height: 1.5; color: var(--muted);
}
.gate-aside .ic { width: 14px; height: 14px; flex: none; margin-top: 1px; }

/* the SSO alternative: a real fork, not a footnote */
.login-doors { display: flex; flex-direction: column; gap: var(--space-2); }
.login-door {
  display: flex; align-items: center; gap: var(--space-3);
  padding: var(--space-3) var(--space-4);
  border: 1px solid var(--border); border-radius: var(--radius);
  background: var(--surface); text-decoration: none; color: inherit;
}
.login-door:hover { border-color: var(--accent); background: var(--accent-soft); }
.login-door .ic { width: 17px; height: 17px; flex: none; color: var(--muted); }
.login-door:hover .ic { color: var(--accent-text); }
.login-door-body { display: flex; flex-direction: column; gap: 1px; min-width: 0; }
.login-door-name { font-size: var(--text-sm); font-weight: 600; color: var(--text-strong); }
.login-door-sub { font-size: var(--text-xs); color: var(--muted); }
.login-door .chev { margin-left: auto; color: var(--muted-2); width: 15px; height: 15px; }
.login-foot { font-size: var(--text-xs); color: var(--muted-2); text-align: center; }

/* App integration for the gate.
   In veralab-core the gate is a standalone page with stacked .field rows. Here it
   renders inside main.app-main > section.page, and the rows come from the
   labelinput widget (.frow, a two-column label/control grid) so that server-side
   validation, the generated ids and the eye-button keep working. Adapt the two
   here rather than forking either the design or widgets.xsl. */
.page > .login-shell { min-height: auto; padding: 0; }
.gate .frow { grid-template-columns: 1fr; gap: 6px; }
.gate .frow-label { font-size: var(--text-xs); font-weight: 600; color: var(--muted); }
.gate .form-actions { display: flex; flex-direction: column; gap: var(--space-2); padding: 0; }
.gate .check-row label { font-size: var(--text-sm); color: var(--text-soft); }

/* ---------- 11b. SELF-SERVICE STATS BOARD ----------
   Ported verbatim from veralab-core/veralab.css (section 11b) in the Claude
   Design project "Dashboard and admin files". Two columns on wide screens;
   .dash-wide spans both for the tables whose columns need the room. */
.dash-grid {
  display: grid; gap: var(--space-4);
  /* veralab-core uses auto-fit here, which on a wide screen yields three
     tracks and leaves the paired cards at a third of the width each. The
     pairing is the point — occupancy beside visits, OS versions beside who is
     online — so the grid is capped at two equal tracks and collapses to one
     when there is no room for two. */
  grid-template-columns: repeat(2, minmax(0, 1fr));
  /* stretch, not start: paired cards in a row would otherwise each size to
     their own content and leave the row visually ragged. */
  align-items: stretch;
}
@media (max-width: 900px) { .dash-grid { grid-template-columns: minmax(0, 1fr); } }
.dash-wide { grid-column: 1 / -1; }

.card-foot {
  display: flex; align-items: baseline; justify-content: space-between;
  gap: var(--space-4); flex-wrap: wrap;
  padding: var(--space-3) var(--space-5) var(--space-4);
  border-top: 1px solid var(--border);
}
.card-foot-note { font-size: var(--text-xs); color: var(--muted); max-width: 62ch; margin: 0; }
.card-foot-note strong { color: var(--text-strong); }

.table tfoot td {
  border-top: 1px solid var(--border-strong);
  font-weight: 700; color: var(--text-strong); background: var(--raised);
}

/* per-room composition. One 100%-width track per room, so a 1-station room
   and a 500-station room are directly comparable. */
.occ { display: flex; flex-direction: column; gap: var(--space-4); }
.occ-row { display: flex; flex-direction: column; gap: 6px; }
.occ-head { display: flex; align-items: baseline; justify-content: space-between; gap: var(--space-3); }
.occ-name { font-size: var(--text-sm); font-weight: 600; color: var(--text-strong); }
.occ-total { font-family: var(--font-mono); font-size: var(--text-xs); color: var(--muted); }
.occ-bar { display: flex; height: 14px; border-radius: 3px; overflow: hidden; background: var(--zebra); }
.occ-bar-seg { min-width: 0; }
.occ-occupied { background: var(--accent); }
.occ-vacant { background: var(--ok); }
.occ-connected { background: var(--info); }
.occ-offline { background: var(--danger); }
.occ-unavailable { background: var(--warn); }
.occ-quiet { background: var(--muted-2); opacity: .28; }
.occ-detail { display: flex; flex-wrap: wrap; gap: var(--space-3); font-size: var(--text-xs); color: var(--muted); }
.occ-detail b { color: var(--text-strong); font-family: var(--font-mono); font-weight: 700; }

.legend { display: flex; flex-wrap: wrap; gap: var(--space-3) var(--space-4); margin-top: var(--space-4); padding-top: var(--space-3); border-top: 1px solid var(--border); }
.legend-item { display: flex; align-items: center; gap: 6px; font-size: var(--text-xs); color: var(--text-soft); }
.legend-key { width: 10px; height: 10px; border-radius: 2px; flex: none; }

/* ranked list, replacing a pie whose largest slice was 97% */
.rank { display: flex; flex-direction: column; gap: 7px; }
.rank-row { display: grid; grid-template-columns: minmax(0, 15ch) 1fr 7ch; align-items: center; gap: var(--space-3); }
.rank-name { font-size: var(--text-xs); color: var(--text); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* both are spans, and neither parent is a flex container, so nothing would
   blockify them — width/height are ignored on inline elements. */
.rank-track { display: block; height: 10px; border-radius: 2px; background: var(--zebra); }
.rank-fill { display: block; height: 100%; border-radius: 2px; background: var(--info); min-width: 2px; }
.rank-val { font-family: var(--font-mono); font-size: var(--text-xs); color: var(--muted); text-align: right; }
.rank-more { font-size: var(--text-xs); color: var(--muted); padding-top: 2px; }
.rank-fill-quiet { background: var(--muted-2); opacity: .55; }

/* fleet coverage — its own scale, above the version ranking */
.rank-lede { display: flex; flex-direction: column; gap: 6px; padding-bottom: var(--space-4); }
.rank-lede-head { display: flex; align-items: baseline; justify-content: space-between; gap: var(--space-3); }
.rank-lede-figure { font-family: var(--font-mono); font-size: var(--text-lg); font-weight: 700; color: var(--text-strong); }
.rank-lede-pct { font-family: var(--font-mono); font-size: var(--text-sm); color: var(--muted); }
.rank-lede-note { margin: 0; font-size: var(--text-xs); color: var(--muted); max-width: 54ch; }
.rank-title {
  font-size: var(--text-xs); font-weight: 700; letter-spacing: .02em;
  color: var(--text-soft); padding: var(--space-3) 0 var(--space-3);
  border-top: 1px solid var(--border);
}

/* Small shared helpers introduced alongside the board (schedule slots and the
   two text tones). Also from veralab-core/veralab.css. */
.slot-range { display: flex; align-items: center; gap: 5px; }
.slot-rest { font-size: var(--text-xs); color: var(--warn-text); line-height: 1.35; }
.warn   { color: var(--warn-text); }
.danger { color: var(--danger-text); }

/* ---------- 15u. EMPLOYEE SCHEDULE WEEK BOARD ----------
   Ported verbatim from veralab-core/veralab.css. This is a different component
   from the legacy counter grid, not a restyle of it: one card per room, a
   seven-column week inside it, and each block of the day rendered as a .slot.

   NOTE ON .legend: veralab-core defines it twice — once for the stats board and
   again here, with this one later and therefore winning. That order is
   preserved: this block must stay after section 11b. */
.legend { display: flex; align-items: center; gap: var(--space-4); margin-left: auto; padding-bottom: 7px; }
.legend-item { display: inline-flex; align-items: center; gap: 7px; font-size: var(--text-xs); color: var(--muted); }

.room-head {
  display: flex; align-items: center; gap: var(--space-4); flex-wrap: wrap;
  padding: var(--space-3) var(--space-4);
  border-bottom: 1px solid var(--border);
}
.room-name {
  display: inline-flex; align-items: center; gap: var(--space-2);
  font-size: var(--text-base); font-weight: 700; color: var(--text-strong);
}
.room-name .ic { width: 16px; height: 16px; color: var(--muted); }
.room-cov { display: flex; align-items: center; gap: var(--space-3); margin-left: auto; }
.room-cov-pct { font-family: var(--font-mono); font-size: var(--text-sm); font-weight: 700; color: var(--text-strong); }
.room-cov-note { font-size: var(--text-xs); color: var(--muted); }
.meter { width: 140px; height: 6px; border-radius: 3px; background: var(--zebra); overflow: hidden; }
.meter-fill { height: 100%; background: var(--ok); border-radius: 3px; }

.week {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(160px, 1fr));
  gap: var(--space-3); padding: var(--space-4);
}
/* Scoped to .week: bootstrap-datepicker also uses td.day, and a bare .day rule
   overrides its display:table-cell, collapsing the calendar into one column.
   veralab-core has the same bare rule and the same latent collision. */
.week .day { display: flex; flex-direction: column; gap: 6px; min-width: 0; }

/* Day heading. These three were emitted by the schedule stylesheet but never
   ported from veralab-core, so the coverage figure sat left-aligned against the
   day name instead of being pushed to the right edge of the column.
   veralab-core also uppercases .day-name; that is dropped deliberately, because
   the app emits full weekday names ("Wednesday") and shouting them adds nothing
   the design's three-letter labels needed. */
.day-head { display: flex; align-items: baseline; justify-content: space-between; gap: var(--space-2); }
.day-name { font-size: var(--text-xs); font-weight: 700; color: var(--text-strong); text-transform: uppercase; letter-spacing: .06em; }
.day-cov { font-family: var(--font-mono); font-size: var(--text-xs); color: var(--muted); margin-left: auto; }
.day-cov-zero { color: var(--muted-2); }

/* 24h proportional strip: midnight at the left edge, midnight at the right */
.ribbon { display: flex; height: 5px; border-radius: 3px; overflow: hidden; background: var(--zebra); margin-bottom: 2px; }
.ribbon-seg { background: transparent; }
.ribbon-seg.is-on { background: var(--ok); }

.slot {
  position: relative;
  display: flex; flex-direction: column; gap: 1px;
  padding: 7px 9px; border-radius: 6px;
  border: 1px solid var(--border);
}
.slot-time { font-family: var(--font-mono); font-size: var(--text-xs); color: var(--muted); }
.slot-on { background: var(--surface); border-left: 3px solid var(--ok); padding-left: 8px; }
.slot-who { font-size: var(--text-sm); font-weight: 600; color: var(--text-strong); line-height: 1.3; }
.slot-user { font-family: var(--font-mono); font-size: var(--text-xs); color: var(--muted); }
.slot-off { border-style: dashed; background: transparent; }
.slot-off .slot-label { font-size: var(--text-xs); color: var(--muted-2); }
.slot-actions {
  position: absolute; top: 4px; right: 4px;
  display: flex; gap: 1px; opacity: 0; transition: opacity .12s ease;
}
.slot:hover .slot-actions, .slot:focus-within .slot-actions { opacity: 1; }
.slot-actions .icon-btn { width: 24px; height: 24px; }
.slot-actions .icon-btn .ic { width: 14px; height: 14px; }
/* touch and keyboard have no hover: never hide the only way to act */
@media (hover: none) { .slot-actions { opacity: 1; } }

.slot-assign { align-self: flex-start; margin-top: 3px; font-size: var(--text-xs); }
.slot-edit { display: flex; flex-direction: column; gap: 6px; margin-top: 5px; }
.slot-edit .select { height: 30px; font-size: var(--text-xs); }
.slot-edit-btns { display: flex; gap: 6px; }
/* time range inside the slot editor — two selects reading as one control */
.slot-range { display: flex; align-items: center; gap: 5px; }
.slot-range .select { flex: 1; min-width: 0; padding-left: 6px; padding-right: 18px; }
.slot-range-sep { font-size: var(--text-xs); color: var(--muted); flex: none; }
.slot-rest { font-size: var(--text-xs); color: var(--warn-text); line-height: 1.35; }

.room-empty {
  display: flex; align-items: center; gap: var(--space-3);
  padding: var(--space-4); font-size: var(--text-sm); color: var(--text-soft);
}
.room-empty .ic { width: 18px; height: 18px; color: var(--warn); flex: none; }
.room-empty .btn { margin-left: auto; }

@media print {
  .card.room { break-inside: avoid; }
  .week { grid-template-columns: repeat(7, 1fr); gap: 6pt; padding: 6pt; }
  .slot-assign, .slot-actions { display: none !important; }
  .legend { display: none !important; }
  .ribbon { background: #eee; }
  .ribbon-seg.is-on { background: #000; }
}


/* Ported from veralab-core: a short form (two or three fields) is capped so the
   controls stay in a readable column instead of stretching the full page, and
   .fieldset-hint is the explanatory line that sits under a field. */
.form-narrow { max-width: 680px; }
.fieldset-hint { margin: 0; font-size: var(--text-xs); line-height: 1.55; color: var(--muted); max-width: 68ch; }

/* Re-auth gate additions, ported verbatim from veralab-core. The rest of the
   .gate vocabulary is already present from the sign-in gate (section 15s). */
.gate-badge {
  width: 44px; height: 44px; border-radius: 12px;
  display: flex; align-items: center; justify-content: center;
  background: var(--accent-soft); color: var(--accent-text);
  margin-bottom: var(--space-4);
}
.gate-badge .ic { width: 22px; height: 22px; }
.gate-who {
  display: flex; align-items: center; gap: var(--space-3);
  margin: var(--space-5) 0 var(--space-4);
  padding: var(--space-3); border: 1px solid var(--border);
  border-radius: var(--radius); background: var(--raised);
}
.gate-avatar {
  width: 32px; height: 32px; flex: none; border-radius: 50%;
  display: flex; align-items: center; justify-content: center;
  background: var(--surface); border: 1px solid var(--border); color: var(--muted);
}
.gate-avatar .ic { width: 17px; height: 17px; }
.gate-who-body { display: flex; flex-direction: column; gap: 1px; min-width: 0; }
.gate-who-name { font-size: var(--text-sm); font-weight: 600; color: var(--text-strong); }
.gate-who-sub { font-size: var(--text-xs); color: var(--muted); }

/* Dashboard table refinements, ported from veralab-core. A long list inside a
   dashboard card pushes everything below it off screen, so the card scrolls
   internally with its header pinned. .pager-compact drops the page-size and
   filtered-count controls, which are noise next to a four-row summary. */
.dash-scroll { max-height: 21rem; overflow: auto; }
.dash-scroll thead th { position: sticky; top: 0; z-index: 2; background: var(--raised); }
.pager-compact { padding: var(--space-2) var(--space-4); }
.pager-compact .pager-size, .pager-compact .pager-filtered { display: none; }
/* ---------- 16. RESPONSIVE ---------- */

/* Drawer chrome is desktop-hidden by default; the compact-nav block reveals it. */
.drawer-backdrop { display: none; }
.drawer-head { display: none; }
.drawer-extra { display: none; }

@media (max-width: 1100px) {
  .grid-2, .grid-2-wide { grid-template-columns: 1fr; }
  .kpi-grid { grid-template-columns: repeat(2, 1fr); }
  .cols-3 { grid-template-columns: repeat(2, 1fr); }
}

@media (max-width: 820px), (hover: none) and (pointer: coarse) and (orientation: portrait) {
  .app { min-width: 0; }
  .page { padding: var(--space-4) var(--space-4); }
  .header-center { display: none; }
  .header-welcome { display: none; }
  .header-right { margin-left: auto; }
  .heatmap { grid-template-columns: 38px repeat(13, 1fr); }
  .heat-cell { min-height: 26px; font-size: var(--text-xs); }
  .searchbox { width: 100%; }

  /* ----- TABLES: scroll horizontally instead of cramping ----- */
  .table-scroll {
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
    scrollbar-width: thin;
    scrollbar-color: var(--border-strong) transparent;
  }
  .table-scroll::-webkit-scrollbar { height: 9px; }
  .table-scroll::-webkit-scrollbar-track { background: var(--raised); }
  .table-scroll::-webkit-scrollbar-thumb { background: var(--border-strong); border-radius: var(--radius-pill); }
  /*.table { min-width: 560px; }*/          /* forces the scroll affordance on narrow screens */

  /* ----- OFF-CANVAS NAV DRAWER ----- */
  .drawer-backdrop {
    display: block; position: fixed; inset: 0;
    background: rgba(10,16,22,.55);
    opacity: 0; visibility: hidden;
    transition: opacity .24s ease, visibility .24s ease;
    z-index: 70;
  }
  .drawer-backdrop.is-open { opacity: 1; visibility: visible; }

  .app-nav {
    position: fixed; top: 0; left: 0; bottom: 0;
    width: 286px; max-width: 86vw; height: 100%;
    flex-direction: column; align-items: stretch;
    padding: 0; gap: 0;
    background: var(--header-bg);
    transform: translateX(-100%);
    transition: transform .24s ease;
    overflow-y: auto; z-index: 80;
    box-shadow: var(--shadow-pop);
  }
  .app-nav-utility { display: flex; }
  .app-nav.is-drawer-open { transform: translateX(0); }

  .drawer-head {
    display: flex; align-items: center; flex: none;
    height: var(--header-h);
    padding: 0 var(--space-2) 0 var(--space-4);
    border-bottom: 1px solid rgba(255,255,255,.08);
  }
  .drawer-head-title { font-size: var(--text-md); font-weight: 700; color: var(--on-dark); }
  .drawer-close {
    margin-left: auto; width: 38px; height: 38px;
    display: flex; align-items: center; justify-content: center;
    background: none; border: none; color: var(--on-dark-dim);
    font-size: 19px; border-radius: 6px;
  }
  .drawer-close:hover { background: rgba(255,255,255,.08); color: #fff; }

  .menu-wrap { flex-direction: column; align-items: stretch; }
  .app-nav > .nav-item,
  .app-nav > .menu-wrap,
  .app-nav > .drawer-extra {
    flex: none;
  }

  .app-nav .nav-item {
    width: 100%; height: 48px; min-height: 48px;
    flex: 0 0 48px;
    justify-content: space-between;
    padding: 0 var(--space-4);
    color: var(--on-dark); font-size: var(--text-md);
    border-bottom: 1px solid rgba(255,255,255,.06);
    box-shadow: none;
  }
  .app-nav .nav-item:hover { background: rgba(255,255,255,.05); color: var(--on-dark); }
  .app-nav .nav-item-active {
    color: #fff; background: rgba(255,255,255,.04);
    box-shadow: inset 3px 0 0 var(--accent);
  }
  .nav-item .caret { transition: transform .18s ease; }
  .menu-wrap:has(.menu.is-open) .nav-item .caret { transform: rotate(180deg); }

  /* dropdown panels become inline accordions inside the drawer */
  .app-nav .menu {
    position: static; min-width: 0; width: 100%;
    border: none; border-radius: 0; box-shadow: none;
    background: rgba(0,0,0,.22); padding: 0;
  }
  .app-nav .menu-item { color: #cfd9e3; padding: 12px var(--space-5); border-radius: 0; }
  .app-nav .menu-item:hover { background: rgba(255,255,255,.06); }
  .app-nav .menu-item-primary { color: var(--accent-on-dark); }
  .app-nav .menu-item-primary:hover { background: rgba(232,130,14,.14); }

  /* drawer footer: department + theme controls */
  .drawer-extra {
    display: block; margin-top: auto;
    padding: var(--space-4);
    border-top: 1px solid rgba(255,255,255,.08);
  }
  .app-nav-utility .drawer-extra { margin-top: 0; }
  .drawer-extra-label {
    font-size: var(--text-xs); font-weight: 600;
    text-transform: uppercase; letter-spacing: .08em;
    color: var(--on-dark-dim); margin: var(--space-2) 0;
  }
  .drawer-links {
    display: flex; flex-direction: column;
    margin: 0 calc(-1 * var(--space-4)) var(--space-4);
  }
  .drawer-links .menu-item {
    display: flex; width: 100%;
  }
  .nav-sub { height: 42px; border-bottom: 1px solid rgba(255,255,255,.06); }
  .theme-seg { display: flex; gap: 6px; margin-top: 6px; }
  .theme-seg button {
    flex: 1; height: 38px; border-radius: 6px;
    border: 1px solid rgba(255,255,255,.14);
    background: transparent; color: var(--on-dark-dim);
    font-size: var(--text-sm); font-weight: 600;
  }
  .theme-seg button.is-active { background: var(--accent-fill); color: var(--on-accent); border-color: var(--accent-fill); }

  /* burger now opens the drawer; hide its desktop dropdown */
  [data-menu-panel="burger"] { display: none !important; }
}

@media (max-width: 620px) {
  .kpi-grid { grid-template-columns: 1fr 1fr; }
  .page-title { font-size: var(--text-xl); }
  .toolbar .field { flex: 1 1 100%; }
  .toolbar .input, .toolbar .select { width: 100%; }
  .form-actions { align-items: stretch; }
  .form-actions > .button-wrapper,
  .form-actions > .btn {
    flex: 1 1 min(140px, 100%);
  }
  .form-actions > .button-wrapper > .btn {
    flex: 1 1 auto;
  }
  .form-actions .btn {
    height: auto;
    min-height: var(--control-h);
    padding-top: var(--space-2);
    padding-bottom: var(--space-2);
    line-height: 1.2;
    text-align: center;
    white-space: normal;
  }
  .cols-3, .cols-2 { grid-template-columns: 1fr; }
  .settings-grid { grid-template-columns: 1fr; }
  .deflist { grid-template-columns: 1fr; gap: 2px var(--space-4); }
  .deflist .dt { margin-top: var(--space-2); }
}

@media (max-width: 440px) {
  .kpi-grid { grid-template-columns: 1fr; }
}

/* ============================================================
   17. CERTIFICATE MANAGEMENT
   Components for Settings ▸ Certificate Management. Tokens only —
   no new colours or spacing values are introduced here.
   ============================================================ */
/* connection-type chips + muted cells */
.conn-chip {
  display: inline-block; font-size: 10.5px; font-weight: 600;
  padding: 1px 7px; border-radius: var(--radius-pill);
  background: var(--zebra); color: var(--text-soft);
  border: 1px solid var(--border); white-space: nowrap;
}
.muted-cell { color: var(--muted-2); }
.muted { color: var(--muted); font-weight: 400; }
.nowrap { white-space: nowrap; }

/* breadcrumb */
.crumb { display: flex; align-items: center; gap: 6px; font-size: var(--text-xs); color: var(--muted); }
.crumb button { background: none; border: none; padding: 0; font: inherit; color: var(--accent-text); font-weight: 600; }
.crumb button:hover { text-decoration: underline; }
.crumb .ic { width: 12px; height: 12px; }

/* certificate identity cell */
.cert-name { display: flex; align-items: flex-start; gap: var(--space-2); text-align: left; }
.cert-name-btn {
  background: none; border: none; padding: 0; font: inherit; text-align: left;
  color: var(--accent-text); font-weight: 600;
}
.cert-name-btn:hover { text-decoration: underline; }
.cert-name-sub { display: block; font-weight: 400; color: var(--muted); font-size: var(--text-xs); margin-top: 2px; }
.cert-ic { color: var(--muted); margin-top: 2px; }
.cert-ic-root { color: var(--accent-hover); }
.cert-ic-ok { color: var(--ok); }

/* monospace blocks: PEM, fingerprints */
.code-block {
  width: 100%; min-height: 190px; resize: vertical;
  font-family: var(--font-mono); font-size: var(--text-xs); line-height: 1.55;
  color: var(--text); background: var(--raised);
  border: 1px solid var(--control-border); border-radius: var(--radius);
  padding: var(--space-3); outline: none; white-space: pre; overflow: auto;
}
.code-block:focus { border-color: var(--accent-hover); background: var(--surface); }
.fingerprint {
  font-family: var(--font-mono); font-size: 11.5px; line-height: 1.6;
  color: var(--text-soft); word-break: break-all;
}

/* chain returned by "retrieve from server" */
.chain { display: flex; flex-direction: column; gap: var(--space-3); }
.chain-item {
  display: flex; gap: var(--space-3); align-items: flex-start;
  padding: var(--space-4);
  border: 1px solid var(--border); border-radius: var(--radius);
  background: var(--surface);
}
.chain-item.is-selected { border-color: var(--accent); background: var(--accent-soft); }
.chain-item.is-disabled { opacity: .6; }
.chain-body { flex: 1; min-width: 0; }
.chain-title { font-size: var(--text-sm); font-weight: 700; color: var(--text-strong); }
.chain-meta { font-size: var(--text-xs); color: var(--muted); margin-top: 3px; line-height: 1.6; }
.chain-depth {
  font-size: 10px; font-weight: 700; letter-spacing: .06em; text-transform: uppercase;
  color: var(--muted); background: var(--zebra);
  padding: 2px 7px; border-radius: var(--radius-pill); white-space: nowrap;
}

/* empty / loading states */
.state {
  display: flex; flex-direction: column; align-items: center; gap: var(--space-3);
  padding: var(--space-7) var(--space-5); text-align: center;
  color: var(--muted); font-size: var(--text-sm);
}
.state .ic { width: 30px; height: 30px; color: var(--muted-2); }
.spinner {
  width: 22px; height: 22px; border-radius: 50%;
  border: 2.5px solid var(--border); border-top-color: var(--accent-hover);
  animation: spin .7s linear infinite;
}
@keyframes spin { to { transform: rotate(360deg); } }

/* two-column detail rows inside the certificate modal */
.modal-cert { max-width: 640px; }
.cert-facts { display: grid; grid-template-columns: minmax(120px,150px) 1fr; gap: var(--space-2) var(--space-4); font-size: var(--text-sm); }
.cert-facts .dt { color: var(--muted); font-weight: 600; }
.cert-facts .dd { color: var(--text); word-break: break-word; }
.section-label {
  font-size: 10.5px; font-weight: 700; letter-spacing: .1em; text-transform: uppercase;
  color: var(--muted); margin: var(--space-5) 0 var(--space-2);
}
.section-label:first-child { margin-top: 0; }

@media (max-width: 620px) {
  .cert-facts { grid-template-columns: 1fr; gap: 2px var(--space-4); }
  .cert-facts .dt { margin-top: var(--space-2); }
  .chain-item { flex-wrap: wrap; }
}

.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  border: 0;
}
.sort-span {
  padding-left: var(--space-1);
}
.invisible-form {display:none;}
.notification {color: var(--danger);}
.license-terms-header {padding-bottom: var(--space-1);}
.justify-text {text-align: justify;}
.help-button {color: var(--accent);}
#modalWindow {display:none;}
.srkbold {
  font-weight: bold;
}
.eye-button {
  position: absolute!important;
  right: 8px;
  font-size: 16px;
  cursor: pointer;
}
.password-box {
  position: relative;

  input[type=password], input[type=text] {
    padding-right:30px;
  }
}

.jnotify-container {
  position: fixed;
  top: 0;
  right: 0;
  width: 400px;
  z-index: 100000;
  max-height: 270px;
  overflow-x: hidden;
  overflow-y: auto;
}

@media(max-width: 400px) {
.jnotify-container {
  max-width:100%;
}
}

.jnotify-container .jnotify-notification {
  position: relative;
  min-height: 30px;
  padding: 10px 0;
  /*border: 1px solid #FFF;*/
  border: 1px solid rgba(255, 255, 255, .0);
  -webkit-background-clip: padding-box; /* for Safari */
  background-clip: padding-box;
  border: 1px solid #FFF;
  background-color: #4c4c4c;
  opacity(0.9);
}
.jnotify-container .jnotify-notification .jnotify-background {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 0px;
  background-color: #4c4c4c;
  opacity(0.9);
  z-index: 1;
}
.jnotify-container .jnotify-notification a.jnotify-close,
.jnotify-container .jnotify-notification a.jnotify-close:link,
.jnotify-container .jnotify-notification a.jnotify-close:visited,
.jnotify-container .jnotify-notification a.jnotify-close:focus,
.jnotify-container .jnotify-notification a.jnotify-close:hover {
  position: absolute;
  top: 2px;
  right: 5px;
  padding: 0 5px;
  font-size: 10pt;
  font-weight: bold;
  color: #fff;
  text-decoration: none;
  z-index: 3;
  cursor: pointer;
}
.jnotify-container .jnotify-notification .jnotify-message {
  position: relative;
  z-index: 2;
  padding: 0 16px;
  text-align: left;
  color: #fff;
  display: table-cell;
  vertical-align: middle;
  /*min-height:50px;*/
  font-size: 10pt;
  font-weight: bold;
}
.jnotify-container .jnotify-notification .jnotify-message * {
  font-size: 10pt;
}
/* notification type == "error" */
.jnotify-container .jnotify-notification-error .jnotify-background, .jnotify-notification-error {
  background-color: #d79eac!important;
}
.jnotify-container .jnotify-notification-error .jnotify-close,
.jnotify-container .jnotify-notification-error .jnotify-message {
  color: #a72947 !important;
}
/* notification type == "warning" */
.jnotify-container .jnotify-notification-warning .jnotify-background {
  background-color: #fff7d1;
}
.jnotify-container .jnotify-notification-warning .jnotify-close,
.jnotify-container .jnotify-notification-warning .jnotify-message {
  color: #c2a928 !important;
}

#closeButton {display: none;}

.srkInputFormCellAttention {
  background-color: var(--accent);
}

.thumbnails-container {
  padding: 10px 0;
  display: flex;
  gap: 10px;
  flex-wrap: wrap;
}

.thumbnail-block {
  display: table;
  max-width: 350px;
  white-space: nowrap;
  padding: 0 10px 10px 0;
  min-height: 100px;
}

.thumbnail-check {
  display: table-cell;
  white-space: normal;
  min-width: 24px;
  vertical-align: middle;
  padding-right: var(--space-2);
}

.thumbnail-image {
  display: table-cell;
  white-space: normal;
  min-width: 100px;
  vertical-align: middle;
}

.thumbnail-text {
  display: table-cell;
  white-space: normal;
  min-width: 220px;
  padding-left: 10px;
  vertical-align: middle;
}

.input-help { display: flex; align-items: center; gap: 6px; }
.input-help .form-control { flex: 1; }
.help-btn {
  width: 32px; height: var(--control-h); flex: none;
  display: inline-flex; align-items: center; justify-content: center;
  background: var(--surface); color: var(--accent-hover);
}
.help-btn:hover { background: var(--hover); }

/* Employee Schedule coverage cells.
   The old page painted a green/red carpet: every uncovered hour was a pink
   block, so a normally-staffed week read as a failure. veralab-core encodes the
   same two states far more quietly — an assigned shift is an ordinary surface
   with a green left edge, uncovered time is just a dashed outline. These two
   rules mirror .legend-on / .legend-off exactly, so the legend and the grid
   agree. The --coverage-*-block-color tokens stay defined but unused. */
.srkCoveragedCell {
  background: var(--surface);
  padding: 1px;
  border: 1px solid var(--border);
  border-left: 3px solid var(--ok);
  margin: 1px;
}

.srkUncoveragedCell {
  background: transparent;
  padding-top: 1px;
  border: 1px dashed var(--border-strong);
  margin: 1px;
}


.coverage-block {
  padding:8px 5px;
  color: var(--coverage-block-color);
}

.hidden-print {
  @media print {
    display: none !important;
  }
}

.visible-print {
  display: none !important;

  @media print {
    display: block !important;
  }
}

.separator {
  border-top: 1px solid var(--border);
  border-bottom: 0;
  border-left: 0;
  border-right: 0;
  width: 100%;
}

.srkDashVacantText, .srkDashVacantText:hover {
  color: var(--ok-text);
}
.srkDashUsedText, .srkDashUsedText:hover {
  color: var(--text-strong);
}
.srkDashUnavailableText, .srkDashUnavailableText:hover {
  color: var(--danger);
}
.srkDashClassText, .srkDashClassText:hover {
  color: var(--info);
}
.srkDashWaitlistText, .srkDashWaitlistText:hover {
  color: var(--info);
}
.c-red {color: var(--danger-text)!important;}
.srkred {color: var(--danger-text);}
.centered-cell, .report-action-cell {text-align: center!important;}
#occupancy-legend {padding: 10px 0;text-align: center;}
#occupancy-legend table {width:auto;}
.legendColorBox {padding: 0 10px;}
.flot-text, .legendLabel {
  color: var(--text)!important;
}
.more-analysis-link {text-align:right;}

/* This is the core CSS of Tooltipster */

/* GENERAL STRUCTURE RULES (do not edit this section) */

.tooltipster-base {
  /* this ensures that a constrained height set by functionPosition,
  if greater that the natural height of the tooltip, will be enforced
  in browsers that support display:flex */
  display: flex;
  pointer-events: none;
  /* this may be overriden in JS for fixed position origins */
  position: absolute;
}

.tooltipster-box {
  /* see .tooltipster-base. flex-shrink 1 is only necessary for IE10-
  and flex-basis auto for IE11- (at least) */
  flex: 1 1 auto;
}

.tooltipster-content {
  /* prevents an overflow if the user adds padding to the div */
  box-sizing: border-box;
  /* these make sure we'll be able to detect any overflow */
  max-height: 100%;
  max-width: 100%;
  overflow: auto;
}

.tooltipster-ruler {
  /* these let us test the size of the tooltip without overflowing the window */
  bottom: 0;
  left: 0;
  overflow: hidden;
  position: fixed;
  right: 0;
  top: 0;
  visibility: hidden;
}

/* ANIMATIONS */

/* Open/close animations */

/* fade */

.tooltipster-fade {
  opacity: 0;
  transition-property: opacity;
}
.tooltipster-fade.tooltipster-show {
  opacity: 1;
}

/* grow */

.tooltipster-grow {
  transform: scale(0, 0);
  transition-property: transform;
}
.tooltipster-grow.tooltipster-show {
  transform: scale(1, 1);
  transition-timing-function: cubic-bezier(0.175, 0.885, 0.320, 1.15);
}

/* swing */

.tooltipster-swing {
  opacity: 0;
  transform: rotateZ(4deg);
  transition-property: transform;
}
.tooltipster-swing.tooltipster-show {
  opacity: 1;
  transform: rotateZ(0deg);
  transition-timing-function: cubic-bezier(0.230, 0.635, 0.495, 2.4);
}

/* fall */

.tooltipster-fall {
  transition-property: top;
  transition-timing-function: cubic-bezier(0.175, 0.885, 0.320, 1.15);
}
.tooltipster-fall.tooltipster-initial {
  top: 0 !important;
}
.tooltipster-fall.tooltipster-dying {
  transition-property: all;
  top: 0 !important;
  opacity: 0;
}

/* slide */

.tooltipster-slide {
  transition-property: left;
  transition-timing-function: cubic-bezier(0.175, 0.885, 0.320, 1.15);
}
.tooltipster-slide.tooltipster-initial {
  left: -40px !important;
}
.tooltipster-slide.tooltipster-dying {
  transition-property: all;
  left: 0 !important;
  opacity: 0;
}

/* Update animations */

/* We use animations rather than transitions here because
 transition durations may be specified in the style tag due to
 animationDuration, and we try to avoid collisions and the use
 of !important */

/* fade */

@keyframes tooltipster-fading {
  0% {
    opacity: 0;
  }
  100% {
    opacity: 1;
  }
}

.tooltipster-update-fade {
  animation: tooltipster-fading 400ms;
}

/* rotate */

@keyframes tooltipster-rotating {
  25% {
    transform: rotate(-2deg);
  }
  75% {
    transform: rotate(2deg);
  }
  100% {
    transform: rotate(0);
  }
}

.tooltipster-update-rotate {
  animation: tooltipster-rotating 600ms;
}

/* scale */

@keyframes tooltipster-scaling {
  50% {
    transform: scale(1.1);
  }
  100% {
    transform: scale(1);
  }
}

.tooltipster-update-scale {
  animation: tooltipster-scaling 600ms;
}

/**
 * DEFAULT STYLE OF THE SIDETIP PLUGIN
 *
 * All styles are "namespaced" with .tooltipster-sidetip to prevent
 * conflicts between plugins.
 */

/* .tooltipster-box */

.tooltipster-sidetip .tooltipster-box {
  background: #ffffcc;
  border: 1px solid black;
  border-radius: 4px;
}

.tooltipster-sidetip.tooltipster-bottom .tooltipster-box {
  margin-top: 8px;
}

.tooltipster-sidetip.tooltipster-left .tooltipster-box {
  margin-right: 8px;
}

.tooltipster-sidetip.tooltipster-right .tooltipster-box {
  margin-left: 8px;
}

.tooltipster-sidetip.tooltipster-top .tooltipster-box {
  margin-bottom: 8px;
}

/* .tooltipster-content */

.tooltipster-sidetip .tooltipster-content {
  line-height: 18px;
  padding: 6px 14px;
}

/* .tooltipster-arrow : will keep only the zone of .tooltipster-arrow-uncropped that
corresponds to the arrow we want to display */

.tooltipster-sidetip .tooltipster-arrow {
  overflow: hidden;
  position: absolute;
}

.tooltipster-sidetip.tooltipster-bottom .tooltipster-arrow {
  height: 10px;
  /* half the width, for centering */
  margin-left: -10px;
  top: -1px;
  width: 20px;
}

.tooltipster-sidetip.tooltipster-left .tooltipster-arrow {
  height: 20px;
  margin-top: -10px;
  right: 0;
  /* top 0 to keep the arrow from overflowing .tooltipster-base when it has not
  been positioned yet */
  top: 0;
  width: 10px;
}

.tooltipster-sidetip.tooltipster-right .tooltipster-arrow {
  height: 20px;
  margin-top: -10px;
  left: 0;
  /* same as .tooltipster-left .tooltipster-arrow */
  top: 0;
  width: 10px;
}

.tooltipster-sidetip.tooltipster-top .tooltipster-arrow {
  bottom: -1px;
  height: 10px;
  margin-left: -10px;
  width: 20px;
}

/* common rules between .tooltipster-arrow-background and .tooltipster-arrow-border */

.tooltipster-sidetip .tooltipster-arrow-background,
.tooltipster-sidetip .tooltipster-arrow-border {
  height: 0;
  position: absolute;
  width: 0;
}

/* .tooltipster-arrow-border */

.tooltipster-sidetip .tooltipster-arrow-border {
  border: 10px solid transparent;
  left: 0;
  top: 0;
}

.tooltipster-sidetip.tooltipster-bottom .tooltipster-arrow-border {
  border-bottom-color: black;
}

.tooltipster-sidetip.tooltipster-left .tooltipster-arrow-border {
  border-left-color: black;
}

.tooltipster-sidetip.tooltipster-right .tooltipster-arrow-border {
  border-right-color: black;
}

.tooltipster-sidetip.tooltipster-top .tooltipster-arrow-border {
  border-top-color: black;
}

/* tooltipster-arrow-uncropped */

.tooltipster-sidetip .tooltipster-arrow-uncropped {
  position: relative;
}

.tooltipster-sidetip.tooltipster-bottom .tooltipster-arrow-uncropped {
  top: -10px;
}

.tooltipster-sidetip.tooltipster-right .tooltipster-arrow-uncropped {
  left: -10px;
}

.tooltipster-content {
  text-align: left;
  background-color: var(--tooltipster-bg);
  color: var(--tooltipster-text);
}

/* .tooltipster-arrow-background */

.tooltipster-sidetip .tooltipster-arrow-background {
  border: 10px solid transparent;
}

.tooltipster-sidetip.tooltipster-bottom .tooltipster-arrow-background {
  border-bottom-color: var(--tooltipster-bg);
  left: 0;
  top: 1px;
}

.tooltipster-sidetip.tooltipster-left .tooltipster-arrow-background {
  border-left-color: var(--tooltipster-bg);
  left: -1px;
  top: 0;
}

.tooltipster-sidetip.tooltipster-right .tooltipster-arrow-background {
  border-right-color: var(--tooltipster-bg);
  left: 1px;
  top: 0;
}

.tooltipster-sidetip.tooltipster-top .tooltipster-arrow-background {
  border-top-color: var(--tooltipster-bg);
  left: 0;
  top: -1px;
}

.app-form .table-card {
  overflow-x: auto;
}

.img-responsive {
  width: 100%; height: auto;
}

/* end custom block */

/* booking styles */
.base_tile, .booking_tile, .booking_tile_admin, .booking_tile_waitlist, .class_booking_tile, .my_booking_tile, .other_booking_tile {
  border-bottom: 1px solid white;
  display: block;
  margin-left: 1px;
  padding: 3px 3px;
  text-decoration: none;
}

.delete-button-cell {
  width: var(--admin-booking-del-cell-width);
  max-width: var(--admin-booking-del-cell-width);
}

.delete-class-button-cell {
  width: var(--admin-class-booking-del-cell-width);
  max-width: var(--admin-class-booking-del-cell-width);
  text-align: center;
}

.booking_tile {
  background-color: #CCCCCC;
  color: black;
  max-width: calc(var(--admin-booking-tile-width) - var(--admin-booking-del-cell-width) - 1px);
}

.booking_tile_admin {
  background-color: #CCCCFF;
  color: black;
  max-width: calc(var(--admin-booking-tile-width) - var(--admin-booking-del-cell-width) - 1px);
}

.booking_tile_waitlist {
  background-color: #ff9999;
  color: black;
  max-width: calc(var(--admin-booking-tile-width) - 1px);
}

.class_booking_tile {
  background-color: #AAAAAA;
  color: black;
  max-width: calc(var(--admin-booking-tile-width) - 1px);
}

.my_booking_tile {
  background-color: #AAD5BF;
  color: black;
  max-width: calc(var(--admin-booking-tile-width) - var(--admin-booking-del-cell-width) - 1px);
}

.other_booking_tile {
  background-color: #CCCCCC;
  color: black;
  max-width: calc(var(--admin-booking-tile-width) - 1px);
}


.class_book_tile {
  display: block;
  margin-bottom: 1px;
  padding: 3px;
  text-decoration: none;
  background-color: #AAAAAA;
  color: black;
  max-width: calc(var(--admin-class-booking-tile-width) - var(--admin-class-booking-del-cell-width));
}

.ws_tile {
  display: block;
  margin-bottom: 1px;
  padding: 1px;
  text-decoration: none;
  background-color: var(--nav-bg);
  width: 80px;
  color: white;
}

.ws_tile_a {
  display: block;
  border-bottom: 1px solid white;
  margin-left:1px;
  padding: 3px 1px;
  text-decoration: none;
  background-color: var(--nav-bg);
  color: white;
  text-align: center;
  max-width: calc(var(--admin-booking-tile-width) - 1px);
}

.dow-block {
  text-align: center;
  padding:3px;
}

.class_tile {
  display: block;
  margin-bottom: 1px;
  padding: 3px;
  text-decoration: none;
  background-color: var(--nav-bg);
  width: 120px;
  font-size: 12px;
  color: white;
  text-align: center;
}

.mesh_grid {
  display: flex;
  gap: 10px;
  flex-wrap: wrap;

  .booking-tile {
    margin-bottom: 0;
  }
}

table.mesh_grid td {
  border: 1px solid var(--blue);
  width: 98px;
}

.class_mesh_grid {
  border: 1px solid var(--blue);
  border-collapse: collapse;
}

table.class_mesh_grid>tbody>tr>td {
  border: 1px solid var(--blue);
  width: var(--admin-class-booking-tile-width);
}


.tile_grid {
  border: 0;
  width: var(--admin-booking-tile-width);
}

.class_tile_grid {
  border: 0;
  width: var(--admin-class-booking-tile-width);
}

.srktooltip {
  border: 1px solid black;
  padding: 2px 3px 3px 3px;
  background-color: #ffffcc;
  white-space:nowrap;
}

.srkLoadingText {
  font-size: 10pt;
  color: black;
  font-weight: 700;
  text-decoration: none;
  white-space: nowrap;
}

.station_tile {
  float:left;
  /*padding-right: 4px;*/
}

.booking-tooltip {
  text-align:left;
}

.booking-table {
  width:auto;
  thead {
    position: -webkit-sticky;
    position: sticky;
    top: 0;
  }
  th {
    white-space: normal!important;
  }
  td:nth-child(1), th:nth-child(1) {
    width: var(--booking-first-column-width);
    max-width: var(--booking-first-column-width);
    min-width: var(--booking-first-column-width);
  }
  td:nth-child(1) {
    background-color: var(--stripped-table-header-color);
    border: 1px solid #bfbfbf;
    position: -webkit-sticky;
    position: sticky;
    left:0;
    padding: 4px 12px 0.34em!important;
  }
}

.bk-schedule td:nth-child(1),
.bk-schedule th:nth-child(1) {
  width: 80px;
  max-width: 80px;
  min-width: 80px;
}

.tf-24h {
  td, th {
    width: var(--booking-cell-width-24h);
    max-width: var(--booking-cell-width-24h);
    min-width: var(--booking-cell-width-24h);
  }
}

.tf-12h {
  td, th {
    width: var(--booking-cell-width-12h);
    max-width: var(--booking-cell-width-12h);
    min-width: var(--booking-cell-width-12h);
  }
}

.booking-tile {
  thead {
    tr {
      th {
        background-color: var(--nav-bg);
        color: white;
      }
    }
  }
}

.base-booking-cell, .class-booking-cell, .free-booking-cell, .admin-booking-cell, .user-booking-cell, .my-booking-cell, .waitlist-booking-cell, .unavailable-booking-cell {
  vertical-align: top !important;
  color: #000!important;
  text-align: left;
  border: 1px solid #bfbfbf !important;
  padding: 4px 12px 0.34em!important;
}

.class-booking-cell {
  padding: var(--space-2)!important;
}

.class-booking-cell {
  white-space: normal!important;
  background-color: #AAAAAA;
}

.closed-class-cell {
  vertical-align: top !important;
  text-align: left;
  border: 1px solid #bfbfbf !important;
  white-space: normal!important;
  background-color: var(--stripped-table-header-color);
}

.free-booking-cell {
  background-color: var(--surface);
}

.free-booking-cell:hover {
  border: 1px solid #bfbfbf !important;
  text-align: center;
  background-color: #AAD5BF;
  cursor: pointer;
}


.admin-booking-cell {
  background-color: #CCCCFF;
}

.user-booking-cell {
  background-color: #CCCCCC;
}

.my-booking-cell {
  background-color: #AAD5BF;
}

.waitlist-booking-cell {
  background-color: #ff9999;
}

.unavailable-booking-cell {
  background-color: #dddddd;
}

.booking-text-wrapper {
  display: block;
  width: 99%;
  white-space: normal;
  height: 100%;
  float: left;
}

.tf-24h .booking-text-wrapper {
  max-width: 105px;
}

.tf-12h .booking-text-wrapper {
  max-width: 125px;
}


.booking-button-wrapper {
  display: block;
  vertical-align: bottom;
  height: 100%;
  max-width: 20px;
  float: right;
}

.class-booking-tile {
  margin-bottom:0;
  border: 0!important;

  th {
    border-right:0!important;
  }

  .class-booking-cell, .closed-class-cell {
    border-left:0!important;
    border-right:0!important;
  }
}
.add-booking-cell {text-align: center!important;}
/* end of booking styles */

/* Booking Email Settings (bm-*) — section 25g of the design system.
   Ported from veralab/design/design_handoff_booking_emails/design/veralab.css.
   Segmented controls reuse .lm-seg / .lm-seg-sm, which the LiveMap section
   (25f) owns and which is NOT yet in the production sheet -- the minimum
   needed is defined at the end of this file so the screen stands alone. */

/* ---------- 25g. BOOKING EMAIL SETTINGS (bm-*) ----------
   Twelve templates + one shared signature. List on the left, one email on the
   right: read it as the recipient sees it, edit subject and body in one frame
   with insertable, validated variables. "Read all" lays the twelve out at full
   height for comparison — no inner scroll boxes anywhere.
   Reuses .lm-seg (§25f) for segmented controls. No new tokens. */
.bm-toolbar { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-2) var(--space-4); }
.bm-toolbar .field-note { margin-left: auto; }
.bm-shell { display: grid; grid-template-columns: 300px minmax(0, 1fr); gap: var(--space-4); align-items: start; }
.bm-shell.is-all { grid-template-columns: minmax(0, 1fr); }
.bm-shell.is-all .bm-list { display: none; }

.bm-list {
  position: sticky; top: var(--space-4); max-height: calc(100vh - 120px); min-height: 320px;
  display: flex; flex-direction: column; gap: var(--space-3); padding: var(--space-4);
  background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius);
}
.bm-list > .bm-list-head, .bm-list > .lm-seg { flex: none; }
.bm-list-head { display: flex; align-items: baseline; justify-content: space-between; gap: var(--space-2); }
.bm-list-title { font-size: var(--text-sm); font-weight: 700; color: var(--text-strong); }
.bm-tally { font-size: var(--text-xs); color: var(--muted); }
.bm-list-body { display: flex; flex-direction: column; gap: var(--space-3); flex: 1 1 auto; min-height: 0; overflow-y: auto; margin-right: calc(var(--space-2) * -1); padding-right: var(--space-2); }
.bm-group { display: flex; flex-direction: column; gap: 2px; }
.bm-group-title { padding: 0 10px var(--space-1); }
.bm-row {
  display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: 2px var(--space-2); align-items: baseline;
  width: 100%; padding: 7px 10px; text-align: left; color: var(--text);
  background: none; border: 1px solid transparent; border-radius: 6px;
}
.bm-row:hover { background: var(--hover); }
.bm-row.is-sel { background: var(--accent-soft); border-color: color-mix(in srgb, var(--accent) 45%, transparent); }
.bm-row-name { font-size: var(--text-sm); font-weight: 600; color: var(--text-strong); min-width: 0; }
.bm-row-subj { grid-column: 1 / -1; font-size: var(--text-xs); color: var(--muted); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.bm-list-empty { padding: var(--space-3) 10px; font-size: var(--text-sm); color: var(--muted); }

/* state marker: word + shape, never colour alone.
   default = hollow ring · custom = filled dot · unsaved = square · needs a fix = diamond */
.bm-state { display: inline-flex; align-items: center; gap: 6px; font-size: var(--text-xs); font-weight: 600; color: var(--muted); white-space: nowrap; }
.bm-state::before { content: ''; width: 7px; height: 7px; flex: none; border-radius: 50%; border: 1.5px solid currentColor; box-sizing: border-box; }
.bm-state-custom { color: var(--accent-text); }
.bm-state-custom::before { background: currentColor; }
.bm-state-draft { color: var(--warn-text); }
.bm-state-draft::before { background: currentColor; border-radius: 1px; }
.bm-state-bad { color: var(--danger-text); }
.bm-state-bad::before { background: currentColor; border-radius: 1px; transform: rotate(45deg); }

.bm-detail { display: flex; flex-direction: column; gap: var(--space-4); min-width: 0; padding: var(--space-5); background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius); }
.bm-head { display: flex; flex-wrap: wrap; align-items: flex-start; justify-content: space-between; gap: var(--space-3) var(--space-5); }
.bm-head-text { display: flex; flex-direction: column; gap: var(--space-1); min-width: 0; flex: 1 1 320px; }
.bm-title { font-size: var(--text-xl); font-weight: 700; color: var(--text-strong); }
.bm-desc { font-size: var(--text-sm); color: var(--text-soft); line-height: 1.5; text-wrap: pretty; }
.bm-meta { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-1) var(--space-3); font-size: var(--text-xs); color: var(--muted); }
.bm-head-acts { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-3); }

.bm-edit { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: var(--space-5); align-items: start; }
.bm-pane { display: flex; flex-direction: column; gap: var(--space-3); min-width: 0; }
.bm-pane-head { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: var(--space-2); min-height: 30px; }
.bm-pane-title { font-size: var(--text-sm); font-weight: 700; color: var(--text-strong); }
.bm-side { position: sticky; top: var(--space-4); }

/* the source: subject and body in ONE frame, because together they are one email */
.bm-frame { display: flex; flex-direction: column; background: var(--surface); border: 1px solid var(--border-strong); border-radius: var(--radius); overflow: hidden; }
.bm-frame:focus-within { border-color: var(--accent-hover); }
.bm-frame.has-error { border-color: var(--danger); }
.bm-pane-wrap [hidden] { display: none; }
.bm-frame .form-group { margin: 0; gap: 0; }
.bm-frame .help-block:empty { display: none; }
.bm-frame-body { display: block; }
.bm-pane-wrap > .bm-head { margin-bottom: var(--space-4); }
.bm-pane-wrap form { margin: 0; }
.bm-frame-row { display: grid; grid-template-columns: 72px minmax(0, 1fr); align-items: center; border-bottom: 1px solid var(--border); }
.bm-frame-label { padding: 0 var(--space-3); font-size: var(--text-xs); font-weight: 600; color: var(--muted); }
.bm-frame-input { width: 100%; height: 42px; padding: 0 var(--space-3) 0 0; border: 0; outline: none; background: transparent; font: inherit; font-size: var(--text-sm); font-weight: 600; color: var(--text-strong); }
.bm-vars { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; padding: var(--space-2) var(--space-3); background: var(--raised); border-bottom: 1px solid var(--border); }
.bm-vars-label { font-size: var(--text-xs); font-weight: 600; color: var(--muted); margin-right: 2px; }
.bm-var {
  padding: 2px var(--space-2); border: 1px solid var(--border-strong); border-radius: var(--radius-cell);
  background: var(--surface); font-family: var(--font-mono); font-size: var(--text-xs); color: var(--text-soft); cursor: pointer; white-space: nowrap;
}
.bm-var:hover, .bm-var:focus-visible { border-color: var(--accent); background: var(--accent-soft); color: var(--accent-text); outline: none; }
.bm-frame-body { width: 100%; min-height: 220px; padding: var(--space-3); border: 0; outline: none; resize: vertical; background: transparent; font-family: var(--font-mono); font-size: var(--text-sm); line-height: 1.65; color: var(--text-strong); }
.bm-frame-sig { padding: var(--space-2) var(--space-3); border-top: 1px dashed var(--border-strong); background: var(--raised); font-size: var(--text-sm); color: var(--muted); white-space: pre-wrap; line-height: 1.5; }
.bm-frame-sig b { display: block; font-size: var(--text-xs); font-weight: 600; }

.bm-issues { display: flex; flex-direction: column; gap: 6px; margin: 0; padding: 0; list-style: none; font-size: var(--text-sm); color: var(--danger-text); }
.bm-issues:empty { display: none; }
.bm-issues li { display: flex; flex-wrap: wrap; align-items: baseline; gap: 4px var(--space-2); }
.bm-issues .ic { width: 15px; height: 15px; flex: none; align-self: center; }
.bm-issues li > span { flex: 1 1 260px; line-height: 1.5; }
.bm-issues code { font-weight: 600; white-space: nowrap; }

/* the email as the recipient sees it */
.bm-mail { display: flex; flex-direction: column; background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius); box-shadow: var(--shadow-1); overflow: hidden; }
.bm-mail-head { display: grid; grid-template-columns: 64px minmax(0, 1fr); gap: 3px 0; padding: var(--space-3) var(--space-4); background: var(--raised); border-bottom: 1px solid var(--border); font-size: var(--text-sm); }
.bm-mail-k { font-size: var(--text-xs); font-weight: 600; color: var(--muted); align-self: baseline; }
.bm-mail-v { color: var(--text-soft); overflow-wrap: anywhere; }
.bm-mail-subj { font-size: var(--text-md); font-weight: 700; color: var(--text-strong); }
.bm-mail-body { padding: var(--space-4) var(--space-4) 0; font-size: var(--text-base); line-height: 1.6; color: var(--text); white-space: pre-wrap; overflow-wrap: anywhere; }
.bm-mail-body:last-child { padding-bottom: var(--space-4); }
.bm-mail-sig { padding: var(--space-4); font-size: var(--text-base); line-height: 1.6; color: var(--text-soft); white-space: pre-wrap; }
.bm-mail-sig.is-draft { background: var(--warn-soft); }
.bm-val { background: var(--accent-soft); color: inherit; border-radius: 3px; padding: 0 2px; box-shadow: inset 0 -1px 0 var(--accent); }
.bm-bad { background: var(--danger-soft); color: var(--danger-text); font-family: var(--font-mono); font-size: .92em; border-radius: 3px; padding: 0 2px; box-shadow: inset 0 -1px 0 var(--danger); }
.bm-source { margin: 0; padding: var(--space-4); background: var(--raised); border: 1px solid var(--border); border-radius: var(--radius); font-family: var(--font-mono); font-size: var(--text-sm); line-height: 1.65; color: var(--text-strong); white-space: pre-wrap; overflow-wrap: anywhere; }
.bm-source b { display: block; margin-bottom: var(--space-2); font-weight: 600; }

.bm-sig-input { font-family: var(--font-mono); min-height: 110px; line-height: 1.6; }
.bm-ro { display: flex; align-items: flex-start; gap: var(--space-2); }
.bm-ro .ic { width: 15px; height: 15px; flex: none; margin-top: 3px; color: var(--muted); }

.bm-foot { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-2); padding-top: var(--space-4); border-top: 1px solid var(--border); }
.bm-foot-state { margin-right: auto; font-size: var(--text-sm); color: var(--muted); }
.bm-foot-state.is-dirty { color: var(--warn-text); font-weight: 600; }

/* Read all: the set at full height, equal-height cards per row */
.bm-all { display: flex; flex-direction: column; gap: var(--space-6); }
.bm-all-group { display: flex; flex-direction: column; gap: var(--space-3); }
.bm-all-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(min(100%, 380px), 1fr)); gap: var(--space-4); }
.bm-card { display: flex; flex-direction: column; gap: var(--space-2); min-width: 0; }
.bm-card-head { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-1) var(--space-3); }
.bm-card-name { font-size: var(--text-sm); font-weight: 700; color: var(--text-strong); margin-right: auto; }
.bm-card .bm-mail { flex: 1; }

@media (max-width: 1180px) {
  .bm-edit { grid-template-columns: minmax(0, 1fr); }
  .bm-side { position: static; }
}
@media (max-width: 820px) {
  .bm-shell { grid-template-columns: minmax(0, 1fr); }
  .bm-list { position: static; max-height: 340px; }
}
@media (max-width: 520px) {
  .bm-detail { padding: var(--space-3); }
  .bm-row { grid-template-columns: minmax(0, 1fr); }
  .bm-row-subj { grid-column: 1; }
  .bm-pane-head .lm-seg { flex-wrap: wrap; max-width: 100%; }
  .bm-pane-head .lm-seg button { white-space: normal; }
}

/* ---------- segmented control, borrowed from 25f (LIVEMAP EDITOR) ----------
   .bm-* reuses .lm-seg for its two segmented controls. The LiveMap screen
   is not ported yet, so its section is absent from the production sheet and
   these six rules would be undefined. Delete this block when 25f lands,
   rather than leaving two definitions to drift. */
.lm-seg { display: inline-flex; border: 1px solid var(--border-strong); border-radius: var(--radius); overflow: hidden; background: var(--surface); }
.lm-seg button { white-space: nowrap; padding: 6px var(--space-3); border: 0; border-right: 1px solid var(--border); background: transparent; font: inherit; font-size: var(--text-sm); color: var(--text-soft); cursor: pointer; }
.lm-seg button:last-child { border-right: 0; }
.lm-seg button:hover { background: var(--hover); }
.lm-seg button.is-on { background: var(--accent-soft); color: var(--accent-text); font-weight: 600; }
.lm-seg-sm button { padding: 4px var(--space-2); font-size: var(--text-xs); }
.lm-seg button:disabled { color: var(--muted-2); cursor: not-allowed; background: var(--raised); }
.report-toolbar {
  display: flex; flex-wrap: wrap; align-items: center;
  gap: var(--space-3) var(--space-5);
  margin-bottom: var(--space-5);
}
.report-toggle { display: inline-flex; align-items: center; gap: var(--space-2); font-size: var(--text-sm); color: var(--text); cursor: pointer; }

.report-search { position: relative; display: flex; align-items: center; flex: 0 1 340px; }
.report-search .input { width: 100%; padding-left: 34px; padding-right: 30px; }
.report-search .input::-webkit-search-cancel-button { display: none; }
.report-search-icon {
  position: absolute; left: 10px; width: 16px; height: 16px;
  color: var(--muted-2); pointer-events: none;
}
.report-search-clear {
  position: absolute; right: 6px;
  display: inline-flex; padding: 3px; cursor: pointer;
  background: none; border: 0; border-radius: 4px; color: var(--muted);
}
.report-search-clear:hover { background: var(--hover); color: var(--text); }
.report-search-clear .ic { width: 14px; height: 14px; }

.report-count { font-size: var(--text-sm); color: var(--muted); font-variant-numeric: tabular-nums; }
.report-empty { font-size: var(--text-sm); color: var(--text-soft); padding: var(--space-5) 0; }
.report-empty strong { color: var(--text-strong); }

/* match highlight — a tint rather than the browser's yellow */
.report-columns mark {
  background: var(--accent-soft); color: inherit;
  border-radius: 3px; padding: 0 1px;
}
.report-column[hidden], .aside-list tr[hidden] { display: none; }

.report-columns {
  column-width: 400px;
  column-gap: var(--space-6);
  max-width: 1440px;
}

.report-column {
  break-inside: avoid; page-break-inside: avoid;
  display: inline-block; width: 100%;
  margin: 0 0 var(--space-6);
}
.report-group {
  font-size: var(--text-md); font-weight: 700; letter-spacing: .04em;
  text-transform: uppercase; color: var(--muted);
  margin: 0 0 var(--space-2);
}

.aside-list { width: 100%; border-collapse: collapse; background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius); overflow: hidden; }
.aside-list td { padding: var(--space-3) var(--space-4); border: 0; vertical-align: top; }
.aside-list tr:nth-child(even) td { background: var(--zebra); }
.aside-list tr + tr td { border-top: 1px solid var(--border); }
.aside-list tr:hover td { background: var(--hover); }
.report-link { display: block; font-size: var(--text-sm); font-weight: 600; color: var(--accent-text); text-decoration: none; }
.report-link:hover { text-decoration: underline; }
.report-desc { margin-top: var(--space-1); font-size: var(--text-xs); color: var(--text-soft); line-height: 1.45; text-wrap: pretty; }
.report-columns.hide-descriptions .report-desc { display: none; }


/*
 * This combined file was created by the DataTables downloader builder:
 *   https://datatables.net/download
 *
 * To rebuild or modify this file with the latest versions of the included
 * software please visit:
 *   https://datatables.net/download/#dt/dt-3.1.4
 *
 * Included libraries:
 *  DataTables 3.1.4
 */

:root {
  --dt_background-selected: 13, 110, 253;
  --dt_color-selected: 255, 255, 255;
  --dt_link_color-selected: 228, 228, 228;
  --dt-row_background: transparent;
  --dt-row_background-selected: var(--dt_background-selected);
  --dt-row-text_color-selected: var(--dt_color-selected);
  --dt-row-link_color-selected: var(--dt_link_color-selected);
  --dt-row_background-stripe: 0, 0, 0;
  --dt-row_background-hover: 0, 0, 0;
  --dt-column-ordering_background: 0, 0, 0;
  --dt-header-cell_align-items: center;
  --dt-header-cell_vertical-align: middle;
  --dt-html_background: white;
}
:root.dark {
  --dt-html_background: rgb(33, 37, 41);
}

table.dataTable tbody td.dt-control {
  text-align: center;
  cursor: pointer;
}
table.dataTable tbody td.dt-control:before {
  display: inline-block;
  box-sizing: border-box;
  content: "";
  border-top: 5px solid transparent;
  border-left: 10px solid rgba(0, 0, 0, 0.5);
  border-bottom: 5px solid transparent;
  border-right: 0px solid transparent;
}
table.dataTable tbody tr.dt-hasChild td.dt-control:before {
  border-top: 10px solid rgba(0, 0, 0, 0.5);
  border-left: 5px solid transparent;
  border-bottom: 0px solid transparent;
  border-right: 5px solid transparent;
}

:root.dark table.dataTable td.dt-control:before,
:root[data-bs-theme=dark] table.dataTable td.dt-control:before,
:root[data-theme=dark] table.dataTable td.dt-control:before {
  border-left-color: rgba(255, 255, 255, 0.5);
}
:root.dark table.dataTable tr.dt-hasChild td.dt-control:before,
:root[data-bs-theme=dark] table.dataTable tr.dt-hasChild td.dt-control:before,
:root[data-theme=dark] table.dataTable tr.dt-hasChild td.dt-control:before {
  border-top-color: rgba(255, 255, 255, 0.5);
  border-left-color: transparent;
}

div.dt-scroll {
  width: 100%;
}

div.dt-scroll-body thead tr,
div.dt-scroll-body tfoot tr {
  height: 0;
}
div.dt-scroll-body thead tr th, div.dt-scroll-body thead tr td,
div.dt-scroll-body tfoot tr th,
div.dt-scroll-body tfoot tr td {
  height: 0 !important;
  padding-top: 0px !important;
  padding-bottom: 0px !important;
  border-top-width: 0px !important;
  border-bottom-width: 0px !important;
}
div.dt-scroll-body thead tr th div.dt-scroll-sizing, div.dt-scroll-body thead tr td div.dt-scroll-sizing,
div.dt-scroll-body tfoot tr th div.dt-scroll-sizing,
div.dt-scroll-body tfoot tr td div.dt-scroll-sizing {
  height: 0 !important;
  overflow: hidden !important;
}

:root {
  --dt-order-arrow_color: rgb(51, 51, 51);
  --dt-order-arrow_color-current: rgb(51, 51, 51);
  --dt-order-arrow-height: 7px;
  --dt-order-arrow_opacity: 0.125;
  --dt-order-arrow_opacity-current: 0.65;
  --dt-order-arrow-width: 8px;
  --dt-order-arrow-gap: 1px;
  --dt-order-header_outline-hover: 2px solid rgba(0, 0, 0, 0.05);
}
:root.dark, :root[data-bs-theme=dark], :root[data-theme=dark] {
  --dt-order-arrow_color: rgb(229, 233, 238);
  --dt-order-arrow_color-current: rgb(229, 233, 238);
  --dt-order-header_outline-hover: 2px solid rgba(255, 255, 255, 0.05);
}

table.dataTable thead > tr > th:active,
table.dataTable thead > tr > td:active {
  outline: none;
}
table.dataTable thead > tr > th.dt-orderable-asc .dt-column-order:before, table.dataTable thead > tr > th.dt-ordering-asc .dt-column-order:before,
table.dataTable thead > tr > td.dt-orderable-asc .dt-column-order:before,
table.dataTable thead > tr > td.dt-ordering-asc .dt-column-order:before {
  bottom: calc(50% + var(--dt-order-arrow-gap));
  border-bottom: var(--dt-order-arrow-height) solid var(--dt-order-arrow_color);
  border-left: calc(var(--dt-order-arrow-width) / 2) solid transparent;
  border-right: calc(var(--dt-order-arrow-width) / 2) solid transparent;
}
table.dataTable thead > tr > th.dt-orderable-desc .dt-column-order:after, table.dataTable thead > tr > th.dt-ordering-desc .dt-column-order:after,
table.dataTable thead > tr > td.dt-orderable-desc .dt-column-order:after,
table.dataTable thead > tr > td.dt-ordering-desc .dt-column-order:after {
  top: calc(50% + 1px);
  border-top: var(--dt-order-arrow-height) solid var(--dt-order-arrow_color);
  border-left: calc(var(--dt-order-arrow-width) / 2) solid transparent;
  border-right: calc(var(--dt-order-arrow-width) / 2) solid transparent;
}
table.dataTable thead > tr > th.dt-orderable-asc .dt-column-order, table.dataTable thead > tr > th.dt-orderable-desc .dt-column-order, table.dataTable thead > tr > th.dt-ordering-asc .dt-column-order, table.dataTable thead > tr > th.dt-ordering-desc .dt-column-order,
table.dataTable thead > tr > td.dt-orderable-asc .dt-column-order,
table.dataTable thead > tr > td.dt-orderable-desc .dt-column-order,
table.dataTable thead > tr > td.dt-ordering-asc .dt-column-order,
table.dataTable thead > tr > td.dt-ordering-desc .dt-column-order {
  position: relative;
  width: var(--dt-order-arrow-width);
  align-self: stretch;
}
table.dataTable thead > tr > th.dt-orderable-asc .dt-column-order:before, table.dataTable thead > tr > th.dt-orderable-asc .dt-column-order:after, table.dataTable thead > tr > th.dt-orderable-desc .dt-column-order:before, table.dataTable thead > tr > th.dt-orderable-desc .dt-column-order:after, table.dataTable thead > tr > th.dt-ordering-asc .dt-column-order:before, table.dataTable thead > tr > th.dt-ordering-asc .dt-column-order:after, table.dataTable thead > tr > th.dt-ordering-desc .dt-column-order:before, table.dataTable thead > tr > th.dt-ordering-desc .dt-column-order:after,
table.dataTable thead > tr > td.dt-orderable-asc .dt-column-order:before,
table.dataTable thead > tr > td.dt-orderable-asc .dt-column-order:after,
table.dataTable thead > tr > td.dt-orderable-desc .dt-column-order:before,
table.dataTable thead > tr > td.dt-orderable-desc .dt-column-order:after,
table.dataTable thead > tr > td.dt-ordering-asc .dt-column-order:before,
table.dataTable thead > tr > td.dt-ordering-asc .dt-column-order:after,
table.dataTable thead > tr > td.dt-ordering-desc .dt-column-order:before,
table.dataTable thead > tr > td.dt-ordering-desc .dt-column-order:after {
  position: absolute;
  display: block;
  content: " ";
  height: 0;
  width: 0;
  left: 0;
  color: var(--dt-order-arrow_color);
  opacity: var(--dt-order-arrow_opacity);
}
table.dataTable thead > tr > th.dt-orderable-asc, table.dataTable thead > tr > th.dt-orderable-desc,
table.dataTable thead > tr > td.dt-orderable-asc,
table.dataTable thead > tr > td.dt-orderable-desc {
  cursor: pointer;
}
table.dataTable thead > tr > th.dt-orderable-asc:hover, table.dataTable thead > tr > th.dt-orderable-desc:hover,
table.dataTable thead > tr > td.dt-orderable-asc:hover,
table.dataTable thead > tr > td.dt-orderable-desc:hover {
  outline: var(--dt-order-header_outline-hover);
  outline-offset: -2px;
}
table.dataTable thead > tr > th.dt-ordering-asc .dt-column-order:before,
table.dataTable thead > tr > td.dt-ordering-asc .dt-column-order:before {
  border-bottom-color: var(--dt-order-arrow_color-current);
  opacity: var(--dt-order-arrow_opacity-current);
}
table.dataTable thead > tr > th.dt-ordering-desc .dt-column-order:after,
table.dataTable thead > tr > td.dt-ordering-desc .dt-column-order:after {
  border-top-color: var(--dt-order-arrow_color-current);
  opacity: var(--dt-order-arrow_opacity-current);
}
table.dataTable thead > tr > th.dt-orderable-none:not(.dt-ordering-asc, .dt-ordering-desc) .dt-column-order:empty, table.dataTable thead > tr > th.sorting_desc_disabled .dt-column-order:after, table.dataTable thead > tr > th.sorting_asc_disabled .dt-column-order:before,
table.dataTable thead > tr > td.dt-orderable-none:not(.dt-ordering-asc, .dt-ordering-desc) .dt-column-order:empty,
table.dataTable thead > tr > td.sorting_desc_disabled .dt-column-order:after,
table.dataTable thead > tr > td.sorting_asc_disabled .dt-column-order:before {
  display: none;
}
table.dataTable thead > tr > th:active,
table.dataTable thead > tr > td:active {
  outline: none;
}

table.dataTable thead > tr > th div.dt-column-header,
table.dataTable thead > tr > th div.dt-column-footer,
table.dataTable thead > tr > td div.dt-column-header,
table.dataTable thead > tr > td div.dt-column-footer,
table.dataTable tfoot > tr > th div.dt-column-header,
table.dataTable tfoot > tr > th div.dt-column-footer,
table.dataTable tfoot > tr > td div.dt-column-header,
table.dataTable tfoot > tr > td div.dt-column-footer {
  display: flex;
  justify-content: space-between;
  align-items: var(--dt-header-cell_align-items);
  gap: 4px;
}
table.dataTable thead > tr > th div.dt-column-header .dt-column-title,
table.dataTable thead > tr > th div.dt-column-footer .dt-column-title,
table.dataTable thead > tr > td div.dt-column-header .dt-column-title,
table.dataTable thead > tr > td div.dt-column-footer .dt-column-title,
table.dataTable tfoot > tr > th div.dt-column-header .dt-column-title,
table.dataTable tfoot > tr > th div.dt-column-footer .dt-column-title,
table.dataTable tfoot > tr > td div.dt-column-header .dt-column-title,
table.dataTable tfoot > tr > td div.dt-column-footer .dt-column-title {
  flex-grow: 1;
}
table.dataTable thead > tr > th div.dt-column-header .dt-column-title:empty,
table.dataTable thead > tr > th div.dt-column-footer .dt-column-title:empty,
table.dataTable thead > tr > td div.dt-column-header .dt-column-title:empty,
table.dataTable thead > tr > td div.dt-column-footer .dt-column-title:empty,
table.dataTable tfoot > tr > th div.dt-column-header .dt-column-title:empty,
table.dataTable tfoot > tr > th div.dt-column-footer .dt-column-title:empty,
table.dataTable tfoot > tr > td div.dt-column-header .dt-column-title:empty,
table.dataTable tfoot > tr > td div.dt-column-footer .dt-column-title:empty {
  display: none;
}

div.dt-scroll-body > table.dataTable > thead > tr > th,
div.dt-scroll-body > table.dataTable > thead > tr > td {
  overflow: hidden;
}

:root.dark table.dataTable thead > tr > th.dt-orderable-asc:hover, :root.dark table.dataTable thead > tr > th.dt-orderable-desc:hover,
:root.dark table.dataTable thead > tr > td.dt-orderable-asc:hover,
:root.dark table.dataTable thead > tr > td.dt-orderable-desc:hover,
:root[data-bs-theme=dark] table.dataTable thead > tr > th.dt-orderable-asc:hover,
:root[data-bs-theme=dark] table.dataTable thead > tr > th.dt-orderable-desc:hover,
:root[data-bs-theme=dark] table.dataTable thead > tr > td.dt-orderable-asc:hover,
:root[data-bs-theme=dark] table.dataTable thead > tr > td.dt-orderable-desc:hover {
  outline: var(--dt-order-header_outline-hover);
}

:root {
  --dt-processing-circle_background: var(--dt_background-selected);
}

div.dt-processing {
  position: absolute;
  top: 50%;
  left: 50%;
  width: 200px;
  margin-left: -100px;
  margin-top: -22px;
  text-align: center;
  padding: 2px;
  z-index: 10;
}
div.dt-processing > div:last-child {
  position: relative;
  width: 80px;
  height: 15px;
  margin: 1em auto;
}
div.dt-processing > div:last-child > div {
  position: absolute;
  top: 0;
  width: 13px;
  height: 13px;
  border-radius: 50%;
  background: rgb(var(--dt-processing-circle_background));
  animation-timing-function: cubic-bezier(0, 1, 1, 0);
}
div.dt-processing > div:last-child > div:nth-child(1) {
  left: 8px;
  animation: datatables-loader-1 0.6s infinite;
}
div.dt-processing > div:last-child > div:nth-child(2) {
  left: 8px;
  animation: datatables-loader-2 0.6s infinite;
}
div.dt-processing > div:last-child > div:nth-child(3) {
  left: 32px;
  animation: datatables-loader-2 0.6s infinite;
}
div.dt-processing > div:last-child > div:nth-child(4) {
  left: 56px;
  animation: datatables-loader-3 0.6s infinite;
}

@keyframes datatables-loader-1 {
  0% {
    transform: scale(0);
  }
  100% {
    transform: scale(1);
  }
}
@keyframes datatables-loader-3 {
  0% {
    transform: scale(1);
  }
  100% {
    transform: scale(0);
  }
}
@keyframes datatables-loader-2 {
  0% {
    transform: translate(0, 0);
  }
  100% {
    transform: translate(24px, 0);
  }
}
table.dataTable.nowrap th, table.dataTable.nowrap td {
  white-space: nowrap;
}
table.dataTable th,
table.dataTable td {
  box-sizing: border-box;
}
table.dataTable th.dt-type-numeric, table.dataTable th.dt-type-date,
table.dataTable td.dt-type-numeric,
table.dataTable td.dt-type-date {
  text-align: right;
}
table.dataTable th.dt-type-numeric div.dt-column-header,
table.dataTable th.dt-type-numeric div.dt-column-footer, table.dataTable th.dt-type-date div.dt-column-header,
table.dataTable th.dt-type-date div.dt-column-footer,
table.dataTable td.dt-type-numeric div.dt-column-header,
table.dataTable td.dt-type-numeric div.dt-column-footer,
table.dataTable td.dt-type-date div.dt-column-header,
table.dataTable td.dt-type-date div.dt-column-footer {
  flex-direction: row-reverse;
}
table.dataTable th.dt-left,
table.dataTable td.dt-left {
  text-align: left;
}
table.dataTable th.dt-left div.dt-column-header,
table.dataTable th.dt-left div.dt-column-footer,
table.dataTable td.dt-left div.dt-column-header,
table.dataTable td.dt-left div.dt-column-footer {
  flex-direction: row;
}
table.dataTable th.dt-center,
table.dataTable td.dt-center {
  text-align: center;
}
table.dataTable th.dt-right,
table.dataTable td.dt-right {
  text-align: right;
}
table.dataTable th.dt-right div.dt-column-header,
table.dataTable th.dt-right div.dt-column-footer,
table.dataTable td.dt-right div.dt-column-header,
table.dataTable td.dt-right div.dt-column-footer {
  flex-direction: row-reverse;
}
table.dataTable th.dt-justify,
table.dataTable td.dt-justify {
  text-align: justify;
}
table.dataTable th.dt-justify div.dt-column-header,
table.dataTable th.dt-justify div.dt-column-footer,
table.dataTable td.dt-justify div.dt-column-header,
table.dataTable td.dt-justify div.dt-column-footer {
  flex-direction: row;
}
table.dataTable th.dt-nowrap,
table.dataTable td.dt-nowrap {
  white-space: nowrap;
}
table.dataTable th.dt-empty,
table.dataTable td.dt-empty {
  text-align: center;
  vertical-align: top;
}
table.dataTable thead th,
table.dataTable thead td,
table.dataTable tfoot th,
table.dataTable tfoot td {
  text-align: left;
  vertical-align: var(--dt-header-cell_vertical-align);
}
table.dataTable thead th.dt-head-left,
table.dataTable thead td.dt-head-left,
table.dataTable tfoot th.dt-head-left,
table.dataTable tfoot td.dt-head-left {
  text-align: left;
}
table.dataTable thead th.dt-head-left div.dt-column-header,
table.dataTable thead th.dt-head-left div.dt-column-footer,
table.dataTable thead td.dt-head-left div.dt-column-header,
table.dataTable thead td.dt-head-left div.dt-column-footer,
table.dataTable tfoot th.dt-head-left div.dt-column-header,
table.dataTable tfoot th.dt-head-left div.dt-column-footer,
table.dataTable tfoot td.dt-head-left div.dt-column-header,
table.dataTable tfoot td.dt-head-left div.dt-column-footer {
  flex-direction: row;
}
table.dataTable thead th.dt-head-center,
table.dataTable thead td.dt-head-center,
table.dataTable tfoot th.dt-head-center,
table.dataTable tfoot td.dt-head-center {
  text-align: center;
}
table.dataTable thead th.dt-head-right,
table.dataTable thead td.dt-head-right,
table.dataTable tfoot th.dt-head-right,
table.dataTable tfoot td.dt-head-right {
  text-align: right;
}
table.dataTable thead th.dt-head-right div.dt-column-header,
table.dataTable thead th.dt-head-right div.dt-column-footer,
table.dataTable thead td.dt-head-right div.dt-column-header,
table.dataTable thead td.dt-head-right div.dt-column-footer,
table.dataTable tfoot th.dt-head-right div.dt-column-header,
table.dataTable tfoot th.dt-head-right div.dt-column-footer,
table.dataTable tfoot td.dt-head-right div.dt-column-header,
table.dataTable tfoot td.dt-head-right div.dt-column-footer {
  flex-direction: row-reverse;
}
table.dataTable thead th.dt-head-justify,
table.dataTable thead td.dt-head-justify,
table.dataTable tfoot th.dt-head-justify,
table.dataTable tfoot td.dt-head-justify {
  text-align: justify;
}
table.dataTable thead th.dt-head-justify div.dt-column-header,
table.dataTable thead th.dt-head-justify div.dt-column-footer,
table.dataTable thead td.dt-head-justify div.dt-column-header,
table.dataTable thead td.dt-head-justify div.dt-column-footer,
table.dataTable tfoot th.dt-head-justify div.dt-column-header,
table.dataTable tfoot th.dt-head-justify div.dt-column-footer,
table.dataTable tfoot td.dt-head-justify div.dt-column-header,
table.dataTable tfoot td.dt-head-justify div.dt-column-footer {
  flex-direction: row;
}
table.dataTable thead th.dt-head-nowrap,
table.dataTable thead td.dt-head-nowrap,
table.dataTable tfoot th.dt-head-nowrap,
table.dataTable tfoot td.dt-head-nowrap {
  white-space: nowrap;
}
table.dataTable tbody th.dt-body-left,
table.dataTable tbody td.dt-body-left {
  text-align: left;
}
table.dataTable tbody th.dt-body-center,
table.dataTable tbody td.dt-body-center {
  text-align: center;
}
table.dataTable tbody th.dt-body-right,
table.dataTable tbody td.dt-body-right {
  text-align: right;
}
table.dataTable tbody th.dt-body-justify,
table.dataTable tbody td.dt-body-justify {
  text-align: justify;
}
table.dataTable tbody th.dt-body-nowrap,
table.dataTable tbody td.dt-body-nowrap {
  white-space: nowrap;
}

:root {
  --dt-header_border: 1px solid rgba(0, 0, 0, 0.3);
  --dt-header_padding: 10px;
  --dt-footer_border: var(--dt-header_border);
  --dt-footer_padding: 10px 10px 6px 10px;
  --dt-body_border: 1px solid rgba(0, 0, 0, 0.15);
  --dt-body_padding: 8px 10px;
  --dt-column-ordering_alpha: 0.019;
  --dt-column-ordering_alpha-selected: 0.919;
  --dt-row_alpha-hover: 0.035;
  --dt-row_alpha-selected-stripe: 0.923;
  --dt-row_alpha-stripe: 0.023;
  --dt-control_color: inherit;
  --dt-paging-button_box-shadow: none;
  --dt-paging-button_box-shadow-active: inset 0 0 3px #111;
  --dt-paging-button_padding: 0.5em 1em;
  --dt-paging-button_margin-left: 2px;
  --dt-paging-button_border-radius: 3px;
  --dt-paging-button_background: transparent;
  --dt-paging-button_border: 1px solid transparent;
  --dt-paging-button_color: var(--dt-control_color);
  --dt-paging-button_background-disabled: transparent;
  --dt-paging-button_border-disabled: 1px solid transparent;
  --dt-paging-button_color-disabled: rgba(0, 0, 0, 0.5);
  --dt-paging-button_background-current: rgba(0, 0, 0, 0.05);
  --dt-paging-button_border-current: 1px solid rgba(0, 0, 0, 0.3);
  --dt-paging-button_color-current: var(--dt-control_color);
  --dt-paging-button_background-current-hover: rgba(0, 0, 0, 0.1);
  --dt-paging-button_border-current-hover: 1px solid rgba(0, 0, 0, 0.5);
  --dt-paging-button_color-current-hover: var(--dt-control_color);
  --dt-paging-button_background-hover: rgba(0, 0, 0, 0.1);
  --dt-paging-button_border-hover: 1px solid transparent;
  --dt-paging-button_color-hover: var(--dt-control_color);
  --dt-input_border: 1px solid #aaa;
  --dt-input_border-radius: 3px;
  --dt-input_padding: 7px 5px;
  --dt-input_background: transparent;
  --dt-input_color: inherit;
}
:root.dark {
  --dt-row_background-stripe: 255, 255, 255;
  --dt-row_background-hover: 255, 255, 255;
  --dt-column-ordering_background: 255, 255, 255;
  --dt-header_border: 1px solid rgb(89, 91, 94);
  --dt-body_border: 1px solid rgb(64, 67, 70);
  --dt-paging-button_color: var(--dt-control_color);
  --dt-paging-button_background-current: rgba(255, 255, 255, 0.05);
  --dt-paging-button_border-current: 1px solid rgba(255, 255, 255, 0.1);
  --dt-paging-button_background-current-hover: rgba(0, 0, 0, 0.1);
  --dt-paging-button_border-current-hover: 1px solid rgba(255, 255, 255, 0.3);
  --dt-paging-button_color-disabled: rgba(255, 255, 255, 0.25);
  --dt-paging-button_background-hover: rgba(0, 0, 0, 0.2);
  --dt-paging-button_border-hover: 1px solid transparent;
  --dt-input_border: 1px solid rgb(255, 255, 255, 0.2);
  --dt-input_background: rgb(44, 48, 51);
}

/*
 * Table styles
 */
table.dataTable {
  width: 100%;
  margin: 0 auto;
  border-spacing: 0;
  /*
   * Header and footer styles
   */
}
table.dataTable thead th,
table.dataTable tfoot th {
  font-weight: bold;
}
table.dataTable > thead > tr > th,
table.dataTable > thead > tr > td {
  padding: var(--dt-header_padding);
  border-bottom: var(--dt-header_border);
}
table.dataTable > thead > tr > th:active,
table.dataTable > thead > tr > td:active {
  outline: none;
}
table.dataTable > tfoot > tr > th,
table.dataTable > tfoot > tr > td {
  border-top: var(--dt-footer_border);
  padding: var(--dt-footer_padding);
}
table.dataTable {
  /*
   * Body styles
   */
}
table.dataTable > tbody > tr {
  background-color: var(--dt-row_background);
}
table.dataTable > tbody > tr:first-child > * {
  border-top: none;
}
table.dataTable > tbody > tr:last-child > * {
  border-bottom: none;
}
table.dataTable > tbody > tr.selected > * {
  box-shadow: inset 0 0 0 9999px rgba(var(--dt-row_background-selected), 0.9);
  color: rgb(var(--dt-row-text_color-selected));
}
table.dataTable > tbody > tr.selected a {
  color: rgb(var(--dt-row-link_color-selected));
}
table.dataTable > tbody > tr > th,
table.dataTable > tbody > tr > td {
  padding: var(--dt-body_padding);
}
table.dataTable.row-border > tbody > tr > *, table.dataTable.display > tbody > tr > * {
  border-top: var(--dt-body_border);
}
table.dataTable.row-border > tbody > tr:first-child > *, table.dataTable.display > tbody > tr:first-child > * {
  border-top: none;
}
table.dataTable.row-border > tbody > tr.selected + tr.selected > td, table.dataTable.display > tbody > tr.selected + tr.selected > td {
  border-top-color: rgba(var(--dt-row_background-selected), 0.65);
}
table.dataTable.cell-border > tbody > tr > * {
  border-top: var(--dt-body_border);
  border-right: var(--dt-body_border);
}
table.dataTable.cell-border > tbody > tr > *:first-child {
  border-left: var(--dt-body_border);
}
table.dataTable.cell-border > tbody > tr:first-child > * {
  border-top: var(--dt-header_border);
}
table.dataTable.stripe > tbody > tr:nth-child(odd) > *, table.dataTable.display > tbody > tr:nth-child(odd) > * {
  box-shadow: inset 0 0 0 9999px rgba(var(--dt-row_background-stripe), var(--dt-row_alpha-stripe));
}
table.dataTable.stripe > tbody > tr:nth-child(odd).selected > *, table.dataTable.display > tbody > tr:nth-child(odd).selected > * {
  box-shadow: inset 0 0 0 9999px rgba(var(--dt-row_background-selected), var(--dt-row_alpha-selected-stripe));
}
table.dataTable.hover > tbody > tr:hover > *, table.dataTable.display > tbody > tr:hover > * {
  box-shadow: inset 0 0 0 9999px rgba(var(--dt-row_background-hover), var(--dt-row_alpha-hover));
}
table.dataTable.hover > tbody > tr.selected:hover > *, table.dataTable.display > tbody > tr.selected:hover > * {
  box-shadow: inset 0 0 0 9999px rgba(var(--dt-row_background-selected), 1) !important;
}
table.dataTable.order-column > tbody tr > .sorting_1,
table.dataTable.order-column > tbody tr > .sorting_2,
table.dataTable.order-column > tbody tr > .sorting_3, table.dataTable.display > tbody tr > .sorting_1,
table.dataTable.display > tbody tr > .sorting_2,
table.dataTable.display > tbody tr > .sorting_3 {
  box-shadow: inset 0 0 0 9999px rgba(var(--dt-column-ordering_background), var(--dt-column-ordering_alpha));
}
table.dataTable.order-column > tbody tr.selected > .sorting_1,
table.dataTable.order-column > tbody tr.selected > .sorting_2,
table.dataTable.order-column > tbody tr.selected > .sorting_3, table.dataTable.display > tbody tr.selected > .sorting_1,
table.dataTable.display > tbody tr.selected > .sorting_2,
table.dataTable.display > tbody tr.selected > .sorting_3 {
  box-shadow: inset 0 0 0 9999px rgba(var(--dt-row_background-selected), var(--dt-column-ordering_alpha-selected));
}
table.dataTable.display > tbody > tr:nth-child(odd) > .sorting_1, table.dataTable.order-column.stripe > tbody > tr:nth-child(odd) > .sorting_1 {
  box-shadow: inset 0 0 0 9999px rgba(var(--dt-column-ordering_background), calc(var(--dt-row_alpha-stripe) + var(--dt-column-ordering_alpha)));
}
table.dataTable.display > tbody > tr:nth-child(odd) > .sorting_2, table.dataTable.order-column.stripe > tbody > tr:nth-child(odd) > .sorting_2 {
  box-shadow: inset 0 0 0 9999px rgba(var(--dt-column-ordering_background), calc(var(--dt-row_alpha-stripe) + var(--dt-column-ordering_alpha) - 0.007));
}
table.dataTable.display > tbody > tr:nth-child(odd) > .sorting_3, table.dataTable.order-column.stripe > tbody > tr:nth-child(odd) > .sorting_3 {
  box-shadow: inset 0 0 0 9999px rgba(var(--dt-column-ordering_background), calc(var(--dt-row_alpha-stripe) + var(--dt-column-ordering_alpha) - 0.015));
}
table.dataTable.display > tbody > tr:nth-child(odd).selected > .sorting_1, table.dataTable.order-column.stripe > tbody > tr:nth-child(odd).selected > .sorting_1 {
  box-shadow: inset 0 0 0 9999px rgba(var(--dt-row_background-selected), calc(var(--dt-row_alpha-selected-stripe) + var(--dt-column-ordering_alpha)));
}
table.dataTable.display > tbody > tr:nth-child(odd).selected > .sorting_2, table.dataTable.order-column.stripe > tbody > tr:nth-child(odd).selected > .sorting_2 {
  box-shadow: inset 0 0 0 9999px rgba(var(--dt-row_background-selected), calc(var(--dt-row_alpha-selected-stripe) + var(--dt-column-ordering_alpha) - 0.007));
}
table.dataTable.display > tbody > tr:nth-child(odd).selected > .sorting_3, table.dataTable.order-column.stripe > tbody > tr:nth-child(odd).selected > .sorting_3 {
  box-shadow: inset 0 0 0 9999px rgba(var(--dt-row_background-selected), calc(var(--dt-row_alpha-selected-stripe) + var(--dt-column-ordering_alpha) - 0.015));
}
table.dataTable.display tbody tr:hover > .sorting_1, table.dataTable.order-column.hover tbody tr:hover > .sorting_1 {
  box-shadow: inset 0 0 0 9999px rgba(var(--dt-row_background-hover), calc(var(--dt-row_alpha-stripe) + var(--dt-column-ordering_alpha) + var(--dt-row_alpha-hover)));
}
table.dataTable.display tbody tr:hover > .sorting_2, table.dataTable.order-column.hover tbody tr:hover > .sorting_2 {
  box-shadow: inset 0 0 0 9999px rgba(var(--dt-row_background-hover), calc(var(--dt-row_alpha-stripe) + var(--dt-column-ordering_alpha) + var(--dt-row_alpha-hover) - 0.007));
}
table.dataTable.display tbody tr:hover > .sorting_3, table.dataTable.order-column.hover tbody tr:hover > .sorting_3 {
  box-shadow: inset 0 0 0 9999px rgba(var(--dt-row_background-hover), calc(var(--dt-row_alpha-stripe) + var(--dt-column-ordering_alpha) + var(--dt-row_alpha-hover) - 0.015));
}
table.dataTable.display tbody tr:hover.selected > .sorting_1, table.dataTable.order-column.hover tbody tr:hover.selected > .sorting_1 {
  box-shadow: inset 0 0 0 9999px rgba(var(--dt-row_background-selected), calc(var(--dt-row_alpha-selected-stripe) + var(--dt-column-ordering_alpha)));
}
table.dataTable.display tbody tr:hover.selected > .sorting_2, table.dataTable.order-column.hover tbody tr:hover.selected > .sorting_2 {
  box-shadow: inset 0 0 0 9999px rgba(var(--dt-row_background-selected), calc(var(--dt-row_alpha-selected-stripe) + var(--dt-column-ordering_alpha) + var(--dt-row_alpha-hover) - 0.007));
}
table.dataTable.display tbody tr:hover.selected > .sorting_3, table.dataTable.order-column.hover tbody tr:hover.selected > .sorting_3 {
  box-shadow: inset 0 0 0 9999px rgba(var(--dt-row_background-selected), calc(var(--dt-row_alpha-selected-stripe) + var(--dt-column-ordering_alpha) + var(--dt-row_alpha-hover) - 0.015));
}
table.dataTable.compact thead th,
table.dataTable.compact thead td,
table.dataTable.compact tfoot th,
table.dataTable.compact tfoot td,
table.dataTable.compact tbody th,
table.dataTable.compact tbody td {
  padding: 4px;
}

div.dt-container div.dt-layout-row {
  display: flex;
  justify-content: space-between;
  align-items: center;
  width: 100%;
  margin: 0.75em 0;
}
div.dt-container div.dt-layout-row div.dt-layout-cell {
  display: flex;
  justify-content: space-between;
  align-items: center;
}
div.dt-container div.dt-layout-row div.dt-layout-cell.dt-layout-start {
  justify-content: flex-start;
  margin-right: auto;
}
div.dt-container div.dt-layout-row div.dt-layout-cell.dt-layout-end {
  justify-content: flex-end;
  margin-left: auto;
}
div.dt-container div.dt-layout-row div.dt-layout-cell:empty {
  display: none;
}

@media screen and (max-width: 767px) {
  div.dt-container div.dt-layout-row:not(.dt-layout-table) {
    display: block;
  }
  div.dt-container div.dt-layout-row:not(.dt-layout-table) div.dt-layout-cell {
    display: block;
    text-align: center;
  }
  div.dt-container div.dt-layout-row:not(.dt-layout-table) div.dt-layout-cell > * {
    margin: 0.5em 0;
  }
  div.dt-container div.dt-layout-row:not(.dt-layout-table) div.dt-layout-cell.dt-layout-start {
    margin-right: 0;
  }
  div.dt-container div.dt-layout-row:not(.dt-layout-table) div.dt-layout-cell.dt-layout-end {
    margin-left: 0;
  }
}
div.dt-container div.dt-layout-start > *:not(:last-child) {
  margin-right: 1em;
}
div.dt-container div.dt-layout-end > *:not(:first-child) {
  margin-left: 1em;
}
div.dt-container div.dt-layout-full {
  width: 100%;
}
div.dt-container div.dt-layout-full > *:only-child {
  margin-left: auto;
  margin-right: auto;
}
div.dt-container div.dt-layout-table > div {
  display: block !important;
}

@media screen and (max-width: 767px) {
  div.dt-container div.dt-layout-start > *:not(:last-child) {
    margin-right: 0;
  }
  div.dt-container div.dt-layout-end > *:not(:first-child) {
    margin-left: 0;
  }
}
/*
 * Control feature layout
 */
div.dt-container {
  position: relative;
  clear: both;
}
div.dt-container .dt-search input {
  border: var(--dt-input_border);
  border-radius: var(--dt-input_border-radius);
  padding: var(--dt-input_padding);
  background-color: var(--dt-input_background);
  color: var(--dt-input_color);
  margin-left: 3px;
}
div.dt-container .dt-input {
  border: var(--dt-input_border);
  border-radius: var(--dt-input_border-radius);
  padding: var(--dt-input_padding);
  background-color: var(--dt-input_background);
  color: var(--dt-input_color);
}
div.dt-container .dt-paging .dt-paging-button {
  box-sizing: border-box;
  display: inline-block;
  min-width: 1.5em;
  padding: var(--dt-paging-button_padding);
  margin-left: var(--dt-paging-button_margin-left);
  text-align: center;
  text-decoration: none !important;
  cursor: pointer;
  color: var(--dt-paging-button_color);
  border: var(--dt-paging-button_border);
  border-radius: var(--dt-paging-button_border-radius);
  background: var(--dt-paging-button_background);
  box-shadow: var(--dt-paging-button_box-shadow);
}
div.dt-container .dt-paging .dt-paging-button.current {
  color: var(--dt-paging-button_color-current) !important;
  border: var(--dt-paging-button_border-current);
  background: var(--dt-paging-button_background-current);
}
div.dt-container .dt-paging .dt-paging-button.current:hover {
  color: var(--dt-paging-button_color-current-hover) !important;
  border: var(--dt-paging-button_border-current-hover);
  background: var(--dt-paging-button_background-current-hover);
}
div.dt-container .dt-paging .dt-paging-button.disabled, div.dt-container .dt-paging .dt-paging-button.disabled:hover, div.dt-container .dt-paging .dt-paging-button.disabled:active {
  cursor: default;
  color: var(--dt-paging-button_color-disabled) !important;
  border: var(--dt-paging-button_border-disabled);
  background: var(--dt-paging-button_background-disabled);
  box-shadow: none;
}
div.dt-container .dt-paging .dt-paging-button:hover {
  color: var(--dt-paging-button_color-hover) !important;
  border: var(--dt-paging-button_border-hover);
  background: var(--dt-paging-button_background-hover);
}
div.dt-container .dt-paging .dt-paging-button:active {
  outline: none;
  background: var(--dt-paging-button_background-hover);
  box-shadow: var(--dt-paging-button_box-shadow-active);
}
div.dt-container .dt-paging .ellipsis {
  padding: 0 1em;
}
div.dt-container .dt-length,
div.dt-container .dt-search,
div.dt-container .dt-info,
div.dt-container .dt-processing,
div.dt-container .dt-paging {
  color: var(--dt-control_color);
}
div.dt-container.dt-empty-footer tbody > tr:last-child > * {
  border-bottom: var(--dt-header_border);
}
div.dt-container.dt-empty-footer .dt-scroll-body {
  border-bottom: var(--dt-header_border);
}
div.dt-container.dt-empty-footer .dt-scroll-body tbody > tr:last-child > * {
  border-bottom: none;
}

html.dark table.dataTable.row-border > tbody > tr.selected + tr.selected > td, html.dark table.dataTable.display > tbody > tr.selected + tr.selected > td {
  border-top-color: rgba(var(--dt-row_background-selected), 0.65);
}

/*
 * Overrides for RTL support
 */
*[dir=rtl] table.dataTable thead th,
*[dir=rtl] table.dataTable thead td,
*[dir=rtl] table.dataTable tfoot th,
*[dir=rtl] table.dataTable tfoot td {
  text-align: right;
}
*[dir=rtl] table.dataTable th.dt-type-numeric, *[dir=rtl] table.dataTable th.dt-type-date,
*[dir=rtl] table.dataTable td.dt-type-numeric,
*[dir=rtl] table.dataTable td.dt-type-date {
  text-align: left;
}
*[dir=rtl] div.dt-container div.dt-layout-cell.dt-start {
  text-align: right;
}
*[dir=rtl] div.dt-container div.dt-layout-cell.dt-end {
  text-align: left;
}
*[dir=rtl] div.dt-container div.dt-search input {
  margin: 0 3px 0 0;
}
/* VeraLab styling for DataTables; keep separate from the vendor stylesheet. */
/* Preserve VeraLab alignment and footer borders without editing vendor CSS. */
table.dataTable th.dt-type-numeric div.dt-column-header,
table.dataTable th.dt-type-numeric div.dt-column-footer,
table.dataTable th.dt-type-date div.dt-column-header,
table.dataTable th.dt-type-date div.dt-column-footer,
table.dataTable td.dt-type-numeric div.dt-column-header,
table.dataTable td.dt-type-numeric div.dt-column-footer,
table.dataTable td.dt-type-date div.dt-column-header,
table.dataTable td.dt-type-date div.dt-column-footer {
  flex-direction: row;
  justify-content: flex-end !important;
}

div.dt-container.dt-empty-footer tbody > tr:last-child > *,
div.dt-container.dt-empty-footer .dt-scroll-body {
  border-bottom: none;
}

.datatable-staging {
  display: none;
}

.datatable-card {
  overflow: hidden;
}

.datatable-card #table-container,
.datatable-card .dt-container {
  min-width: 0;
}

.datatable-toolbar {
  display: flex;
  align-items: flex-end;
  flex-wrap: wrap;
  gap: var(--space-3) var(--space-4);
  padding: var(--space-4);
  border-bottom: 1px solid var(--border);
  background: var(--surface);
}

.datatable-filter {
  flex: 1 1 260px;
  max-width: 360px;
}

.datatable-toggle-slot {
  flex: 0 0 auto;
}

.datatable-filter .dt-search {
  display: flex;
  flex-direction: column;
  gap: 6px;
}

.datatable-filter .dt-search label {
  margin: 0;
}

div.dt-container .datatable-filter .dt-search input.dt-input {
  width: 100%;
  margin: 0;
}

div.dt-container .datatable-toolbar .dt-input {
  height: var(--control-h);
  padding: 0 11px;
  font-size: var(--text-sm);
  color: var(--text-strong);
  background: var(--surface);
  border: 1px solid var(--border-strong);
  border-radius: var(--radius);
  outline: none;
}

div.dt-container .datatable-toolbar .dt-input:focus {
  border-color: var(--accent-hover);
}

.datatable-toggle,
.datatable-actions {
  min-height: var(--control-h);
  display: flex;
  align-items: center;
}

.datatable-toggle {
  gap: var(--space-2);
  font-size: var(--text-sm);
  color: var(--text);
  cursor: pointer;
}

.datatable-actions {
  gap: var(--space-2);
  margin-left: auto;
}

.user-selector-card .user_selector_table th:first-child,
.user-selector-card .user_selector_table td:first-child {
  width: 52px;
  text-align: center;
}

.user-selector-card .user_selector_table th:first-child .dt-column-header {
  justify-content: center;
}

.user-selector-card .check-all .check-info {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  border: 0;
}

div.dt-container .table-scroll {
  overflow-x: auto;
}

div.dt-container table.dataTable.table {
  width: 100% !important;
  margin: 0;
  border-collapse: collapse;
  border-spacing: 0;
}

div.dt-container table.dataTable.table > thead > tr > th,
div.dt-container table.dataTable.table > thead > tr > td {
  padding: var(--space-3) var(--space-4);
  background: var(--raised);
  color: var(--muted);
  font-size: var(--text-xs);
  font-weight: 600;
  border-bottom: 1px solid var(--border);
  white-space: nowrap;
}

div.dt-container table.dataTable.table > tbody > tr > th,
div.dt-container table.dataTable.table > tbody > tr > td {
  padding: var(--space-3) var(--space-4);
  border-top: 1px solid var(--border);
  color: var(--text-soft);
  font-size: var(--text-sm);
  vertical-align: middle;
}

div.dt-container table.dataTable.table > tbody > tr:first-child > th,
div.dt-container table.dataTable.table > tbody > tr:first-child > td {
  border-top: none;
}

div.dt-container table.dataTable.table-zebra > tbody > tr:nth-child(even) > th,
div.dt-container table.dataTable.table-zebra > tbody > tr:nth-child(even) > td {
  background: var(--zebra);
}

div.dt-container table.dataTable thead > tr > th.dt-orderable-asc:hover,
div.dt-container table.dataTable thead > tr > th.dt-orderable-desc:hover,
div.dt-container table.dataTable thead > tr > td.dt-orderable-asc:hover,
div.dt-container table.dataTable thead > tr > td.dt-orderable-desc:hover {
  outline: none;
}

div.dt-container table.dataTable thead > tr > th .dt-column-header,
div.dt-container table.dataTable thead > tr > td .dt-column-header {
  display: inline-flex;
  position: relative;
  justify-content: flex-start;
  align-items: center;
  gap: var(--space-1);
  min-height: 24px;
  width: auto;
}

div.dt-container table.dataTable thead > tr > th .dt-column-title,
div.dt-container table.dataTable thead > tr > td .dt-column-title {
  flex: 0 0 auto;
}

div.dt-container table.dataTable thead > tr > th.dt-orderable-asc .dt-column-title,
div.dt-container table.dataTable thead > tr > th.dt-orderable-desc .dt-column-title,
div.dt-container table.dataTable thead > tr > td.dt-orderable-asc .dt-column-title,
div.dt-container table.dataTable thead > tr > td.dt-orderable-desc .dt-column-title {
  text-decoration: underline;
}

/* The keyboard target covers the heading without reserving space for an
   inactive indicator. Pointer clicks still reach the heading's own controls. */
div.dt-container table.dataTable thead > tr > th .dt-column-order,
div.dt-container table.dataTable thead > tr > td .dt-column-order {
  display: none;
  position: absolute;
  inset: 0;
  width: auto;
  height: auto;
  pointer-events: none;
  color: var(--muted);
  border-radius: 3px;
}

div.dt-container table.dataTable thead > tr > th .dt-column-order[role="button"],
div.dt-container table.dataTable thead > tr > td .dt-column-order[role="button"],
div.dt-container table.dataTable thead > tr > th.dt-ordering-asc .dt-column-order,
div.dt-container table.dataTable thead > tr > th.dt-ordering-desc .dt-column-order,
div.dt-container table.dataTable thead > tr > td.dt-ordering-asc .dt-column-order,
div.dt-container table.dataTable thead > tr > td.dt-ordering-desc .dt-column-order {
  display: block;
}

div.dt-container table.dataTable thead > tr > th.dt-ordering-asc .dt-column-header,
div.dt-container table.dataTable thead > tr > th.dt-ordering-desc .dt-column-header,
div.dt-container table.dataTable thead > tr > td.dt-ordering-asc .dt-column-header,
div.dt-container table.dataTable thead > tr > td.dt-ordering-desc .dt-column-header {
  padding-inline-end: calc(var(--dt-order-arrow-width) + var(--space-1));
}

div.dt-container table.dataTable thead > tr > th .dt-column-order:focus-visible,
div.dt-container table.dataTable thead > tr > td .dt-column-order:focus-visible,
div.dt-container .dt-paging .dt-paging-button:focus-visible {
  outline: 2px solid var(--accent-text);
  outline-offset: 2px;
}

div.dt-container table.dataTable thead > tr > th .dt-column-order:before,
div.dt-container table.dataTable thead > tr > th .dt-column-order:after,
div.dt-container table.dataTable thead > tr > td .dt-column-order:before,
div.dt-container table.dataTable thead > tr > td .dt-column-order:after {
  display: none;
  font-size: var(--text-xs);
  top: 50%;
  bottom: auto;
  left: auto;
  right: auto;
  inset-inline-end: 0;
  transform: translateY(-50%);
}

div.dt-container table.dataTable thead > tr > th.dt-ordering-asc .dt-column-order:before,
div.dt-container table.dataTable thead > tr > td.dt-ordering-asc .dt-column-order:before {
  opacity: 1;
  color: var(--muted);
  border-bottom-color: var(--muted);
  display: block;
}

div.dt-container table.dataTable thead > tr > th.dt-ordering-desc .dt-column-order:after,
div.dt-container table.dataTable thead > tr > td.dt-ordering-desc .dt-column-order:after {
  opacity: 1;
  color: var(--muted);
  border-top-color: var(--muted);
  display: block;
}

div.dt-container .pager {
  margin: 0;
}

div.dt-container .pager .dt-info {
  color: var(--muted);
  font-size: var(--text-xs);
  font-variant-numeric: tabular-nums;
}

div.dt-container .pager .dt-paging nav {
  display: flex;
  align-items: center;
  gap: 2px;
}

div.dt-container .dt-paging .dt-paging-button {
  min-width: 30px;
  height: 30px;
  padding: 0 6px;
  margin: 0;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  background: var(--surface);
  border: 1px solid var(--border-strong);
  border-radius: 6px;
  box-shadow: none;
  color: var(--text) !important;
  font-size: var(--text-xs);
  font-weight: 600;
  font-variant-numeric: tabular-nums;
  line-height: 1;
}

div.dt-container .dt-paging .dt-paging-button:hover:not(.disabled):not(.current) {
  background: var(--hover);
  border-color: var(--muted-2);
  color: var(--text) !important;
}

div.dt-container .dt-paging .dt-paging-button.current,
div.dt-container .dt-paging .dt-paging-button.current:hover {
  background: var(--accent-fill);
  border-color: var(--accent-fill);
  color: var(--on-accent) !important;
}

div.dt-container .dt-paging .dt-paging-button.disabled,
div.dt-container .dt-paging .dt-paging-button.disabled:hover,
div.dt-container .dt-paging .dt-paging-button.disabled:active {
  opacity: .45;
  cursor: not-allowed;
  background: var(--surface);
  border-color: var(--border-strong);
  color: var(--text) !important;
}

div.dt-container .dt-paging .ellipsis {
  padding: 0 var(--space-2);
  color: var(--muted-2);
}
/* ---------- SCHEDULE ASSIGN ----------
   The small dialog opened from an empty block of the week board. The
   Assign control itself is veralab-core's .slot-assign action link, which
   the stylesheet already defines: it sits at the foot of the block and
   stays visible, since it is the only way in. */

/* Which counter and day the dialog was opened from — context, not input, so it
   reads as a caption above the fields rather than another form row. */
.assign-context {
  display: flex; align-items: baseline; gap: var(--space-2);
  margin: 0 0 var(--space-4); font-size: var(--text-sm); color: var(--muted);
}
.assign-context-counter { font-weight: 700; color: var(--text-strong); }
.assign-context-day::before { content: "·"; padding-right: var(--space-2); }

/* Start and end sit side by side: they are one decision, and splitting them
   across two full-width rows makes the dialog taller than it needs to be. */
.assign-times { display: grid; grid-template-columns: 1fr 1fr; gap: var(--space-4); }
@media (max-width: 480px) { .assign-times { grid-template-columns: 1fr; } }

.assign-error {
  display: none; margin: var(--space-3) 0 0;
  font-size: var(--text-xs); color: var(--danger-text);
}

/* Legend swatches for the schedule board. Emitted by the schedule stylesheet
   but never defined, so the legend was two labels with nothing beside them.
   They mirror the .slot-on / .slot-off encoding: a solid edge for covered time,
   a dashed outline for a gap. */
.legend-swatch { width: 14px; height: 10px; border-radius: 3px; flex: none; }
.legend-on { background: var(--surface); border-left: 3px solid var(--ok); border-top: 1px solid var(--border); border-right: 1px solid var(--border); border-bottom: 1px solid var(--border); }
.legend-off { background: transparent; border: 1px dashed var(--border-strong); }

/* Toolbar legend sits at the end of the row rather than pushing the controls. */
.toolbar .legend { margin-left: auto; padding-bottom: 0; }

/* Hiding the empty blocks leaves the covered ones where they were: the days
   keep their columns, so a room's shape stays comparable across the week. */
.sched-hide-open .slot-off { display: none; }

/* Password reveal control. The eye is injected by initPasswordEyes, which used
   to set its colour inline — that beat any :hover rule, so the control had no
   states. Colour lives here instead, matching the .pw-toggle treatment the
   re-auth gate already uses: quiet by default, and only picking up emphasis
   once the password is actually showing. Positioning stays in the earlier
   .eye-button rule (section above); this block only adds tone and states. */
.eye-button { color: var(--muted); border-radius: 5px; }
.eye-button:hover { background: var(--hover); color: var(--text); }
.eye-button[aria-pressed="true"] { color: var(--accent-text); }
/* ---------- BAR BOARD (sb_board) ----------
   Ported verbatim from veralab-core (section 11c). Three stacked full-width
   panels over ONE station axis. The gutter width is declared once on .sb and
   both the panels and the axis row use it, so the plots and the labels under
   them share a track: a column at position n is the same station in all three
   panels. */
/* A large fleet was never in the reference build: at ~60 stations each column
   falls to 2-3px, narrower than the vertical label, so the names painted over
   each other and the overflow escaped to the page - the whole report scrolled
   sideways and the first tile went off-screen. The columns now hold a floor
   width and the board scrolls inside its own card instead, which is what the
   house rule says wide content should do. */
.sb { --sb-gut: 132px; --sb-col-min: 13px; display: flex; flex-direction: column; gap: var(--space-4); padding: var(--space-4) var(--space-5) var(--space-5); overflow-x: auto; }
.sb-panel { display: grid; grid-template-columns: var(--sb-gut) 1fr; gap: var(--space-4); align-items: end; }
.sb-key { display: flex; flex-direction: column; gap: 2px; padding-bottom: var(--space-1); }
.sb-key-name { font-size: var(--text-sm); font-weight: 600; color: var(--text-strong); }
.sb-key-max { font-family: var(--font-mono); font-size: var(--text-xs); color: var(--muted); }
.sb-plot {
  height: 132px; display: flex; align-items: flex-end; gap: 2px;
  border-bottom: 1px solid var(--border-strong);
  background: repeating-linear-gradient(to top, transparent 0 calc(25% - 1px), var(--border) calc(25% - 1px) 25%);
}
.sb-col { flex: 1; min-width: var(--sb-col-min); height: 100%; display: flex; align-items: flex-end; }
.sb-bar { width: 100%; border-radius: 2px 2px 0 0; min-height: 2px; transition: opacity .1s linear; }
.sb-visits { background: var(--accent); }
.sb-hours { background: var(--info); }
.sb-mins { background: var(--muted-2); }
/* pointing at any column dims the rest in all three panels at once, which is
   the whole point of a shared axis */
.sb.is-focused .sb-bar { opacity: .3; }
.sb.is-focused .sb-col.is-focus .sb-bar { opacity: 1; }
.sb-read { margin-left: auto; font-weight: 500; font-size: var(--text-sm); color: var(--text-soft); }

.sb-axis { display: grid; grid-template-columns: var(--sb-gut) 1fr; gap: var(--space-4); }
.sb-axis-track { display: flex; gap: 2px; }
.sb-axis-track span {
  flex: 1; min-width: var(--sb-col-min);
  /* The label box grows to the longest name instead of a fixed 58px, so a room
     of EBE-REDEXT-004s reads in full; the cap keeps it from taking more height
     than the plot it labels. */
  height: auto; min-height: 58px; max-height: 132px;
  writing-mode: vertical-rl; font-family: var(--font-mono); font-size: var(--text-2xs);
  /* In vertical writing mode the line box runs along the horizontal axis, so
     line-height - not font-size - is the label's intrinsic width. At the
     inherited 1.33 that is 14.67px, above the column floor, so the labels drove
     the axis 248px wider than the bars across 149 stations and the two tracks
     drifted apart. Pinned to 1 so the floor governs both. */
  line-height: 1;
  color: var(--muted); display: flex; align-items: flex-start;
  /* flex-start, not center: the main axis here is vertical, so centring left the
     text clipped at BOTH ends and showed the middle of every name. Anchored to
     the top, a name that still does not fit loses only its tail. */
  justify-content: flex-start;
  /* A long station name is clipped at the axis height rather than running down
     the page; the full name is on the bar's title and in the readout. */
  overflow: hidden; white-space: nowrap;
}
/* Sorting the station board. From veralab-core: no separate sort control —
   each panel's own name IS its sort button, the way a sortable table sorts from
   its column headers. Nothing new sits in the header, and the label the reader
   is already looking at does the work. */
.sb-key-btn {
  display: flex; align-items: baseline; gap: 5px; text-align: left;
  background: none; border: 0; padding: 0; cursor: pointer;
  font: inherit; font-size: var(--text-sm); font-weight: 600; color: var(--text-soft);
}
.sb-key-btn:hover { color: var(--text-strong); text-decoration: underline; text-underline-offset: 2px; }
.sb-key-btn.is-active { color: var(--text-strong); }
/* The sort mark, as on the sorted tables and the server-sorted lists (Dev,
   e80eb1192): a triangle after the active name only - down for a measure,
   which sorts high to low, up for the station names, A to Z. */
.sb-caret { display: none; }
.sb-key-btn.is-active .sb-caret { display: inline; }
.sb-key-btn .sb-caret::before { content: "\25BC"; }
.sb-key-btn[data-sb-sort="name"] .sb-caret::before { content: "\25B2"; }
.sb-axis-name { font-size: var(--text-xs); font-weight: 600; color: var(--muted); text-align: right; }
.sb-axis-name .sb-key-btn { justify-content: flex-end; font-size: var(--text-xs); color: var(--muted); }

@media print {
  /* the panels are the report: shrink them to fit a sheet, never split one */
  .sb { padding: 0; gap: 10pt; }
  .sb-plot { height: 78pt; }
  .sb-panel { break-inside: avoid; page-break-inside: avoid; }
  .sb-read { display: none !important; }
  .sb-caret { display: none; }
  .sb-key-btn { color: #000 !important; }
  .sb-axis-track span { height: 40pt; }
  .statusline { color: #000 !important; }
}

/* ---------- LOGINS REPORT BOARD ----------
   Ported from veralab-core. The legacy page drew one stacked bar chart
   where only the bottom room and the grand total were comparable. Here a
   row per period carries the whole-period bar with the rooms as bands
   inside it, and a per-room small multiple below puts each room on its
   own scale, for shape rather than size. */
.lr { display: flex; flex-direction: column; gap: var(--space-5); padding: var(--space-5); }
.lr-title { font-size: var(--text-sm); font-weight: 700; color: var(--text-strong); margin: 0; }
.lr-sub { font-size: var(--text-xs); color: var(--muted); margin: 2px 0 0; }
.lr-note { margin: 0; font-size: var(--text-xs); line-height: 1.55; color: var(--muted); max-width: 96ch; }
.lr-note strong { color: var(--text-strong); }

/* --- week: day rows --- */
.lr-days { display: flex; flex-direction: column; gap: 4px; }
.lr-day {
  display: grid; grid-template-columns: 46px 1fr 68px 16px 34px;
  align-items: center; gap: var(--space-3);
  width: 100%; text-align: left; cursor: pointer;
  background: none; border: 0; border-radius: var(--radius);
  padding: 5px var(--space-2); font: inherit;
}
.lr-day:hover { background: var(--zebra); }
.lr-day:hover .lr-chev { opacity: 1; }
.lr-day-name { font-size: var(--text-sm); font-weight: 600; color: var(--text-strong); }
.lr-track { height: 22px; background: var(--zebra); border-radius: 3px; overflow: hidden; }
.lr-val { font-family: var(--font-mono); font-size: var(--text-sm); font-weight: 600; color: var(--text-strong); text-align: right; }
.lr-chev { color: var(--accent-text); opacity: .25; display: flex; }
.lr-chev .ic { width: 14px; height: 14px; }

/* --- week: five room small multiples, each on its own scale so the busiest
       room does not flatten the other four --- */
.lr-sm { display: grid; grid-template-columns: repeat(auto-fit, minmax(196px, 1fr)); gap: var(--space-4); }
.lr-sm-card { border: 1px solid var(--border); border-radius: var(--radius); padding: var(--space-3); display: flex; flex-direction: column; gap: var(--space-2); }
.lr-sm-name { font-size: var(--text-xs); font-weight: 700; color: var(--text-strong); }
.lr-sm-max { font-family: var(--font-mono); font-size: var(--text-2xs); color: var(--muted); }
.lr-sm-plot { display: flex; align-items: flex-end; gap: 3px; height: 62px; border-bottom: 1px solid var(--border); }
.lr-sm-col { flex: 1; height: 100%; display: flex; align-items: flex-end; }
.lr-sm-bar { width: 100%; background: var(--info); border-radius: 2px 2px 0 0; min-height: 1px; }
.lr-sm-x { display: flex; gap: 3px; }
.lr-sm-x span { flex: 1; text-align: center; font-size: var(--text-2xs); color: var(--muted); }
.lr-legend { display: flex; flex-wrap: wrap; gap: 6px var(--space-2); align-items: center; }
.lr-swatch { width: 10px; height: 10px; border-radius: 2px; flex: none; }

/* stacked day row */
.lr-stack { display: flex; height: 22px; background: var(--zebra); border-radius: 3px; overflow: hidden; }
.lr-seg { min-width: 0; transition: opacity .1s linear; }
.lr-share { font-family: var(--font-mono); font-size: var(--text-2xs); color: var(--muted); text-align: right; }

/* --- logins report: stacked area over the hours of a day ---
   The legacy chart drew one free-floating line per room, so the tallest
   hid the rest and nothing showed the day total. Stacked areas make the
   top boundary the total and each band one room's share of that hour. */
.lr-chart { display: grid; grid-template-columns: 52px 1fr; gap: var(--space-2); }
.lr-y { display: flex; flex-direction: column; justify-content: space-between; font-family: var(--font-mono); font-size: var(--text-2xs); color: var(--muted); text-align: right; }
.lr-plot { position: relative; border-left: 1px solid var(--border-strong); border-bottom: 1px solid var(--border-strong); }
.lr-plot svg { display: block; width: 100%; height: 280px; }
.lr-x { display: grid; grid-template-columns: 52px 1fr; gap: var(--space-2); }
.lr-x-track { display: grid; grid-template-columns: repeat(24, minmax(0, 1fr)); }
.lr-axis-title { font-size: var(--text-xs); font-weight: 600; color: var(--muted); }
.lr-closed-band { fill: var(--zebra); }
.lr-gridline { stroke: var(--border); stroke-width: 1; }
.lr-hit { fill: transparent; }
.lr-hit:hover { fill: var(--text-strong); fill-opacity: .05; }
.lr-peak-line { stroke: var(--danger); stroke-width: 1; stroke-dasharray: 3 3; }

/* The legend chip. Dropped on the first pass because a line-slice cut it in
   half, which left .lr-swatch as an inline span - width and height do not
   apply there, so every swatch collapsed to nothing and the legend lost its
   colours. The chip is what makes the swatch a flex item. */
.lr-lg {
  display: flex; align-items: center; gap: 6px;
  font: inherit; font-size: var(--text-xs); font-weight: 600; color: var(--text-soft);
  background: none; border: 1px solid transparent; border-radius: 999px; padding: 3px 9px 3px 6px;
}

/* Crumb and day chips on the logins report's day view. The chips are
   links here rather than buttons - each is a real report URL, so they
   middle-click and open in a new tab like any other navigation. */
.lr-crumb-btn {
  background: none; border: 0; padding: 0; cursor: pointer; font: inherit;
  color: var(--accent-text); font-weight: 600;
}
.lr-crumb-btn:hover { text-decoration: underline; text-underline-offset: 2px; }
.lr-crumb-sep { color: var(--muted-2); margin: 0 6px; }
.lr-switch { display: flex; flex-wrap: wrap; gap: 6px; }
.lr-chip {
  font: inherit; font-size: var(--text-xs); font-weight: 600; cursor: pointer;
  padding: 5px 11px; border-radius: 999px;
  border: 1px solid var(--border-strong); background: var(--surface); color: var(--text-soft);
}
.lr-chip:hover { border-color: var(--accent); color: var(--text-strong); }
.lr-chip.is-active { background: var(--accent); border-color: var(--accent); color: #fff; }
.lr-chip { display: inline-block; text-decoration: none; }
.lr-chip:hover { text-decoration: none; }
.lr-crumb { margin: 0; font-size: var(--text-xs); color: var(--muted); }

/* The legend chip is a control now, so it needs the states veralab-core gives
   it: a hover edge, and a filled edge on the room currently pulled out. */
.lr-lg { cursor: pointer; }
.lr-lg:hover { border-color: var(--border-strong); color: var(--text-strong); }
.lr-lg.is-active { border-color: var(--accent); background: var(--accent-soft); color: var(--text-strong); }
.lr-lg.is-reset { color: var(--muted); }

/* ---------- 18. AI INSIGHTS TIERS ----------
   Lifted from the design system's §18. The insight rows, source chips and
   heatmap grid already existed here; what was missing were the tier
   headings, the AI badge, the intensity ramp and the trend plot. */
.badge-ai {
  font-size: var(--text-2xs); font-weight: 700; letter-spacing: .1em;
  color: var(--accent-text); background: var(--accent-soft);
  padding: 2px 7px; border-radius: 5px; white-space: nowrap;
}
.card-header.ai-head { color: var(--accent-text); }
.tier-head { display: flex; align-items: baseline; flex-wrap: wrap; gap: var(--space-3); }
.tier-title { font-size: var(--text-xl); font-weight: 700; color: var(--text-strong); }
.tier-meta { font-size: var(--text-xs); color: var(--muted); }

/* one ramp for every heatmap: mixed against the surface so the same classes
   read correctly in both themes and the text stays dark at every step */
.heat-l0 { background: var(--zebra); color: var(--muted-2); }
.heat-l1 { background: color-mix(in srgb, var(--accent) 10%, var(--surface)); }
.heat-l2 { background: color-mix(in srgb, var(--accent) 22%, var(--surface)); }
.heat-l3 { background: color-mix(in srgb, var(--accent) 36%, var(--surface)); }
.heat-l4 { background: color-mix(in srgb, var(--accent) 52%, var(--surface)); }
.heat-l5 { background: color-mix(in srgb, var(--accent) 68%, var(--surface)); font-weight: 700; }
.heat-scale { display: flex; align-items: center; gap: 6px; font-size: var(--text-xs); color: var(--muted); margin-top: var(--space-4); flex-wrap: wrap; }
.heat-scale i { width: 20px; height: 10px; border-radius: 2px; display: block; }
/* unit suffix inside a scorecard figure: $148.2k, 42%, 11 wks */
.kpi-value small { font-size: 60%; font-weight: 600; color: var(--muted); margin-left: 1px; }
.kpi-note .badge { margin-right: 5px; }

/* trend plot: same anatomy as the report screens (ticks in their own column,
   gridlines drawn at the same fractions inside the SVG), scoped to this screen
   so the logins report's lr-* plot stays untouched. */
.ai-chart { display: grid; grid-template-columns: 46px 1fr; gap: var(--space-2); }
.ai-y { display: flex; flex-direction: column; justify-content: space-between; font-family: var(--font-mono); font-size: var(--text-2xs); color: var(--muted); text-align: right; }
.ai-plot { position: relative; border-left: 1px solid var(--border-strong); border-bottom: 1px solid var(--border-strong); }
.ai-plot svg { display: block; width: 100%; height: 260px; }
/* the gap between what peaked and what is paid for, called out in the plot */
.ai-unused { fill: var(--muted-2); fill-opacity: .1; }
.ai-band {
  position: absolute; left: 0; right: 0; display: flex; align-items: center; justify-content: center;
  font-size: var(--text-xs); font-weight: 600; color: var(--muted); pointer-events: none;
}
.ai-mark {
  position: absolute; transform: translate(-50%, -160%);
  font-family: var(--font-mono); font-size: var(--text-2xs); font-weight: 700;
  color: var(--accent-text); background: var(--surface);
  border: 1px solid var(--border); border-radius: 5px; padding: 1px 5px; white-space: nowrap;
}
.ai-dot { fill: var(--accent); }
.ai-gridline { stroke: var(--border); stroke-width: 1; }
.ai-fill { fill: var(--accent); fill-opacity: .16; }
.ai-line { fill: none; stroke: var(--accent); stroke-width: 2; }
.ai-owned { stroke: var(--muted-2); stroke-width: 1.5; stroke-dasharray: 5 4; }
.ai-x { display: grid; grid-template-columns: 46px 1fr; gap: var(--space-2); margin-top: 4px; }
.ai-x-track { display: grid; grid-template-columns: repeat(13, minmax(0, 1fr)); }
.ai-x-track span { font-family: var(--font-mono); font-size: var(--text-2xs); color: var(--muted); text-align: center; }
.ai-legend { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-2) var(--space-4); font-size: var(--text-xs); color: var(--muted); margin-bottom: var(--space-3); }
.ai-key { display: inline-flex; align-items: center; gap: 6px; }
.ai-key-line { width: 18px; height: 2px; background: var(--accent); display: block; }
.ai-key-dash { width: 18px; height: 0; border-top: 2px dashed var(--muted-2); display: block; }
/* AI Insights, busiest hour each week. Ticks and week labels sit at the y / x
   of their gridline or point (-placed), not spread evenly: the axis runs to
   112% and the points are inset, so even spacing drifts off both. Modifiers,
   so the Booking dashboard's evenly spaced plots keep the base rules. */
.ai-y.ai-y-placed { display: block; position: relative; height: 260px; }
.ai-y-placed span { position: absolute; right: 0; transform: translateY(-50%); line-height: 1; }
/* is-fill: as tall as the plot beside it (the Booking dashboard's 132px bars) */
.ai-y.ai-y-placed.is-fill { height: auto; }
.ai-x-track.ai-x-placed { display: block; position: relative; height: 1.4em; }
.ai-x-placed span { position: absolute; top: 0; transform: translateX(-50%); white-space: nowrap; }
.ai-x-placed .is-start { transform: none; }
.ai-x-placed .is-end { transform: translateX(-100%); }
/* narrow screens: every other week label, so even thinned labels do not collide */
@media (max-width: 700px) { .ai-x-placed .is-alt { display: none; } }
.ai-mark.is-start { transform: translate(0, -160%); }
.ai-mark.is-end { transform: translate(-100%, -160%); }
.ai-dot-best { fill: var(--accent-hover); }
/* the week's average seats in use over opening hours: the second, quieter line */
.ai-line-avg { fill: none; stroke: var(--info); stroke-width: 1.5; }
.ai-key-avg { width: 18px; height: 2px; background: var(--info); display: block; }
/* a week the roll-up processed and found empty is a closure: a shaded gap that
   breaks the lines, so a term break does not read as usage collapsing */
.ai-closed { fill: var(--muted-2); fill-opacity: .14; }
.ai-key-closed { width: 12px; height: 12px; border-radius: 2px; background: var(--muted-2); opacity: .4; display: block; }
.ai-gap-label, .ai-ceiling-label {
  position: absolute; font-size: var(--text-2xs); color: var(--muted); pointer-events: none; white-space: nowrap;
}
.ai-gap-label { bottom: 6px; transform: translateX(-50%); }
.ai-ceiling-label { right: 6px; transform: translateY(-115%); }
/* is-start: at the left end, when the busiest week sits under the right end */
.ai-ceiling-label.is-start { right: auto; left: 6px; }
/* larger invisible targets carrying each week's full reading as its title */
.ai-hit { fill: transparent; }
/* full-width variant of the .meter track: a progress bar spanning the page
   reads more precisely than the 140px inline one */
.meter-wide { width: 100%; height: 10px; border-radius: 5px; }

/* VeraLab console - usage reports (ur-*), section 25h
   Extracted from the Claude Design handoff design_handoff_usage_reports.
   Derived file: edit the handoff, not this. */

/* ---------- 25h. USAGE REPORTS (ur-*) ----------
   Monthly Usage Stats by Computer Room + YTD Usage Stats with Totals. Replaces
   three JFreeChart PNGs. One component serves both: a sortable table whose
   measure columns carry their own bars (width = value / column max, the same
   arithmetic the XSLT already does for .sb-bar heights), so a bar and its row
   are one element and there is no second chart to keep in step. Rooms are ROWS
   rather than columns because a site may have eighty and room names are long.
   Monthly adds a rooms x months seat-usage heat grid on the heat-l0..l5 ramp. */
.ur-mock { padding: var(--space-4) var(--space-6) 0; flex-wrap: wrap; }
.ur-mock-opts { display: inline-flex; flex-wrap: wrap; align-items: center; gap: 4px var(--space-3); }
.ur-mock-opts[hidden] { display: none; }
[data-ur-report] .statusline > span, [data-rc-report] .statusline > span { white-space: nowrap; }
.ur-key [hidden] { display: none !important; }
.ur-card-head {
  display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-2) var(--space-4);
  padding: var(--space-3) var(--space-4); border-bottom: 1px solid var(--border);
}
.ur-card-title { display: flex; align-items: center; gap: var(--space-2); font-size: var(--text-base); font-weight: 600; color: var(--text-strong); }
.ur-card-title .ic { width: 16px; height: 16px; color: var(--muted); }
.ur-head-end { margin-left: auto; }
.ur-facts { margin-top: 2px; }
.ur-facts strong { font-family: var(--font-mono); color: var(--text-strong); font-weight: 600; }
.ur-kpi-text { font-family: var(--font-sans); font-size: var(--text-xl); letter-spacing: 0; line-height: 1.25; padding-top: 4px; }
.ur-note { margin: 0; padding: var(--space-3) var(--space-4); font-size: var(--text-xs); line-height: 1.55; color: var(--muted); border-top: 1px solid var(--border); text-wrap: pretty; }
.ur-note strong { color: var(--text-strong); font-weight: 600; }

/* legend */
.ur-key { display: flex; flex-wrap: wrap; align-items: center; gap: 4px var(--space-4); font-size: var(--text-xs); color: var(--muted); }
.ur-key > span { display: inline-flex; align-items: center; gap: 6px; }
.ur-key-row { padding: var(--space-2) var(--space-4); border-bottom: 1px solid var(--border); background: var(--raised); }
.ur-key-end { margin-left: auto; color: var(--muted-2); }
.ur-sw { width: 12px; height: 10px; border-radius: 2px; display: block; flex: none; }
/* a month far above the rest (Usage Trends): outlined, in the top band */
.ur-hm-cell.is-outlier, .ur-sw-outlier { box-shadow: inset 0 0 0 2px var(--warn); }
.ur-sw-outlier { background: color-mix(in srgb, var(--accent) 68%, var(--surface)); }
.ur-hm-cell.is-outlier { color: var(--text-strong); font-weight: 700; }
.ur-sw-meter { width: 22px; background: linear-gradient(to right, var(--info) 0 40%, var(--zebra) 40%); box-shadow: inset 0 0 0 1px var(--border-strong); }
.ur-sw-unknown, .ur-meter.is-unknown .ur-meter-track, .ur-hm-cell.is-unknown {
  background: repeating-linear-gradient(135deg, var(--surface) 0 3px, var(--border-strong) 3px 4px);
}
.ur-sw-unknown { box-shadow: inset 0 0 0 1px var(--border-strong); }
.ur-ramp { display: inline-flex !important; gap: 2px !important; }
.ur-ramp i { width: 16px; height: 10px; border-radius: 2px; display: block; }

/* the bar table */
.ur-scroll { overflow-y: hidden; }
.ur-table thead th, .ur-table thead th.num { vertical-align: bottom; font-family: var(--font-sans); }
.ur-table thead th.num { text-align: right; }
.ur-table td { vertical-align: middle; }
.ur-table td.name { white-space: nowrap; }
.ur-table tbody tr:hover td { background: var(--hover); }
.ur-table tfoot td {
  padding: var(--space-3) var(--space-4); 
  background: var(--raised); font-size: var(--text-sm); font-weight: 700; color: var(--text-strong);
}
.ur-table td.ur-na { color: var(--muted-2); font-weight: 400; }
.ur-sort {
  background: none; border: 0; padding: 0;
  font: inherit; color: inherit; cursor: pointer; text-align: inherit; white-space: nowrap;
}
.ur-sort:focus-visible { outline: 2px solid var(--accent-text); outline-offset: 2px; border-radius: 3px; }
/* Match the server-sorted lists: a triangle after the active column's label. */
.ur-caret { display: none; }
th[aria-sort="ascending"] > .ur-caret,
th[aria-sort="descending"] > .ur-caret { display: inline; }
th[aria-sort="ascending"] > .ur-caret::before { content: "\25B2"; }
th[aria-sort="descending"] > .ur-caret::before { content: "\25BC"; }

.ur-barcell { min-width: 160px; width: 22%; }
.ur-bar, .ur-meter { display: grid; grid-template-columns: 8ch minmax(64px, 1fr); align-items: center; gap: var(--space-3); }
.ur-bar-num { font-family: var(--font-mono); font-size: var(--text-sm); text-align: right; color: var(--text-strong); }
.ur-track { display: block; height: 12px; }
.ur-stack { display: flex; height: 100%; min-width: 2px; border-radius: 2px; overflow: hidden; }
.ur-seg { display: block; height: 100%; }
.ur-seg:last-child { flex: 1; }
.ur-unique { background: var(--accent); }
.ur-reused { background: color-mix(in srgb, var(--accent) 36%, var(--surface)); }
.ur-hours  { background: var(--info); }
.ur-ratio  { background: var(--muted-2); }

/* seat usage: a proportion, so always a full 0-100 track with quarter ticks */
.ur-meter-track {
  position: relative; display: block; height: 12px; border-radius: 2px; overflow: hidden;
  background:
    linear-gradient(to right, transparent calc(25% - 1px), var(--border-strong) calc(25% - 1px) 25%, transparent 25% calc(50% - 1px), var(--border-strong) calc(50% - 1px) 50%, transparent 50% calc(75% - 1px), var(--border-strong) calc(75% - 1px) 75%, transparent 75%),
    var(--zebra);
  box-shadow: inset 0 0 0 1px var(--border);
}
.ur-meter-fill { display: block; height: 100%; background: var(--info); }
.ur-meter.is-unknown .ur-bar-num { color: var(--muted-2); }
.ur-meter.is-unknown .ur-meter-track {
  height: 20px; display: flex; align-items: center; padding: 0 var(--space-2);
  font-size: var(--text-2xs); font-weight: 600; color: var(--text-soft);
  box-shadow: inset 0 0 0 1px var(--border-strong);
}

/* monthly: rooms x months heat grid; the header row doubles as the visits
   trend and as the month picker for the table below */
.ur-hm {
  --ur-months: 9; --ur-hm-room: 180px;
  display: grid; grid-template-columns: var(--ur-hm-room) repeat(var(--ur-months), minmax(40px, 1fr)) minmax(52px, .9fr);
  gap: 3px; padding: var(--space-4); overflow-x: auto;
}
.ur-hm-corner { display: flex; flex-direction: column; justify-content: space-between; font-size: var(--text-2xs); font-weight: 600; color: var(--muted); padding-bottom: 4px; }
.ur-hm-month {
  display: flex; flex-direction: column; gap: 4px; padding: 4px 3px 3px;
  background: none; border: 1px solid transparent; border-radius: 6px; cursor: pointer; font: inherit;
}
.ur-hm-month:hover { background: var(--hover); }
.ur-hm-month.is-sel { background: var(--accent-soft); border-color: color-mix(in srgb, var(--accent) 45%, transparent); }
.ur-hm-month:focus-visible { outline: 2px solid var(--accent-text); outline-offset: 1px; }
.ur-hm-vis { height: 44px; display: flex; align-items: flex-end; justify-content: center; }
.ur-hm-vbar { width: 56%; min-height: 2px; background: var(--accent); border-radius: 2px 2px 0 0; }
.ur-hm-mlabel { font-size: var(--text-xs); font-weight: 600; color: var(--muted); text-align: center; }
.ur-hm-month.is-sel .ur-hm-mlabel { color: var(--accent-text); }
.ur-hm-yhead { align-self: end; padding: 0 0 5px; font-size: var(--text-xs); font-weight: 600; color: var(--muted); text-align: center; }
.ur-hm-room { display: flex; align-items: center; min-width: 0; font-size: var(--text-sm); color: var(--text-strong); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.ur-hm-cell {
  height: 30px; display: flex; align-items: center; justify-content: center; cursor: pointer;
  border-radius: var(--radius-cell); font-family: var(--font-mono); font-size: var(--text-xs); color: var(--text);
}
.ur-hm-cell.is-unknown { color: var(--muted); box-shadow: inset 0 0 0 1px var(--border-strong); }
.ur-hm-cell.is-sel { box-shadow: inset 0 0 0 2px var(--accent-hover); }
.ur-hm-cell.ur-hm-year { cursor: default; font-weight: 700; margin-left: var(--space-2); }

.ur-month-block + .ur-month-block { border-top: 1px solid var(--border-strong); }
.ur-month-title { display: flex; flex-wrap: wrap; align-items: baseline; gap: 4px var(--space-4); padding: var(--space-4) var(--space-4) var(--space-2); font-size: var(--text-base); font-weight: 700; color: var(--text-strong); }
.ur-month-title .statusline strong { font-family: var(--font-mono); color: var(--text-strong); }

/* Numbers only: the bar table becomes a plain report table. No schedule keeps
   its words, because "—" alone would read as missing data. */
.ur-plain .ur-track, .ur-plain .ur-meter:not(.is-unknown) .ur-meter-track, .ur-plain .ur-key-bars { display: none; }
.ur-plain .ur-bar, .ur-plain .ur-meter { display: block; text-align: right; }
.ur-plain .ur-meter.is-unknown .ur-bar-num { display: none; }
.ur-plain .ur-meter.is-unknown .ur-meter-track { display: inline-flex; white-space: nowrap; }
.ur-plain .ur-barcell { min-width: 0; width: auto; }
.ur-plain .ur-table thead th.ur-th-bar { text-align: right; }
.ur-head-end .ur-key-end { margin-left: 0; }

@media (max-width: 900px) {
  .ur-hm { --ur-hm-room: 130px; }
  .ur-key-end { display: none; }
}

@media print {
  .ur-mock, .ur-no-print, .ur-key-end, .ur-caret { display: none !important; }
  .ur-table thead { display: table-header-group; }
  .ur-table tr, .ur-hm, .kpi-grid { break-inside: avoid; page-break-inside: avoid; }
  .ur-month-block { break-before: page; }
  .ur-month-block:first-child { break-before: auto; }
  .ur-seg, .ur-meter-fill, .ur-meter-track, .ur-hm-cell, .ur-hm-vbar, .ur-sw, .ur-ramp i, .ur-hm-month.is-sel {
    -webkit-print-color-adjust: exact; print-color-adjust: exact;
  }
  .ur-hm { overflow: visible; --ur-hm-room: 110pt; padding: 6pt 0; }
  .ur-hm-cell { height: 18pt; }
  .ur-hm-vis { height: 28pt; }
  .ur-barcell { min-width: 0; }
  .ur-sort { color: #000 !important; }
}
/* VeraLab console - report charts (rc-*), section 25i
   Extracted from the Claude Design handoff design_handoff_report_charts.
   Derived file: edit the handoff, not this. */

/* ---------- 25i. REPORT CHARTS, BATCH 2 (rc-*) ----------
   Eleven reports. Most of the work is reuse: the three day-of-week reports are
   the §11d lr-* board with a noun parameter; Headcount and Downtime are §11c
   sb-* panels; Aggregate Software Tracking is the §25h bar table. New here:
   the licence limit bar, the compliance state marker, a half-hour time axis,
   the pressure tone and the few-columns sb variant. */
/* entity names are longer than ALUMNI 1-5: keep each legend chip on one line */
.lr-lg { white-space: nowrap; }
[data-rc-report] .table thead th { font-family: var(--font-sans); }

/* waitlist: queue depth reads as pressure, not volume */
.lr-pressure .lr-val { color: var(--warn-text); }
.lr-pressure .lr-track, .lr-pressure .lr-stack { background: var(--warn-soft); }

/* min-width: 0 so the track in the 1fr column can't hold the grid open at its
   labels' min-content width (harmless for rotated labels, fatal for horizontal ones) */
.sb-axis-track { min-width: 0; }
/* sb-* with a handful of columns (2-12 periods): wide columns, value on top,
   horizontal category labels with an optional second line */
.sb-few .sb-plot { gap: var(--space-5); padding: 22px var(--space-5) 0; height: 150px; }
.sb-few .sb-col { flex-direction: column; align-items: center; justify-content: flex-end; }
.sb-few .sb-bar { max-width: 104px; }
.sb-val { font-family: var(--font-mono); font-size: var(--text-xs); font-weight: 600; color: var(--text-strong); margin-bottom: 4px; white-space: nowrap; }
.sb-val.is-none { font-family: var(--font-sans); font-weight: 400; color: var(--muted); }
.sb-few .sb-axis-track { gap: var(--space-5); padding: 0 var(--space-5); }
.sb-few .sb-axis-track span {
  writing-mode: horizontal-tb; height: auto; flex-direction: column; align-items: center; gap: 2px; padding-top: 6px;
  font-family: var(--font-sans); font-size: var(--text-sm); font-weight: 600; color: var(--text-strong); text-align: center;
}
.sb-few .sb-axis-track small { font-size: var(--text-2xs); font-weight: 400; color: var(--muted); }
/* 56px fits the longest word in a period label ("Autumn", "Sept") and the value on top.
   Labels wrap; break-word only for a single word longer than the column */
.sb-few { --sb-col-min: 56px; }
.sb-few .sb-axis-track span { white-space: normal; overflow-wrap: break-word; overflow: visible; }
/* a date range under an axis label wraps rather than clips, and drops out when the
   column is too narrow for even two lines; the readout always carries the exact dates */
.sb-few .sb-axis-track span { container-type: inline-size; }
.sb-few .sb-axis-track .sb-range { font-family: var(--font-sans); text-wrap: balance; line-height: 1.3; }
@container (max-width: 64px) { .sb-axis-track .sb-range { display: none; } }
.sb-few .sb-axis-name { padding-top: 6px; }

/* headcount: 48 half-hour columns with a label every two hours */
.rc-taxis { display: grid; grid-template-columns: var(--sb-gut) 1fr; gap: var(--space-4); }
/* a custom axis on an sb board must honour the same --sb-col-min floor and 2px gap as .sb-col */
.rc-taxis-track { display: grid; grid-template-columns: repeat(48, minmax(var(--sb-col-min), 1fr)); gap: 2px; min-width: 0; border-top: 0; }
.rc-taxis-track span { font-family: var(--font-mono); font-size: var(--text-2xs); color: var(--muted); padding-top: 4px; border-left: 1px solid var(--border); padding-left: 3px; }
.rc-room-row { display: flex; }
.rc-hm-room { background: none; border: 0; padding: 0 6px 0 0; font: inherit; font-size: var(--text-sm); text-align: left; cursor: pointer; color: var(--text-strong); border-radius: 4px; }
.rc-hm-room:hover { text-decoration: underline; text-underline-offset: 2px; }
.rc-hm-room.is-sel { color: var(--accent-text); font-weight: 700; }
.rc-hm-room:focus-visible { outline: 2px solid var(--accent-text); outline-offset: 1px; }

/* compliance: licences owned are a box; peak is the fill inside it; any peak
   beyond the box is the breach, in danger, past a hard cap line */
.rc-sw-own { background: var(--zebra); box-shadow: inset 0 0 0 1px var(--border-strong); }
.rc-sw-use { background: var(--muted-2); }
.rc-sw-over { background: var(--danger); }
.rc-sw-none, .rc-limit.is-none .rc-limit-use { background: repeating-linear-gradient(135deg, var(--warn) 0 2px, var(--warn-soft) 2px 5px); }
.rc-notice { display: flex; gap: var(--space-2); align-items: flex-start; border-top: 0; border-bottom: 1px solid var(--border); background: var(--raised); font-size: var(--text-sm); color: var(--text-soft); }
.rc-notice .ic { width: 15px; height: 15px; flex: none; margin-top: 2px; color: var(--info); }
.rc-cp-barhead { width: 40%; min-width: 240px; }
.rc-cp-barhead > span:first-child { display: block; margin-bottom: 4px; }
.rc-cp-barcell { min-width: 240px; }
.rc-ticks { position: relative; display: block; height: 12px; }
.rc-ticks span { position: absolute; transform: translateX(-50%); font-family: var(--font-mono); font-size: var(--text-2xs); font-weight: 400; color: var(--muted); }
.rc-limit { position: relative; height: 16px; }
.rc-limit > span { position: absolute; top: 0; bottom: 0; left: 0; display: block; }
.rc-limit-own { background: var(--zebra); box-shadow: inset 0 0 0 1px var(--border-strong); border-radius: 2px; }
.rc-limit-use { top: 3px !important; bottom: 3px !important; background: var(--muted-2); border-radius: 1px; }
.rc-limit-over { background: var(--danger); border-radius: 0 2px 2px 0; }
.rc-limit-cap { top: -3px !important; bottom: -3px !important; width: 2px; margin-left: -1px; background: var(--text-strong); }
.rc-limit.is-none .rc-limit-use { top: 0 !important; bottom: 0 !important; border-radius: 2px; }
/* in-licence rows stay quiet; a breach is the whole point of the report */
.rc-row-ok td { color: var(--muted); }
.rc-row-ok td.name { color: var(--text-soft); font-weight: 500; }
.rc-row-over td.name { color: var(--danger-text); }
.rc-lic-none { color: var(--warn-text); }
/* state: a word plus a shape, never colour alone */
.rc-state { display: inline-flex; align-items: center; gap: 6px; font-size: var(--text-xs); font-weight: 600; color: var(--muted); white-space: nowrap; }
.rc-state::before { content: ""; width: 7px; height: 7px; border-radius: 50%; border: 1.5px solid currentColor; box-sizing: border-box; flex: none; }
.rc-state-limit { color: var(--text-soft); }
.rc-state-limit::before { background: currentColor; }
.rc-state-none { color: var(--warn-text); }
.rc-state-none::before { border-radius: 1px; background: currentColor; }
.rc-state-over { color: var(--danger-text); font-weight: 700; }
.rc-state-over::before { border-radius: 1px; transform: rotate(45deg); background: currentColor; }

/* block booking: the same limit bar, but each row's box is that day's own
   availability, so the fill is the percent; closed days say so in words */
.rc-sw-share, .rc-limit.rc-share .rc-limit-use { background: var(--info); }
.rc-limit.rc-share .rc-limit-use { top: 0 !important; bottom: 0 !important; border-radius: 2px 0 0 2px; }
.rc-closed { font-size: var(--text-xs); color: var(--muted); }
.rc-row-closed td { color: var(--muted); }
/* cost of ownership: money bars in the ur-* bar table; a text column (Room,
   in the workstation view) stays on one line */
.rc-money { background: var(--accent); }
.rc-text { white-space: nowrap; color: var(--text-soft); }
/* sb-few past 8 columns (Usage Trends' first-year months): tighter gaps */
.sb-dense .sb-plot, .sb-dense .sb-axis-track { gap: var(--space-2); }
.sb-dense .sb-plot { padding-left: var(--space-3); padding-right: var(--space-3); }
.sb-dense .sb-axis-track { padding: 0 var(--space-3); }
.sb-dense .sb-val { font-size: var(--text-2xs); }

@media print {
  .rc-limit > span, .rc-sw-own, .rc-sw-use, .rc-sw-over, .rc-sw-none, .rc-sw-share, .rc-money, .lr-pressure .lr-track { -webkit-print-color-adjust: exact; print-color-adjust: exact; }
  .rc-room-row { display: none; }
  .sb-few .sb-plot { height: 100pt; }
}
/* ---------- 23. SAVED QUESTIONS ----------
   Lifted from the design system's section 23. */
.card-toggle {
  width: 100%; border: 0; border-bottom: 1px solid var(--border);
  background: none; font: inherit; text-align: left;
  cursor: pointer; color: var(--text-strong); border-radius: var(--radius);
}
.card-toggle:hover { background: var(--hover); }
.card-toggle .card-caret {
  margin-left: var(--space-3); color: var(--muted);
  transition: transform .15s ease;
}
.card-collapsible:not(.is-collapsed) .card-toggle { border-radius: var(--radius) var(--radius) 0 0; }
.card-collapsible:not(.is-collapsed) .card-caret { transform: rotate(90deg); }
.card-collapsible.is-collapsed .card-toggle { border-bottom: none; }
.card-collapsible.is-collapsed > .qa { display: none; }
.qa { display: grid; grid-template-columns: minmax(260px, 340px) minmax(0, 1fr); }
.qa-list {
  display: flex; flex-direction: column; gap: 1px;
  padding: var(--space-3); border-right: 1px solid var(--border);
  background: var(--raised);
}
.qa-q {
  text-align: left; border: none; background: none; font: inherit;
  font-size: var(--text-sm); color: var(--text-soft); line-height: 1.35;
  padding: 9px 12px; border-radius: 6px; cursor: pointer;
}
.qa-q:hover { background: var(--hover); color: var(--text-strong); }
.qa-q.is-active {
  background: var(--surface); color: var(--text-strong); font-weight: 600;
  box-shadow: inset 2px 0 0 var(--accent), 0 0 0 1px var(--border);
}
/* the answer reads top-down: the question, the figure, the finding, what it
   rests on, then how it is worked out. Figures are sans tabular - mono is for
   codes. One pane per question; only the picked one is shown. */
.qa-answer { padding: var(--space-5) var(--space-6); min-width: 0; }
.qa-answer > [data-tab-pane] { display: flex; flex-direction: column; gap: var(--space-4); max-width: 820px; }
.qa-answer > [data-tab-pane][hidden] { display: none; }
.qa-ask { margin: 0; font-size: var(--text-sm); color: var(--muted); font-weight: 500; }
.qa-figure { display: flex; flex-wrap: wrap; align-items: baseline; column-gap: var(--space-3); row-gap: 2px; }
.qa-value {
  font-size: 40px; font-weight: 600; font-variant-numeric: tabular-nums;
  letter-spacing: -.02em; color: var(--text-strong); line-height: 1;
}
.qa-unit { font-size: var(--text-lg); color: var(--text-soft); font-weight: 500; }
.qa-text { font-size: var(--text-md); line-height: 1.6; color: var(--text-soft); margin: 0; max-width: 64ch; text-wrap: pretty; }
.qa-text strong { color: var(--text-strong); font-weight: 600; }
/* optional evidence strip: the two to four readings the sentence relies on */
.qa-facts {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(140px, 1fr));
  margin: 0; border: 1px solid var(--border); border-radius: var(--radius); overflow: hidden;
}
.qa-facts > div { padding: var(--space-3) var(--space-4); border-left: 1px solid var(--border); min-width: 0; }
.qa-facts > div:first-child { border-left: none; }
.qa-facts dt { font-size: var(--text-xs); color: var(--muted); margin-bottom: 2px; }
.qa-facts dd { margin: 0; font-size: var(--text-md); font-weight: 600; color: var(--text-strong); font-variant-numeric: tabular-nums; overflow-wrap: anywhere; }
.qa-meta {
  display: flex; flex-wrap: wrap; align-items: flex-start; justify-content: space-between;
  gap: var(--space-3) var(--space-5); padding-top: var(--space-4); border-top: 1px solid var(--border);
}
.qa-basis { flex: 1 1 320px; margin: 0; font-size: var(--text-sm); line-height: 1.5; color: var(--muted); text-wrap: pretty; }
.qa-basis b { display: block; font-size: var(--text-xs); font-weight: 600; color: var(--text-soft); margin-bottom: 2px; }
.qa-meta .action-link { flex: none; }

@media (max-width: 900px) {
  .qa { grid-template-columns: 1fr; }
  .qa-list { border-right: none; border-bottom: 1px solid var(--border); }
}
/* a feature that is included but not set up yet (widgets.xsl, promo): what it
   would show and the one thing it needs, in place of an empty chart */
.promo-card { display: flex; gap: var(--space-4); align-items: flex-start; }
.promo-body { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: var(--space-2); }
.promo-text { margin: 0; max-width: 72ch; font-size: var(--text-sm); line-height: 1.55; color: var(--text-soft); }
.promo-foot { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-2) var(--space-4); margin-top: var(--space-2); }
.promo-card .modal-icon { flex: none; }

/* a column heading that can explain its own arithmetic: the icon opens the
   shared help dialog, so a derived figure can be accounted for.

   appearance:none is the point of this rule - without it the browser paints its
   native button face, which reads as a grey square behind the glyph and is most
   obvious in dark mode. The icon sits at a low opacity so eleven of them across
   the page stay quiet, and comes up to the accent colour on hover or keyboard
   focus. */
.col-help { display: inline-flex; align-items: center; gap: 4px; }
.col-help-btn {
  appearance: none; -webkit-appearance: none;
  border: 0; background: transparent; padding: 0; margin: 0;
  line-height: 0; color: inherit; opacity: .45; cursor: help;
  border-radius: 3px;
}
.col-help-btn:hover { opacity: 1; color: var(--accent-text); }
.col-help-btn:focus-visible { opacity: 1; color: var(--accent-text); outline: 2px solid var(--accent-hover); outline-offset: 2px; }
.col-help-btn .ic { width: 13px; height: 13px; display: block; }
@media print { .col-help-btn { display: none; } }
/* a door for a module that is not licensed: visibly shut rather than absent, so
   the feature is discoverable. No hover response and no pointer, because
   nothing happens when it is clicked. */
.login-door.is-disabled {
  opacity: .55; cursor: default;
  background: var(--zebra); border-style: dashed;
}
.login-door.is-disabled:hover { border-color: var(--border); background: var(--zebra); }
.login-door.is-disabled .ic { color: var(--muted-2); }
.login-door.is-disabled:hover .ic { color: var(--muted-2); }

@media print {
  /* force the light palette regardless of the on-screen theme */
  :root, [data-theme="dark"] {
    --page: #fff; --surface: #fff; --zebra: #fff;
    --text: #000; --text-strong: #000; --text-soft: #000;
    --muted: #333; --muted-2: #555;
    --border: #999; --border-strong: #777; --control-border: #777;
    --accent-text: #000; --accent-fill: #000;
  }
  @page { margin: 14mm 12mm; }

  html, body {
    background: #fff !important;
  }
  html[data-theme="dark"] { color-scheme: light;}
  body { font-size: 10pt; }
  input {color-scheme: normal;}

  .report-columns { columns: 1; max-width: none; }
  .report-columns.hide-descriptions .report-desc { display: block; }

  /* --- hide everything interactive --- */
  .header, .app-nav, .app-footer, .drawer-backdrop, .menu,
  .modal-backdrop, .modal, /*.toolbar,*/ .pager, .action-row, .alert-close,
  /*.icon-btn, .btn,*/ .tool-link, .action-link, .datepicker,
  .no-print { display: none !important; }
  /* Row-action columns are marked on the th AND td (data-action-col) so they
     drop out as whole columns. The old rule hid only :last-child, which left a
     dangling "Edit" header over blank cells whenever a table had more than one
     action column. */
  .table [data-action-col] { display: none !important; }
  /* checkbox columns print their value as text instead of an empty control */
  .print-val { display: inline !important; }
  .table input[type="checkbox"] { display: none !important; }

  /* --- only the active screen, no app padding --- */
  .app-main { padding: 0 !important; }
  /*.page { display: block !important; max-width: none; }*/
  .app-header {background:none;}
  .alert {background: none;}
  .srkListHeaderLink {background: none; text-decoration: none;border-bottom:0;}
  .links-block, .links-toolbar {display:none;}

  /* --- print-only header block --- */
  .print-head { display: block !important; margin-bottom: 8pt; }
  .print-head-title {
    font-size: 15pt; font-weight: 700; color: #000;
    margin: 0 0 2pt; letter-spacing: -.01em;
  }
  .print-head-meta {
    font-size: 8.5pt; color: #333;
    border-bottom: 1.5pt solid #000; padding-bottom: 4pt;
  }
  .print-head-meta dl {
    display: flex; flex-wrap: wrap; gap: 2pt 14pt; margin: 3pt 0 0;
  }
  .print-head-meta dt { font-weight: 700; }
  .print-head-meta dd { margin: 0; }
  .print-head-meta dt::after { content: ':'; }

  /* --- cards flatten to plain content --- */
  .card {
    border: none !important; border-radius: 0 !important;
    box-shadow: none !important; background: #fff !important;
    margin: 0 0 10pt;
  }
  .card-pad { padding: 0 !important; }
  .card-header {
    padding: 0 0 3pt; border: none;
    font-size: 11pt; font-weight: 700;
    break-after: avoid; page-break-after: avoid;
  }

  /* --- tables: the main event --- */
  .table-scroll { overflow: visible !important; }
  .table {
    width: 100% !important; min-width: 0 !important;
    border-collapse: collapse; font-size: 8.5pt;
  }
  /* repeat the header on every sheet */
  .table thead { display: table-header-group; }
  .table tfoot { display: table-footer-group; }
  .table tr { page-break-inside: avoid; break-inside: avoid; }
  .table th {
    background: #fff !important; color: #000;
    border-bottom: 1pt solid #000; text-align: left;
    padding: 3pt 5pt; font-size: 8pt;
    text-transform: uppercase; letter-spacing: .03em;
  }
  .table td {
    border-bottom: .5pt solid #bbb;
    padding: 3pt 5pt; color: #000;
    vertical-align: top; word-break: break-word;
  }
  .table-zebra tbody tr:nth-child(even) td { background: #fff !important; }

  /* print EVERY row, not just the visible pagination page */
  .table tbody tr[hidden] { display: table-row !important; }

  /* badges/pills print as text, not filled chips */
  .badge, .pill, .tag {
    background: none !important; border: .5pt solid #666 !important;
    color: #000 !important; padding: 0 3pt !important;
  }
  /* status dots would vanish — render the label instead */
  .swatch, .station svg/*, .ic*/ { display: none !important; }
  .ic {color: #000;}
  .btn-primary {background-color:#FFF;color:#000;border-color: var(--border-strong)}

  /* KPI / chart blocks keep their shape but lose fills */
  .kpi { border: .5pt solid #999 !important; }
  .kpi-value { color: #000 !important; }
  .chart-bar, .donut { filter: grayscale(100%); }

  /* record editor prints as a two-column spec sheet with visible values */
  .editor { display: grid !important; grid-template-columns: 1fr 1fr; gap: 4pt 18pt; }
  .frow { grid-template-columns: var(--label-w, 200px) 1fr; gap: 6pt; align-items: baseline; }
  .frow-label { font-weight: 700; font-size: 8.5pt; }
  .input, .select, .textarea, .form-control {
    /*border: none !important; border-bottom: .5pt solid #999 !important;*/
    border: 1px solid var(--border-strong);
    border-radius: 0 !important; height: auto !important; padding: 4px !important;
    font-size: 8.5pt; color: #000 !important; background: none !important;
    -webkit-appearance: none; appearance: none;
  }
  .cal-btn, .form-actions, .req { display: none !important; }
  .fieldset-title { font-size: 10pt; margin: 8pt 0 2pt; break-after: avoid; }
  .crumb { display: none !important; }

  a { text-decoration: none; color: #000; }
  .print-foot { display: block !important; }

  /* AI Insights and the dashboards (veralab-core 18): a shorter chart, a tier
     heading kept with what follows, a heat grid or ranked list never split */
  .ai-plot svg { height: 150pt; }
  .ai-y.ai-y-placed:not(.is-fill) { height: 150pt; }
  .tier-head { break-after: avoid; page-break-after: avoid; }
  .heatmap, .rank { break-inside: avoid; page-break-inside: avoid; }
}
