/* ══════════════════════════════════════════════════════════════════════════
   canon-scheduler.css — the live Dispatch page (scheduler.html) in the canon.

   Loads last, after css/canon-scheduler-bridge.css, in the same components
   layer. The bridge keeps every legacy Dispatch rule that reaches the page, so
   nothing is ever unstyled; this file reshapes the page to the mockup
   (public/_canon-dispatch-port-mockup.html) one component at a time, and wins
   over the bridge by coming later at equal specificity.

   Colours are canon tokens only. The legacy --app-* palette the bridge reads is
   the same palette, so where a bridged rule still sets a colour it already
   matches; what changes here is shape, type and layout.

   Stage 1: the ground and the three panes as cards, the toolbar, the left rail
   (canon-rail.js), the week and day time grid, the timeline, the inspector.
   Stage 2: section titles, dialogs, fields, the v2 job editor.
   Stage 3: month, list, history, quick create, settings tabs, the records
   sections, the customer drawer, the map. Anything not named here is still
   drawn by the bridge, in canon colour.
   ══════════════════════════════════════════════════════════════════════════ */

@layer components {
  /* ── The ground ─────────────────────────────────────────────────────── */
  body.sched-app { background:var(--c-bg); background-image:none; color:var(--c-text); }
  .sched-app .dash-section { background:transparent; }

  /* ── The toolbar ────────────────────────────────────────────────────── */
  .sched-app .stoolbar { gap:10px 12px; padding:10px 16px; background:var(--c-surface); border-bottom:1px solid var(--c-border); }
  .sched-app .stoolbar-head .section-title { font-size:16px; font-weight:600; letter-spacing:-.01em; text-transform:none; color:var(--c-text); }

  /* Status counts are canon pills. */
  .sched-app .skpis { gap:6px; }
  .sched-app .skpi { gap:6px; padding:3px 9px 3px 7px; border-radius:999px; font-size:11px; font-weight:500; line-height:1.5;
    background:var(--c-sunken); border:1px solid var(--c-border); color:var(--c-text-2); }
  .sched-app .skpi .n { font-family:'Inter', system-ui, sans-serif; font-variant-numeric:tabular-nums; font-weight:600; }
  .sched-app .skpi .sw { width:6px; height:6px; }
  .sched-app .skpi.k-unassigned, .sched-app .skpi.k-onsite { color:var(--c-on-wash-warn); }
  .sched-app .skpi.k-late { color:var(--c-on-wash-danger); border-color:color-mix(in srgb, var(--c-danger) 36%, transparent); background:var(--c-danger-soft); }
  /* Unassigned with work in it is a button: each click walks to the next job. */
  .sched-app .skpi.is-link { font-family:inherit; cursor:pointer; }
  .sched-app .skpi.is-link:hover { border-color:currentColor; }
  .sched-app .skpi.is-link:focus-visible { outline:2px solid var(--c-accent); outline-offset:2px; }

  /* View switch, date stepper and the day-layout segments are canon segs. */
  .sched-app .sviews, .sched-app .sdatenav, .sched-app .sched-td-seg {
    padding:2px; gap:2px; background:var(--c-sunken); border:1px solid var(--c-border); border-radius:6px; }
  .sched-app .sviews button, .sched-app .sched-td-seg button {
    gap:5px; padding:5px 10px; border-radius:4px; font-size:12px; font-weight:500; color:var(--c-cap); }
  .sched-app .sviews button:hover, .sched-app .sched-td-seg button:hover { color:var(--c-text-2); }
  .sched-app .sviews button.active, .sched-app .sched-td-seg button.is-on {
    background:var(--c-card); color:var(--c-text); box-shadow:var(--lift); }
  .sched-app .sviews button.active i { color:var(--c-accent); }
  .sched-app .sdatenav .nav { width:28px; height:26px; border-radius:4px; color:var(--c-text-2); }
  .sched-app .sdatenav .nav:hover { background:var(--c-card); color:var(--c-text); }
  .sched-app .sdatenav .today { height:26px; padding:0 10px; border-radius:4px; font-size:12px; font-weight:600; color:var(--c-text); }
  .sched-app .sdatenav .today .d { font-family:'Inter', system-ui, sans-serif; font-variant-numeric:tabular-nums; font-weight:500; color:var(--c-cap); }
  .sched-app .sched-td-lbl-ico { color:var(--c-cap); }

  /* Tools are canon buttons. */
  .sched-app .sutil .btn, .sched-app .sched-sendupd .btn {
    height:30px; min-height:0; margin:0; padding:0 10px; gap:6px; width:auto;
    border:1px solid var(--c-border); border-radius:6px; background:var(--c-card); color:var(--c-text);
    font-size:12px; font-weight:500; box-shadow:none; }
  .sched-app .sutil .btn:hover { background:var(--c-card-2); border-color:var(--c-border-2); }
  .sched-app .sutil .btn-icon { width:30px; padding:0; justify-content:center; }
  .sched-app .sutil .btn i { font-size:15px; color:var(--c-text-2); }
  .sched-app .sched-req-badge { background:var(--c-danger); color:var(--c-card); font-family:'Inter', system-ui, sans-serif; font-weight:600; }
  .sched-app .sched-add-job { width:auto; height:34px; padding:0 14px; gap:6px; margin:0; border:1px solid var(--c-cta); border-radius:6px;
    background:var(--c-cta); color:var(--c-cta-fg); font-size:12px; font-weight:600; box-shadow:none; }
  .sched-app .sched-add-job:hover { background:var(--c-cta-h); border-color:var(--c-cta-h); box-shadow:none; }

  /* The technician legend and the "needs a human" strip. */
  .sched-app .sched-legend { padding:6px 16px; gap:6px; background:var(--c-surface); border-bottom:1px solid var(--c-border); }
  .sched-app .sched-legend-item { font-size:11px; font-weight:500; color:var(--c-text-2); border-radius:999px; }
  .sched-app .sched-attention { margin:0; padding:8px 16px; border:0; border-bottom:1px solid var(--c-border); border-radius:0; background:var(--c-surface); }
  .sched-app .sched-att-chip, .sched-app .sched-df-row { border-radius:999px; font-size:12px; background:var(--c-card); border:1px solid var(--c-border); color:var(--c-text); }

  /* ── The board: three panes on the ground ──────────────────────────── */
  .sched-app .sboard { gap:12px; padding:12px; background:var(--c-bg); }
  .sched-app #schedulerCalendar.sched-main {
    background:var(--c-card); border:1px solid var(--c-border); border-radius:10px; box-shadow:var(--lift), var(--lift-edge); }
  @media (min-width: 1281px) {
    .sched-app .sboard { grid-template-columns:292px minmax(0,1fr) 330px; }
  }
  @media (min-width: 961px) {
    .sched-app .spane-right {
      background:var(--c-card); border:1px solid var(--c-border); border-radius:10px; box-shadow:var(--lift), var(--lift-edge); overflow:hidden; }
    /* The card clips (overflow:hidden, for its rounded corners), so the inspector
       inside it has to do its own scrolling. Without this a job with more than a
       short screen's worth of detail — a subcontractor section, a long checklist —
       ran off the bottom of the card with no way to reach it. The sticky action
       bar pins to the bottom of this scroller. The phone sheet already had it. */
    .sched-app .spane-right > #schedInspector { flex:1; min-height:0; overflow-y:auto; }
  }
  @media (max-width: 960px) {
    .sched-app .sboard { gap:8px; padding:8px; }
  }

  /* ── The left rail (canon-rail.js) ──────────────────────────────────── */
  .sched-app .spane-left.cr-pane { gap:12px; }
  @media (min-width: 1281px) {
    .sched-app .spane-left.cr-pane { padding:0; background:transparent; border:0; overflow:hidden; }
    .sched-app .cr-pane > .cr-rail { flex:1 1 auto; min-height:0; }
    .sched-app .cr-pane .cr-body { flex:1 1 auto; min-height:0; overflow-y:auto; }
  }
  .sched-app .cr-pane > .cr-weather, .sched-app .cr-pane > .cr-brief { flex:none; }
  .sched-app .cr-pane > .card[hidden] { display:none; }
  .sched-app .cr-icon { display:grid; place-items:center; width:26px; height:26px; border:0; border-radius:6px; background:transparent;
    color:var(--c-muted); cursor:pointer; transition:background var(--dur) var(--ease), color var(--dur) var(--ease); }
  .sched-app .cr-icon:hover { background:var(--c-card-2); color:var(--c-text); }
  .sched-app .cr-icon i { font-size:15px; }

  /* Weather: a head and the week as one strip of seven. */
  .sched-app .cr-weather { padding:10px 12px 8px; }
  .sched-app .cr-weather .sched-weather { margin:0; padding:0; background:none; border:0; }
  .sched-app .cr-weather .sched-rail-head { display:flex; align-items:center; gap:8px; margin:0 0 6px; padding:0 30px 0 2px;
    font-size:10px; font-weight:600; letter-spacing:.09em; text-transform:uppercase; color:var(--c-cap); }
  .sched-app .cr-weather .sched-rail-head::after { display:none; }
  .sched-app .cr-weather .sched-wx-place { margin-left:auto; font-size:11px; font-weight:500; letter-spacing:0; text-transform:none; color:var(--c-muted); }
  .sched-app .cr-weather .sched-wx-list { display:grid; grid-template-columns:repeat(7, minmax(0,1fr)); gap:2px; }
  .sched-app .cr-weather .sched-wx-row { display:flex; flex-direction:column; align-items:center; gap:2px; min-width:0; padding:5px 0; border:0; border-radius:6px; background:transparent; cursor:pointer; }
  .sched-app .cr-weather .sched-wx-row:hover { background:var(--c-card-2); }
  .sched-app .cr-weather .sched-wx-row:first-child { background:var(--c-accent-soft); }
  .sched-app .cr-weather .sched-wx-day { flex:none; font-size:10px; font-weight:600; color:var(--c-text-2); text-align:center; }
  .sched-app .cr-weather .sched-wx-ico { font-size:15px; }
  /* The weather row sits on an accent wash, where the raw accent is 2.96:1. */
  .sched-app .sched-wx-ico { color:var(--c-on-wash-accent); }
  .sched-app .cr-weather .sched-wx-temp { min-width:0; font-family:'Inter', system-ui, sans-serif; font-variant-numeric:tabular-nums; font-size:11px; font-weight:600; color:var(--c-text); text-align:center; }
  .sched-app .cr-weather .sched-wx-lo { display:block; margin:0; font-weight:400; color:var(--c-muted); }
  .sched-app .cr-weather .sched-rail-empty { font-size:12px; color:var(--c-muted); padding:4px 2px; }
  .sched-app .cr-brief-show { position:absolute; top:6px; right:6px; color:var(--c-accent); }

  /* The briefing. */
  .sched-app .cr-brief .sched-brief { margin:0; padding:0; }
  .sched-app .cr-brief .sched-brief-cta { justify-content:flex-start; gap:8px; width:100%; padding:12px 40px 12px 14px; border:0; border-radius:10px;
    background:transparent; color:var(--c-text); font-size:13px; font-weight:600; }
  .sched-app .cr-brief .sched-brief-cta:hover { background:var(--c-card-2); }
  .sched-app .cr-brief .sched-brief-cta i { color:var(--c-accent); }
  .sched-app .cr-brief .sched-rail-head { display:flex; align-items:center; gap:8px; margin:0; padding:12px 40px 6px 14px;
    font-size:13px; font-weight:600; letter-spacing:0; text-transform:none; color:var(--c-text); }
  .sched-app .cr-brief .sched-rail-head i { color:var(--c-accent); }
  .sched-app .cr-brief .sched-brief-refresh { margin-left:auto; width:26px; height:26px; border:0; border-radius:6px; background:transparent; color:var(--c-muted); }
  .sched-app .cr-brief .sched-brief-refresh:hover { background:var(--c-card-2); color:var(--c-text); }
  .sched-app .cr-brief .sched-brief-body, .sched-app .cr-brief .sched-rail-empty { padding:0 14px 12px; font-size:13px; line-height:1.55; color:var(--c-text-2); }
  .sched-app .cr-brief-x { position:absolute; top:9px; right:8px; }

  /* The rail card: strip, tabs, the open panel. */
  .sched-app .cr-rail { overflow:hidden; }
  .sched-app .cr-top { flex:none; border-bottom:1px solid var(--c-border); }
  .sched-app .cr-strip { display:flex; align-items:center; gap:6px; padding:12px 12px 10px; overflow-x:auto; scrollbar-width:none; }
  /* Initials on the technician's own colour, SOLID, measured 3.19-3.31:1 in
     light and no better in dark — the colour is picked to tell people apart on
     a board, never against 11px letters. The tint keeps the identity and puts
     the initials back on the page's ink, the same move as .sched-ev-av. */
  .sched-app .cr-av { position:relative; flex:none; display:grid; place-items:center; width:30px; height:30px; padding:0; border:0; border-radius:8px;
    background:color-mix(in srgb, var(--cr-av, var(--c-accent)) 26%, var(--c-card)); color:var(--c-text); font-size:11px; font-weight:600; cursor:pointer;
    transition:transform var(--dur) var(--ease); }
  .sched-app .cr-av:hover { transform:translateY(-1px); }
  .sched-app .cr-av[aria-pressed="true"] { outline:2px solid var(--c-accent); outline-offset:2px; }
  .sched-app .cr-av-all { background:var(--c-sunken); color:var(--c-text-2); border:1px solid var(--c-border); }
  .sched-app .cr-av-all i { font-size:15px; }
  .sched-app .cr-av .cr-live { position:absolute; right:-3px; bottom:-3px; width:9px; height:9px; border-radius:999px; background:var(--c-ok); border:2px solid var(--c-card); }
  .sched-app .cr-tabs { display:flex; margin:0 12px 12px; }
  .sched-app .cr-tabs button { flex:1 1 auto; display:inline-flex; align-items:center; justify-content:center; gap:4px; padding:4px 6px; white-space:nowrap; font-size:11.5px; }
  .sched-app .cr-tabs button[data-p="techs"] { flex:0 0 32px; padding:0; }
  .sched-app .cr-tabs button i { font-size:14px; }
  .sched-app .cr-tabs button[hidden] { display:none; }
  .sched-app .cr-tabs .cr-n { font-family:'Inter', system-ui, sans-serif; font-variant-numeric:tabular-nums; color:var(--c-cap); }
  .sched-app .cr-tabs .cr-n:empty { display:none; }
  .sched-app .cr-tabs button.sched-drop-active { background:var(--c-accent-soft); color:var(--c-on-wash-accent); box-shadow:inset 0 0 0 1px var(--c-accent-edge); }
  .sched-app .cr-panel { padding:12px; }
  .sched-app .cr-panel:not(.on) { display:none; }
  .sched-app .cr-panel .sched-rail { margin:0; padding:0; background:none; border:0; }
  .sched-app .cr-panel .sched-rail-head { display:flex; align-items:center; gap:8px; margin:0; padding:0 2px 10px;
    font-size:10px; font-weight:600; letter-spacing:.09em; text-transform:uppercase; color:var(--c-cap); }
  .sched-app .cr-panel .sched-rail-head::after { display:none; }
  .sched-app .cr-panel .sched-rail-count { margin-left:auto; padding:0 6px; border-radius:999px; font-family:'Inter', system-ui, sans-serif; font-size:10px; font-weight:600;
    background:var(--c-sunken); color:var(--c-text-2); }
  .sched-app .cr-empty { padding:18px 6px; font-size:12.5px; color:var(--c-muted); text-align:center; }
  .sched-app .cr-panel .sched-unsched-card, .sched-app .cr-panel .sched-stage-card, .sched-app .cr-panel .sched-servicedue-card {
    border-radius:8px; box-shadow:none; }
  .sched-app .cr-panel .sched-unsched-card { background:var(--c-card); border:1px solid var(--c-border); }
  .sched-app .cr-panel .sched-unsched-card:hover { border-color:var(--c-border-2); box-shadow:none; transform:none; }
  .sched-app .cr-panel .sched-trade-tag { border-radius:4px; font-size:10px; font-weight:600; letter-spacing:.06em; }
  .sched-app .cr-panel .sched-tech-item { border-radius:8px; }

  /* ── The week and day time grid ─────────────────────────────────────── */
  .sched-app .sched-tg { background:var(--c-card); border-radius:10px; }
  .sched-app .sched-tg-head { background:var(--c-card); border-bottom:1px solid var(--c-border); border-radius:10px 10px 0 0; }
  .sched-app .sched-tg-corner, .sched-app .sched-tg-gutter { border-right:1px solid var(--c-border); }
  .sched-app .sched-tg-headcell { border-left:1px solid var(--c-border); }
  .sched-app .sched-tg-dow { font-size:10px; font-weight:600; letter-spacing:.08em; color:var(--c-cap); }
  .sched-app .sched-tg-dnum { font-family:'Inter', system-ui, sans-serif; font-variant-numeric:tabular-nums; font-size:16px; font-weight:600; color:var(--c-text); }
  .sched-app .sched-tg-headcell.is-today .sched-tg-dow { color:var(--c-on-wash-accent); }
  .sched-app .sched-tg-headcell.is-today .sched-tg-dnum { background:var(--c-cta); color:var(--c-cta-fg); }
  .sched-app .sched-tg-headcell.is-offday, .sched-app .sched-tg-col.is-offday { background:color-mix(in srgb, var(--c-sunken) 75%, transparent); }
  .sched-app .sched-allday-row { background:var(--c-card); border-bottom:1px solid var(--c-border); }
  .sched-app .sched-allday-label { font-size:9px; font-weight:600; letter-spacing:.08em; color:var(--c-cap); white-space:nowrap; text-align:right; }
  .sched-app .sched-allday-cell, .sched-app .sched-tg-col { border-left:1px solid var(--c-border); }
  .sched-app .sched-tg-cell { border-top:1px solid var(--c-border); }
  .sched-app .sched-tg-cell:hover { background:color-mix(in srgb, var(--c-accent) 6%, transparent); }
  .sched-app .sched-tg-col.is-today { background:color-mix(in srgb, var(--c-accent) 4%, transparent); }
  .sched-app .sched-tg-hour span { font-family:'Inter', system-ui, sans-serif; font-size:10px; color:var(--c-cap); }

  /* Jobs: technician tint, status edge — the legacy encoding, the canon's shape. */
  .sched-app .sched-event, .sched-app .sched-swim-event {
    border-radius:6px; box-shadow:none;
    background:color-mix(in srgb, var(--jc, var(--c-accent)) 12%, var(--c-card));
    border:1px solid color-mix(in srgb, var(--jc, var(--c-accent)) 30%, transparent);
    border-left:3px solid var(--st, var(--jc, var(--c-accent))); }
  .sched-app .sched-event:hover, .sched-app .sched-swim-event:hover { filter:none; box-shadow:0 4px 14px rgb(0 0 0 / .12); }
  .sched-app .sched-event-time { font-family:'Inter', system-ui, sans-serif; font-size:10px; font-weight:600; color:var(--c-text-2); opacity:1; }
  .sched-app .sched-event-title { font-size:11.5px; font-weight:600; color:var(--c-text); }
  /* --c-text-2, not --c-muted. The muted ink is measured on the page's own
     grounds, and an event card is not one of them: it is a 12% technician tint
     over the card, which costs about a point. At 10px that took the sub line to
     3.5:1 and, on a completed job, to 2.3:1. */
  .sched-app .sched-event-sub, .sched-app .sched-swim-sub { font-size:10px; color:var(--c-text-2); opacity:1; }
  /* The avatar was the technician's colour SOLID with white initials — 2.2:1 on
     the default green, 2.96:1 on the blue, at 8px. The tint keeps the technician
     recognisable at a glance and puts the initials back on the page's own ink.
     Same tint idea as the card itself, one step stronger so the square reads. */
  .sched-app .sched-ev-av {
    border-radius:4px; font-weight:600;
    background:color-mix(in srgb, var(--jc, var(--c-accent)) 26%, var(--c-card));
    color:var(--c-text); }
  .sched-app .sched-chip, .sched-app .sched-swim-chip { border-radius:4px; font-size:10.5px; font-weight:500; color:var(--c-text); }
  .sched-app .sched-nowline, .sched-app .sched-swim-now { background:var(--c-danger); }
  .sched-app .sched-nowline::before, .sched-app .sched-swim-now::before { background:var(--c-danger); }
  /* html[data-theme="light"] .sched-nowline-lbl is (0,2,1) in the legacy sheet
     and beat the .sched-app form, which is why the "now" label stayed white on
     the raw accent (3.31:1) in light while dark looked right. */
  html[data-theme] .sched-app .sched-nowline-lbl { font-family:'Inter', system-ui, sans-serif; font-weight:600; background:var(--c-danger); color:var(--c-cta-fg); }

  /* Flags and glyphs written in the board's own palette, on the canon's tints:
     the warranty shield measured 1.88:1, the unassigned signature 2.91:1. */
  .sched-app .sched-warr-ico,
  .sched-app .sched-sig-unassigned { color:var(--c-on-wash-warn); }
  .sched-app .sched-unsched-sug { color:var(--c-cta); }
  .sched-app .sched-insp-empty i { color:var(--c-muted); }
  .sched-app #schedulerCalendar [data-job-id].is-inspecting { outline:2px solid var(--c-accent); outline-offset:1px; }

  /* A finished job: the TINT drains, the text does not fade.
     The legacy board dimmed the whole card (opacity .74, and .5 before the canon
     pass), which is a contrast cut applied to everything inside it — every run
     on a completed event failed AA, the sub line worst at 2.31:1. Draining the
     technician tint says "done" at least as loudly on a board read from across a
     room, and it costs the text nothing. The status edge stays: it is what says
     WHICH end state the job reached. */
  .sched-app .sched-chip.is-complete,
  .sched-app .sched-event.is-complete,
  .sched-app .sched-swim-event.is-complete,
  .sched-app .sched-list-card.is-complete {
    opacity:1;
    background:var(--c-card-2);
    border-color:var(--c-border); }
  .sched-app .sched-event.is-complete .sched-event-title,
  .sched-app .sched-swim-event.is-complete { color:var(--c-text-2); }

  /* ── The timeline ───────────────────────────────────────────────────── */
  .sched-app .sched-swim { background:var(--c-card); border-radius:10px; }
  .sched-app .sched-swim-actions { border-bottom:1px solid var(--c-border); }
  .sched-app .sched-swim-head { background:var(--c-sunken); border-bottom:1px solid var(--c-border); }
  .sched-app .sched-swim-hour { font-family:'Inter', system-ui, sans-serif; font-size:10px; color:var(--c-cap); border-left:1px solid var(--c-border); }
  .sched-app .sched-swim-row { border-bottom:1px solid var(--c-border); }
  .sched-app .sched-swim-row:hover { background:color-mix(in srgb, var(--c-card-2) 60%, transparent); }
  .sched-app .sched-swim-label, .sched-app .sched-swim-corner { border-right:1px solid var(--c-border); }
  .sched-app .sched-lane-av { border-radius:8px; font-weight:600; color:var(--c-accent-fg); }
  .sched-app .sched-lane-name { font-size:13px; font-weight:600; color:var(--c-text); }
  .sched-app .sched-swim-gridline { background:var(--c-border); }
  .sched-app .sched-swim-pct { font-family:'Inter', system-ui, sans-serif; color:var(--c-muted); }

  /* ── The inspector ──────────────────────────────────────────────────── */
  .sched-app .sched-insp-top { border-bottom:1px solid var(--c-border); }
  .sched-app .sched-insp-pill { gap:6px; padding:3px 9px 3px 7px; border-radius:999px; font-size:11px; font-weight:500; letter-spacing:0; text-transform:none;
    border:1px solid color-mix(in srgb, var(--s, var(--c-accent)) 34%, transparent); }
  .sched-app .sched-insp-wo { font-family:'Inter', system-ui, sans-serif; font-weight:500; color:var(--c-cap); }
  .sched-app .sched-insp-title { font-size:16px; font-weight:600; letter-spacing:-.01em; color:var(--c-text); }
  .sched-app .sched-insp-cust { color:var(--c-text-2); }
  .sched-app .sched-insp .sched-insp-sec { border-top:1px solid var(--c-border); }
  .sched-app .sched-insp-t { font-size:10px; font-weight:600; letter-spacing:.09em; color:var(--c-cap); }
  .sched-app .sched-insp-dl dt { color:var(--c-muted); }
  .sched-app .sched-insp-dl dd { font-weight:500; color:var(--c-text); }
  .sched-app .sched-insp-step .lbl { font-weight:500; color:var(--c-cap); }

  /* feature_motion_kit: the current step's static halo (bridge, above) breathes
     instead — done steps stay exactly as they are, never pulsing. */
  :root.mk-on .sched-app .sched-insp-step.is-cur .dot { position:relative; box-shadow:none; }
  :root.mk-on .sched-app .sched-insp-step.is-cur .dot::after {
    content:''; position:absolute; inset:-4px; border-radius:50%;
    border:1.5px solid var(--st, var(--sc-scheduled));
    animation:sched-insp-pulse 1.6s ease-out infinite;
  }
  @keyframes sched-insp-pulse {
    0% { transform:scale(.7); opacity:.8; }
    100% { transform:scale(1.5); opacity:0; }
  }
  @media (prefers-reduced-motion: reduce) {
    :root.mk-on .sched-app .sched-insp-step.is-cur .dot::after { animation:none; opacity:0; }
  }

  /* feature_motion_kit: the rail "Loading…" placeholders (customers, equipment,
     reports, timesheet) get a small spinning icon; off, they stay the same
     bare text they are today. */
  .sched-app .sched-empty i, .sched-app .sched-rail-empty i { display:none; }
  :root.mk-on .sched-app .sched-empty i, :root.mk-on .sched-app .sched-rail-empty i {
    display:inline-block; margin-right:6px; color:var(--c-accent);
    animation:sched-rail-spin 1s linear infinite;
  }
  @keyframes sched-rail-spin { to { transform:rotate(360deg); } }
  @media (prefers-reduced-motion: reduce) {
    :root.mk-on .sched-app .sched-empty i, :root.mk-on .sched-app .sched-rail-empty i { animation-duration:6s; }
  }
  .sched-app .sched-insp-tr, .sched-app .sched-insp-doc, .sched-app .sched-insp-tr-unlink { border-radius:8px; border-color:var(--c-border); background:var(--c-card); }
  .sched-app .sched-insp-tr:hover, .sched-app .sched-insp-doc:hover { background:var(--c-card-2); border-color:var(--c-border-2); }
  .sched-app .sched-insp-actions { background:var(--c-card); border-top:1px solid var(--c-border); }
  .sched-app .sched-insp-actions .btn { height:34px; padding:0 12px; border-radius:6px; font-size:12px; margin:0; }
  .sched-app .sched-insp-actions .btn-primary { background:var(--c-cta); border:1px solid var(--c-cta); color:var(--c-cta-fg); font-weight:600; box-shadow:none; }
  .sched-app .sched-insp-actions .btn-primary:hover { background:var(--c-cta-h); border-color:var(--c-cta-h); box-shadow:none; }
  .sched-app .sched-insp-actions .btn-secondary { width:auto; background:var(--c-card); border:1px solid var(--c-border); color:var(--c-text); font-weight:500; }

  /* ── Section titles ─────────────────────────────────────────────────────
     The legacy title is a 30px gradient-clipped word with a glowing bar. The
     canon titles a page in plain ink, sentence case, and draws no bar. */
  .sched-app .section-title { padding-left:0; background:none; -webkit-text-fill-color:currentColor; text-transform:none; letter-spacing:-.01em; color:var(--c-text); }
  .sched-app .section-title::before { display:none; }
  .sched-app .rec-section .section-title { font-size:20px; font-weight:600; line-height:1.2; margin-bottom:4px; }
  .sched-app .section-subtitle { padding-left:0; font-size:13px; color:var(--c-muted); }

  /* ── Dialogs ────────────────────────────────────────────────────────────
     The same dialog canon-chrome.css draws for Books (.bk-overlay/.bk-modal):
     a flat card with the canon radius and float, a hairline head and foot. */
  .sched-app .modal-overlay { background:color-mix(in srgb, var(--c-ink-deep) 58%, transparent); backdrop-filter:none; }
  .sched-app .modal-box { background:var(--c-card); border:1px solid var(--c-border); border-radius:10px; box-shadow:var(--float); color:var(--c-text); }
  .sched-app .sched-modal-head { padding:14px 18px; border-bottom:1px solid var(--c-border); background:none; }
  .sched-app .sched-modal-head h3 { font-size:16px; font-weight:600; letter-spacing:-.012em; color:var(--c-text); }
  .sched-app .sched-modal-ico { width:28px; height:28px; border:0; border-radius:6px; background:var(--c-accent-soft); color:var(--c-accent); font-size:15px; }
  .sched-app .sched-modal-x { width:30px; height:30px; border:0; border-radius:6px; background:transparent; color:var(--c-muted); }
  .sched-app .sched-modal-x:hover { background:var(--c-card-2); color:var(--c-text); }
  .sched-app .sched-modal-sub { border-color:var(--c-border); color:var(--c-cap); }
  .sched-app .sched-modal .sched-modal-footer { padding:12px 18px; border-top:1px solid var(--c-border); background:var(--c-card); }
  .sched-app .sset-sec-head { font-size:10px; font-weight:600; letter-spacing:.09em; color:var(--c-cap); border-bottom-color:var(--c-border); }
  .sched-app .sset-sec-head i { color:var(--c-accent); }

  /* Fields: the canon well — sunken, 34px, 6px — lifting to the card on focus. */
  .sched-app .form-group label { font-size:12px; font-weight:500; letter-spacing:0; text-transform:none; color:var(--c-text-2); }
  .sched-app .sched-modal-body input[type="text"],
  .sched-app .sched-modal-body input[type="email"],
  .sched-app .sched-modal-body input[type="tel"],
  .sched-app .sched-modal-body input[type="time"],
  .sched-app .sched-modal-body input[type="date"],
  .sched-app .sched-modal-body input[type="number"],
  .sched-app .sset-tabbody input[type="text"],
  .sched-app .sset-tabbody input[type="email"],
  .sched-app .sset-tabbody input[type="tel"],
  .sched-app .sset-tabbody input[type="time"],
  .sched-app .sset-tabbody input[type="date"],
  .sched-app .sset-tabbody input[type="number"],
  .sched-app .sched-modal .filter-select {
    min-height:34px; padding:6px 10px; background:var(--c-sunken); border:1px solid var(--c-border); border-radius:6px;
    color:var(--c-text); font-size:13px; }
  .sched-app .sched-modal textarea { padding:8px 10px; background:var(--c-sunken); border:1px solid var(--c-border); border-radius:6px; color:var(--c-text); font-size:13px; line-height:1.5; }
  .sched-app .sched-modal input::placeholder, .sched-app .sched-modal textarea::placeholder { color:var(--c-cap); }
  .sched-app .sched-modal input:focus, .sched-app .sched-modal textarea:focus, .sched-app .sched-modal .filter-select:focus {
    background:var(--c-card); border-color:var(--c-accent-edge); box-shadow:0 0 0 3px var(--c-accent-soft); outline:none; }
  .sched-app .sched-modal .btn-secondary { width:auto; margin:0; height:34px; padding:0 12px; border:1px solid var(--c-border); border-radius:6px;
    background:var(--c-card); color:var(--c-text); font-size:12px; font-weight:500; }
  .sched-app .sched-modal .btn-secondary:hover { background:var(--c-card-2); border-color:var(--c-border-2); }

  /* ── The job editor (feature_job_editor_v2) ─────────────────────────── */
  .sched-app .jm2-jobno { background:var(--c-sunken); border-color:var(--c-border); color:var(--c-cap); font-weight:600; }
  .sched-app .jm2-meta { color:var(--c-text-2); }
  .sched-app .jm2-stepper { gap:2px; padding:2px; background:var(--c-sunken); border:1px solid var(--c-border); border-radius:6px; }
  .sched-app .jm2-step { border-radius:4px; font-size:12px; font-weight:500; color:var(--c-cap); }
  .sched-app .jm2-step:hover { background:transparent; color:var(--c-text-2); }
  .sched-app .jm2-step.is-done { color:var(--c-on-wash-ok); }
  .sched-app .jm2-step.is-cur { background:var(--c-card); color:var(--c-text); font-weight:600; box-shadow:var(--lift); }
  /* The parts/materials add row: the field rule above sized every number input to
     the full row, which pushed the item field and Add button out of the dialog. */
  .sched-app .sched-modal-body .job-parts-add input[type="number"] { width:68px; flex:0 0 auto; }
  .sched-app .sched-modal-body .job-parts-add input[type="text"] { width:auto; flex:1 1 auto; min-width:0; }
  /* Notes and progress notes span their column; they stopped at their cols width. */
  .sched-app #jobModal textarea { width:100%; box-sizing:border-box; }
  /* Contrast (measured by scripts/canon-contrast-sweep.js with the editor open):
     accent-on-wash and accent links sat at 2.8–3.3:1, the meta separators near
     1.4:1, and the quote → job → invoice trail's washed steps under 3:1. */
  .sched-app .jm2-chip.on, .sched-app .jm2-more-btn, .sched-app #jobModal .sched-newtech { color:var(--c-on-wash-accent); }
  .sched-app .jm2-meta .jm2-sep { color:var(--c-cap); }
  .sched-app #jobModal .ui-lc__step.is-current > :is(span, em, i) { color:var(--c-on-wash-accent); }
  .sched-app #jobModal .ui-lc__step.is-todo > :is(span, i) { color:var(--c-text-2); }
  .sched-app #jobModal .ui-lc__sep { color:var(--c-muted); }

  /* ── Stage 3: month ─────────────────────────────────────────────────── */
  .sched-app .sched-month-head { background:var(--c-card); border-bottom:1px solid var(--c-border); border-radius:10px 10px 0 0; }
  .sched-app .sched-month-head > div { font-size:10px; font-weight:600; letter-spacing:.08em; color:var(--c-cap); border-left-color:var(--c-border); }
  .sched-app .sched-month-cell { border-color:var(--c-border); }
  .sched-app .sched-month-cell:hover { background:color-mix(in srgb, var(--c-accent) 4%, transparent); }
  .sched-app .sched-month-cell.is-blank { background:var(--c-sunken); }
  .sched-app .sched-month-cell.is-offday { background:color-mix(in srgb, var(--c-sunken) 75%, transparent); }
  .sched-app .sched-daynum { font-family:'Inter', system-ui, sans-serif; font-variant-numeric:tabular-nums; font-size:12px; font-weight:500; color:var(--c-text-2); }
  .sched-app .sched-month-cell.is-today .sched-daynum { background:var(--c-cta); color:var(--c-cta-fg); font-weight:600; }
  .sched-app .sched-more { font-size:10px; font-weight:500; color:var(--c-cap); }

  /* ── List ───────────────────────────────────────────────────────────── */
  .sched-app .sched-list-date { font-size:10px; font-weight:600; letter-spacing:.09em; color:var(--c-cap); border-bottom-color:var(--c-border); }
  .sched-app .sched-list-card { border:1px solid var(--c-border); border-radius:8px; background:var(--c-card); box-shadow:none; }
  .sched-app .sched-list-card:hover { background:var(--c-card-2); border-color:var(--c-border-2); box-shadow:none; }
  .sched-app .sched-list-card.is-selected { background:var(--c-accent-soft); border-color:var(--c-accent-edge); outline:0; }
  .sched-app .sched-list-cust { font-size:13px; font-weight:600; color:var(--c-text); }
  .sched-app .sched-list-meta { font-size:12px; color:var(--c-muted); }
  .sched-app .sched-list-check { accent-color:var(--c-accent); }

  /* ── History ────────────────────────────────────────────────────────── */
  .sched-app .sched-history-title { font-size:16px; font-weight:600; color:var(--c-text); }
  .sched-app input.sched-history-search { height:34px; padding:0 10px 0 34px; background:var(--c-sunken); border:1px solid var(--c-border); border-radius:6px; color:var(--c-text); }
  .sched-app input.sched-history-search:focus { background:var(--c-card); border-color:var(--c-accent-edge); box-shadow:0 0 0 3px var(--c-accent-soft); }
  .sched-app .sched-hist-count, .sched-app .shist-date { font-size:10px; font-weight:600; letter-spacing:.09em; color:var(--c-cap); }
  .sched-app .shist-date { border-bottom-color:var(--c-border); }
  .sched-app .shist-card { border:1px solid var(--c-border); border-radius:8px; background:var(--c-card); }
  .sched-app .shist-card:hover { background:var(--c-card-2); border-color:var(--c-border-2); }
  .sched-app .shist-stripe { width:3px; }
  .sched-app .shist-name { font-size:14px; font-weight:600; color:var(--c-text); }
  .sched-app .shist-badge { padding:2px 8px; font-size:11px; font-weight:500; letter-spacing:0; text-transform:none; }
  .sched-app .shist-meta { color:var(--c-text-2); }
  .sched-app .shist-type { font-weight:500; color:var(--c-text); }
  .sched-app .shist-time, .sched-app .shist-addr { color:var(--c-muted); }
  .sched-app .shist-flags { background:color-mix(in srgb, var(--c-warn) 12%, transparent); color:var(--c-on-wash-warn); font-weight:600; }

  /* ── Quick create ───────────────────────────────────────────────────── */
  .sched-app .sched-qc-pop { background:var(--c-card); border:1px solid var(--c-border); border-radius:10px; box-shadow:var(--float); color:var(--c-text); }
  .sched-app .sched-qc-pop .sched-qc-head { font-size:13px; font-weight:600; color:var(--c-text); border-bottom-color:var(--c-border); }
  .sched-app .sched-qc-pop .sched-qc-f > label { font-size:10px; font-weight:600; letter-spacing:.07em; color:var(--c-cap); }
  .sched-app .sched-qc-pop .sched-qc-cust, .sched-app .sched-qc-pop .sched-qc-type, .sched-app .sched-qc-pop .sched-qc-tech {
    background:var(--c-sunken); border-color:var(--c-border); border-radius:6px; color:var(--c-text); }
  .sched-app .sched-qc-pop .sched-qc-dchip { background:var(--c-card); border-color:var(--c-border); border-radius:6px; color:var(--c-text-2); font-weight:500; }
  .sched-app .sched-qc-pop .sched-qc-dchip.on { background:var(--c-accent-soft); border-color:var(--c-accent-edge); color:var(--c-on-wash-accent); }
  .sched-app .sched-qc-pop .sched-qc-more { color:var(--c-on-wash-accent); }
  .sched-app .sched-qc-pop .sched-qc-cancel { background:var(--c-card); border-color:var(--c-border); border-radius:6px; color:var(--c-text); font-weight:500; }
  .sched-app .sched-qc-pop .sched-qc-go { background:var(--c-cta); color:var(--c-cta-fg); border-radius:6px; font-weight:600; box-shadow:none; }
  .sched-app .sched-qc-pop .sched-qc-go:hover { background:var(--c-cta-h); }

  /* ── Settings tabs ──────────────────────────────────────────────────── */
  .sched-app .sset-tabs { background:var(--c-surface); border-right-color:var(--c-border); }
  .sched-app .sset-tab { border-radius:6px; font-weight:500; color:var(--c-text-2); }
  .sched-app .sset-tab i { color:var(--c-muted); }
  .sched-app .sset-tab:hover { background:var(--c-card-2); color:var(--c-text); }
  .sched-app .sset-tab.active { background:var(--c-accent-soft); color:var(--c-on-wash-accent); font-weight:600; }
  .sched-app .sset-tab.active i { color:var(--c-accent); }

  /* ── Records: customers, equipment, reports ─────────────────────────────
     Status chips keep their tones and coloured avatars their white initials:
     only shape is set on .rec-chip and .rec-avatar, never colour. */
  .sched-app .rec-search input { height:34px; padding:0 10px 0 32px; background:var(--c-sunken); border:1px solid var(--c-border); border-radius:6px; color:var(--c-text); }
  .sched-app .rec-search input:focus { background:var(--c-card); border-color:var(--c-accent-edge); box-shadow:0 0 0 3px var(--c-accent-soft); }
  .sched-app .rec-count { font-size:10px; font-weight:600; letter-spacing:.09em; text-transform:uppercase; color:var(--c-cap); }
  .sched-app .rec-card { border:1px solid var(--c-border); border-radius:10px; background:var(--c-card); box-shadow:var(--lift), var(--lift-edge); }
  .sched-app .rec-card:hover { background:var(--c-card-2); border-color:var(--c-border-2); }
  .sched-app .rec-avatar { border-radius:8px; font-weight:600; }
  .sched-app .rec-title { font-weight:600; color:var(--c-text); }
  .sched-app .rec-sub { color:var(--c-muted); }
  .sched-app .rec-chip { padding:3px 9px; border-radius:999px; font-weight:500; }
  .sched-app .rec-empty { color:var(--c-muted); }
  .sched-app .equip-row, .sched-app .equip-form { border-color:var(--c-border); border-radius:8px; background:var(--c-sunken); }
  .sched-app .eqv-hero-ico { border-radius:8px; background:var(--c-accent-soft); color:var(--c-accent); }
  .sched-app .eqv-hero-title { font-weight:600; color:var(--c-text); }
  .sched-app .eqv-specs { border-radius:8px; background:var(--c-border); border-color:var(--c-border); }
  .sched-app .eqv-spec { background:var(--c-card); }
  .sched-app .eqv-k, .sched-app .eqv-block-h { font-size:10px; font-weight:600; letter-spacing:.07em; color:var(--c-cap); }

  /* ── The customer drawer ────────────────────────────────────────────── */
  .sched-app .cust-drawer-backdrop { background:color-mix(in srgb, var(--c-ink-deep) 45%, transparent); backdrop-filter:none; }
  .sched-app .cust-drawer { background:var(--c-card); border-left:1px solid var(--c-border); box-shadow:var(--float); }
  .sched-app .cust-drawer-avatar { border-radius:8px; }

  /* ── Map ────────────────────────────────────────────────────────────────
     Leaflet draws the tiles; the canon draws the frame, the bar and the stop list. */
  .sched-app .sched-mapview { background:var(--c-card); border-radius:10px; overflow:hidden; }
  .sched-app .sched-mapview-bar { gap:10px; padding:10px 14px; border-bottom:1px solid var(--c-border); background:var(--c-card); }
  .sched-app .sched-mapview #dayMapStatus { font-size:12px; color:var(--c-muted); }
  .sched-app .sched-mapview #dayMapList { background:var(--c-surface); border-left:1px solid var(--c-border); }
  .sched-app .day-map-stop { border-radius:8px; }
  .sched-app .day-map-stop:hover { background:var(--c-card-2); }
  .sched-app .day-map-num { font-family:'Inter', system-ui, sans-serif; font-variant-numeric:tabular-nums; font-weight:600; }
  .sched-app .day-map-total { font-size:12px; font-weight:600; color:var(--c-text-2); }
  .sched-app .day-map-leg { color:var(--c-muted); }
  .sched-app .day-map-leg.tight { color:var(--c-on-wash-warn); }
  .sched-app .day-map-unlocated { border-top-color:var(--c-border); }
  .sched-app .day-map-tight-badge { border-radius:999px; }

  /* ── Job activity (jobactivity.js, feature_job_activity) ────────────────
     A quiet, newest-first list: one sentence, then who and when. The dot says
     who acted — the office, the field app, or the system. */
  .sched-app .jact-list { display:flex; flex-direction:column; }
  .sched-app .jact-row { display:flex; align-items:flex-start; gap:10px; padding:8px 0; border-bottom:1px solid var(--c-border); }
  .sched-app .jact-row:last-child { border-bottom:0; }
  .sched-app .jact-dot { flex:none; width:7px; height:7px; margin-top:6px; border-radius:50%; background:var(--c-cap); }
  .sched-app .jact-row[data-actor="tech"] .jact-dot { background:var(--c-accent); }
  .sched-app .jact-row[data-actor="system"] .jact-dot { background:var(--c-border); }
  .sched-app .jact-row[data-tone="warn"] .jact-dot { background:var(--c-warn); }
  .sched-app .jact-main { min-width:0; }
  .sched-app .jact-label { font-size:13px; color:var(--c-text); line-height:1.4; }
  .sched-app .jact-meta { margin-top:2px; font-size:12px; color:var(--c-muted); }
  .sched-app .jact-empty { padding:6px 0; font-size:12px; color:var(--c-muted); }

  /* ── Multi-select drag (multimove.js, feature_sched_multidrag) ──────────
     "+N" on the ghost — the count of OTHER jobs coming along, so dropping a
     group doesn't read as one chip moving and the rest left behind. */
  .sched-app .sched-drag-ghost { position: relative; }
  .sched-app .sched-drag-ghost-count {
    position: absolute; top: -8px; right: -8px; min-width: 20px; height: 20px; padding: 0 6px;
    border-radius: 999px; background: var(--c-accent-soft); color: var(--c-on-wash-accent);
    box-shadow: inset 0 0 0 1px var(--c-accent-edge), 0 1px 4px rgba(0,0,0,.35);
    font-size: 11px; font-weight: 700; line-height: 20px; text-align: center;
  }

  /* ── Landing slot + drop glide (dnd.js, feature_sched_drop_glide) ────────
     :root.sched-glide is the flag, parked on <html> by initSchedulerDnD. With
     it off nothing below matches, and the drag is the one that shipped.

     The ghost stands upright on the canon's float shadow. The legacy one
     leant 1° on a heavy black drop (the bridge's .sched-drag-ghost), which
     read as a toy against a flat board. */
  :root.sched-glide .sched-app > .sched-drag-ghost { transform:none; opacity:.96; box-shadow:var(--float); }

  /* A block says it can be picked up, and the closed hand holds for the whole
     move. The resize grip is a child with its own ns-resize, so it keeps it;
     a resize never sets .sched-dnd-moving. */
  :root.sched-glide #schedulerCalendar :is(.sched-event, .sched-swim-event, .sched-chip),
  :root.sched-glide .sched-stage-card { cursor:grab; }
  :root.sched-glide body.sched-dnd-moving,
  :root.sched-glide body.sched-dnd-moving *,
  :root.sched-glide body.sched-dnd-moving #schedulerCalendar * { cursor:grabbing; }

  /* Where the job will land: its exact footprint in the column or lane under
     the pointer, snapped by the drop's own maths (dnd.js _dropStartMin). It
     replaces the whole-column wash on time targets — the target gets
     .sched-drop-slotted instead of .sched-drop-active. Under the now line,
     the sticky lane labels and the header (z-index 1); over the jobs, so a
     clash shows as an overlap rather than hiding behind one. */
  :root.sched-glide .sched-drop-slot {
    position:absolute; inset-inline:var(--sp-0_5); z-index:1; box-sizing:border-box; pointer-events:none;
    border:1px solid var(--app-accent); border-radius:6px;
    background:color-mix(in srgb, var(--app-accent) 12%, transparent);
  }
  /* A lane runs sideways: left/width come inline, top/bottom from here. */
  :root.sched-glide .sched-drop-slot.is-swim { inset-inline:auto; inset-block:var(--sp-0_5); }
  /* Lane state (feature_sched_lane_state) marks the TARGET as clashing or on
     leave; the slot takes the same colour, since it is what the eye is on. */
  :root.sched-glide .sched-drop-warn > .sched-drop-slot {
    border-color:var(--c-warn); background:color-mix(in srgb, var(--c-warn) 12%, transparent);
  }
  :root.sched-glide .sched-drop-block > .sched-drop-slot {
    border-color:var(--c-danger); background:color-mix(in srgb, var(--c-danger) 12%, transparent);
  }
  /* The new range, on <body> above the ghost (which otherwise sits right on
     top of the slot). Inter figures, one line, the technician after it when
     the drop hands the job to someone else. */
  :root.sched-glide .sched-drop-slot-tag {
    position:fixed; z-index:10000; pointer-events:none; box-sizing:border-box;
    display:inline-flex; align-items:baseline; gap:var(--sp-1_5);
    padding:var(--sp-0_5) var(--sp-2); border:1px solid var(--app-accent); border-radius:4px;
    background:var(--c-card); box-shadow:var(--float);
    font-size:11px; line-height:1.4; white-space:nowrap; color:var(--c-text-2);
  }
  :root.sched-glide .sched-drop-slot-time { font-family:'Inter', system-ui, sans-serif; font-variant-numeric:tabular-nums; font-weight:600; color:var(--c-on-wash-accent); }
  :root.sched-glide .sched-drop-slot-who { font-weight:500; }
  :root.sched-glide .sched-drop-slot-who[hidden] { display:none; }

  /* The glide itself: a View Transition in which only the dropped job is
     named (dnd.js _glideVT). The root's default cross-fade is switched off, so
     the rest of the board swaps in one frame and only the block travels.
     .sched-gliding is on <html> only while a glide runs. */
  :root.sched-gliding::view-transition-group(*) {
    animation-duration:220ms; animation-timing-function:var(--ease-standard, cubic-bezier(.2, .8, .2, 1));
  }
  :root.sched-gliding::view-transition-old(root),
  :root.sched-gliding::view-transition-new(root) { animation:none; }
  @media (prefers-reduced-motion: reduce) {
    /* dnd.js never starts one under reduce; this is the belt to that brace. */
    :root.sched-gliding::view-transition-group(*),
    :root.sched-gliding::view-transition-old(*),
    :root.sched-gliding::view-transition-new(*) { animation:none; }
  }

  /* ── Fit to screen (views.js _schedPaintFitted) ──────────────────────────
     The hour-axis views get .is-fit when their hour size is worked out from
     this box. The grid's body is flex:1, so its height is exactly the room left
     under the day header and the all-day row — which is what views.js measures.
     It stays the scroller for the one case fit can't cover (a floor was hit),
     so the header still pins and "now" still anchors. The bridge's leftover
     560px cap from the retired full-height board would otherwise cut it short. */
  .sched-app #schedulerCalendar.is-fit { display:flex; flex-direction:column; overflow:hidden; padding:0; }
  .sched-app #schedulerCalendar.is-fit > .sched-tg,
  .sched-app #schedulerCalendar.is-fit > .sched-swim { flex:1 1 auto; min-height:0; }
  .sched-app #schedulerCalendar.is-fit .sched-tg-body { flex:1 1 auto; min-height:0; max-height:none; overflow-y:auto; }
  .sched-app #schedulerCalendar.is-fit .sched-swim-scroll { flex:1 1 auto; min-height:0; }
  /* Hour labels ride 7px above their line; the first one would be clipped by the
     body's top edge now the body sits flush under the all-day row. */
  .sched-app #schedulerCalendar.is-fit .sched-tg-hour:first-child span { top:1px; }
  @media (min-width: 961px) {
    /* The timeline's print button had a whole bar to itself above the lanes;
       the empty corner over the names column holds it just as well. */
    .sched-app #schedulerCalendar.is-fit > .sched-swim { position:relative; gap:0; }
    .sched-app #schedulerCalendar.is-fit .sched-swim-actions {
      position:absolute; top:1px; left:1px; z-index:7; width:198px; height:34px; box-sizing:border-box;
      padding:0 8px; border:0; background:transparent; justify-content:flex-start; align-items:center; }
    .sched-app #schedulerCalendar.is-fit .sched-swim-actions .btn { height:26px; min-height:0; padding:0 8px; font-size:11.5px; }
    .sched-app #schedulerCalendar.is-fit .sched-swim-hour { height:34px; box-sizing:border-box; }
    /* Two-line lane labels, so a normal crew fits a laptop's height too:
         [av] Name  On site
         [av] ▬▬▬▬▬ 4.9/8h · 61%
       was three lines and ~89px a lane. The name row's pieces are lifted out of
       .sched-swim-tech (display:contents) so the lane state can sit beside it. */
    .sched-app #schedulerCalendar.is-fit .sched-swim-label {
      display:grid; grid-template-columns:22px auto minmax(0,1fr); align-items:center; align-content:center;
      column-gap:8px; row-gap:3px; padding:5px 12px; }
    .sched-app #schedulerCalendar.is-fit .sched-swim-tech { display:contents; }
    .sched-app #schedulerCalendar.is-fit .sched-swim-label > * { grid-column:2 / -1; min-width:0; }
    .sched-app #schedulerCalendar.is-fit .sched-lane-av { grid-column:1; grid-row:1 / span 2; width:22px; height:22px; border-radius:7px; font-size:10px; }
    .sched-app #schedulerCalendar.is-fit .sched-lane-name { grid-column:2; grid-row:1; min-width:0; }
    .sched-app #schedulerCalendar.is-fit .sched-swim-label > [data-lane-state] { grid-column:3; grid-row:1; overflow:hidden; white-space:nowrap; text-overflow:ellipsis; }
    .sched-app #schedulerCalendar.is-fit .sched-swim-label > [data-lane-state] > * { flex-wrap:nowrap; white-space:nowrap; }
    .sched-app #schedulerCalendar.is-fit .sched-swim-util { flex-direction:row; align-items:center; gap:6px; }
    .sched-app #schedulerCalendar.is-fit .sched-swim-util .sched-swim-bar { flex:1 1 auto; min-width:24px; }
    .sched-app #schedulerCalendar.is-fit .sched-swim-util .sched-swim-pct { flex:none; white-space:nowrap; }
  }

  /* ── Short screens: give the height back to the board ────────────────────
     A laptop lost ~280px of a 657px window before the board began: a toolbar
     title the Board tab already says, the live pip wrapping onto a line of its
     own, a stray 12px under the legend, a two-line day header. */
  @media (min-width: 961px) and (max-height: 900px) {
    .sched-app .stoolbar { padding:6px 16px; gap:8px 12px; }
    .sched-app .stoolbar-head { display:flex; align-items:center; gap:8px; min-width:0; }
    .sched-app .stoolbar-head .section-title { display:none; }
    .sched-app .stoolbar-head .skpis { margin-top:0; }
    .sched-app .sched-legend { margin-bottom:0; padding:4px 16px; }
    .sched-app .sched-attention { padding:4px 10px; }
    .sched-app .sboard { padding:8px; gap:8px; }
    .sched-app .sched-tg-headcell:not(.sched-td-head) { display:flex; flex-direction:row; align-items:center; justify-content:center; gap:6px; padding:5px 6px; }
    .sched-app .sched-tg-headcell:not(.sched-td-head) .sched-tg-dnum { margin:0; }
    .sched-app .sched-tg-headcell.is-today:not(.sched-td-head) .sched-tg-dnum { width:22px; height:22px; font-size:13px; }
  }
}

