/* ══════════════════════════════════════════════════════════════════════════
   canon-dispatch.css — the dispatch half of the canon v5 vocabulary.

   A PORT, NOT AN INTERPRETATION: the component extensions of
   public/_canon-sched-app-mockup.html, verbatim. That mockup is the spec;
   scripts/canon-diff.js renders it against this file and fails on any pixel
   that moves.

   The one departure is spelling, not design: ten colour literals the mockups
   write inline are declared as --c-* tokens in canon.src.css and referenced
   here, because .stylelintrc.json exempts these files from the spacing rule but
   deliberately not from color-no-hex. Every value is unchanged, which is why
   the differ still reads zero.

   Vocabulary a DAY needs and a ledger does not: lanes, the hour ruler, the job
   block, drive legs and the capacity read-out.

   Loads AFTER css/canon.css, which declares the layer order. Declaring
   @layer components here slots these rules into the layer canon.css already
   opened, so the utilities layer still outranks them — which is what lets a
   utility in the markup override a component, exactly as it does in the mockup.

   WHY THIS IS NOT PART OF canon.css. The apps reuse short component names for
   different things: .fld is a text input in Books and a tool row in the job
   view, .meta is a flex strip in work and a definition grid in field, and .trk
   and .chk disagree between dispatch and work. Five selectors collide across
   the four extension sets. Merged into one file the last one loaded wins and
   the other app breaks silently — no error, no failing selector, just a
   component quietly wearing someone else's shape. So each app gets its own
   file and a page loads exactly one of them.
   ══════════════════════════════════════════════════════════════════════════ */

/* ══════════════════════════════════════════════════════════════════════════
   SCHEDULING EXTENSIONS — everything above this line is the showcase's
   component layer, verbatim. Everything below is vocabulary a DAY needs and
   a ledger does not. No token is renamed, no canon component is retuned.
   ══════════════════════════════════════════════════════════════════════════ */

