/* =========================================================================
   Components
   ========================================================================= */

@layer components {
  .chat { display:grid;grid-template-columns:19rem minmax(0,1fr);height:min(72vh,52rem);min-height:30rem;border:1px solid var(--rule);border-radius:12px;background:var(--surface);overflow:hidden;margin-top:var(--s4) }
  .chat__sidebar { background:var(--surface-sunk);border-right:1px solid var(--rule);display:flex;flex-direction:column;min-height:0 }
  .chat__search { padding:var(--s4);border-bottom:1px solid var(--rule) }
  .chat__list { overflow-y:auto;flex:1;min-height:0 }
  .chat__conversation { width:100%;display:flex;align-items:center;gap:.75rem;padding:1rem;text-align:left;border:0;border-bottom:1px solid var(--rule);background:transparent;color:var(--ink);cursor:pointer }
  .chat__conversation:hover { background:var(--surface-alt) }
  .chat__conversation.is-active { background:var(--surface-alt);box-shadow:inset 3px 0 var(--brand) }
  .chat__avatar { display:inline-flex;width:2.5rem;height:2.5rem;flex-shrink:0;border-radius:12px;background:var(--surface-alt);color:var(--brand-lift);align-items:center;justify-content:center;font-weight:600 }
  .chat__summary { display:flex;flex-direction:column;gap:.35rem;min-width:0;flex:1 }
  .chat__summary strong,.chat__preview { overflow:hidden;text-overflow:ellipsis;white-space:nowrap }
  .chat__preview { color:var(--ink-muted);font-size:var(--t-sm) }
  .chat__unread { background:var(--brand);color:var(--brand-on);border-radius:1rem;padding:.15rem .45rem;font-size:var(--t-xs);font-weight:600 }
  .chat__main { min-width:0;display:flex;flex-direction:column;min-height:0;position:relative }
  .chat__empty { flex:1;display:flex;flex-direction:column;align-items:center;justify-content:center;text-align:center;gap:1rem;padding:2rem }
  .chat__empty>.icon { color:var(--brand-lift) }
  .chat__thread { display:flex;flex-direction:column;flex:1;min-height:0 }
  .chat__header { display:flex;justify-content:space-between;align-items:center;gap:1rem;padding:1rem 1.5rem;border-bottom:1px solid var(--rule) }
  .chat__header h2 { font-size:1.1rem;margin:0 0 .3rem }
  .chat__header p { font-size:var(--t-xs);margin:0 }
  .chat__secure { display:flex;align-items:center;gap:.3rem;white-space:nowrap;color:var(--ink-muted);font-size:var(--t-xs) }
  .chat__history { flex:1;min-height:0;overflow-y:auto;padding:1rem 1.5rem;scrollbar-gutter:stable }
  .chat__message { display:flex;justify-content:flex-start;margin:.75rem 0 }
  .chat__message.is-mine { justify-content:flex-end }
  .chat__bubble { max-width:min(85%,36rem);border-radius:12px;background:var(--surface-alt);padding:.75rem 1rem;border:1px solid var(--rule) }
  .is-mine .chat__bubble { border-color:var(--brand-lift);background:var(--surface-sunk) }
  .chat__sender { display:block;font-size:var(--t-xs);color:var(--brand-lift) }
  .chat__body { white-space:pre-wrap;overflow-wrap:anywhere;margin:.4rem 0 .5rem }
  .chat__time { display:block;text-align:right;color:var(--ink-faint);font-size:.7rem }
  .chat__day { text-align:center;color:var(--ink-faint);font-size:var(--t-xs);margin:1.5rem 0 1rem }
  .chat__composer { border-top:1px solid var(--rule);padding:1rem 1.5rem }
  .chat__composer textarea { resize:vertical;min-height:4rem;max-height:10rem }
  .chat__compose-actions { display:flex;align-items:center;justify-content:space-between;gap:1rem;margin-top:.65rem }
  .chat__compose-actions>span { font-size:var(--t-xs) }
  .chat__status { padding:0 1.5rem;color:var(--ink-muted);font-size:var(--t-sm) }
  .chat__status:empty { display:none }
  .chat__back { display:none }
  .chat__no-results { text-align:center;padding:1.5rem }
  .chat-dialog { color:var(--ink);background:var(--surface);border:1px solid var(--rule-strong);border-radius:14px;padding:1.5rem;width:min(34rem,calc(100vw - 2rem));max-height:85vh;overflow-y:auto;box-shadow:0 24px 80px #0005 }
  .chat-dialog::backdrop { background:#0007;backdrop-filter:blur(3px) }
  .chat-dialog h2 { font-size:1.25rem;margin:0 }
  .chat__kind { display:flex;gap:1.5rem;border:0;padding:0 }
  .chat__people { max-height:18rem;min-height:8rem;overflow-y:auto;border:1px solid var(--rule);border-radius:8px }
  .chat__person { display:flex;align-items:center;gap:.8rem;padding:.75rem 1rem;cursor:pointer;border-bottom:1px solid var(--rule) }
  .chat__person:last-child { border-bottom:0 }
  .chat__person:has(input:checked) { background:var(--surface-alt) }
  @media(max-width:760px) {
    .chat { grid-template-columns:minmax(0,1fr);height:75vh;min-height:30rem }
    .chat__main { display:none }.chat.has-thread .chat__main { display:flex }.chat.has-thread .chat__sidebar { display:none }
    .chat__back { display:inline-flex }.chat__secure { display:none }
    .chat__header,.chat__history,.chat__composer { padding:1rem }
    .chat__compose-actions>span { display:none }
  }
}

@layer components {

  /* =======================================================================
     THE DOCUMENT PLATE  —  the signature element
     =======================================================================
     Every work order number, delivery ticket number and equipment serial is
     set in this. It is the same mark in a table cell, in a page heading, and
     on the printed PDF, because those three places are where the same number
     gets compared by eye and read aloud down a phone line.

     Monospace with the digits opened up, a navy edge lifted from the logo
     plate, and a hairline box so it reads as a stamped field on a form rather
     than as running text. It never changes size to suit its surroundings —
     recognition depends on it looking identical everywhere.
     ===================================================================== */

  .docno {
    display: inline-flex;
    align-items: center;
    gap: 0.375rem;
    padding: 0.125rem 0.4375rem 0.125rem 0.375rem;
    font-family: var(--font-mono);
    font-size: var(--t-sm);
    font-weight: 500;
    letter-spacing: var(--track-doc);
    font-variant-numeric: tabular-nums;
    color: var(--ink);
    background: var(--surface);
    border: 1px solid var(--rule-strong);
    border-left: 3px solid var(--brand);
    border-radius: var(--r-sm);
    white-space: nowrap;
    text-decoration: none;
  }

  a.docno:hover { border-color: var(--brand); background: var(--brand-tint); }

  .docno--lg { font-size: var(--t-md); padding: 0.25rem 0.5rem 0.25rem 0.4375rem; }

  /* Serials sit inside product rows where the navy edge would compete with
     the row's own status marker, so they drop it and stay monospace. */
  .docno--serial { border-left-color: var(--rule-strong); font-size: var(--t-xs); }

  /* =======================================================================
     Buttons
     ===================================================================== */

  .btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 0.4375rem;
    padding: 0.4375rem 0.875rem;
    font-size: var(--t-base);
    font-weight: 500;
    line-height: 1.3;
    color: var(--ink);
    background: var(--surface);
    border: 1px solid var(--rule-strong);
    border-radius: var(--r);
    box-shadow: var(--shadow-1);
    cursor: pointer;
    white-space: nowrap;
    text-decoration: none;
    transition: background-color 0.12s var(--ease), border-color 0.12s var(--ease),
                box-shadow 0.12s var(--ease), transform 0.06s var(--ease);
  }

  .btn:hover { background: var(--surface-alt); border-color: var(--ink-faint); }
  .btn:active { transform: translateY(0.5px); box-shadow: none; }

  .btn svg { width: 1rem; height: 1rem; flex: none; }

  .btn--primary {
    background: var(--brand);
    border-color: var(--brand);
    color: var(--brand-on);
  }
  .btn--primary:hover { background: var(--brand-lift); border-color: var(--brand-lift); }

  .btn--danger {
    background: var(--surface);
    border-color: color-mix(in srgb, var(--danger) 40%, var(--rule-strong));
    color: var(--danger);
  }
  .btn--danger:hover { background: var(--danger-tint); border-color: var(--danger); }

  .btn--ghost { background: transparent; border-color: transparent; box-shadow: none; }
  .btn--ghost:hover { background: var(--surface-alt); border-color: transparent; }

  .btn--sm { padding: 0.25rem 0.5rem; font-size: var(--t-sm); }
  .btn--icon { padding: 0.375rem; }
  .btn--block { width: 100%; }

  .btn[disabled], .btn[aria-disabled="true"] {
    opacity: 0.5;
    pointer-events: none;
  }

  /* A button group reads as one control: shared edges, single outline. */
  .btn-group { display: inline-flex; }
  .btn-group .btn { border-radius: 0; margin-left: -1px; box-shadow: none; }
  .btn-group .btn:first-child { border-radius: var(--r) 0 0 var(--r); margin-left: 0; }
  .btn-group .btn:last-child { border-radius: 0 var(--r) var(--r) 0; }
  .btn-group .btn[aria-pressed="true"] {
    background: var(--brand-tint);
    border-color: var(--brand);
    color: var(--brand);
    z-index: 1;
  }

  /* =======================================================================
     Cards and panels
     ===================================================================== */

  .card {
    background: var(--surface);
    border: 1px solid var(--rule);
    border-radius: var(--r-lg);
    box-shadow: var(--shadow-1);
  }

  .card__head {
    display: flex;
    align-items: center;
    gap: var(--s3);
    padding: var(--s4) var(--s5);
    border-bottom: 1px solid var(--rule);
  }

  .card__title { font-size: var(--t-base); font-weight: 600; }
  .card__head .btn { margin-left: auto; }
  .card__body { padding: var(--s5); }
  .card__body--tight { padding: var(--s4); }
  .card__foot {
    padding: var(--s3) var(--s5);
    border-top: 1px solid var(--rule);
    background: var(--surface-sunk);
    border-radius: 0 0 var(--r-lg) var(--r-lg);
    font-size: var(--t-sm);
  }

  /* A card whose whole body is a table gets no padding, or the table's own
     rules stop meeting its edges. */
  .card--table .card__body { padding: 0; }
  .card--table .table { border-radius: 0 0 var(--r-lg) var(--r-lg); }

  /* =======================================================================
     Tables
     =======================================================================
     Ruled rows, no zebra striping. Striping fights the status markers, and on
     a table where every row is a live job the eye needs the colour budget for
     meaning rather than for finding its place along a row.
     ===================================================================== */

  .table-wrap { overflow-x: auto; }

  .table { font-size: var(--t-sm); }

  /* The column a person actually reads. Without a floor, every nowrap pill
     and date beside it took its width first, and on a laptop the job title
     was left one or two words to a line. */
  .table th.table__grow { min-width: 15rem; }

  .table th {
    position: sticky;
    top: 0;
    z-index: 1;
    padding: var(--s3) var(--s4);
    text-align: left;
    font-size: var(--t-xs);
    font-weight: 600;
    letter-spacing: var(--track-label);
    text-transform: uppercase;
    color: var(--ink-faint);
    background: var(--surface-sunk);
    border-bottom: 1px solid var(--rule-strong);
    white-space: nowrap;
  }

  .table td {
    padding: var(--s3) var(--s4);
    border-bottom: 1px solid var(--rule);
    vertical-align: middle;
  }

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

  .table tbody tr { transition: background-color 0.1s var(--ease); }
  .table tbody tr:hover { background: var(--surface-sunk); }

  /* Whole-row links: the <a> covers the first cell but the row highlights. */
  .table tbody tr[data-href] { cursor: pointer; }

  /* Right alignment is opt-in with `.right`, and is for quantities and money —
     the digits that get compared down a column. A date or a document number is
     monospaced for legibility but still reads left to right, so `.num` sets the
     face and the figures only. */
  .table td.right, .table th.right { text-align: right; }

  /* A timestamp or a document number must not wrap. On a narrow screen the
     table scrolls sideways instead — "11 / Aug / 02:40" stacked over three
     lines is unreadable and makes every row a different height. */
  .table .num { white-space: nowrap; }

  /* Sortable column headers carry their direction as a caret rather than an
     icon font, so they survive the CSP with no extra request. */
  .table th a { display: inline-flex; align-items: center; gap: 0.25rem; text-decoration: none; }
  .table th a:hover { color: var(--ink); }
  .table th [data-sort]::after { content: '↕'; opacity: 0.35; font-size: 0.85em; }
  .table th [data-sort="asc"]::after  { content: '↑'; opacity: 1; }
  .table th [data-sort="desc"]::after { content: '↓'; opacity: 1; }

  /* The status edge marker. Colour AND a label, always — a printed or
     photocopied queue has to stay readable, and about one man in twelve
     cannot separate the red from the green. */
  .table tbody tr[data-signal] td:first-child { position: relative; padding-left: calc(var(--s4) + 3px); }
  .table tbody tr[data-signal] td:first-child::before {
    content: '';
    position: absolute;
    left: 0; top: 0; bottom: 0;
    width: 3px;
    background: var(--neutral);
  }
  tr[data-signal="ok"]      td:first-child::before { background: var(--ok); }
  tr[data-signal="warn"]    td:first-child::before { background: var(--warn); }
  tr[data-signal="danger"]  td:first-child::before { background: var(--danger); }
  tr[data-signal="info"]    td:first-child::before { background: var(--info); }
  tr[data-signal="brand"]   td:first-child::before { background: var(--brand); }

  .table--compact td, .table--compact th { padding: 0.375rem var(--s3); }

  /* =======================================================================
     Status pills
     ===================================================================== */

  .pill {
    display: inline-flex;
    align-items: center;
    gap: 0.375rem;
    padding: 0.0625rem 0.5rem 0.0625rem 0.375rem;
    font-size: var(--t-xs);
    font-weight: 600;
    letter-spacing: 0.01em;
    border-radius: 999px;
    border: 1px solid transparent;
    white-space: nowrap;
  }

  /* The dot is a square, not a circle: at 6px a square holds its shape when
     the page is printed at 300dpi and photocopied twice. */
  .pill::before {
    content: '';
    width: 0.375rem;
    height: 0.375rem;
    border-radius: 1px;
    background: currentColor;
    flex: none;
  }

  .pill--ok      { color: var(--ok);      background: var(--ok-tint);      border-color: color-mix(in srgb, var(--ok) 25%, transparent); }
  .pill--warn    { color: var(--warn);    background: var(--warn-tint);    border-color: color-mix(in srgb, var(--warn) 25%, transparent); }
  .pill--danger  { color: var(--danger);  background: var(--danger-tint);  border-color: color-mix(in srgb, var(--danger) 25%, transparent); }
  .pill--info    { color: var(--info);    background: var(--info-tint);    border-color: color-mix(in srgb, var(--info) 25%, transparent); }
  .pill--brand   { color: var(--brand);   background: var(--brand-tint);   border-color: color-mix(in srgb, var(--brand) 25%, transparent); }
  .pill--neutral { color: var(--neutral); background: var(--neutral-tint); border-color: color-mix(in srgb, var(--neutral) 25%, transparent); }

  .pill--plain::before { display: none; }

  /* =======================================================================
     Forms
     ===================================================================== */

  .field { display: flex; flex-direction: column; gap: 0.3125rem; }

  .field__label {
    font-size: var(--t-xs);
    font-weight: 600;
    letter-spacing: var(--track-label);
    text-transform: uppercase;
    color: var(--ink-muted);
  }

  .field__label .req { color: var(--danger); margin-left: 0.125rem; }

  .field__hint { font-size: var(--t-xs); color: var(--ink-faint); }

  .field__error {
    font-size: var(--t-xs);
    font-weight: 500;
    color: var(--danger);
  }

  .input, .select, .textarea {
    width: 100%;
    padding: 0.4375rem 0.625rem;
    font-size: var(--t-base);
    color: var(--ink);
    background: var(--surface);
    border: 1px solid var(--rule-strong);
    border-radius: var(--r);
    transition: border-color 0.12s var(--ease), box-shadow 0.12s var(--ease);
  }

  .input::placeholder, .textarea::placeholder { color: var(--ink-faint); }

  .input:hover, .select:hover, .textarea:hover { border-color: var(--ink-faint); }

  .input:focus, .select:focus, .textarea:focus {
    outline: none;
    border-color: var(--brand);
    box-shadow: 0 0 0 3px color-mix(in srgb, var(--brand) 16%, transparent);
  }

  .textarea { min-height: 5.5rem; resize: vertical; line-height: var(--lh-body); }

  .input--mono { font-family: var(--font-mono); letter-spacing: var(--track-doc); }

  /* The caret is drawn as a background gradient pair rather than an SVG data
     URI, so it inherits the theme and costs no bytes. */
  .select {
    appearance: none;
    padding-right: 2rem;
    background-image:
      linear-gradient(45deg, transparent 50%, currentColor 50%),
      linear-gradient(135deg, currentColor 50%, transparent 50%);
    background-position: calc(100% - 1rem) 55%, calc(100% - 0.6875rem) 55%;
    background-size: 0.3125rem 0.3125rem, 0.3125rem 0.3125rem;
    background-repeat: no-repeat;
  }

  [aria-invalid="true"].input,
  [aria-invalid="true"].select,
  [aria-invalid="true"].textarea {
    border-color: var(--danger);
    background: var(--danger-tint);
  }

  /* -----------------------------------------------------------------------
     Searchable select (combobox.js)

     The real <select> is still there, sitting behind the text box at full
     size and fully transparent. It is not `display: none` on purpose: a
     required control the browser cannot focus blocks submission with no
     message the user ever sees, and at this size its validation bubble
     points at the field rather than the top of the page.

     Nothing here is required for the field to work — before the script runs,
     and if it never runs, these selects are ordinary dropdowns.
     --------------------------------------------------------------------- */

  .combo { position: relative; }

  .combo__native {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    opacity: 0;
    pointer-events: none;
  }

  /* The caret is borrowed from `.select` so an upgraded field still reads as
     a dropdown rather than as a free-text box. */
  .combo__input {
    position: relative;
    padding-right: 2rem;
    background-image:
      linear-gradient(45deg, transparent 50%, currentColor 50%),
      linear-gradient(135deg, currentColor 50%, transparent 50%);
    background-position: calc(100% - 1rem) 55%, calc(100% - 0.6875rem) 55%;
    background-size: 0.3125rem 0.3125rem, 0.3125rem 0.3125rem;
    background-repeat: no-repeat;
    text-overflow: ellipsis;
  }

  .combo__input:disabled {
    color: var(--ink-faint);
    background-color: var(--surface-sunk);
    cursor: not-allowed;
  }

  .combo__list {
    position: absolute;
    z-index: 30;
    top: calc(100% + 0.25rem);
    left: 0;
    right: 0;
    max-height: 16rem;
    overflow-y: auto;
    padding: 0.25rem;
    background: var(--surface);
    border: 1px solid var(--rule-strong);
    border-radius: var(--r);
    box-shadow: var(--shadow-2);
  }

  /* In the top layer the list is laid out against the viewport, so combobox.js
     works out where the text box is and writes the coordinates. The UA's own
     popover rules — `inset: 0` and `margin: auto`, the same pair that centres a
     <dialog> — have to be undone or it lands in the middle of the screen.
     `position` has to be restated because the author `absolute` above outranks
     the UA's `fixed`, and it is the viewport these coordinates are measured
     against. */
  .combo__list[popover] {
    position: fixed;
    inset: auto;
    margin: 0;
    z-index: auto;
    overscroll-behavior: contain;
  }

  .combo__option {
    display: flex;
    align-items: baseline;
    gap: var(--s2);
    padding: 0.375rem 0.5rem;
    border-radius: var(--r-sm);
    font-size: var(--t-base);
    cursor: pointer;
  }

  /* Keyboard and pointer share one highlight. Two — a hover colour and a
     separate "active" one — put the field in two states at once and Enter
     then takes the row the mouse is not over. */
  .combo__option[data-active="yes"] {
    background: var(--brand-tint);
    color: var(--brand);
  }

  .combo__name { flex: 1; min-width: 0; }

  .combo__meta {
    flex: none;
    font-size: var(--t-xs);
    color: var(--ink-faint);
  }

  .combo__option[data-active="yes"] .combo__meta { color: inherit; opacity: 0.75; }

  .combo__empty {
    padding: 0.5rem;
    font-size: var(--t-sm);
    color: var(--ink-faint);
  }

  .check {
    display: inline-flex;
    align-items: flex-start;
    gap: var(--s2);
    font-size: var(--t-base);
    cursor: pointer;
  }
  .check input { margin-top: 0.1875rem; accent-color: var(--brand); width: 0.9375rem; height: 0.9375rem; }

  fieldset { border: 0; padding: 0; }

  .form-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(15rem, 1fr));
    gap: var(--s4);
  }
  .form-grid .span-2 { grid-column: 1 / -1; }

  .form-actions {
    display: flex;
    gap: var(--s2);
    align-items: center;
    padding-top: var(--s4);
    margin-top: var(--s4);
    border-top: 1px solid var(--rule);
  }
  .form-actions .spacer { margin-left: auto; }

  /* --- filter bar ------------------------------------------------------ */

  .filters {
    display: flex;
    gap: var(--s2);
    align-items: center;
    flex-wrap: wrap;
    padding: var(--s3) var(--s4);
    background: var(--surface);
    border: 1px solid var(--rule);
    border-radius: var(--r-lg);
    box-shadow: var(--shadow-1);
  }
  .filters .input, .filters .select { width: auto; min-width: 9rem; }
  .filters .search { flex: 1 1 16rem; min-width: 12rem; }

  /* =======================================================================
     Definition lists — the shape every detail page uses
     ===================================================================== */

  .facts { display: grid; gap: 0; }

  .facts > div {
    display: grid;
    grid-template-columns: 9.5rem minmax(0, 1fr);
    gap: var(--s4);
    padding: 0.5rem 0;
    border-bottom: 1px solid var(--rule);
  }
  .facts > div:last-child { border-bottom: 0; }

  .facts dt {
    font-size: var(--t-xs);
    font-weight: 600;
    letter-spacing: var(--track-label);
    text-transform: uppercase;
    color: var(--ink-faint);
    padding-top: 0.125rem;
  }

  .facts dd { font-size: var(--t-base); min-width: 0; overflow-wrap: break-word; }

  /* The same definition list appears in the wide main column and in the 20rem
     sidebar. A viewport media query cannot tell those apart — the window is
     the same width in both cases — so it is the *card* that has to answer,
     which is what a container query is for. Below 24rem the label and value
     stack instead of "Whitfield Grocers, Inc." wrapping into a 6rem column. */
  .card__body { container-type: inline-size; }

  @container (max-width: 24rem) {
    .facts > div { grid-template-columns: minmax(0, 1fr); gap: 0.125rem; }
  }

  @media (max-width: 560px) {
    .facts > div { grid-template-columns: minmax(0, 1fr); gap: 0.125rem; }
  }

  /* =======================================================================
     Feedback
     ===================================================================== */

  .alert {
    display: flex;
    gap: var(--s3);
    padding: var(--s3) var(--s4);
    border: 1px solid;
    border-left-width: 3px;
    border-radius: var(--r);
    font-size: var(--t-base);
  }
  .alert svg { flex: none; width: 1.125rem; height: 1.125rem; margin-top: 0.125rem; }
  .alert--ok     { color: var(--ok);     background: var(--ok-tint);     border-color: color-mix(in srgb, var(--ok) 35%, transparent);     border-left-color: var(--ok); }
  .alert--warn   { color: var(--warn);   background: var(--warn-tint);   border-color: color-mix(in srgb, var(--warn) 35%, transparent);   border-left-color: var(--warn); }
  .alert--danger { color: var(--danger); background: var(--danger-tint); border-color: color-mix(in srgb, var(--danger) 35%, transparent); border-left-color: var(--danger); }
  .alert--info   { color: var(--info);   background: var(--info-tint);   border-color: color-mix(in srgb, var(--info) 35%, transparent);   border-left-color: var(--info); }
  .alert strong { font-weight: 600; }

  .maintenance-notice {
    display: flex;
    align-items: flex-start;
    gap: var(--s2);
    padding: var(--s2) var(--s5);
    border-bottom: 1px solid color-mix(in srgb, var(--warn) 35%, transparent);
    background: var(--warn-tint);
    color: var(--warn);
    font-size: var(--t-sm);
    line-height: 1.5;
  }
  .maintenance-notice svg { flex: none; width: 1rem; height: 1rem; margin-top: 0.15em; }
  .maintenance-notice span { min-width: 0; white-space: pre-wrap; overflow-wrap: anywhere; }
  @media print { .maintenance-notice { display: none; } }

  /* Flash messages slide in once at the top of the page and then sit still.
     They do not auto-dismiss: a dispatcher who looked away must still be able
     to read what happened. */
  .flash { animation: flash-in 0.22s var(--ease); }
  @keyframes flash-in {
    from { opacity: 0; transform: translateY(-0.375rem); }
    to   { opacity: 1; transform: none; }
  }

  .empty {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: var(--s3);
    padding: var(--s7) var(--s5);
    text-align: center;
    color: var(--ink-muted);
  }
  .empty__title { font-size: var(--t-md); font-weight: 600; color: var(--ink); }
  .empty__mark {
    display: grid;
    place-items: center;
    width: 2.75rem; height: 2.75rem;
    border-radius: var(--r);
    background: var(--surface-alt);
    color: var(--ink-faint);
    border: 1px solid var(--rule);
  }
  .empty__mark svg { width: 1.25rem; height: 1.25rem; }

  /* =======================================================================
     Pagination
     ===================================================================== */

  .pager {
    display: flex;
    align-items: center;
    gap: var(--s3);
    padding: var(--s3) var(--s4);
    border-top: 1px solid var(--rule);
    font-size: var(--t-sm);
    color: var(--ink-muted);
    flex-wrap: wrap;
  }
  .pager__links { margin-left: auto; display: flex; gap: 0.25rem; align-items: center; }
  .pager__links a, .pager__links span {
    display: inline-grid;
    place-items: center;
    min-width: 1.875rem;
    height: 1.875rem;
    padding-inline: 0.375rem;
    border: 1px solid var(--rule-strong);
    border-radius: var(--r-sm);
    background: var(--surface);
    text-decoration: none;
    font-variant-numeric: tabular-nums;
  }
  .pager__links a:hover { background: var(--surface-alt); }
  .pager__links [aria-current] { background: var(--brand); border-color: var(--brand); color: var(--brand-on); }
  .pager__links .disabled { opacity: 0.4; }

  /* =======================================================================
     Avatar
     ===================================================================== */

  .avatar {
    display: inline-grid;
    place-items: center;
    width: 1.75rem; height: 1.75rem;
    flex: none;
    border-radius: 50%;
    font-size: var(--t-xs);
    font-weight: 600;
    letter-spacing: 0.02em;
    color: #fff;
    background: var(--neutral);
    user-select: none;
  }
  .avatar--sm { width: 1.375rem; height: 1.375rem; font-size: var(--t-2xs); }
  .avatar--lg { width: 2.5rem; height: 2.5rem; font-size: var(--t-base); }

  /* Stacked assignee lists on the dispatch board. */
  .avatars { display: inline-flex; }
  .avatars .avatar + .avatar { margin-left: -0.4375rem; box-shadow: 0 0 0 2px var(--surface); }

  /* =======================================================================
     Menus and modals
     ===================================================================== */

  .menu {
    position: relative;
    display: inline-flex;
  }

  .menu__panel {
    position: absolute;
    top: calc(100% + 0.375rem);
    right: 0;
    z-index: 40;
    min-width: 12rem;
    padding: 0.3125rem;
    background: var(--surface);
    border: 1px solid var(--rule-strong);
    border-radius: var(--r);
    box-shadow: var(--shadow-2);
  }
  .menu__panel[hidden] { display: none; }

  /* The panel has to be able to overhang whatever it is inside. Every table on
     the site sits in `.table-wrap`, and `overflow-x: auto` there computes the
     unset `overflow-y` to `auto` as well — so an absolutely positioned panel in
     the last cell of a row is clipped by a scroll box that only ever existed to
     handle wide columns, and the actions are reachable only by scrolling a
     table that has nothing else below it. As a popover it is promoted to the
     top layer, which no ancestor's `overflow`, `z-index` or `contain` can
     reach, and which sits above an open <dialog> rather than behind it.

     Laid out against the viewport, so menu.js works out where the button is
     and writes the coordinates. The UA's own popover rules — `inset: 0` and
     `margin: auto`, the same pair that centres a <dialog> — have to be undone
     or it lands in the middle of the screen, and `position` has to be restated
     because the author `absolute` above outranks the UA's `fixed`. */
  .menu__panel[popover] {
    position: fixed;
    inset: auto;
    margin: 0;
    z-index: auto;
    overflow-y: auto;
    overscroll-behavior: contain;
  }

  .menu__item {
    display: flex;
    align-items: center;
    gap: var(--s2);
    width: 100%;
    padding: 0.375rem 0.5rem;
    border-radius: var(--r-sm);
    font-size: var(--t-base);
    text-align: left;
    text-decoration: none;
    color: var(--ink);
  }
  .menu__item:hover { background: var(--surface-alt); }
  .menu__item svg { width: 1rem; height: 1rem; opacity: 0.7; }
  .menu__item--danger { color: var(--danger); }
  .menu__sep { height: 1px; margin: 0.3125rem 0; background: var(--rule); }

  /* A modal dialog centres itself through the user-agent rule
     `inset: 0; margin: auto` — and the reset's `* { margin: 0 }` wipes exactly
     half of that, which pins the dialog to the top-left corner. Restoring the
     auto margin here is what centres it; without it, `inset: 0` alone stretches
     the box to the top-left of the viewport. */
  dialog.modal {
    position: fixed;
    inset: 0;
    margin: auto;

    width: min(40rem, calc(100vw - 2rem));

    /* A long form must not run off the bottom of the screen with its buttons
       out of reach. The dialog caps its height and the body scrolls inside it,
       so the header and the actions stay put. */
    max-height: min(88vh, 52rem);
    flex-direction: column;

    padding: 0;
    color: var(--ink);
    background: var(--surface);
    border: 1px solid var(--rule-strong);
    border-radius: var(--r-lg);
    box-shadow: var(--shadow-3);
  }

  /* `display` is set only on the open state. Declaring it on the bare
     selector beats the user-agent's `dialog:not([open]) { display: none }` —
     a class selector outranks it — and the dialog then sits on the page
     permanently, closed but visible. */
  dialog.modal[open] { display: flex; }

  dialog.modal > form {
    display: flex;
    flex-direction: column;
    min-height: 0;
  }

  dialog.modal::backdrop {
    background: rgba(10, 12, 24, 0.5);
    backdrop-filter: blur(2px);
  }

  /* An open modal must not leave the page scrolling behind it. */
  body:has(dialog.modal[open]) { overflow: hidden; }
  dialog.modal[open] { animation: modal-in 0.16s var(--ease); }
  @keyframes modal-in {
    from { opacity: 0; transform: translateY(0.5rem) scale(0.985); }
    to   { opacity: 1; transform: none; }
  }
  .modal__head {
    display: flex;
    align-items: center;
    gap: var(--s3);
    flex: none;
    padding: var(--s4) var(--s5);
    border-bottom: 1px solid var(--rule);
  }
  .modal__title { font-size: var(--t-md); font-weight: 600; }
  .modal__head .btn--icon { margin-left: auto; }

  .modal__body {
    padding: var(--s5);
    overflow-y: auto;
    min-height: 0;
  }

  /* A connect dialog is a vertical flow, not an auto-fit form grid. Giving
     its fallback its own full-width row keeps the message and download action
     together at every desktop width. */
  .remote-launch__body {
    display: flex;
    flex-direction: column;
    gap: var(--s4);
  }
  .remote-launch__status {
    margin: 0;
    color: var(--ink-faint);
    font-size: var(--t-sm);
  }
  .remote-launch__status:empty { display: none; }
  .remote-launch__status.is-problem { color: var(--danger); }
  .remote-launch__fallback {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--s4);
    min-width: 0;
    padding: var(--s4);
    color: var(--ink);
    background: var(--surface-sunk);
    border: 1px solid var(--rule);
    border-radius: var(--r);
  }
  .remote-launch__fallback[hidden] { display: none; }
  .remote-launch__fallback-copy { min-width: 0; }
  .remote-launch__fallback-copy strong { font-weight: 600; }
  .remote-launch__fallback-copy p {
    margin: 0.25rem 0 0;
    color: var(--ink-faint);
    font-size: var(--t-sm);
  }

  @media (max-width: 560px) {
    .remote-launch__fallback {
      align-items: stretch;
      flex-direction: column;
    }
    .remote-launch__fallback .btn { align-self: flex-start; }
  }

  .modal__foot {
    display: flex;
    gap: var(--s2);
    justify-content: flex-end;
    flex: none;
    padding: var(--s3) var(--s5);
    border-top: 1px solid var(--rule);
    background: var(--surface-sunk);
    border-radius: 0 0 var(--r-lg) var(--r-lg);
  }

  @media (max-width: 560px) {
    /* Full-bleed on a phone: a centred card with margins wastes the width the
       form needs, and the on-screen keyboard eats the rest. */
    dialog.modal {
      width: 100vw;
      max-width: 100vw;
      max-height: 100dvh;
      height: 100dvh;
      border-radius: 0;
      border: 0;
    }
    .modal__foot { border-radius: 0; }
  }

  /* The in-page confirm (confirm.js). A question and two buttons, so it stays
     a small centred card on a phone too rather than taking the full-bleed
     treatment a long form gets just above — a whole screen for "Delete this
     note?" reads as a page that navigated away. */
  /* Sized to its content both ways. `fit-content`, not `auto`: with
     `inset: 0` an auto height stretches the box to the full max-height, which
     is how "Delete this note?" ended up in a box most of the screen tall. The
     floor keeps a one-word question from shrinking to a sliver, and the
     ceiling keeps a long one readable as a paragraph. */
  dialog.modal.modal--confirm {
    width: fit-content;
    min-width: min(24rem, calc(100vw - 2rem));
    max-width: min(36rem, calc(100vw - 2rem));
    height: fit-content;
    max-height: min(88vh, 52rem);
    border: 1px solid var(--rule-strong);
    border-radius: var(--r-lg);
  }
  .modal--confirm .modal__foot { border-radius: 0 0 var(--r-lg) var(--r-lg); }
  .modal__message { white-space: pre-line; overflow-wrap: anywhere; }

  /* =======================================================================
     Command palette
     =======================================================================
     Sits near the top of the screen rather than dead centre: it grows
     downwards as results arrive, and a vertically centred box would shift the
     first result under the cursor every time the list changed length.
     ===================================================================== */

  dialog.palette {
    position: fixed;
    inset: 0;
    margin: 10vh auto auto;

    width: min(40rem, calc(100vw - 2rem));
    max-height: min(70vh, 34rem);
    flex-direction: column;

    padding: 0;
    color: var(--ink);
    background: var(--surface);
    border: 1px solid var(--rule-strong);
    border-radius: var(--r-lg);
    box-shadow: var(--shadow-3);
    overflow: hidden;
  }

  /* Same trap as the modal above: only the open state gets a display value. */
  dialog.palette[open] { display: flex; }

  dialog.palette::backdrop {
    background: rgba(10, 12, 24, 0.4);
    backdrop-filter: blur(2px);
  }

  .palette__field {
    display: flex;
    align-items: center;
    gap: var(--s3);
    flex: none;
    padding: var(--s3) var(--s4);
    border-bottom: 1px solid var(--rule);
    color: var(--ink-faint);
  }

  .palette__input {
    flex: 1;
    min-width: 0;
    border: 0;
    background: none;
    outline: none;
    font-size: var(--t-md);
    color: var(--ink);
  }
  .palette__input::placeholder { color: var(--ink-faint); }
  .palette__input::-webkit-search-cancel-button { display: none; }

  .palette__results { overflow-y: auto; min-height: 0; padding: var(--s2); }

  .palette__group + .palette__group { margin-top: var(--s2); }

  .palette__group-label {
    padding: var(--s2) var(--s3) 0.25rem;
    font-size: var(--t-2xs);
    font-weight: 600;
    letter-spacing: var(--track-label);
    text-transform: uppercase;
    color: var(--ink-faint);
  }

  .palette__row {
    display: flex;
    align-items: baseline;
    gap: var(--s3);
    padding: 0.4375rem var(--s3);
    border-radius: var(--r);
    text-decoration: none;
    color: var(--ink);
  }

  /* Highlighted by the keyboard, not by :hover — the pointer and the arrow
     keys must not be able to disagree about which row Enter will open. */
  .palette__row[aria-selected="true"] { background: var(--brand-tint); }
  .palette__row[aria-selected="true"] .palette__title { color: var(--brand); }

  .palette__title { font-weight: 500; white-space: nowrap; }
  .palette__sub {
    flex: 1;
    min-width: 0;
    font-size: var(--t-sm);
    color: var(--ink-faint);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
  }

  .palette__empty { padding: var(--s4) var(--s3); color: var(--ink-faint); font-size: var(--t-sm); }

  .palette__foot {
    display: flex;
    gap: var(--s4);
    flex: none;
    padding: var(--s2) var(--s4);
    border-top: 1px solid var(--rule);
    background: var(--surface-sunk);
    font-size: var(--t-xs);
    color: var(--ink-faint);
  }
  .palette__foot span { display: flex; align-items: center; gap: 0.25rem; }

  @media (max-width: 560px) {
    dialog.palette { margin: 0 auto auto; width: 100vw; max-height: 100dvh; height: 100dvh; border-radius: 0; }
  }

  /* =======================================================================
     Tabs
     ===================================================================== */

  .tabs {
    display: flex;
    gap: var(--s5);
    border-bottom: 1px solid var(--rule);
    margin-bottom: var(--s5);
    overflow-x: auto;
  }
  .tabs a {
    padding: var(--s3) 0;
    font-size: var(--t-base);
    color: var(--ink-muted);
    text-decoration: none;
    border-bottom: 2px solid transparent;
    margin-bottom: -1px;
    white-space: nowrap;
  }
  .tabs a:hover { color: var(--ink); }
  .tabs a[aria-current] { color: var(--brand); border-bottom-color: var(--brand); font-weight: 500; }
  .tabs .count { font-family: var(--font-mono); font-size: var(--t-xs); color: var(--ink-faint); margin-left: 0.25rem; }

  .tabs--resources {
    flex-wrap: wrap;
    gap: 0 var(--s3);
    margin: 0 var(--s5);
    overflow: visible;
  }
  .tabs--resources a {
    min-width: 0;
    margin-bottom: 0;
    font-size: var(--t-sm);
    white-space: normal;
  }

  /* =======================================================================
     Dashboard figures
     ===================================================================== */

  .tile {
    display: flex;
    flex-direction: column;
    gap: 0.25rem;
    padding: var(--s4);
    background: var(--surface);
    border: 1px solid var(--rule);
    border-radius: var(--r-lg);
    box-shadow: var(--shadow-1);
    text-decoration: none;
  }
  a.tile:hover { border-color: var(--brand); }
  .tile__label { font-size: var(--t-xs); font-weight: 600; letter-spacing: var(--track-label); text-transform: uppercase; color: var(--ink-faint); }
  .tile__value { font-family: var(--font-mono); font-size: var(--t-2xl); font-weight: 500; line-height: 1.05; font-variant-numeric: tabular-nums; letter-spacing: -0.02em; }
  .tile__note { font-size: var(--t-xs); color: var(--ink-muted); }

  /* =======================================================================
     Auth screens
     =======================================================================
     One card, centred on a plain ground. The card is the whole page: a navy
     brand band carrying the dealer's logo, the form on paper under it, and a
     small "powered by" foot naming the software.

     Every screen that extends layouts/auth uses this — sign-in, the two-factor
     challenge, enrollment and the recovery-code list — so the box has to hold
     a four-field form and a ten-item list equally well. It is sized by its
     content and only bounded in width.
     ===================================================================== */

  .auth {
    min-height: 100vh;
    min-height: 100dvh;
    display: flex;
    flex-direction: column;
    align-items: center;
    padding: var(--s6) var(--s4);

    /* `safe center` for the enrollment screen, which is the tall one. Plain
       centring pushes overflow off the TOP of the viewport, where there is no
       scrollbar to bring it back — the recovery codes would be reachable and
       the heading above them would not. The unprefixed value is listed first
       as the fallback for anything that does not understand the keyword. */
    justify-content: center;
    justify-content: safe center;

    /* A single wash lifted from the brand, strongest behind the card and gone
       well before the edges. It gives the card a ground to sit on without
       introducing a second colour: at 7% the navy is a tint of the paper
       rather than a colour of its own.

       Mixed from --brand rather than written as a literal so it re-points with
       the theme. A fixed #000080 wash would darken the dark theme's ground
       instead of lifting it, which reads as a vignette — as though the corners
       of the page were dirty. The flat --paper on the line above is what a
       browser without color-mix falls back to. */
    background: var(--paper);
    background:
      radial-gradient(80rem 45rem at 50% -12rem,
        color-mix(in srgb, var(--brand) 7%, transparent), transparent 70%),
      var(--paper);
  }

  .auth__card {
    width: min(26rem, 100%);
    background: var(--surface);
    border: 1px solid var(--rule);
    border-radius: var(--r-lg);
    box-shadow: var(--shadow-3);

    /* The brand band is flush to the card's top corners, so the radius has to
       be clipped rather than inherited by a child that cannot know it. */
    overflow: hidden;
  }

  .auth__brand {
    display: flex;
    align-items: center;
    justify-content: center;
    padding: var(--s5);
    background: var(--brand);
  }

  /* Bounded on both axes. The artwork behind it is replaced per white-label
     install (see App\Support\Branding), so the band has to hold a lockup of
     any proportion — given only a width, a square logo would make this band
     three times as tall as the one it was drawn for.

     The pair is set so a 3:1 lockup — the shape most of them are — uses the
     full 13rem and is not also caught by the height cap. Anything taller than
     that is fitted inside the box rather than stretched, which is what
     `contain` is for: a squashed logo is the one defect a client notices on
     the first screen they are shown. */
  .auth__logo {
    width: min(13rem, 100%);
    max-height: 4.5rem;
    height: auto;
    object-fit: contain;
  }

  .auth__body { padding: var(--s6) var(--s5) var(--s5); }

  /* The product's own credit, ruled off under the form. Quiet on purpose:
     it names the software to somebody who wants to know and stays out of the
     way of somebody who is only trying to sign in. */
  .auth__powered {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: var(--s2);
    padding: var(--s3) var(--s5);
    border-top: 1px solid var(--rule);
    background: var(--surface-sunk);
    font-size: var(--t-xs);
    color: var(--ink-faint);
  }
  .auth__powered img { width: 1.125rem; height: 1.125rem; object-fit: contain; }
  .auth__powered strong { font-weight: 600; color: var(--ink-muted); }

  @media (max-width: 480px) {
    .auth { padding: var(--s4) var(--s3); }
    .auth__body { padding: var(--s5) var(--s4) var(--s4); }
  }

  /* Recovery codes, shown once after enrollment. Monospace and boxed so they
     survive being copied into a password manager or written down. */
  .codes {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(9rem, 1fr));
    gap: var(--s2);
    font-family: var(--font-mono);
    font-size: var(--t-base);
    letter-spacing: 0.04em;
  }
  .codes li {
    padding: 0.375rem 0.625rem;
    background: var(--surface-sunk);
    border: 1px solid var(--rule);
    border-radius: var(--r-sm);
    text-align: center;
  }

  .qr {
    display: grid;
    place-items: center;
    padding: var(--s3);
    background: #fff;
    border: 1px solid var(--rule-strong);
    border-radius: var(--r);
    width: fit-content;
  }
  /* The QR arrives as inline SVG that already carries its own fills — a white
     background rect and black modules. Do not restyle them: painting every
     rect black fills the background in too and produces a solid square. The
     white plate is here so it still scans in the dark theme. */
  .qr svg { display: block; }

  /* =======================================================================
     Timeline — comment threads and audit history
     ===================================================================== */

  .timeline { position: relative; padding-left: var(--s5); }
  .timeline::before {
    content: '';
    position: absolute;
    left: 0.4375rem; top: 0.5rem; bottom: 0.5rem;
    width: 1px;
    background: var(--rule);
  }
  .timeline__item { position: relative; padding-bottom: var(--s4); }
  .timeline__item::before {
    content: '';
    position: absolute;
    left: calc(-1 * var(--s5) + 0.25rem);
    top: 0.4375rem;
    width: 0.4375rem; height: 0.4375rem;
    border-radius: 50%;
    background: var(--rule-strong);
    box-shadow: 0 0 0 3px var(--surface);
  }
  .timeline__item[data-signal="brand"]::before { background: var(--brand); }
  .timeline__meta { font-size: var(--t-xs); color: var(--ink-faint); }

  /* =======================================================================
     Loading
     ===================================================================== */

  [aria-busy="true"] { position: relative; }
  [aria-busy="true"]::after {
    content: '';
    position: absolute;
    inset: 0;
    background: color-mix(in srgb, var(--surface) 55%, transparent);
    cursor: progress;
  }
}