/* Outside the components layer on purpose. ui.css (unlayered) dims the quote →
   job → invoice trail with opacity, which no layered rule can undo; inside the
   job editor those dimmed steps measured 2–4:1 (scripts/canon-contrast-sweep.js
   dispatch-jobsheet). Full opacity here, and the layered rules above give each
   part a token colour that clears 4.5:1 in both themes. */
.sched-app #jobModal .ui-lc__step.is-todo,
.sched-app #jobModal .ui-lc__step i:first-child,
.sched-app #jobModal .ui-lc__step em,
.sched-app #jobModal button.ui-lc__step.is-action,
.sched-app #jobModal .ui-lc__sep { opacity: 1; }

/* Technician photo (state.js schedTechPhoto, db/add-tech-avatar.sql). Drawn
   over the initials inside whichever avatar circle hosts it, so each host only
   has to be a positioning context; the circle's own radius clips the photo. */
@layer components {
  .sched-app :is(.sched-tech-av, .cr-av, .sched-lane-av, .sched-td-av, .sched-insp-mav .a, .sched-qc-av, .jsh-av) { position:relative; }
  .sched-app .sched-tech-photo { position:absolute; inset:0; width:100%; height:100%; object-fit:cover; border-radius:inherit; }
  /* The technician editor's picker: the same circle, large enough to judge the
     crop. Tinted like .cr-av, so the initials sit on the page's ink, not on a
     colour picked to tell people apart. */
  .sched-app .sched-tech-photo-row { display:flex; align-items:center; gap:10px; }
  .sched-app .sched-tech-photo-prev { position:relative; flex:none; display:grid; place-items:center; width:48px; height:48px; border-radius:50%;
    background:color-mix(in srgb, var(--av, var(--c-accent)) 26%, var(--c-card)); color:var(--c-text); font-size:16px; font-weight:600; }
}