@layer components {
  /* ── Lanes ──────────────────────────────────────────────────────────────
     TRAP 6. The technician cell beside a lane is three lines tall and the
     lane is one block tall. If the LANE fixes the height, a taller cell
     pushes every row below it out of register with the hour ruler. So the
     flex row sets the height, the lane only asserts a MINIMUM, and every
     absolutely-positioned child hangs off the lane's own centre line. */
  .lane-lg { min-height:86px; }
  .lane-sm { min-height:54px; }
  /* The technician column and the now-spine's offset are the SAME number, so
     it is one variable. On a phone the column halves and the hour track stops
     being a sliver; the spine follows because it reads the variable too. */
  .swim { --lblw:206px; }
  @media (max-width: 700px) { .swim { --lblw:126px; } }
  .lane-lbl { width:var(--lblw); flex:none; }

  /* ── The promise ────────────────────────────────────────────────────────
     A bracket above the block: window_start → window_end. Drawn above the
     centre line so it tracks the block whatever the row height becomes. */
  .prom {
    position:absolute; top:calc(50% - 32px); height:9px; pointer-events:none;
    border:1px solid var(--c-border-2); border-bottom:0; border-radius:3px 3px 0 0;
  }
  .prom::after {
    content:"PROMISED"; position:absolute; left:5px; top:-9px;
    font-size:8px; font-weight:600; letter-spacing:.1em; color:var(--c-cap);
    background:var(--c-card); padding:0 3px; line-height:1;
  }
  .prom.narrow::after, .prom.mute::after { content:""; }
  .prom.miss { border-color:color-mix(in srgb, var(--c-danger) 55%, transparent); }
  .prom.miss::after { content:"MISSED"; color:var(--c-on-wash-danger); }

  /* ── The drive, given a verdict ─────────────────────────────────────────
     Canon .leg draws the road to scale. These two say whether it fits. */
  .leg.tight { border-top-color:color-mix(in srgb, var(--c-warn) 60%, transparent); }
  .leg.tight span { color:var(--c-on-wash-warn); font-weight:500; }
  .leg.short { border-top-style:solid; border-top-color:var(--c-danger); }
  .leg.short span { color:var(--c-on-wash-danger); font-weight:600; }
  .leg.tiny span { display:none; }

  /* ── Off-shift / on leave ───────────────────────────────────────────────── */
  .hatch {
    position:absolute; top:0; bottom:0; pointer-events:none;
    background-image:repeating-linear-gradient(135deg,
      var(--c-grid) 0 1px, transparent 1px 6px);
    background-color:color-mix(in srgb, var(--c-sunken) 55%, transparent);
  }

  /* ── The now spine ─────────────────────────────────────────────────────── */
  .spine { position:absolute; top:0; bottom:0; width:1px; background:var(--c-danger);
           opacity:.62; pointer-events:none; z-index:5; }
  .spine-cap {
    position:absolute; top:2px; transform:translateX(-50%); z-index:6;
    font-family:'Inter', system-ui, sans-serif; font-variant-numeric:tabular-nums;
    font-size:10px; font-weight:600; padding:1px 5px; border-radius:4px;
    /* --c-on-wash-danger over the card ink: 6.5:1 light, 5.8:1 dark. */
    background:var(--c-on-wash-danger); color:var(--c-card); pointer-events:none;
  }

  /* ── Block additions ───────────────────────────────────────────────────── */
  .blk.two { height:50px; top:calc(50% - 25px); padding-top:6px; }
  .blk.parts { border-style:dashed; }
  .blk.un { color:var(--c-danger); background:var(--c-danger-soft);
            border-color:color-mix(in srgb, var(--c-danger) 34%, transparent); border-style:dashed; }
  .blk.ghost { opacity:.5; border-style:dashed; }
  .blk .bl-ico { position:absolute; right:5px; top:5px; font-size:12px; line-height:1; }

  /* ── Dispatch status vocabulary. Built only from the on-wash inks. ─────── */
  .pill.sched { color:var(--c-text-2); }
  .pill.route { color:var(--c-on-wash-accent); border-color:var(--c-accent-edge); background:var(--c-accent-soft); }
  .pill.site  { color:var(--c-on-wash-warn);   border-color:color-mix(in srgb, var(--c-warn) 34%, transparent);   background:color-mix(in srgb, var(--c-warn) 10%, transparent); }
  .pill.done  { color:var(--c-on-wash-ok);     border-color:color-mix(in srgb, var(--c-ok) 32%, transparent);     background:color-mix(in srgb, var(--c-ok) 10%, transparent); }
  .pill.late  { color:var(--c-on-wash-danger); border-color:color-mix(in srgb, var(--c-danger) 36%, transparent); background:var(--c-danger-soft); }
  .pill.un    { color:var(--c-on-wash-danger); border-color:color-mix(in srgb, var(--c-danger) 36%, transparent); background:var(--c-danger-soft); }
  .pill.emerg { color:var(--c-on-wash-danger); border-color:color-mix(in srgb, var(--c-danger) 36%, transparent); background:var(--c-danger-soft); font-weight:600; }
  .pill.flat::before { display:none; }
  .pill.flat { padding-left:9px; }

  /* ── Attention chips: a .pill that is also a filter button ─────────────── */
  .achip { cursor:pointer; transition:border-color var(--dur) var(--ease), background var(--dur) var(--ease); }
  .achip:hover { border-color:var(--c-border-2); }
  .achip[aria-pressed="true"] { box-shadow:0 0 0 2px var(--c-accent-soft); border-color:var(--c-accent); }
  .achip b { font-family:'Inter', system-ui, sans-serif; font-variant-numeric:tabular-nums; font-weight:600; }

  /* ── Promised versus actual ────────────────────────────────────────────── */
  .trk { position:relative; height:12px; border-radius:999px; background:var(--c-sunken);
         border:1px solid var(--c-border); }
  .trk i { position:absolute; top:-1px; bottom:-1px; border-radius:999px; }
  .trk .win { background:var(--c-accent-soft); border:1px solid var(--c-accent-edge); }
  .trk .act { background:var(--c-accent); }
  .trk .act.miss { background:var(--c-danger); }
  .trk .mk { position:absolute; top:-5px; width:2px; height:22px; border-radius:1px; background:var(--c-text-2); }

  /* ── The week grid. One hue, four strengths — a load ramp, not a palette. */
  .wcell {
    position:relative; min-height:62px; padding:8px 9px; border-radius:6px;
    border:1px solid var(--c-border); background:var(--c-card);
    transition:border-color var(--dur) var(--ease), transform var(--dur) var(--ease);
    display:flex; flex-direction:column; gap:5px; cursor:pointer;
  }
  .wcell:hover { border-color:var(--c-border-2); transform:translateY(-1px); }
  .wcell.l1 { background:color-mix(in srgb, var(--c-accent) 5%, var(--c-card)); }
  .wcell.l2 { background:color-mix(in srgb, var(--c-accent) 10%, var(--c-card)); }
  .wcell.l3 { background:color-mix(in srgb, var(--c-accent) 16%, var(--c-card)); border-color:var(--c-accent-edge); }
  .wcell.over { background:var(--c-danger-soft); border-color:color-mix(in srgb, var(--c-danger) 38%, transparent); }
  .wcell.off { background:var(--c-sunken); cursor:default; }
  .wcell.off:hover { transform:none; border-color:var(--c-border); }
  .wcell .wbar { height:3px; border-radius:999px; background:var(--c-border); overflow:hidden; margin-top:auto; }
  .wcell .wbar i { display:block; height:100%; border-radius:999px; background:var(--c-cta); }
  .wcell.over .wbar i { background:var(--c-danger); }

  /* ── Unbooked work ─────────────────────────────────────────────────────── */
  .qcard { cursor:grab; transition:background var(--dur) var(--ease); }
  .qcard:hover { background:var(--c-card-2); }
  .qcard:active { cursor:grabbing; }

  /* ── Meters ────────────────────────────────────────────────────────────── */
  .mini { display:block; height:3px; border-radius:999px; background:var(--c-sunken);
          overflow:hidden; }
  .mini i { display:block; height:100%; border-radius:999px; background:var(--c-cta); }
  .mini i.warn { background:var(--c-warn); }
  .mini i.bad  { background:var(--c-danger); }
  .hbar { height:10px; border-radius:999px; background:var(--c-sunken); overflow:hidden; display:flex; }
  .hbar i { display:block; height:100%; }

  /* ── Forms ─────────────────────────────────────────────────────────────── */
  .field { display:block; }
  .inp {
    width:100%; height:34px; padding:0 10px; border-radius:6px;
    border:1px solid var(--c-border); background:var(--c-sunken);
    color:var(--c-text); font:inherit; font-size:13px; outline:none;
    transition:border-color var(--dur) var(--ease), background var(--dur) var(--ease);
  }
  textarea.inp { height:auto; padding:8px 10px; line-height:1.5; resize:vertical; }
  select.inp { appearance:none; padding-right:28px; cursor:pointer; }
  .inp:focus { border-color:var(--c-accent); background:var(--c-card); }
  .inp::placeholder { color:var(--c-cap); }
  .chkrow { display:flex; align-items:center; gap:10px; padding:8px 0; }
  .chk {
    width:16px; height:16px; border-radius:4px; flex:none;
    border:1px solid var(--c-border-2); background:var(--c-card);
    display:grid; place-items:center; font-size:11px; color:transparent; cursor:pointer;
  }
  .chk.on { background:var(--c-cta); border-color:var(--c-cta); color:var(--c-cta-fg); }

  /* ── Overlay (Quick create) ────────────────────────────────────────────── */
  .scrim { position:fixed; inset:0; z-index:45; background:color-mix(in srgb, var(--c-bg) 62%, transparent);
           backdrop-filter:blur(2px); }
  .sheet { position:relative; z-index:46; }

  /* ── The drawn map ─────────────────────────────────────────────────────── */
  .mp-water { fill:var(--c-accent-soft); stroke:var(--c-accent-edge); stroke-width:1; }
  .mp-blob  { fill:var(--c-sunken); stroke:var(--c-border); stroke-width:1; }
  .mp-blob.on { fill:var(--c-accent-soft); stroke:var(--c-accent-edge); }
  .mp-road  { fill:none; stroke:var(--c-border-2); stroke-width:3.5; stroke-linecap:round; stroke-linejoin:round; }
  .mp-road.minor { stroke-width:2; opacity:.8; }
  .mp-rail  { fill:none; stroke:var(--c-border-2); stroke-width:1.5; stroke-dasharray:7 5; opacity:.75; }
  .mp-lbl   { fill:var(--c-cap); font-size:9px; font-weight:600; letter-spacing:.09em;
              text-transform:uppercase; font-family:'Sora', system-ui, sans-serif; }
  .mp-route { fill:none; stroke:var(--c-border-2); stroke-width:1.9; stroke-dasharray:6 4; opacity:.85; }
  .mp-route.on { stroke:var(--c-accent); stroke-width:2.5; stroke-dasharray:none; opacity:1; }
  .mp-n     { fill:var(--c-cta-fg); font-size:10px; font-weight:600; text-anchor:middle;
              font-family:'Inter', system-ui, sans-serif; }
  .mp-pin   { cursor:pointer; }
  .mp-pin circle { transition:r var(--dur) var(--ease); }
  .mp-tech rect { fill:var(--c-card); stroke:var(--c-accent); stroke-width:2; }
  .mp-tech text { fill:var(--c-on-wash-accent); font-size:10px; font-weight:600; text-anchor:middle;
                  font-family:'Inter', system-ui, sans-serif; }

  /* ── Table density modifier (the canon .tbl, tightened for 30 rows) ────── */
  .tbl.dense td { padding:7px 12px; font-size:13px; }
  .tbl.dense th { padding:7px 12px; }

  /* ── Ink on a plain card ────────────────────────────────────────────────
     TRAP 7, the other half of it. The canon's --c-ok / --c-warn / --c-danger /
     --c-accent-h are chart and figure colours: as INK at 12-17px they measure
     4.27 (danger) and 4.47 (accent-h) on a white card, which is under AA. The
     on-wash inks the canon already ships clear it, so small coloured text uses
     these four and nothing else. 26px+ figures keep the raw canon colour. */
  .ink-bad  { color:var(--c-on-wash-danger); }
  .ink-warn { color:var(--c-on-wash-warn); }
  .ink-ok   { color:var(--c-on-wash-ok); }
  .ink-acc  { color:var(--c-on-wash-accent); }

  /* The ONE canon value this file overrides, and only toward the canon's own
     fix: an unpressed .seg label is --c-muted on --c-sunken, which measures
     3.9:1 in light. --c-cap is the ink the canon already uses for micro-labels
     on a sunken ground, and it measures 5.1:1. Pressed and hover untouched. */
  .seg button:not([aria-pressed="true"]) { color:var(--c-cap); }
  .seg button:not([aria-pressed="true"]):hover { color:var(--c-text); }

  /* ── Reports ───────────────────────────────────────────────────────────── */
  .kpi { display:flex; flex-direction:column; gap:2px; }
  .swatch { width:9px; height:9px; border-radius:2px; flex:none; }
}