@layer components {

  /* =======================================================================
     Attachments
     ===================================================================== */

  .files {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(9rem, 1fr));
    gap: var(--s3);
  }

  .file { position: relative; }

  .file__link {
    display: flex;
    flex-direction: column;
    gap: 0.25rem;
    padding: var(--s2);
    border: 1px solid var(--rule);
    border-radius: var(--r);
    background: var(--surface-sunk);
    text-decoration: none;
    color: var(--ink);
  }
  .file__link:hover { border-color: var(--brand); }

  .file__thumb {
    display: grid;
    place-items: center;
    width: 100%;
    aspect-ratio: 4 / 3;
    object-fit: cover;
    border-radius: var(--r-sm);
    background: var(--surface-alt);
    color: var(--ink-faint);
  }
  .file__thumb--doc svg { width: 1.75rem; height: 1.75rem; }

  .file__name {
    font-size: var(--t-xs);
    font-weight: 500;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
  }
  .file__meta {
    font-size: var(--t-2xs);
    color: var(--ink-faint);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
  }

  /* The delete control sits over the corner of the tile rather than below it,
     so a grid of eight files does not become a grid of eight files and eight
     buttons. */
  .file__remove { position: absolute; top: 0.375rem; right: 0.375rem; }
  .file__remove .btn {
    background: color-mix(in srgb, var(--surface) 85%, transparent);
    backdrop-filter: blur(2px);
  }

  /* =======================================================================
     Serial picker
     ===================================================================== */

  .serial-picker {
    max-height: 12rem;
    overflow-y: auto;
    padding: var(--s2);
    border: 1px solid var(--rule-strong);
    border-radius: var(--r);
    background: var(--surface-sunk);
  }

  .serial-picker__row {
    display: flex;
    align-items: center;
    gap: var(--s2);
    padding: 0.1875rem 0.25rem;
    border-radius: var(--r-sm);
  }
  .serial-picker__row:hover { background: var(--surface-alt); }

  /* Scanning and ticking act on the same checkboxes — there is one list, and
     the mode only decides how much of it is on screen. In scan mode the list
     shows what has been scanned so far, and unticking a row is how you take a
     unit back off, so the checkbox stays the control in both modes. */
  [data-serial-mode="scan"] .serial-picker__row:not(:has(:checked)) { display: none; }

  [data-serial-mode="scan"] .serial-picker { max-height: 9rem; }

  /* Nothing scanned yet is not worth an empty bordered box. Guarded on the
     list actually holding checkboxes, so the messages that appear in its place
     — "loading", "no units available here" — are still shown. */
  [data-serial-mode="scan"] .serial-picker:has(input[type="checkbox"]):not(:has(:checked)) {
    display: none;
  }

  .scan { display: flex; flex-direction: column; gap: 0.3125rem; }

  .scan__field {
    display: flex;
    align-items: center;
    gap: var(--s2);
    padding: 0.25rem 0.5rem;
    border: 1px solid var(--brand);
    border-radius: var(--r);
    background: var(--surface);
    box-shadow: 0 0 0 3px color-mix(in srgb, var(--brand) 12%, transparent);
  }

  /* The box is already outlined as the live target; a second ring on focus
     just makes it flicker as the scanner fires. */
  .scan__field .input {
    border: 0;
    padding: 0.1875rem 0;
    background: none;
  }
  .scan__field .input:focus { box-shadow: none; }
  .scan__field .icon { flex: none; color: var(--brand); }
  .scan__field .btn { flex: none; }

  .scan__say { font-size: var(--t-xs); min-height: 1rem; color: var(--ink-faint); }
  .scan__say[data-tone="ok"]   { color: var(--ok); }
  .scan__say[data-tone="warn"] { color: var(--warn); }
  .scan__say[data-tone="bad"]  { color: var(--danger); }

  /* =======================================================================
     Dispatch board
     ===================================================================== */

  /* Eight columns have to fit a laptop screen, because a week you have to
     scroll sideways to see is not a week you can plan against. The day columns
     are sized to just fit at 1440px and scroll below that. */
  .board {
    display: grid;
    grid-template-columns: 13rem repeat(7, minmax(7.5rem, 1fr));
    gap: var(--s2);
    align-items: start;
    overflow-x: auto;
    padding-bottom: var(--s3);
  }

  .board__column {
    min-width: 0;
    background: var(--surface);
    border: 1px solid var(--rule);
    border-radius: var(--r-lg);
    box-shadow: var(--shadow-1);
  }

  /* Today is marked by its heading, not by tinting the whole column — a
     coloured column would compete with the priority colours of the jobs in it,
     and those are the ones that matter. */
  .board__head {
    padding: var(--s3);
    border-bottom: 1px solid var(--rule);
  }
  .board__head[data-today] { border-bottom-color: var(--brand); box-shadow: inset 0 3px 0 var(--brand); }

  .board__day { font-size: var(--t-xs); font-weight: 600; letter-spacing: var(--track-label); text-transform: uppercase; color: var(--ink-faint); }
  .board__date { font-family: var(--font-mono); font-size: var(--t-md); font-weight: 500; }

  .board__list { padding: var(--s2); display: flex; flex-direction: column; gap: var(--s2); min-height: 4rem; }

  .board__job {
    display: block;
    padding: var(--s2);
    border: 1px solid var(--rule);
    border-left: 3px solid var(--neutral);
    border-radius: var(--r-sm);
    background: var(--surface-sunk);
    text-decoration: none;
    color: var(--ink);
    font-size: var(--t-sm);
  }
  .board__job:hover { border-color: var(--brand); }
  .board__job[data-signal="danger"] { border-left-color: var(--danger); }
  .board__job[data-signal="warn"] { border-left-color: var(--warn); }
  .board__job[data-signal="brand"] { border-left-color: var(--brand); }
  .board__job[data-signal="ok"] { border-left-color: var(--ok); }
  .board__job[data-signal="info"] { border-left-color: var(--info); }

  .board__time { font-family: var(--font-mono); font-size: var(--t-xs); color: var(--ink-faint); }
  .board__title { font-weight: 500; display: block; }
  .board__where { font-size: var(--t-xs); color: var(--ink-muted); display: block; }
}