/* ── Board legibility (unconditional) ─────────────────────────────────────
   THE NOW LINE drew over the cards (z-index 4), so every job it crossed read
   as struck through. It sits UNDER them now: no z-index, and it comes before
   the cards in each column (viewhtml.js / techday.js), so a card paints over
   it and the line shows only in the gaps. The dot stays on top as the marker.
   The Timeline's vertical line gets the same treatment.
   SHORT CARDS: viewhtml.js drops the sub-line below ~52px (.is-short) and runs
   time and name on one row below 30px (.is-tiny), so neither is clipped. */
@layer components {
  .sched-app .sched-nowline, .sched-app .sched-swim-now { z-index:auto; }
  .sched-app .sched-nowline::before { z-index:3; }
  /* Its time is told in the hour gutter (viewhtml.js _nowGutterHTML), where no
     card can cover it; the in-column label would sit under the cards now. */
  html[data-theme] .sched-app .sched-nowline-lbl { display:none; }
  .sched-app .sched-tg-gutter { position:relative; }
  .sched-app .sched-now-gutter { position:absolute; right:3px; transform:translateY(-50%); z-index:2; pointer-events:none;
    padding:0 4px; border-radius:4px; font-family:'Inter', system-ui, sans-serif; font-size:9.5px; font-weight:600; line-height:15px;
    font-variant-numeric:tabular-nums; white-space:nowrap; background:var(--c-danger); color:var(--c-cta-fg); }
  .sched-app .sched-event.is-short { gap:0; padding-top:3px; padding-bottom:3px; }
  .sched-app .sched-event.is-short .sched-event-time { line-height:1.25; }
  .sched-app .sched-event.is-short .sched-event-title { line-height:1.3; }
  .sched-app .sched-event.is-tiny { flex-direction:row; align-items:center; gap:6px; padding-top:1px; padding-bottom:1px; }
  .sched-app .sched-event.is-tiny .sched-event-time { flex:none; padding-right:0; }
  .sched-app .sched-event.is-tiny .sched-event-time .sched-ev-av,
  .sched-app .sched-event.is-tiny .sched-event-win { display:none; }
  .sched-app .sched-event.is-tiny .sched-event-title { flex:1 1 auto; min-width:0; }

  /* ── Records pages: the shared page head ──────────────────────────────
     The hub / Books head: an eyebrow, the title in plain ink, the subtitle,
     then the actions as their OWN row — search on the left, filters and the
     primary on the right, every control the same 34px. It used to be a 22px
     title jammed under the bar with the controls squeezed beside it, cutting
     the search placeholder off ("phone, ac…"), Report template sitting low,
     and the Reports sub-tabs above the title. */
  .sched-app .rec-section { padding-top:28px; }
  .sched-app .rec-toolbar.rec-pagehead { display:flex; flex-direction:column; align-items:stretch; gap:14px; margin-bottom:18px; padding:0; }
  .sched-app .rec-eyebrow { font-size:10.5px; font-weight:600; letter-spacing:.09em; text-transform:uppercase; color:var(--c-cap); margin-bottom:8px; }
  .sched-app .rec-pagehead .section-title { font-size:24px; font-weight:600; line-height:1.15; letter-spacing:-.015em; margin-bottom:6px; }
  .sched-app .rec-pagehead .rec-toolbar-controls { display:flex; align-items:center; gap:8px; flex-wrap:wrap; width:100%; }
  .sched-app .rec-pagehead .rec-search { flex:1 1 260px; max-width:420px; min-width:0; margin-right:auto; }
  .sched-app .rec-pagehead .rec-search input { width:100%; }
  .sched-app .rec-pagehead .rec-toolbar-controls > select,
  .sched-app .rec-pagehead .rec-toolbar-controls > .btn { height:34px; margin:0; display:inline-flex; align-items:center; gap:6px; }
  .sched-app .rec-pagehead .section-subtitle { margin:0; }
  .sched-app .rec-pagehead .rh-seg { margin:0; }

  /* The designed empty state (hub plenum.css .empty): icon tile, title, a
     line of body, an action — instead of one grey sentence. */
  .sched-app .rec-empty.rec-empty-state { display:flex; flex-direction:column; align-items:center; gap:8px; padding:48px 18px 40px; text-align:center; }
  .sched-app .rec-es-ico { width:40px; height:40px; border-radius:11px; display:grid; place-items:center; font-size:20px;
    background:var(--c-card); border:1px solid var(--c-border); color:var(--c-muted); }
  .sched-app .rec-empty.rec-empty-state .rec-es-ico i { display:inline; margin:0; font-size:20px; opacity:1; }
  .sched-app .rec-es-title { font-size:14px; font-weight:600; color:var(--c-text); }
  .sched-app .rec-es-body { max-width:340px; font-size:12.5px; line-height:1.55; color:var(--c-muted); }
  .sched-app .rec-es-act { margin-top:6px; }
  .sched-app .rec-empty.rec-empty-state .rec-es-act i { display:inline; margin:0; font-size:14px; opacity:1; }
}