@layer components {

  /* =======================================================================
     Choice cards
     =======================================================================
     For a decision with two or three answers that change the rest of the form.
     A select would hide the options behind a click; these state the trade-off
     where it can be read.
     ===================================================================== */

  .choice {
    display: flex;
    align-items: flex-start;
    gap: var(--s2);
    flex: 1 1 16rem;
    padding: var(--s3);
    border: 1px solid var(--rule-strong);
    border-radius: var(--r);
    background: var(--surface);
    cursor: pointer;
    transition: border-color 0.12s var(--ease), background-color 0.12s var(--ease);
  }
  .enrollment-choice-list > .choice { flex: none; }
  .choice:hover { border-color: var(--ink-faint); }

  /* :has() rather than a JS class — the selected state follows the radio
     itself, so it cannot fall out of step with what will actually be posted. */
  .choice:has(input:checked) {
    border-color: var(--brand);
    background: var(--brand-tint);
  }
  .choice:has(input:focus-visible) { box-shadow: var(--focus); }

  .choice input { margin-top: 0.1875rem; accent-color: var(--brand); }
  .choice strong { display: block; font-weight: 600; }
  .choice__hint { display: block; font-size: var(--t-xs); color: var(--ink-muted); margin-top: 0.125rem; }

  /* =======================================================================
     Document summary strip — the facts of a printed document, on screen
     ===================================================================== */

  .docfacts {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(9rem, 1fr));
    gap: 0;
    border: 1px solid var(--rule);
    border-radius: var(--r-lg);
    overflow: hidden;
    background: var(--surface);
  }

  .docfacts > div {
    padding: var(--s3) var(--s4);
    border-right: 1px solid var(--rule);
  }
  .docfacts > div:last-child { border-right: 0; }

  .docfacts dt {
    font-size: var(--t-2xs);
    font-weight: 600;
    letter-spacing: var(--track-label);
    text-transform: uppercase;
    color: var(--ink-faint);
  }
  .docfacts dd { font-size: var(--t-base); font-weight: 500; margin-top: 0.125rem; }
}

@layer components {

  /* =======================================================================
     Report index cards
     ===================================================================== */

  .report-card {
    display: flex;
    flex-direction: column;
    gap: 0.25rem;
    padding: var(--s4);
    background: var(--surface);
    border: 1px solid var(--rule);
    border-left: 3px solid var(--rule-strong);
    border-radius: var(--r-lg);
    box-shadow: var(--shadow-1);
    text-decoration: none;
    color: var(--ink);
    transition: border-color 0.12s var(--ease), transform 0.06s var(--ease);
  }
  .report-card:hover { border-left-color: var(--brand); border-color: var(--rule-strong); }
  .report-card:active { transform: translateY(0.5px); }

  .report-card__title { font-weight: 600; }
  .report-card__desc { font-size: var(--t-sm); color: var(--ink-muted); }

  /* =======================================================================
     Bar chart
     =======================================================================
     Boxes, not SVG — see the component for why. Each row carries its number
     as text beside the bar, so the chart reads in greyscale and to a screen
     reader, and the bar length is the redundant part rather than the only
     part.
     ===================================================================== */

  .bars { display: flex; flex-direction: column; gap: 0.375rem; }

  .bars__row {
    display: grid;
    grid-template-columns: minmax(6rem, 12rem) minmax(0, 1fr) minmax(4rem, auto);
    align-items: center;
    gap: var(--s3);
    font-size: var(--t-sm);
  }

  .bars__label {
    color: var(--ink-muted);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
  }

  .bars__track {
    height: 1.125rem;
    background: var(--surface-alt);
    border-radius: var(--r-sm);
    overflow: hidden;
  }

  .bars__fill {
    display: block;
    height: 100%;
    background: var(--brand);
    border-radius: var(--r-sm);
    min-width: 2px;
  }

  .bars__value {
    font-family: var(--font-mono);
    font-size: var(--t-xs);
    color: var(--ink-muted);
    text-align: right;
    white-space: nowrap;
  }

  @media (max-width: 640px) {
    .bars__row { grid-template-columns: minmax(0, 1fr) minmax(3.5rem, auto); }
    .bars__track { grid-column: 1 / -1; order: 3; }
  }
}

@layer components {

  /* =======================================================================
     Error pages
     ===================================================================== */

  .errorpage {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: var(--s4);
    min-height: 100vh;
    padding: clamp(var(--s4), 6vw, var(--s8));
    background: var(--paper);
  }

  .errorpage__brand {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-height: 3.5rem;
    margin-bottom: var(--s2);
  }

  .errorpage__logo {
    display: block;
    width: auto;
    max-width: min(17rem, 70vw);
    height: auto;
    max-height: 3.5rem;
    object-fit: contain;
  }

  /* Dealer artwork that sits on the page background rather than on navy:
     dark lettering in the light theme, light lettering in the dark one. Keyed
     to the same two switches as tokens.css — the OS preference unless the
     person picked a theme, and their pick when they did. */
  img.brand-art--on-dark { display: none; }

  @media (prefers-color-scheme: dark) {
    :root:not([data-theme="light"]) img.brand-art--on-light { display: none; }
    :root:not([data-theme="light"]) img.brand-art--on-dark { display: block; }
  }

  :root[data-theme="dark"] img.brand-art--on-light { display: none; }
  :root[data-theme="dark"] img.brand-art--on-dark { display: block; }

  .errorpage__card {
    width: min(38rem, 100%);
    padding: clamp(var(--s5), 6vw, var(--s7));
    background: var(--surface);
    border: 1px solid var(--rule);
    border-top: 2px solid var(--brand);
    border-radius: var(--r-xl);
    box-shadow: var(--shadow-3);
  }

  .errorpage__eyebrow {
    display: flex;
    align-items: center;
    gap: var(--s2);
    color: var(--ink-muted);
    font-size: var(--t-xs);
    font-weight: 600;
    letter-spacing: var(--track-label);
    text-transform: uppercase;
  }

  .errorpage__indicator {
    width: .5rem;
    height: .5rem;
    flex: 0 0 auto;
    border-radius: 50%;
    background: var(--danger);
    box-shadow: 0 0 0 .25rem var(--danger-tint);
  }

  .errorpage__code {
    margin-left: auto;
    font-family: var(--font-mono);
    font-size: var(--t-sm);
    font-weight: 600;
    letter-spacing: var(--track-label);
    color: var(--brand);
  }

  .errorpage__title { font-size: clamp(var(--t-xl), 4vw, var(--t-2xl)); line-height: 1.2; margin: var(--s4) 0 var(--s3); }
  .errorpage__body { max-width: 54ch; color: var(--ink-muted); line-height: 1.65; }
  .errorpage__foot { display: flex; flex-wrap: wrap; justify-content: center; gap: var(--s2); font-size: var(--t-xs); color: var(--ink-faint); }
  .errorpage__product { padding-left: var(--s2); border-left: 1px solid var(--rule-strong); }

  @media (max-width: 480px) {
    .errorpage { justify-content: flex-start; padding-top: 12vh; }
    .errorpage__card { padding: var(--s5); }
    .errorpage .row { align-items: stretch; flex-direction: column; }
  }
}

@layer components {

  /* =======================================================================
     Grouped report tables
     =======================================================================
     A group heading is a ruled band rather than a tinted row: the tint would
     compete with the status colours in the rows beneath it, and the rule
     survives being printed in mono.
     ===================================================================== */

  .table .group-row th {
    position: static;
    padding-top: var(--s4);
    background: var(--surface);
    border-bottom: 1px solid var(--ink);
    color: var(--brand);
    font-size: var(--t-sm);
    letter-spacing: 0;
    text-transform: none;
  }

  .table tbody:first-of-type .group-row th { padding-top: var(--s3); }

  .group-row__name { font-weight: 600; }
  .group-row__count {
    margin-left: var(--s2);
    font-weight: 400;
    color: var(--ink-faint);
    font-size: var(--t-xs);
  }

  .table .group-total td {
    font-family: var(--font-mono);
    font-weight: 600;
    background: var(--surface-sunk);
    border-top: 1px solid var(--rule-strong);
    border-bottom: 1px solid var(--rule-strong);
  }

  /* A grouped report is a wide table. Below its natural width it would keep
     shrinking until a notes cell wrapped to ten lines and every row in the
     table inherited that height — so it stops shrinking and .table-wrap
     scrolls instead, which is the behaviour the wrapper is there for. */
  .table--wide { min-width: 58rem; }

  .table .group-total--grand td {
    border-top: 2px solid var(--ink);
    background: var(--surface-alt);
    font-weight: 700;
  }
}

/* Persistent browser shells: the editable command line shares the terminal viewport. */
.rmm-terminal{background:#0b1018;color:#d7e2ef;border:1px solid var(--rule-strong);border-radius:var(--r-lg);overflow:hidden}
.rmm-terminal__head{display:flex;align-items:center;gap:1rem;background:#141c28;padding:.7rem 1rem;font-size:.85rem;border-bottom:1px solid #293445}
.rmm-terminal__head span{margin-left:auto;color:#96a9bf}
.rmm-terminal__head button{color:#bdcddd;background:transparent;border:1px solid #344155;border-radius:.3rem;padding:.2rem .65rem;cursor:pointer}
.rmm-terminal__viewport{height:420px;min-height:240px;overflow:auto;padding:1rem;cursor:text;font-family:'IBM Plex Mono',Consolas,monospace;font-size:13px;line-height:1.55;scrollbar-color:#344155 #0b1018}
.rmm-terminal__output{margin:0;font:inherit;white-space:pre-wrap;overflow-wrap:anywhere;background:none;border:0;padding:0;color:inherit}
.rmm-terminal__line{display:flex;align-items:flex-start;gap:.35rem;min-height:1.55em}
.rmm-terminal__line span{white-space:pre-wrap;color:#7bd3a7;flex-shrink:0}
.rmm-terminal__line textarea{border:0;border-radius:0;outline:0;box-shadow:none;resize:none;padding:0;margin:0;background:transparent;color:inherit;caret-color:#d7e2ef;font:inherit;line-height:inherit;width:100%;min-width:0;min-height:1.55em}
.rmm-terminal__line textarea:disabled{opacity:.45}
.rmm-terminal__foot{border-top:1px solid #293445;padding:.5rem 1rem;font-size:.75rem;color:#96a9bf}

/* Messenger attachments */
@layer components {
  .chat__files:empty { display: none; }
  .chat__files { display: grid; gap: .375rem; margin-bottom: .75rem; }
  .chat__file { display: flex; align-items: center; justify-content: space-between; gap: .75rem; padding: .375rem .75rem; border: 1px solid var(--rule); border-radius: var(--r); }
  .chat__file > span { overflow-wrap: anywhere; min-width: 0; }
  .chat__attachment { margin-block: .75rem; }
  .chat__picture { display: block; max-width: min(100%, 360px); max-height: 260px; object-fit: contain; border-radius: .5rem; margin-bottom: .5rem; }
  .chat__download { display: block; overflow-wrap: anywhere; font-size: .8125rem; color: inherit; text-decoration: underline; }
}

/* =========================================================================
   The record screen — a service ticket, and the new-ticket form shaped like it
   =========================================================================
   Laid out the way the big service desks lay a ticket out, because that is
   what technicians arriving from one already read without thinking: a header
   bar with the number and the toolbar, the summary under it, a tab strip, then
   the record on the left — company and caller FIRST, then the ticket's own
   fields — and what was reported and said on the right.

   Fields sit beside their labels rather than under them (`.lf`). It is denser,
   and on a form people scan rather than fill top to bottom, a right-aligned
   label column is what lets the eye run straight down the values.
   ========================================================================= */

@layer components {

  .record { display: flex; flex-direction: column; gap: var(--s4); }

  /* --- header bar ----------------------------------------------------- */

  .record__bar {
    display: flex;
    flex-direction: column;
    gap: var(--s3);
    padding: var(--s3) var(--s4) var(--s4);
    background: var(--surface);
    border: 1px solid var(--rule);
    border-left: 4px solid var(--brand);
    border-radius: var(--r-lg);
    box-shadow: var(--shadow-1);
  }

  .record__top { display: flex; align-items: center; gap: var(--s4); flex-wrap: wrap; }

  .record__ident { display: flex; flex-direction: column; gap: 0.25rem; min-width: 0; }

  .record__kind {
    font-size: var(--t-xs);
    font-weight: 600;
    letter-spacing: var(--track-label);
    text-transform: uppercase;
    color: var(--ink-faint);
  }

  .record__title { font-size: var(--t-lg); line-height: var(--lh-tight); display: flex; align-items: center; gap: var(--s2); }

  /* The plate a number will be printed in, before there is a number. */
  .docno--pending { font-family: var(--font-sans); letter-spacing: 0; color: var(--ink-muted); }

  .record__meta { display: flex; align-items: center; gap: var(--s2); flex-wrap: wrap; font-size: var(--t-sm); }
  .record__age { color: var(--ink-muted); }
  .record__age strong { color: var(--ink); font-weight: 600; }

  .record__tools { margin-left: auto; display: flex; align-items: center; gap: var(--s2); flex-wrap: wrap; }
  .record__tools form { display: contents; }
  .record__tools .btn:disabled { opacity: 0.45; cursor: not-allowed; }

  /* The summary is the ticket's title, so it runs the full width of the bar
     under the number — a small label above it rather than a label column
     pushing it in from the left. */
  .record__summary {
    display: flex;
    flex-direction: column;
    gap: 0.3125rem;
    padding-top: var(--s3);
    border-top: 1px solid var(--rule);
  }
  .record__summary-label {
    font-size: var(--t-xs);
    font-weight: 600;
    letter-spacing: var(--track-label);
    text-transform: uppercase;
    color: var(--ink-faint);
  }
  .record__summary-label .req { color: var(--danger); margin-left: 0.125rem; }
  .record__summary-input { font-size: var(--t-md); font-weight: 500; padding-block: 0.5625rem; }
  .record__summary-input::placeholder { font-weight: 400; }

  @media (max-width: 820px) {
    .record__tools { margin-left: 0; }
  }

  /* --- tabs ------------------------------------------------------------ */

  /* overflow-y: the active tab's -1px margin otherwise counts as overflow and
     draws a scrollbar beside a strip that never needs one vertically. */
  .record__tabs { margin-bottom: 0; padding-inline: var(--s2); overflow-y: hidden; }
  .record__tabs .tabs__off { padding: var(--s3) 0; font-size: var(--t-base); color: var(--ink-faint); opacity: 0.6; cursor: not-allowed; white-space: nowrap; }

  /* --- two columns ------------------------------------------------------ */

  .record__grid {
    display: grid;
    grid-template-columns: minmax(0, 1.35fr) minmax(0, 1fr);
    gap: var(--s4);
    align-items: start;
  }
  .record__grid[hidden], .record__panel[hidden] { display: none; }

  @media (max-width: 1180px) {
    .record__grid { grid-template-columns: minmax(0, 1fr); }
  }


  /* --- collapsible sections ---------------------------------------------- */

  .section > .section__head {
    display: flex;
    align-items: center;
    gap: var(--s2);
    padding: 0.625rem var(--s4);
    list-style: none;
    cursor: pointer;
    user-select: none;
    font-size: var(--t-base);
    border-radius: var(--r-lg);
  }
  .section > .section__head::-webkit-details-marker { display: none; }
  .section > .section__head:hover { background: var(--surface-sunk); }
  .section > .section__head:focus-visible { outline: none; box-shadow: var(--focus); }
  .section[open] > .section__head { border-bottom: 1px solid var(--rule); border-radius: var(--r-lg) var(--r-lg) 0 0; }
  .section__head > svg:first-child { color: var(--brand-lift); flex: none; }
  .section__label { color: var(--ink-muted); font-weight: 500; }
  .section__name { font-weight: 600; color: var(--ink); min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  .section__link { margin-left: var(--s2); font-size: var(--t-xs); white-space: nowrap; }
  .section__chevron { margin-left: auto; color: var(--ink-faint); flex: none; transition: transform 0.15s var(--ease); }
  .section:not([open]) .section__chevron { transform: rotate(-90deg); }

  .section__body { padding: var(--s4); container-type: inline-size; }

  /* --- label-beside-field rows ------------------------------------------ */

  .lfields {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 0.5rem var(--s5);
  }

  .lf {
    display: grid;
    grid-template-columns: 6.25rem minmax(0, 1fr);
    align-items: center;
    column-gap: var(--s3);
    row-gap: 0.25rem;
    min-width: 0;
  }
  .lf > .field__error, .lf > .field__hint { grid-column: 2; }

  .lf__label {
    font-size: var(--t-sm);
    color: var(--ink-muted);
    text-align: right;
    line-height: var(--lh-snug);
  }
  .lf__label .req { color: var(--danger); margin-left: 0.125rem; }

  .lf__value { font-size: var(--t-base); padding: 0.3125rem 0; min-width: 0; overflow-wrap: anywhere; }

  .lf__control { display: flex; align-items: center; gap: 0.375rem; min-width: 0; }
  .lf__control > :first-child { flex: 1; min-width: 0; }
  .lf__control > .btn[hidden] { display: none; }

  /* A phone number is read aloud digit by digit, hence the mono face — but
     the full document tracking makes "(413) 555-0110" too wide for a half-
     column, and a number cut off at the box edge is a number misread. */
  .lf .input--mono { letter-spacing: 0.01em; }
  .lf .input::placeholder { font-family: var(--font-sans); letter-spacing: normal; }

  /* What cannot be changed here should not look like a box to type in. */
  .lf .input[readonly], .lf .input:disabled, .lf .select:disabled {
    background: var(--surface-sunk);
    color: var(--ink-muted);
  }


  .lf-hint { margin-top: var(--s3); padding-left: calc(6.25rem + var(--s3)); }

  /* Narrow column (or a laptop with both columns side by side): one field per
     row. Narrower still: the label goes back above the field. A container
     query, because the same section sits in a wide column on a desktop and a
     narrow one beside the notes. */
  @container (max-width: 40rem) {
    .lfields { grid-template-columns: minmax(0, 1fr); }
  }
  @container (max-width: 26rem) {
    .lf { grid-template-columns: minmax(0, 1fr); }
    .lf > .field__error, .lf > .field__hint { grid-column: 1; }
    .lf__label { text-align: left; font-size: var(--t-xs); font-weight: 600; letter-spacing: var(--track-label); text-transform: uppercase; }
    .lf-hint { padding-left: 0; }
  }

  /* --- a caller who is not on file -------------------------------------- */

  .newcaller {
    margin-top: var(--s4);
    border: 1px dashed var(--rule-strong);
    border-radius: var(--r);
  }
  .newcaller[open] { border-style: solid; background: var(--surface-sunk); }
  .newcaller__toggle {
    display: flex;
    align-items: center;
    gap: var(--s2);
    padding: 0.5rem var(--s3);
    font-size: var(--t-sm);
    font-weight: 500;
    color: var(--brand-lift);
    list-style: none;
    cursor: pointer;
  }
  .newcaller__toggle::-webkit-details-marker { display: none; }
  .newcaller__toggle:focus-visible { outline: none; box-shadow: var(--focus); border-radius: var(--r); }
  .newcaller__body { padding: var(--s2) var(--s3) 0; }
  .newcaller > .lf-hint { padding: 0 var(--s3) var(--s3); padding-left: calc(6.25rem + var(--s3) * 2); }
  @container (max-width: 26rem) { .newcaller > .lf-hint { padding-left: var(--s3); } }

  /* --- initial description ---------------------------------------------- */

  .desc { border-top: 3px solid var(--brand); }
  .desc .card__head { background: var(--brand-tint); border-radius: calc(var(--r-lg) - 1px) calc(var(--r-lg) - 1px) 0 0; }
  .desc__box {
    display: block;
    min-height: 7rem;
    border: 0;
    border-radius: 0 0 var(--r-lg) var(--r-lg);
    padding: var(--s4);
    resize: vertical;
    box-shadow: none;
  }
  .desc__box:focus { box-shadow: inset 0 0 0 2px var(--brand-lift); }

  /* --- notes -------------------------------------------------------------- */

  .notes .card__head { flex-wrap: wrap; }

  .seg {
    display: inline-flex;
    margin-left: auto;
    border: 1px solid var(--rule-strong);
    border-radius: var(--r);
    overflow: hidden;
  }
  .seg[hidden] { display: none; }
  .seg__btn {
    padding: 0.25rem 0.625rem;
    font-size: var(--t-xs);
    font-weight: 500;
    color: var(--ink-muted);
    background: var(--surface);
    border: 0;
    border-left: 1px solid var(--rule);
    cursor: pointer;
  }
  .seg__btn:first-child { border-left: 0; }
  .seg__btn:hover { color: var(--ink); background: var(--surface-sunk); }
  .seg__btn[aria-pressed="true"] { color: var(--brand); background: var(--brand-tint); font-weight: 600; }
  .seg__btn:focus-visible { outline: none; box-shadow: inset var(--focus); }
  .seg__btn .count { font-family: var(--font-mono); opacity: 0.75; margin-left: 0.125rem; }

  .composer { display: flex; flex-direction: column; gap: var(--s2); }
  .composer__kinds { display: flex; gap: var(--s2); flex-wrap: wrap; }
  .composer__kind { cursor: pointer; }
  .composer__kind input { position: absolute; opacity: 0; pointer-events: none; }
  .composer__kind > span {
    display: inline-flex;
    align-items: center;
    gap: 0.375rem;
    padding: 0.3125rem 0.625rem;
    font-size: var(--t-sm);
    color: var(--ink-muted);
    border: 1px solid var(--rule-strong);
    border-radius: var(--r);
    background: var(--surface);
  }
  .composer__kind:hover > span { color: var(--ink); }
  .composer__kind input:focus-visible + span { box-shadow: var(--focus); }
  .composer__kind input:checked + span,
  .composer__kind--only > span { color: var(--ink); font-weight: 600; border-color: var(--ink-faint); background: var(--surface-alt); }
  .composer__kind input[value="public"]:checked + span { color: var(--brand); border-color: var(--brand); background: var(--brand-tint); }
  .composer__box { min-height: 4.5rem; }
  /* The box says which kind of note is about to be posted, so a customer-
     facing reply is never typed into what looks like the internal one. */
  .composer:has(input[value="public"]:checked) .composer__box { border-color: var(--brand); }

  /* One note. Discussion carries the brand edge — it is what left the
     building — and internal the neutral one. The words in the pill say the
     same thing, so nothing here depends on the hue being seen. */
  .entry {
    border: 1px solid var(--rule);
    border-left: 3px solid var(--neutral);
    border-radius: var(--r);
    background: var(--surface-sunk);
  }
  .entry[hidden] { display: none; }
  .entry[data-visibility="public"] { border-left-color: var(--brand); background: color-mix(in srgb, var(--brand-tint) 55%, var(--surface)); }
  .entry__head {
    display: flex;
    align-items: center;
    gap: var(--s2);
    padding: 0.5rem var(--s3);
    border-bottom: 1px solid var(--rule);
  }
  .entry__who { display: flex; flex-direction: column; line-height: var(--lh-snug); min-width: 0; font-size: var(--t-sm); }
  .entry__when { font-size: var(--t-xs); color: var(--ink-faint); }
  .entry__tags { margin-left: auto; display: flex; align-items: center; gap: 0.375rem; flex-wrap: wrap; justify-content: flex-end; }
  .entry__body { padding: 0.625rem var(--s3); white-space: pre-wrap; overflow-wrap: anywhere; font-size: var(--t-base); }

  /* --- caller context ----------------------------------------------------- */

  [data-caller-context][aria-busy="true"] { opacity: 0.55; transition: opacity 0.15s var(--ease); }

  .ctx-empty { display: flex; gap: var(--s3); align-items: center; color: var(--ink-faint); font-size: var(--t-sm); }
  .ctx-notes { border-left: 3px solid var(--brand); }

  .ctx-list { list-style: none; margin: 0; padding: 0; }
  .ctx-list li { padding: 0.5rem var(--s4); border-bottom: 1px solid var(--rule); }
  .ctx-list li:last-child { border-bottom: 0; }
  .ctx-list__row { display: flex; align-items: center; gap: var(--s2); text-decoration: none; color: inherit; min-width: 0; }
  .ctx-list__row:hover .ctx-list__text { text-decoration: underline; }
  .ctx-list__text { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: var(--t-sm); }
  .ctx-list__meta { display: block; font-size: var(--t-xs); color: var(--ink-faint); margin-top: 0.125rem; }
}

@layer components {
  /* A fieldset's default min-width is its content's, which lets one long
     select push the whole left column wider than its grid track. */
  .record fieldset { min-width: 0; margin: 0; }
}

/* -------------------------------------------------------------------------
   Record screen — the quiet layer
   -------------------------------------------------------------------------
   The record screens are where people spend the day, so they carry as little
   ornament as possible: hairline rules instead of shadows, no decorative
   icons in headings, no tinted bands. Colour is left to the things that MEAN
   something — status, priority, due, and the edge that marks a note as said
   to the customer — so it is never competing with itself.
   ------------------------------------------------------------------------- */
@layer components {
  .record .card,
  .record__bar { box-shadow: none; }

  .record__bar { border-left-width: 1px; }

  .record .card__head { padding-block: 0.75rem; }
  .record .card__head > svg:first-child { display: none; }
  .record .card__title { font-size: var(--t-sm); font-weight: 600; letter-spacing: 0.01em; }

  .section > .section__head { padding-block: 0.75rem; }
  .section__label { font-size: var(--t-sm); }
  .section__name { font-size: var(--t-sm); }

  .desc { border-top-width: 1px; border-top-color: var(--rule); }
  .desc .card__head { background: none; }

  .ctx-notes { border-left-width: 1px; border-left-color: var(--rule); }

  .entry,
  .entry[data-visibility="public"] { background: var(--surface); }
  .entry { border-left-width: 2px; border-left-color: var(--rule-strong); }
  .entry[data-visibility="public"] { border-left-color: var(--brand-lift); }
  .entry__head { border-bottom: 0; padding-bottom: 0; }
  .entry__body { padding-top: 0.375rem; }

  .entry--system {
    display: flex;
    gap: var(--s3);
    justify-content: space-between;
    align-items: baseline;
    padding: 0.375rem var(--s3);
    font-size: var(--t-xs);
    color: var(--ink-muted);
    border: 0;
    border-left: 2px solid transparent;
    background: none;
  }
  .entry--system strong { color: var(--ink); font-weight: 600; }

  .notes__empty { font-size: var(--t-sm); color: var(--ink-faint); }

  .composer__kind > span { padding: 0.25rem 0.625rem; font-size: var(--t-xs); }

  .record__tabs a, .record__tabs .tabs__off { font-size: var(--t-sm); }
}

@layer components {
  /* The active tab, the pressed filter and the chosen note kind are said in
     ink with a brand rule, not in brand-coloured text: navy type disappears
     on the dark theme's ground, and the rule carries the state on its own. */
  .record__tabs a[aria-current] { color: var(--ink); border-bottom-color: var(--brand-lift); font-weight: 600; }
  .seg__btn[aria-pressed="true"] { color: var(--ink); background: var(--surface-alt); }
  .composer__kind input[value="public"]:checked + span { color: var(--ink); border-color: var(--brand-lift); background: var(--surface-alt); }
  .record .tabs--resources a[aria-current] { color: var(--ink); }

  .entry--system .entry__when { white-space: nowrap; flex: none; }

  /* The resources editor brings its own "Resources" label for the long-form
     page; inside a card already titled Resources it would say it twice. */
  .record .card [data-resource-schedules] > .field__label { display: none; }
}

/* =========================================================================
   Configuration
   =========================================================================
   One area for every administrative screen: a categorized menu on the left,
   the screen on the right. The menu is a list of plain links, grouped under
   small headings, so it reads like a settings app rather than a second
   sidebar. App Settings (Flagship Command's own controls) sits last, set off
   by a rule.
   ========================================================================= */
@layer components {
  .config {
    display: grid;
    grid-template-columns: 14rem minmax(0, 1fr);
    gap: var(--s6);
    align-items: start;
  }

  .config__nav {
    position: sticky;
    top: calc(var(--topbar-h) + var(--s4));
    display: flex;
    flex-direction: column;
    gap: var(--s4);
    font-size: var(--t-sm);
  }

  .config__home {
    display: flex;
    align-items: center;
    gap: var(--s2);
    padding: 0.375rem 0.625rem;
    font-weight: 600;
    color: var(--ink);
    text-decoration: none;
    border-radius: var(--r);
  }

  .config__group { display: flex; flex-direction: column; gap: 1px; }
  .config__group--app { padding-top: var(--s4); border-top: 1px solid var(--rule); }

  .config__heading {
    padding: 0 0.625rem 0.25rem;
    font-size: var(--t-xs);
    font-weight: 600;
    letter-spacing: var(--track-label);
    text-transform: uppercase;
    color: var(--ink-faint);
  }

  .config__link {
    padding: 0.375rem 0.625rem;
    color: var(--ink-muted);
    text-decoration: none;
    border-radius: var(--r);
    border-left: 2px solid transparent;
  }
  .config__link:hover, .config__home:hover { color: var(--ink); background: var(--surface-alt); }
  .config__link[aria-current], .config__home[aria-current] {
    color: var(--ink);
    font-weight: 600;
    background: var(--surface);
    border-left-color: var(--brand-lift);
    border-radius: 0 var(--r) var(--r) 0;
  }

  .config__main { min-width: 0; }
  .config__main > .page__head { margin-bottom: var(--s5); }
  .config-narrow { max-width: 52rem; }
  .config .card { box-shadow: none; }

  @media (max-width: 960px) {
    .config { grid-template-columns: minmax(0, 1fr); gap: var(--s4); }
    /* On a narrow screen the menu becomes a wrapped row of links above the
       screen, rather than a column eating half the width. */
    .config__nav { position: static; flex-direction: row; flex-wrap: wrap; gap: var(--s2) var(--s4); }
    .config__group { flex-direction: row; flex-wrap: wrap; align-items: center; gap: var(--s1); }
    .config__group--app { padding-top: 0; border-top: 0; }
    .config__heading { width: 100%; padding-bottom: 0; }
  }

  /* --- overview ---------------------------------------------------------- */

  .config-overview {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(18rem, 1fr));
    gap: var(--s4);
  }
  .config-card--app { border-style: dashed; }
  .config-card__intro { font-size: var(--t-sm); color: var(--ink-muted); margin-bottom: var(--s3); }
  .config-card__list { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: var(--s3); }
  .config-card__list a { font-weight: 600; text-decoration: none; }
  .config-card__list a:hover { text-decoration: underline; }
  .config-card__list span { display: block; font-size: var(--t-xs); color: var(--ink-faint); margin-top: 0.125rem; }

  /* --- user groups --------------------------------------------------------- */

  .perm-meter {
    display: inline-block;
    width: 4.5rem;
    height: 0.375rem;
    margin-right: var(--s2);
    vertical-align: middle;
    background: var(--surface-alt);
    border-radius: 999px;
    overflow: hidden;
  }
  .perm-meter > span { display: block; height: 100%; background: var(--ink-muted); }

  .group-members {
    display: flex;
    flex-wrap: wrap;
    gap: var(--s2);
    align-items: baseline;
    margin-top: var(--s4);
    padding-top: var(--s4);
    border-top: 1px solid var(--rule);
    font-size: var(--t-sm);
  }

  .perm-toolbar { display: flex; align-items: flex-end; gap: var(--s4); flex-wrap: wrap; }
  .perm-toolbar__title { font-size: var(--t-lg); font-weight: 600; }
  .perm-toolbar__count { font-size: var(--t-sm); color: var(--ink-muted); }
  .perm-toolbar__count strong { color: var(--ink); font-family: var(--font-mono); }
  .perm-toolbar__tools { margin-left: auto; display: flex; gap: var(--s2); align-items: center; flex-wrap: wrap; }
  .perm-toolbar__tools[hidden] { display: none; }
  .perm-toolbar__tools .input { width: 16rem; }

  .perm-area[hidden] { display: none; }
  .perm-area > .perm-area__head {
    display: flex;
    align-items: center;
    gap: var(--s3);
    padding: 0.875rem var(--s4);
    cursor: pointer;
    list-style: none;
    border-radius: var(--r-lg);
  }
  .perm-area > .perm-area__head::-webkit-details-marker { display: none; }
  .perm-area > .perm-area__head:hover { background: var(--surface-sunk); }
  .perm-area > .perm-area__head:focus-visible { outline: none; box-shadow: var(--focus); }
  .perm-area[open] > .perm-area__head { border-bottom: 1px solid var(--rule); border-radius: var(--r-lg) var(--r-lg) 0 0; }
  .perm-area:not([open]) .section__chevron { transform: rotate(-90deg); }

  .perm-area__titles { display: flex; flex-direction: column; gap: 0.125rem; min-width: 0; }
  .perm-area__title { font-weight: 600; font-size: var(--t-base); }
  .perm-area__desc { font-size: var(--t-xs); color: var(--ink-faint); }

  .perm-area__count {
    margin-left: auto;
    font-size: var(--t-xs);
    font-family: var(--font-mono);
    color: var(--ink-muted);
    white-space: nowrap;
  }
  .perm-area__count[data-state="all"] { color: var(--ok); }
  .perm-area__count[data-state="none"] { color: var(--ink-faint); }

  .perm-area__body { padding: var(--s2) var(--s4) var(--s4); }
  .perm-area__bulk { display: flex; gap: var(--s2); justify-content: flex-end; padding: var(--s2) 0; }
  .perm-area__bulk[hidden] { display: none; }

  .perm-group[hidden] { display: none; }
  .perm-group__heading {
    margin-top: var(--s3);
    padding-bottom: 0.25rem;
    font-size: var(--t-xs);
    font-weight: 600;
    letter-spacing: var(--track-label);
    text-transform: uppercase;
    color: var(--ink-faint);
    border-bottom: 1px solid var(--rule);
  }

  .perm-row {
    display: flex;
    align-items: center;
    gap: var(--s4);
    padding: 0.625rem 0;
    border-bottom: 1px solid var(--rule);
  }
  .perm-row:last-child { border-bottom: 0; }
  .perm-row[hidden] { display: none; }

  .perm-row__text { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 0.125rem; }
  .perm-row__label { font-weight: 500; }
  .perm-row__desc { font-size: var(--t-sm); color: var(--ink-muted); }
  .perm-row__needs { font-size: var(--t-xs); color: var(--ink-faint); }
  .perm-row.is-locked .perm-row__label { color: var(--ink-muted); }

  /* Allow / Deny as one segmented control. Allow is filled when chosen — the
     state worth noticing on a long list — and Deny stays quiet. The word is
     always there, so nothing depends on seeing the colour. */
  .perm-switch {
    display: inline-flex;
    flex: none;
    border: 1px solid var(--rule-strong);
    border-radius: var(--r);
    overflow: hidden;
  }
  .perm-switch__opt { position: relative; cursor: pointer; }
  .perm-switch__opt input { position: absolute; opacity: 0; pointer-events: none; }
  .perm-switch__opt span {
    display: block;
    min-width: 4.25rem;
    padding: 0.3125rem 0.75rem;
    text-align: center;
    font-size: var(--t-sm);
    font-weight: 500;
    color: var(--ink-muted);
    background: var(--surface);
  }
  .perm-switch__opt + .perm-switch__opt span { border-left: 1px solid var(--rule-strong); }
  .perm-switch__opt:hover span { color: var(--ink); }
  .perm-switch__opt input:focus-visible + span { box-shadow: inset var(--focus); }
  .perm-switch__opt--allow input:checked + span { color: #fff; background: var(--ok); }
  .perm-switch__opt--deny input:checked + span { color: var(--ink); background: var(--surface-alt); }
  .perm-switch__opt input:disabled + span { cursor: not-allowed; opacity: 0.55; }

  @media (max-width: 560px) {
    .perm-row { flex-direction: column; align-items: stretch; gap: var(--s2); }
    .perm-switch { align-self: flex-start; }
    .perm-toolbar__tools .input { width: 100%; }
  }
}

/* =========================================================================
   RMM workspace (remote/partials/rmm-workspace) and the script library
   ========================================================================= */
@layer components {
  .rmm {
    margin-bottom: var(--s5);
    border: 1px solid var(--rule);
    border-radius: var(--r-lg);
    background: var(--surface);
    box-shadow: var(--shadow-1);
    overflow: hidden;
  }
  .rmm__bar {
    display: flex; align-items: center; gap: var(--s3);
    padding: 0.875rem 1rem;
  }
  .rmm.is-open .rmm__bar { border-bottom: 1px solid var(--rule); background: var(--surface-alt); }
  .rmm__mark {
    display: grid; place-items: center; flex: none;
    width: 2.25rem; height: 2.25rem; border-radius: var(--r);
    background: var(--brand-tint); color: var(--brand);
  }
  .rmm__mark svg { width: 1.125rem; height: 1.125rem; }
  .rmm__title { display: flex; flex-direction: column; min-width: 0; }
  .rmm__title strong { font-size: var(--t-md); color: var(--ink); }
  .rmm__title span { font-size: var(--t-sm); color: var(--ink-muted); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  .rmm__bar .spacer { flex: 1; }
  .rmm__body { padding: 1rem; display: flex; flex-direction: column; gap: 1rem; }
  .rmm__message { margin: 0; font-size: var(--t-xs); color: var(--ink-faint); }

  /* --- performance tiles ------------------------------------------------- */
  .rmm__kpis { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 0.75rem; }
  .rmm-kpi {
    padding: 0.75rem 0.875rem; border: 1px solid var(--rule); border-radius: var(--r);
    background: var(--surface-sunk); display: flex; flex-direction: column; gap: 0.375rem;
  }
  .rmm-kpi__head { display: flex; align-items: center; gap: 0.375rem; font-size: var(--t-xs); font-weight: 500; color: var(--ink-muted); text-transform: uppercase; letter-spacing: var(--track-label); }
  .rmm-kpi__head svg { color: var(--ink-faint); }
  .rmm-kpi__value { font-size: var(--t-xl); font-weight: 600; color: var(--ink); font-variant-numeric: tabular-nums; line-height: 1.1; }
  .rmm-kpi__meter { height: 0.3125rem; border-radius: 999px; background: color-mix(in srgb, var(--ink) 9%, transparent); overflow: hidden; }
  .rmm-kpi__meter span { display: block; height: 100%; width: 0; border-radius: inherit; background: var(--ok); transition: width 0.4s var(--ease); }
  .rmm-kpi[data-level="warn"] .rmm-kpi__meter span { background: var(--warn); }
  .rmm-kpi[data-level="high"] .rmm-kpi__meter span { background: var(--danger); }
  .rmm-kpi__detail { font-size: var(--t-xs); color: var(--ink-faint); min-height: 1.2em; }

  /* --- navigation + panes ------------------------------------------------- */
  .rmm__layout { display: grid; grid-template-columns: 11.5rem minmax(0, 1fr); gap: 1rem; align-items: start; }
  .rmm__nav { display: flex; flex-direction: column; gap: 0.125rem; position: sticky; top: calc(var(--topbar-h, 3.5rem) + 0.75rem); }
  .rmm__nav button {
    display: flex; align-items: center; gap: 0.5rem; width: 100%;
    padding: 0.5rem 0.625rem; border: 0; border-radius: var(--r-sm);
    background: transparent; color: var(--ink-muted); font: inherit; font-size: var(--t-sm); text-align: left; cursor: pointer;
  }
  .rmm__nav button svg { color: var(--ink-faint); flex: none; }
  .rmm__nav button:hover { background: var(--surface-alt); color: var(--ink); }
  .rmm__nav button[aria-selected="true"] { background: var(--brand-tint); color: var(--ink); font-weight: 600; box-shadow: inset 2px 0 0 var(--brand); }
  .rmm__nav button[aria-selected="true"] svg { color: var(--brand); }
  .rmm__nav button:focus-visible { outline: none; box-shadow: var(--focus); }
  .rmm__nav .count { margin-left: auto; font-family: var(--font-mono); font-size: var(--t-2xs, 0.6875rem); color: var(--ink-faint); }
  .rmm__panes { min-width: 0; }
  .rmm-pane { display: flex; flex-direction: column; gap: 0.875rem; }
  .rmm-pane[hidden] { display: none; }
  .rmm-pane__head { display: flex; align-items: flex-end; justify-content: space-between; gap: 0.75rem; flex-wrap: wrap; }
  .rmm-pane__head h3 { margin: 0; font-size: var(--t-md); color: var(--ink); }
  .rmm-pane__head p { margin: 0.125rem 0 0; font-size: var(--t-sm); color: var(--ink-muted); }
  .rmm-pane__head .row { gap: 0.5rem; flex-wrap: wrap; }
  .rmm-pane__head .seg { margin-left: 0; }
  .rmm .input--sm, .rmm .select--sm { padding-top: 0.3125rem; padding-bottom: 0.3125rem; font-size: var(--t-sm); }
  .rmm .search { min-width: 13rem; }

  /* --- tools -------------------------------------------------------------- */
  .rmm-tools h4 { margin: 0 0 0.5rem; font-size: var(--t-xs); font-weight: 600; text-transform: uppercase; letter-spacing: var(--track-label); color: var(--ink-faint); }
  .rmm-tools[hidden] { display: none; }
  .rmm-tools__grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(15rem, 1fr)); gap: 0.5rem; }
  .rmm-tool {
    display: flex; align-items: flex-start; gap: 0.625rem; padding: 0.625rem 0.75rem;
    border: 1px solid var(--rule); border-radius: var(--r); background: var(--surface);
    color: var(--ink); font: inherit; text-align: left; cursor: pointer;
    transition: border-color 0.15s var(--ease), background 0.15s var(--ease), transform 0.15s var(--ease);
  }
  .rmm-tool[hidden] { display: none; }
  .rmm-tool:hover { border-color: var(--brand-lift); background: var(--surface-alt); }
  .rmm-tool:active { transform: translateY(1px); }
  .rmm-tool:focus-visible { outline: none; box-shadow: var(--focus); }
  .rmm-tool__icon { display: grid; place-items: center; flex: none; width: 2rem; height: 2rem; border-radius: var(--r-sm); background: var(--brand-tint); color: var(--brand); }
  .rmm-tool--danger .rmm-tool__icon { background: color-mix(in srgb, var(--warn) 14%, transparent); color: var(--warn); }
  .rmm-tool__text { display: flex; flex-direction: column; gap: 0.125rem; min-width: 0; }
  .rmm-tool__text strong { font-size: var(--t-sm); font-weight: 600; }
  .rmm-tool__text span { font-size: var(--t-xs); color: var(--ink-muted); line-height: var(--lh-snug); }

  /* --- output console ----------------------------------------------------- */
  .rmm-output { border: 1px solid #293445; border-radius: var(--r); overflow: hidden; background: #0b1018; color: #d7e2ef; }
  .rmm-output__head { display: flex; align-items: center; gap: 0.5rem; padding: 0.5rem 0.75rem; background: #141c28; border-bottom: 1px solid #293445; font-size: var(--t-sm); }
  .rmm-output__head svg { color: #7bd3a7; }
  .rmm-output__head .spacer { flex: 1; }
  .rmm-output__btn { background: transparent; border: 1px solid #344155; border-radius: var(--r-sm); color: #bdcddd; font: inherit; font-size: var(--t-xs); padding: 0.125rem 0.5rem; cursor: pointer; }
  .rmm-output__btn:hover { border-color: #5b6b82; color: #fff; }
  .rmm-output__body { margin: 0; padding: 0.75rem; min-height: 6rem; max-height: 26rem; overflow: auto; font-family: var(--font-mono); font-size: 12.5px; line-height: 1.55; white-space: pre-wrap; overflow-wrap: anywhere; background: none; border: 0; color: inherit; scrollbar-color: #344155 #0b1018; }
  .rmm-output[data-state="running"] .rmm-output__body { color: #96a9bf; }
  .rmm-output[data-state="failed"] { border-color: color-mix(in srgb, var(--danger) 55%, #293445); }

  /* --- scripts ------------------------------------------------------------ */
  .rmm-library { display: grid; grid-template-columns: 16rem minmax(0, 1fr); gap: 0.75rem; min-height: 16rem; }
  .rmm-library[hidden], .rmm-adhoc[hidden] { display: none; }
  .rmm-library__list { display: flex; flex-direction: column; gap: 0.5rem; min-width: 0; }
  .rmm-library__list .search { min-width: 0; width: 100%; }
  .rmm-library__items { border: 1px solid var(--rule); border-radius: var(--r); padding: 0.25rem; max-height: 22rem; overflow: auto; }
  .rmm-library__group[hidden] { display: none; }
  .rmm-library__cat { display: block; padding: 0.5rem 0.5rem 0.25rem; font-size: var(--t-2xs, 0.6875rem); font-weight: 600; text-transform: uppercase; letter-spacing: var(--track-label); color: var(--ink-faint); }
  .rmm-library__item { display: flex; align-items: center; gap: 0.5rem; width: 100%; padding: 0.4375rem 0.5rem; border: 0; border-radius: var(--r-sm); background: transparent; color: var(--ink); font: inherit; font-size: var(--t-sm); text-align: left; cursor: pointer; }
  .rmm-library__item[hidden] { display: none; }
  .rmm-library__item:hover { background: var(--surface-alt); }
  .rmm-library__item[aria-selected="true"] { background: var(--brand-tint); font-weight: 600; }
  .rmm-library__none { padding: 0.75rem; font-size: var(--t-sm); margin: 0; }
  .rmm-library__shell, .script-card__icon { flex: none; display: inline-grid; place-items: center; font-family: var(--font-mono); font-weight: 600; border-radius: var(--r-sm); }
  .rmm-library__shell { font-size: 0.625rem; width: 2rem; padding: 0.125rem 0; }
  .rmm-library__shell--powershell, .script-card__icon--powershell { background: color-mix(in srgb, var(--info) 15%, transparent); color: var(--info); }
  .rmm-library__shell--cmd, .script-card__icon--cmd { background: color-mix(in srgb, var(--ink) 10%, transparent); color: var(--ink-muted); }
  .rmm-library__detail { border: 1px solid var(--rule); border-radius: var(--r); padding: 1rem; min-width: 0; }
  .rmm-library__detail .empty { padding: var(--s5) var(--s3); }
  .rmm-library__form { display: flex; flex-direction: column; gap: 0.875rem; }
  .rmm-library__head { display: flex; align-items: flex-start; justify-content: space-between; gap: 0.75rem; }
  .rmm-library__head h4 { margin: 0; font-size: var(--t-md); color: var(--ink); }
  .rmm-library__head p { margin: 0.125rem 0 0; font-size: var(--t-xs); }
  .rmm-library__desc { margin: 0; font-size: var(--t-sm); color: var(--ink-muted); }
  .rmm-library__args { display: grid; grid-template-columns: repeat(auto-fill, minmax(14rem, 1fr)); gap: 0.75rem; }
  .rmm-library__noargs { margin: 0; font-size: var(--t-sm); }
  .rmm-run { display: flex; align-items: center; gap: 0.75rem; }
  .rmm-run .spacer { flex: 1; }
  .rmm-adhoc { display: flex; flex-direction: column; gap: 0.75rem; }

  /* --- tables ------------------------------------------------------------- */
  .rmm-table { max-height: 30rem; overflow: auto; border: 1px solid var(--rule); border-radius: var(--r); }
  .rmm-table thead th { position: sticky; top: 0; background: var(--surface-alt); z-index: 1; }
  .rmm-cell-title { font-weight: 500; color: var(--ink); }
  .rmm-cell-sub { font-family: var(--font-mono); font-size: var(--t-xs); color: var(--ink-faint); }
  .rmm-actions { white-space: nowrap; }
  .rmm-actions .btn + .btn { margin-left: 0.25rem; }
  .rmm-bar { height: 0.25rem; margin-top: 0.25rem; border-radius: 999px; background: color-mix(in srgb, var(--ink) 8%, transparent); max-width: 9rem; }
  .rmm-bar span { display: block; height: 100%; border-radius: inherit; background: var(--brand-lift); }
  .rmm .mono { font-family: var(--font-mono); font-size: var(--t-xs); }

  /* --- activity ----------------------------------------------------------- */
  .rmm-activity { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 0.5rem; }
  .rmm-activity > li.muted { font-size: var(--t-sm); }
  .rmm-activity__item { border: 1px solid var(--rule); border-radius: var(--r); padding: 0.625rem 0.75rem; }
  .rmm-activity__head { display: flex; align-items: center; gap: 0.5rem; font-size: var(--t-sm); }
  .rmm-activity__head .faint { margin-left: auto; font-size: var(--t-xs); }
  .rmm-activity details { margin-top: 0.375rem; font-size: var(--t-xs); }
  .rmm-activity summary { cursor: pointer; color: var(--ink-muted); }
  .rmm-activity__out { margin: 0.375rem 0 0; padding: 0.5rem; max-height: 14rem; overflow: auto; background: var(--surface-sunk); border-radius: var(--r-sm); font-family: var(--font-mono); white-space: pre-wrap; }

  /* --- terminal touch-up -------------------------------------------------- */
  .rmm-terminal { border-radius: var(--r); }
  .rmm-terminal__dots { display: inline-flex; gap: 0.3rem; }
  .rmm-terminal__dots i { width: 0.5rem; height: 0.5rem; border-radius: 50%; background: #344155; }
  .rmm-terminal__head span[data-rmm-terminal-status] { margin-left: auto; }

  @media (max-width: 960px) {
    .rmm__kpis { grid-template-columns: repeat(2, minmax(0, 1fr)); }
    .rmm__layout { grid-template-columns: 1fr; }
    .rmm__nav { position: static; flex-direction: row; overflow-x: auto; padding-bottom: 0.25rem; }
    .rmm__nav button { width: auto; white-space: nowrap; }
    .rmm__nav button[aria-selected="true"] { box-shadow: inset 0 -2px 0 var(--brand); }
    .rmm-library { grid-template-columns: 1fr; }
  }
  @media (max-width: 560px) {
    .rmm__bar { flex-wrap: wrap; }
    .rmm .search { min-width: 0; width: 100%; }
  }

  /* --- code editor (Monaco or its textarea) ------------------------------- */
  .code-card { border: 1px solid var(--rule); border-radius: var(--r-lg); overflow: hidden; background: var(--surface); }
  .code-card.card { padding: 0; }
  .code-card__head { display: flex; align-items: center; gap: 0.75rem; padding: 0.5rem 0.75rem; border-bottom: 1px solid var(--rule); background: var(--surface-alt); font-size: var(--t-sm); }
  .code-card__head .spacer { flex: 1; }
  .code-card__shell { font-weight: 600; color: var(--ink); }
  .code-card__badge { display: inline-flex; align-items: center; gap: 0.25rem; font-size: var(--t-xs); color: var(--ink-muted); }
  .code-card__fallback { display: block; width: 100%; border: 0; border-radius: 0; padding: 0.75rem; resize: vertical; font-family: var(--font-mono); font-size: 13px; line-height: 19px; background: var(--surface); color: var(--ink); tab-size: 4; }
  .code-card__fallback:focus { outline: none; box-shadow: inset var(--focus); }
  .code-card__foot { padding: 0.5rem 0.75rem; border-top: 1px solid var(--rule); font-size: var(--t-xs); color: var(--ink-muted); }
  .code-card__foot code { font-family: var(--font-mono); }
  .code-card__error { padding: 0 0.75rem 0.5rem; }
  .code-host { width: 100%; }

  /* --- script library ----------------------------------------------------- */
  .script-group__title { margin: 0 0 0.5rem; font-size: var(--t-xs); font-weight: 600; text-transform: uppercase; letter-spacing: var(--track-label); color: var(--ink-muted); }
  .script-group__title .faint { font-family: var(--font-mono); margin-left: 0.25rem; }
  .script-list { display: grid; grid-template-columns: repeat(auto-fill, minmax(22rem, 1fr)); gap: 0.5rem; }
  .script-card { display: flex; align-items: center; gap: 0.75rem; padding: 0.75rem 0.875rem; border: 1px solid var(--rule); border-radius: var(--r); background: var(--surface); color: var(--ink); text-decoration: none; box-shadow: var(--shadow-1); transition: border-color 0.15s var(--ease); }
  .script-card:hover { border-color: var(--brand-lift); }
  .script-card:focus-visible { outline: none; box-shadow: var(--focus); }
  .script-card > svg { color: var(--ink-faint); transform: rotate(-90deg); flex: none; }
  .script-card__icon { width: 2.25rem; height: 2.25rem; font-size: 0.6875rem; }
  .script-card__body { display: flex; flex-direction: column; gap: 0.125rem; min-width: 0; flex: 1; }
  .script-card__body strong { font-size: var(--t-sm); }
  .script-card__desc { font-size: var(--t-xs); color: var(--ink-muted); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  .script-card__meta { font-size: var(--t-xs); color: var(--ink-faint); }

  .script-editor { display: grid; grid-template-columns: minmax(0, 1fr) 20rem; gap: var(--s5); align-items: start; }
  .script-editor__side { position: sticky; top: calc(var(--topbar-h, 3.5rem) + 1rem); }
  @media (max-width: 1100px) { .script-editor { grid-template-columns: 1fr; } .script-editor__side { position: static; } }
  .script-facts { display: flex; flex-direction: column; gap: 0.625rem; font-size: var(--t-sm); }
  .script-facts .field__label { display: block; }
  .script-facts code { font-family: var(--font-mono); font-size: var(--t-xs); }

  .segmented { display: flex; border: 1px solid var(--rule-strong); border-radius: var(--r); overflow: hidden; }
  .segmented__option { flex: 1; position: relative; cursor: pointer; }
  .segmented__option input { position: absolute; opacity: 0; pointer-events: none; }
  .segmented__option span { display: block; padding: 0.4375rem 0.5rem; text-align: center; font-size: var(--t-sm); color: var(--ink-muted); background: var(--surface); border-left: 1px solid var(--rule); }
  .segmented__option:first-child span { border-left: 0; }
  .segmented__option input:checked + span { background: var(--brand-tint); color: var(--ink); font-weight: 600; box-shadow: inset 0 -2px 0 var(--brand); }
  .segmented__option input:focus-visible + span { box-shadow: inset var(--focus); }
  .segmented__option input:disabled + span { cursor: default; }

  .arg-list { display: flex; flex-direction: column; gap: 0.75rem; }
  .arg-row { margin: 0; padding: 0.875rem; border: 1px solid var(--rule); border-radius: var(--r); background: var(--surface-sunk); min-width: 0; }
  .arg-row__grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 0.625rem 0.75rem; }
  .arg-row__options, .arg-row__hint { grid-column: span 2; }
  .arg-row__options[hidden] { display: none; }
  .arg-row__foot { display: flex; align-items: center; justify-content: space-between; margin-top: 0.625rem; }
  @media (max-width: 640px) { .arg-row__grid { grid-template-columns: 1fr; } .arg-row__options, .arg-row__hint { grid-column: auto; } }

  .btn--danger-text { color: var(--danger); }
}

/* =========================================================================
   Insight → Analytics (analytics/index)

   Series colours are the validated categorical slots (light and dark stepped
   separately, checked against this application's own surfaces: #ffffff and
   #191c2c). Slot 3 sits under 3:1 on white, which is why every chart carries
   its numbers in the legend, the tooltip and a table view.
   ========================================================================= */
@layer components {
  .an { --an-1: #2a78d6; --an-2: #eb6834; --an-3: #1baf7a; display: flex; flex-direction: column; gap: var(--s4); }
  @media (prefers-color-scheme: dark) {
    :root:not([data-theme="light"]) .an { --an-1: #3987e5; --an-2: #d95926; --an-3: #199e70; }
  }
  :root[data-theme="dark"] .an { --an-1: #3987e5; --an-2: #d95926; --an-3: #199e70; }

  /* --- tabs -------------------------------------------------------------- */
  .an-tabs { display: flex; align-items: center; gap: var(--s2); border-bottom: 1px solid var(--rule); }
  .an-tabs__list { display: flex; gap: 0.125rem; flex: 1; min-width: 0; overflow-x: auto; overflow-y: hidden; }
  .an-tab {
    display: inline-flex; align-items: center; gap: 0.375rem; padding: 0.625rem 0.75rem;
    color: var(--ink-muted); text-decoration: none; font-size: var(--t-sm); white-space: nowrap;
    border-bottom: 2px solid transparent; margin-bottom: -1px;
  }
  .an-tab:hover { color: var(--ink); }
  .an-tab[aria-current] { color: var(--ink); font-weight: 600; border-bottom-color: var(--brand); }
  .an-tab__grip { color: var(--ink-faint); font-size: 0.625rem; letter-spacing: -0.15em; cursor: grab; opacity: 0; transition: opacity 0.15s; }
  .an-tab:hover .an-tab__grip, .an-tab[aria-current] .an-tab__grip { opacity: 1; }
  .an-tab__count { font-family: var(--font-mono); font-size: var(--t-2xs); color: var(--ink-faint); }
  .an-tab.is-dragging { opacity: 0.4; }
  .an-tabmenu { min-width: 18rem; }
  .an-tabmenu__form { padding: 0.5rem; display: flex; flex-direction: column; gap: 0.375rem; }
  .an-tabmenu__form .row { gap: 0.375rem; }
  .an-tabmenu__form .input { flex: 1; }
  .an-hint { margin: 0; font-size: var(--t-xs); color: var(--ink-faint); }

  /* --- grid -------------------------------------------------------------- */
  .an-grid { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: var(--s4); align-items: start; }
  .an-w { grid-column: span 2; background: var(--surface); border: 1px solid var(--rule); border-radius: var(--r-lg); box-shadow: var(--shadow-1); min-width: 0; display: flex; flex-direction: column; }
  .an-w--kpi { grid-column: span 1; }
  .an-w--wide { grid-column: span 4; }
  .an-w.is-dragging { opacity: 0.35; outline: 2px dashed var(--brand-lift); outline-offset: 2px; }
  .an-w__head { display: flex; align-items: flex-start; gap: 0.5rem; padding: 0.875rem 1rem 0.25rem; cursor: grab; }
  .an-w__head:active { cursor: grabbing; }
  .an-w__titles { flex: 1; min-width: 0; }
  .an-w__titles h2 { margin: 0; font-size: var(--t-sm); font-weight: 600; color: var(--ink); }
  .an-w__titles p { margin: 0.125rem 0 0; font-size: var(--t-xs); color: var(--ink-muted); }
  .an-w__more { border: 0; background: transparent; color: var(--ink-faint); font-size: 1.125rem; line-height: 1; padding: 0.125rem 0.375rem; border-radius: var(--r-sm); cursor: pointer; }
  .an-w__more:hover { background: var(--surface-alt); color: var(--ink); }
  .an-w__more:focus-visible { outline: none; box-shadow: var(--focus); }
  .an-w__body { padding: 0.5rem 1rem 1rem; }
  .an-none { margin: 0; padding: 1.5rem 0; text-align: center; font-size: var(--t-sm); color: var(--ink-faint); }

  @media (max-width: 1100px) { .an-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); } .an-w--wide { grid-column: span 2; } }
  @media (max-width: 640px) { .an-grid { grid-template-columns: 1fr; } .an-w, .an-w--kpi, .an-w--wide { grid-column: auto; } }

  /* --- KPI --------------------------------------------------------------- */
  .an-kpi { display: flex; flex-direction: column; gap: 0.25rem; }
  .an-kpi__value { font-size: var(--t-3xl); font-weight: 600; line-height: 1.1; color: var(--ink); text-decoration: none; font-variant-numeric: tabular-nums; }
  a.an-kpi__value:hover { color: var(--brand-lift); }
  .an-kpi__note { display: inline-flex; align-items: center; gap: 0.375rem; font-size: var(--t-xs); color: var(--ink-muted); }
  .an-dot { width: 0.5rem; height: 0.5rem; border-radius: 50%; flex: none; }
  .an-dot--ok { background: var(--ok); } .an-dot--warn { background: var(--warn); } .an-dot--danger { background: var(--danger); }

  /* --- time series ------------------------------------------------------- */
  .an-legend { display: flex; flex-wrap: wrap; align-items: center; gap: 0.25rem 1rem; margin-bottom: 0.375rem; font-size: var(--t-xs); color: var(--ink-muted); }
  .an-legend__item { display: inline-flex; align-items: center; gap: 0.375rem; }
  .an-legend__item strong { color: var(--ink); font-variant-numeric: tabular-nums; }
  .an-legend__period { margin-left: auto; color: var(--ink-faint); }
  .an-swatch { width: 0.75rem; height: 0.1875rem; border-radius: 2px; }
  .an-swatch--1 { background: var(--an-1); } .an-swatch--2 { background: var(--an-2); } .an-swatch--3 { background: var(--an-3); }
  .an-chart { position: relative; margin: 0; }
  .an-chart svg { display: block; width: 100%; height: auto; overflow: visible; }
  .an-grid-line { stroke: var(--rule); stroke-width: 1; }
  .an-axis { fill: var(--ink-faint); font-size: 11px; font-family: var(--font-sans); }
  .an-col { fill: var(--an-1); }
  .an-line { fill: none; stroke-width: 2; stroke-linejoin: round; stroke-linecap: round; }
  .an-line--1 { stroke: var(--an-1); } .an-line--2 { stroke: var(--an-2); } .an-line--3 { stroke: var(--an-3); }
  .an-marker { stroke: var(--surface); stroke-width: 2; }
  .an-marker--1 { fill: var(--an-1); } .an-marker--2 { fill: var(--an-2); } .an-marker--3 { fill: var(--an-3); }
  .an-hit { fill: transparent; }
  .an-hit.is-active { fill: color-mix(in srgb, var(--ink) 5%, transparent); }
  .an-crosshair { stroke: var(--rule-strong); stroke-width: 1; stroke-dasharray: 3 3; }
  .an-crosshair[hidden], .an-marker[hidden] { display: none; }
  .an-tip {
    position: absolute; top: -0.25rem; transform: translate(-50%, -100%); pointer-events: none; z-index: 5;
    padding: 0.3125rem 0.5rem; border-radius: var(--r-sm); background: var(--ink); color: var(--surface);
    font-size: var(--t-xs); white-space: nowrap; box-shadow: var(--shadow-2);
  }
  .an-table { margin-top: 0.5rem; font-size: var(--t-xs); }
  .an-table summary { cursor: pointer; color: var(--ink-muted); }
  .an-table .table-wrap { margin-top: 0.375rem; max-height: 14rem; overflow: auto; }

  /* --- horizontal bars --------------------------------------------------- */
  .an-bars { display: flex; flex-direction: column; gap: 0.5rem; }
  .an-bars__row { display: grid; grid-template-columns: minmax(6rem, 38%) 1fr auto; align-items: center; gap: 0.625rem; font-size: var(--t-sm); }
  .an-bars__label { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; color: var(--ink); }
  .an-bars__track { height: 0.625rem; }
  .an-bars__fill { display: block; height: 100%; border-radius: 0 4px 4px 0; background: var(--an-1); }
  .an-bars__value { font-variant-numeric: tabular-nums; color: var(--ink-muted); min-width: 2.5rem; text-align: right; }

  /* --- list -------------------------------------------------------------- */
  .an-list { list-style: none; margin: 0; padding: 0; }
  .an-list li { display: flex; align-items: center; justify-content: space-between; gap: 0.75rem; padding: 0.4375rem 0; border-top: 1px solid var(--rule); font-size: var(--t-sm); }
  .an-list li:first-child { border-top: 0; }
  .an-list a { display: flex; flex-direction: column; min-width: 0; color: var(--ink); text-decoration: none; }
  .an-list a span { font-family: var(--font-mono); font-size: var(--t-xs); color: var(--ink-faint); }
  .an-list a:hover strong { color: var(--brand-lift); }
  .an-list__value { display: inline-flex; align-items: center; gap: 0.375rem; font-variant-numeric: tabular-nums; white-space: nowrap; }

  /* --- add-a-chart catalogue --------------------------------------------- */
  dialog.modal.modal--wide { width: min(52rem, calc(100vw - 2rem)); }
  .an-catalogue { display: flex; flex-direction: column; gap: var(--s4); max-height: 70vh; overflow: auto; }
  .an-catalogue h3 { margin: 0 0 0.5rem; font-size: var(--t-xs); text-transform: uppercase; letter-spacing: var(--track-label); color: var(--ink-faint); }
  .an-catalogue__grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(18rem, 1fr)); gap: 0.5rem; }
  .an-catalogue__item {
    display: flex; align-items: center; gap: 0.75rem; width: 100%; padding: 0.625rem 0.75rem;
    border: 1px solid var(--rule); border-radius: var(--r); background: var(--surface); color: var(--ink);
    font: inherit; text-align: left; cursor: pointer;
  }
  .an-catalogue__item:hover { border-color: var(--brand-lift); background: var(--surface-alt); }
  .an-catalogue__item > span:nth-child(2) { display: flex; flex-direction: column; gap: 0.125rem; flex: 1; min-width: 0; }
  .an-catalogue__item strong { font-size: var(--t-sm); }
  .an-catalogue__item > span:nth-child(2) span { font-size: var(--t-xs); color: var(--ink-muted); }
  .an-catalogue__item > svg { color: var(--ink-faint); flex: none; }
  .an-catalogue__kind { flex: none; width: 2rem; height: 1.5rem; border-radius: var(--r-sm); background: var(--brand-tint); position: relative; }
  .an-catalogue__kind--kpi::after { content: "12"; position: absolute; inset: 0; display: grid; place-items: center; font-size: 0.6875rem; font-weight: 700; color: var(--brand); }
  .an-catalogue__kind--wide::after, .an-catalogue__kind--half::after { content: ""; position: absolute; left: 0.3rem; right: 0.3rem; bottom: 0.3rem; height: 0.6rem; background: linear-gradient(90deg, var(--brand) 0 18%, transparent 18% 27%, var(--brand) 27% 45%, transparent 45% 54%, var(--brand) 54% 72%, transparent 72% 82%, var(--brand) 82%); opacity: 0.6; border-radius: 1px; }

  /* =======================================================================
     Schedule (schedule/index)

     Kind of booking is the colour, whose booking is the column (day, week)
     or a dot (month). Every block also carries its kind and time as words in
     its tooltip, so colour is never the only way to tell them apart.
     ===================================================================== */

  .flip-x { transform: scaleX(-1); }

  .sched { --hour-h: 4.25rem; display: flex; flex-direction: column; gap: var(--s4); }

  .sched-bar { display: flex; align-items: center; justify-content: space-between; gap: var(--s3); flex-wrap: wrap; }
  .sched-bar__nav { display: flex; align-items: center; gap: var(--s2); min-width: 0; }
  .sched-bar__title { margin-left: var(--s2); font-size: var(--t-xl); font-weight: 650; letter-spacing: -0.01em; color: var(--ink); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }

  .sched-views { display: inline-flex; padding: 3px; gap: 2px; background: var(--surface-sunk); border: 1px solid var(--rule); border-radius: var(--r); }
  .sched-views a { padding: 0.3125rem 0.875rem; border-radius: var(--r-sm); font-size: var(--t-sm); font-weight: 550; color: var(--ink-muted); text-decoration: none; }
  .sched-views a:hover { color: var(--ink); }
  .sched-views a[aria-current] { background: var(--surface); color: var(--ink); box-shadow: var(--shadow-1); }

  .sched-people { display: flex; align-items: flex-start; gap: var(--s3); padding: 0.625rem var(--s4); background: var(--surface); border: 1px solid var(--rule); border-radius: var(--r-lg); }
  .sched-people__label { display: inline-flex; align-items: center; gap: var(--s2); flex: none; min-height: 2.25rem; font-size: var(--t-sm); font-weight: 600; color: var(--ink); }
  .sched-people .people-picker { flex: 1; min-width: 0; }
  .sched-people__actions { display: flex; gap: var(--s1); flex: none; min-height: 2.25rem; align-items: center; }
  @media (max-width: 720px) { .sched-people { flex-wrap: wrap; } .sched-people .people-picker { flex-basis: 100%; order: 2; } }

  .sched-legend { display: flex; flex-wrap: wrap; gap: var(--s1) var(--s4); margin: calc(-1 * var(--s1)) 0 0; padding: 0; list-style: none; font-size: var(--t-xs); color: var(--ink-muted); }
  .sched-legend li { display: inline-flex; align-items: center; gap: 0.4rem; }
  .sched-legend__swatch { width: 0.75rem; height: 0.75rem; border-radius: 3px; border: 1px solid; border-left-width: 3px; }

  /* Kind colours: a tinted fill, a solid edge, ink text — readable in both
     themes because the tints and the inks are the theme's own. */
  /* Ticket, work order and delivery take the analytics palette's hues;
     events are amber and time off is the neutral grey, so the two kinds that
     are NOT customer work read as quieter than the ones that are. */
  .sched { --sk-ticket: #2a78d6; --sk-work: #7856d0; --sk-delivery: #1a9e6f; --sk-event: #c98a0c; }
  @media (prefers-color-scheme: dark) {
    :root:not([data-theme="light"]) .sched { --sk-ticket: #4b93ea; --sk-work: #9a7ff0; --sk-delivery: #22b47f; --sk-event: #e0a52a; }
  }
  :root[data-theme="dark"] .sched { --sk-ticket: #4b93ea; --sk-work: #9a7ff0; --sk-delivery: #22b47f; --sk-event: #e0a52a; }

  :is(.sched-ev, .sched-chip, .sched-legend__swatch) { --k-tint: color-mix(in srgb, var(--k) 13%, var(--surface)); }
  :is(.sched-ev, .sched-chip, .sched-legend__swatch):is(.sched-ev--ticket, .sched-chip--ticket) { --k: var(--sk-ticket); }
  :is(.sched-ev, .sched-chip, .sched-legend__swatch):is(.sched-ev--work_order, .sched-chip--work_order) { --k: var(--sk-work); }
  :is(.sched-ev, .sched-chip, .sched-legend__swatch):is(.sched-ev--delivery, .sched-chip--delivery) { --k: var(--sk-delivery); }
  :is(.sched-ev, .sched-chip, .sched-legend__swatch):is(.sched-ev--event, .sched-chip--event) { --k: var(--sk-event); }
  :is(.sched-ev, .sched-chip, .sched-legend__swatch):is(.sched-ev--time_off, .sched-chip--time_off) { --k: var(--neutral); }
  .sched-legend__swatch { background: var(--k-tint); border-color: var(--k); }

  /* --- day: time grid ---------------------------------------------------- */

  .sched-day { overflow: auto; max-height: calc(100dvh - 12rem); min-height: 24rem; background: var(--surface); border: 1px solid var(--rule); border-radius: var(--r-lg); box-shadow: var(--shadow-1); }
  .sched-day__grid { display: grid; grid-template-columns: 4.25rem repeat(var(--cols), minmax(11rem, 1fr)); min-width: min-content; }

  .sched-day__corner, .sched-day__head { position: sticky; top: 0; z-index: 3; background: var(--surface); border-bottom: 1px solid var(--rule-strong); }
  .sched-day__corner { left: 0; z-index: 4; display: flex; align-items: flex-end; justify-content: flex-end; padding: 0 0.625rem 0.5rem; font-size: var(--t-2xs); font-weight: 600; color: var(--ink-faint); letter-spacing: 0.04em; }
  .sched-day__head { display: grid; grid-template-columns: auto 1fr; align-items: center; column-gap: var(--s2); padding: 0.625rem 0.75rem 0.5rem; border-left: 1px solid var(--rule); box-shadow: inset 0 3px 0 var(--who); }
  .sched-day__name { font-weight: 600; font-size: var(--t-sm); color: var(--ink); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
  .sched-day__load { grid-column: 2; font-size: var(--t-xs); color: var(--ink-faint); font-variant-numeric: tabular-nums; }

  .sched-day__allday-label { position: sticky; left: 0; z-index: 2; background: var(--surface); padding: 0.5rem 0.625rem; font-size: var(--t-2xs); color: var(--ink-faint); text-align: right; border-bottom: 1px solid var(--rule); }
  .sched-day__allday { padding: 0.25rem; border-left: 1px solid var(--rule); border-bottom: 1px solid var(--rule); background: var(--surface-alt); }

  .sched-day__gutter, .sched-day__col { position: relative; height: calc(var(--hours) * var(--hour-h)); }
  .sched-day__gutter { position: sticky; left: 0; z-index: 2; background: var(--surface); }
  .sched-day__gutter span { position: absolute; right: 0.625rem; top: calc(var(--start) * var(--hour-h) / 60); transform: translateY(-50%); font-size: var(--t-2xs); font-weight: 500; color: var(--ink-faint); white-space: nowrap; font-variant-numeric: tabular-nums; }
  .sched-day__gutter span:first-child { transform: translateY(0.25rem); }

  /* Hour lines solid, half-hour lines faint — drawn as a background so a
     day of fifty bookings is not also four hundred line elements. */
  .sched-day__col {
    border-left: 1px solid var(--rule);
    background-image:
      linear-gradient(to bottom, var(--rule) 1px, transparent 1px),
      linear-gradient(to bottom, color-mix(in srgb, var(--rule) 45%, transparent) 1px, transparent 1px);
    background-size: 100% var(--hour-h), 100% var(--hour-h);
    background-position: 0 0, 0 calc(var(--hour-h) / 2);
  }

  .sched-ev {
    position: absolute;
    top: calc(var(--start) * var(--hour-h) / 60 + 1px);
    height: max(calc(var(--len) * var(--hour-h) / 60 - 3px), 1.625rem);
    left: calc(var(--lane) * (100% - 6px) / var(--lanes) + 3px);
    width: calc((100% - 6px) / var(--lanes) - 3px);
    display: flex; flex-direction: column; gap: 1px;
    padding: 0.3125rem 0.5rem;
    overflow: hidden;
    background: var(--k-tint);
    border: 1px solid color-mix(in srgb, var(--k) 35%, transparent);
    border-left: 3px solid var(--k);
    border-radius: var(--r-sm);
    color: var(--ink);
    text-decoration: none;
    font-size: var(--t-xs);
    line-height: 1.3;
    transition: box-shadow 0.12s var(--ease), transform 0.12s var(--ease);
  }
  .sched-ev:hover, .sched-ev:focus-visible { z-index: 1; box-shadow: var(--shadow-2); transform: translateY(-1px); }
  .sched-ev__primary { font-weight: 600; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
  .sched-ev__secondary { color: var(--ink-muted); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
  .sched-ev__meta { margin-top: auto; padding-top: 2px; font-size: var(--t-2xs); color: var(--ink-faint); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
  /* Time off is a long block that should read as background, not as work. */
  .sched-ev--time_off { background-image: repeating-linear-gradient(135deg, transparent 0 6px, color-mix(in srgb, var(--neutral) 10%, transparent) 6px 12px); }

  .sched-now { position: absolute; left: 0; right: 0; top: calc(var(--start) * var(--hour-h) / 60); z-index: 2; height: 2px; background: var(--danger); pointer-events: none; }
  .sched-day__col:nth-child(1 of .sched-day__col) .sched-now::before { content: ""; position: absolute; left: -5px; top: -4px; width: 10px; height: 10px; border-radius: 50%; background: var(--danger); }

  /* --- chips (week, month, all-day strip) ------------------------------ */

  .sched-chip {
    display: flex; align-items: baseline; gap: 0.375rem;
    padding: 0.25rem 0.4375rem;
    margin-bottom: 3px;
    background: var(--k-tint);
    border-left: 3px solid var(--k);
    border-radius: var(--r-sm);
    color: var(--ink);
    text-decoration: none;
    font-size: var(--t-xs);
    line-height: 1.3;
    min-width: 0;
  }
  .sched-chip:hover, .sched-chip:focus-visible { box-shadow: inset 0 0 0 1px var(--k); }
  .sched-chip__time { flex: none; font-size: var(--t-2xs); font-weight: 600; color: var(--ink-muted); font-variant-numeric: tabular-nums; }
  .sched-chip__text { min-width: 0; font-weight: 550; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  .sched-chip__sub { display: block; font-weight: 400; color: var(--ink-muted); overflow: hidden; text-overflow: ellipsis; }
  .sched-dot { flex: none; width: 0.5rem; height: 0.5rem; border-radius: 50%; align-self: center; }
  .sched-dots { display: inline-flex; align-self: center; flex: none; }
  .sched-dots .sched-dot + .sched-dot { margin-left: -2px; box-shadow: 0 0 0 1.5px var(--k-tint); }

  /* --- week: technicians × days ---------------------------------------- */

  .sched-week, .sched-month { overflow-x: auto; background: var(--surface); border: 1px solid var(--rule); border-radius: var(--r-lg); box-shadow: var(--shadow-1); }
  .sched-week__grid { display: grid; grid-template-columns: 13rem repeat(7, minmax(8.5rem, 1fr)); min-width: min-content; }
  .sched-week__corner, .sched-week__day { position: sticky; top: 0; z-index: 2; background: var(--surface); border-bottom: 1px solid var(--rule-strong); }
  .sched-week__corner { left: 0; z-index: 3; padding: 0.75rem var(--s4); font-size: var(--t-2xs); font-weight: 600; letter-spacing: 0.05em; text-transform: uppercase; color: var(--ink-faint); display: flex; align-items: flex-end; }
  .sched-week__day { display: flex; align-items: baseline; gap: 0.375rem; padding: 0.625rem 0.75rem; border-left: 1px solid var(--rule); color: var(--ink-muted); text-decoration: none; font-size: var(--t-xs); }
  .sched-week__day strong { font-size: var(--t-lg); font-weight: 600; color: var(--ink); }
  .sched-week__day:hover strong { color: var(--brand); }
  .sched-week__day.is-today { box-shadow: inset 0 -2px 0 var(--brand); }
  .sched-week__day.is-today strong { color: var(--brand); }

  .sched-week__person { position: sticky; left: 0; z-index: 1; display: grid; grid-template-columns: auto 1fr; column-gap: var(--s2); align-content: start; padding: 0.75rem var(--s4); background: var(--surface); border-bottom: 1px solid var(--rule); }
  .sched-week__name { font-weight: 600; font-size: var(--t-sm); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
  .sched-week__load { grid-column: 2; font-size: var(--t-xs); color: var(--ink-faint); }
  .sched-week__cell { min-height: 5.5rem; padding: 0.375rem; border-left: 1px solid var(--rule); border-bottom: 1px solid var(--rule); min-width: 0; }
  .sched-week__cell.is-weekend, .sched-month__cell.is-weekend { background: var(--surface-alt); }
  .sched-week__cell.is-today { background: color-mix(in srgb, var(--brand-tint) 45%, transparent); }

  /* --- month ----------------------------------------------------------- */

  .sched-month__grid { display: grid; grid-template-columns: repeat(7, minmax(8.5rem, 1fr)); min-width: min-content; }
  .sched-month__weekday { padding: 0.5rem 0.625rem; font-size: var(--t-2xs); font-weight: 600; letter-spacing: 0.05em; text-transform: uppercase; color: var(--ink-faint); border-bottom: 1px solid var(--rule-strong); }
  .sched-month__cell { min-height: 7.5rem; padding: 0.375rem; border-bottom: 1px solid var(--rule); border-left: 1px solid var(--rule); min-width: 0; }
  .sched-month__cell:nth-child(7n + 1) { border-left: 0; }
  .sched-month__cell.is-outside { background: var(--surface-sunk); }
  .sched-month__cell.is-outside .sched-month__date { color: var(--ink-faint); }
  .sched-month__date { display: inline-grid; place-items: center; min-width: 1.625rem; height: 1.625rem; margin-bottom: 0.25rem; padding: 0 0.3rem; border-radius: 999px; font-size: var(--t-xs); font-weight: 600; color: var(--ink-muted); text-decoration: none; font-variant-numeric: tabular-nums; }
  .sched-month__date:hover { background: var(--surface-sunk); color: var(--ink); }
  .sched-month__cell.is-today .sched-month__date { background: var(--brand); color: var(--brand-on); }
  .sched-month__more { display: block; padding: 0.125rem 0.4375rem; font-size: var(--t-2xs); font-weight: 600; color: var(--ink-muted); text-decoration: none; }
  .sched-month__more:hover { color: var(--brand); }

  @media (max-width: 640px) {
    .sched-bar__title { font-size: var(--t-lg); margin-left: 0; flex-basis: 100%; order: -1; }
    .sched-bar__nav { flex-wrap: wrap; }
    .sched-week__grid { grid-template-columns: 9rem repeat(7, minmax(8rem, 1fr)); }
    .sched-week__load { display: none; }
  }

  /* --- resources on a ticket or work order (x-resource-schedules) ------- */

  .resource-row { display: grid; grid-template-columns: minmax(0, 1fr) minmax(12rem, 15rem) auto; align-items: center; gap: var(--s2); padding: 0.375rem 0.375rem 0.375rem 0.75rem; background: var(--surface-alt); border: 1px solid var(--rule); border-radius: var(--r-sm); }
  .resource-row__name { min-width: 0; font-size: var(--t-sm); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
  .resource-add { display: grid; grid-template-columns: minmax(0, 1fr) minmax(12rem, 15rem); gap: var(--s3); align-items: end; }
  @media (max-width: 560px) {
    .resource-row { grid-template-columns: minmax(0, 1fr) auto; }
    .resource-row__when { grid-column: 1 / -1; grid-row: 2; }
    .resource-add { grid-template-columns: 1fr; }
  }

  /* --- people picker (x-people-picker) ---------------------------------- */

  .people-picker { display: flex; flex-wrap: wrap; align-items: center; gap: var(--s2); }
  .people-picker__chosen { display: contents; list-style: none; }
  .people-picker > .field__hint { margin: 0; }
  .people-picker__add { display: flex; gap: var(--s2); align-items: center; flex: 1 1 14rem; max-width: 20rem; }
  .people-picker__add .combo, .people-picker__add > .select { flex: 1; }
  .person-chip { display: inline-flex; align-items: center; gap: 0.375rem; height: 2.25rem; padding: 0 0.25rem 0 0.375rem; background: var(--surface-alt); border: 1px solid var(--rule); border-radius: 999px; font-size: var(--t-sm); max-width: 16rem; }
  .person-chip__name { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
  .person-chip__remove { display: inline-grid; place-items: center; width: 1.5rem; height: 1.5rem; flex: none; border-radius: 50%; font-size: 1rem; line-height: 1; color: var(--ink-faint); text-decoration: none; background: none; border: 0; cursor: pointer; }
  .person-chip__remove:hover, .person-chip__remove:focus-visible { background: var(--surface-sunk); color: var(--ink); }
}
