/* ---- KPIs (mod/kpi.js) ----
   Chart colours follow the dataviz method, validated (scratchpad
   viz-check.mjs, 2026-09-02 brand pass) against the card surface of each
   theme — --chrome, navy #101D3B in dark and white in light. One blue for a
   single series, now a step of the WrenchUr blue; the first three
   categorical slots (blue, orange, aqua — the order that passes the
   colour-vision checks in both modes) for the work trend and the PM
   columns; and a light-to-dark blue ramp for ordered states — open work's
   unassigned / assigned / in progress, and acknowledge -> close in the
   responsiveness trend (light and mid steps only — the dark step sits under
   3:1 on the card and a 2px line at that contrast disappears). Status
   colours (good / warn / bad) stay the app's own and are used only for the
   PM meter and the delta pills, never for a series. Text never wears a
   series colour. theme.css re-points the grid and axis tokens for light
   mode; the light-mode series steps are set here so both files stay small. */
.kpi{--viz-1:#4f8fe8; --viz-2:#d95926; --viz-3:#199e70;
     --viz-o1:#9cc2f5; --viz-o2:#4f8fe8; --viz-o3:#2456a8;
     --viz-gl:#1B2C52; --viz-axis:#2B4272;}
html[data-theme="light"] .kpi{--viz-1:#2B63C4; --viz-2:#eb6834; --viz-3:#1baf7a;
     --viz-o1:#86b6ef; --viz-o2:#3987e5; --viz-o3:#1c5cab;}

/* the window bar: date range first, then the group; one row above everything it scopes */
.kpi-bar{max-width:920px; margin:0 auto 12px;}
.kpi-chips{margin:0;}
.kpi-custom{display:flex; flex-wrap:wrap; align-items:center; gap:8px; margin-top:10px;}
.kpi-custom[hidden], .kpi-tip[hidden]{display:none;}   /* display:flex would otherwise beat the hidden attribute */
.kpi-custom label{margin:0; font-size:12.5px;}
.kpi-custom input{width:auto; min-width:150px; padding:8px 10px; font-size:14px;}
.kpi-custom button{width:auto;}
.kpi-caption{margin:10px 0 0; font-size:12.5px;}
.kpi-groups{margin-top:10px;}
.kpi-content{transition:opacity .15s;}
.kpi-content.loading{opacity:.55; pointer-events:none;}

.kpi-barbtns{margin-top:10px; flex-wrap:wrap; align-items:center; gap:8px 14px;}
.kpi-barbtns button{flex:0 0 auto; width:auto;}
.kpi-barbtns .kpi-orders{margin:0 0 0 auto; flex:0 0 auto;}
/* the section under the original cards that holds the 2026-09-03 additions */
.kpi-more{grid-column:1 / -1; margin-top:4px;}
.kpi-more .kpi-morehead{display:flex; align-items:center; justify-content:space-between; gap:10px;
  padding:12px 16px; border:1px solid var(--line); border-radius:var(--r-lg); background:var(--chrome); cursor:pointer;}
.kpi-more .kpi-morehead h3{margin:0;}
.kpi-more .kpi-morehead .sub{margin:0;}
.kpi-more .kpi-morehead button{width:auto;}
.kpi-more .kpi-moregrid{margin-top:12px;}
.kpi-more.closed .kpi-moregrid{display:none;}
/* My KPIs (D83): the picker's rows — tick, name, up / down */
.kpi-laylist{display:flex; flex-direction:column; gap:4px; max-height:52vh; overflow:auto;}
.kpi-layrow{display:flex; align-items:center; gap:6px;}
.kpi-layrow label{display:flex; align-items:center; flex:1 1 auto; margin:0; font-size:14px; color:var(--text);}
.kpi-layrow button{width:auto; padding:4px 9px; flex:0 0 auto;}
.kpi-ordered{margin-top:14px; padding-top:10px; border-top:1px dashed var(--line);}
/* the line that heads the printed page: what was set, when, by whom. Screen: hidden */
.kpi-printhead{display:none;}

/* ---- printing the KPI screen as set (owner, 2026-09-03) ----
   html.kpi-on is on only while the print dialog is open (mod/kpi.js
   printPicker). The app's shell goes, the cards print black on white, each
   in its own frame, unticked cards (.kpi-noprint) stay off the paper, and
   the charts keep their fills (they tell apart by hatch and line style, not
   only colour — rule 8). */
@media print{
  html.kpi-on, html.kpi-on body{height:auto !important; overflow:visible !important; background:#fff !important; color:#000 !important; display:block !important;}
  html.kpi-on .screen{display:none !important;}
  html.kpi-on #screen-module{display:block !important;}
  html.kpi-on #modBar, html.kpi-on #toast, html.kpi-on .modal, html.kpi-on .kpi-bar,
  html.kpi-on .kpi-segs, html.kpi-on .kpi-everyone, html.kpi-on .kpi-card button{display:none !important;}
  html.kpi-on .modroot{display:block !important; position:static !important;}
  html.kpi-on .kpi{overflow:visible !important; height:auto !important; flex:none !important; padding:0 !important; background:#fff !important;}
  html.kpi-on .kpi-content{opacity:1 !important;}
  html.kpi-on .kpi-printhead{display:block; margin:0 0 10px; padding-bottom:6px; border-bottom:2px solid #000; break-after:avoid;}
  html.kpi-on .kpi-printtitle{font-size:18px; font-weight:800; color:#000;}
  html.kpi-on .kpi-printhead .sub{color:#222; font-size:11px;}
  html.kpi-on .kpi-grid{display:grid !important; grid-template-columns:1fr 1fr !important; gap:10px; max-width:none; width:100%;}
  html.kpi-on .kpi-card{background:#fff !important; color:#000 !important; border:1px solid #000 !important; box-shadow:none !important;
    padding:8px 10px; break-inside:avoid; page-break-inside:avoid;}
  html.kpi-on .kpi-card.wide{grid-column:1 / -1;}
  html.kpi-on .kpi-card.kpi-noprint{display:none !important;}
  /* a ticked card prints even if its section is folded away on screen */
  html.kpi-on .kpi-more.closed .kpi-moregrid{display:grid !important;}
  html.kpi-on .kpi-more .kpi-morehead{display:none !important;}
  html.kpi-on .kpi-card *, html.kpi-on .kpi-card .sub, html.kpi-on .kpi-card .kpi-h{color:#000 !important;}
  html.kpi-on .kpi-h{font-size:11px; border-bottom:1px solid #000; padding-bottom:2px;}
  html.kpi-on .kpi-sub{font-size:9.5px;}
  html.kpi-on .kpi-hero{font-size:22px;}
  html.kpi-on .kpi-tile, html.kpi-on .kpi-ordered{border-color:#000 !important; background:#fff !important;}
  html.kpi-on .kpi-card svg text{fill:#000 !important;}
  html.kpi-on *{-webkit-print-color-adjust:exact; print-color-adjust:exact;}
  /* the page, not a phone column: every container spans the paper, and
     nothing inside a card is allowed to clip — big figures and long labels
     wrap instead (owner, 2026-09-03: "it shows clipping on the print for
     kpi. that will not do") */
  html.kpi-on #screen-module, html.kpi-on .modroot, html.kpi-on .kpi, html.kpi-on .kpi-content, html.kpi-on .kpi-grid{
    width:100% !important; max-width:none !important; min-width:0 !important; margin:0 !important; overflow:visible !important;}
  html.kpi-on .kpi-card{overflow:visible !important;}
  html.kpi-on .kpi-hero, html.kpi-on .kpi-tile, html.kpi-on .kpi-sub, html.kpi-on .kpi-h, html.kpi-on .kpi-tile *{
    overflow:visible !important; overflow-wrap:anywhere; word-break:break-word; white-space:normal;}
  html.kpi-on .kpi-hero{font-size:20px; flex-wrap:wrap;}
  /* ranked bars: the label keeps its two-line clamp so it never runs over the
     bar; the row grows to fit it */
  html.kpi-on .kpi-hrow{align-items:start;}
  html.kpi-on .kpi-hl{font-size:10.5px; line-height:1.2;}
  html.kpi-on .kpi-hv{font-size:10.5px;}
  html.kpi-on .kpi-tiles{display:grid; grid-template-columns:repeat(auto-fit, minmax(130px, 1fr)); gap:6px;}
  html.kpi-on .kpi-tile .v, html.kpi-on .kpi-tile .v span{font-size:15px; line-height:1.2;}
  html.kpi-on .kpi-tile .s, html.kpi-on .kpi-tile .l{font-size:8.5px;}
  html.kpi-on .kpi-bars > *{break-inside:avoid;}
  /* the folded section spans the paper like the cards above it, and its own
     grid is two columns of full width — not one column squeezed in half */
  html.kpi-on .kpi-more{display:block !important; grid-column:1 / -1 !important; width:100% !important;}
  html.kpi-on .kpi-moregrid{display:grid !important; grid-template-columns:1fr 1fr !important; width:100% !important; margin:0 !important;}
  @page{size:Letter portrait; margin:.4in;}
}
.kpi-grid{display:grid; gap:12px; grid-template-columns:1fr; max-width:920px; margin:0 auto;}
@media (min-width:720px){
  .kpi-grid{grid-template-columns:1fr 1fr;}
  .kpi-card.wide{grid-column:1 / -1;}
}
.kpi-card{padding:16px; min-width:0;}
.kpi-head{display:flex; align-items:center; justify-content:space-between; gap:10px; margin:0 0 3px;}
.kpi-h{margin:0; min-width:0;}
/* Line · Bars on a card's title row; Everyone beside "Repairs by technician" */
.kpi-segs{margin:0; flex:0 0 auto;}
.kpi-segs button.seg{min-height:26px; padding:3px 11px; font-size:12px;}
button.small.kpi-everyone{width:auto; min-height:26px; padding:3px 11px; font-size:12px; border-radius:var(--r-pill); flex:0 0 auto;}
/* the note when a chosen technician has nothing in the window */
.kpi-technote{margin:6px 0 0; font-size:12.5px; color:var(--text); border-left:3px solid var(--text); padding-left:8px;}
.kpi-technote[hidden]{display:none;}
.kpi-sub{margin:0 0 12px; font-size:12.5px;}
.kpi-note{max-width:920px; margin:16px auto 0;}

/* the one big number a card leads with, with its change against the window before */
.kpi-hero{font-size:44px; font-weight:600; line-height:1; letter-spacing:-.02em; margin:2px 0 6px;
  display:flex; align-items:baseline; gap:10px; flex-wrap:wrap;}

/* delta pill: direction plus colour only where the direction is unambiguous */
.kpi-delta{display:inline-block; font-size:12px; font-family:var(--mono); font-weight:600; line-height:1;
  padding:4px 8px; border-radius:var(--r-pill); border:1px solid var(--line); color:var(--muted);
  letter-spacing:0; white-space:nowrap; vertical-align:middle;}
.kpi-delta.good{color:var(--good); border-color:rgba(61,220,132,.45); background:rgba(61,220,132,.10);}
.kpi-delta.bad{color:var(--bad); border-color:rgba(255,115,115,.45); background:rgba(255,115,115,.10);}
html[data-theme="light"] .kpi-delta{border-width:1.5px;}
html[data-theme="light"] .kpi-delta.good{border-color:var(--good);}
html[data-theme="light"] .kpi-delta.bad{border-color:var(--bad);}

/* stat tiles */
.kpi-tiles{display:grid; grid-template-columns:1fr 1fr; gap:10px;}
.kpi-tile{background:var(--panel); border:1px solid var(--line); border-radius:var(--r-md); padding:12px; min-width:0;}
.kpi-tile .l{font-size:12px; color:var(--muted); line-height:1.35;}
.kpi-tile .v{font-size:26px; font-weight:600; margin:4px 0 2px; display:flex; align-items:baseline; gap:8px; flex-wrap:wrap;}
.kpi-tile .s{font-size:11.5px; color:var(--muted); font-family:var(--mono); line-height:1.4;}

/* the three small window counts under open work */
.kpi-minis{display:grid; grid-template-columns:repeat(3, minmax(0, 1fr)); gap:8px; margin-top:14px; padding-top:12px; border-top:1px solid var(--line);}
.kpi-mini .l{font-size:11.5px; color:var(--muted); line-height:1.3;}
.kpi-mini .v{display:flex; align-items:baseline; gap:6px; flex-wrap:wrap; margin-top:3px;}
.kpi-mini .v b{font-size:20px; font-weight:600;}

/* ranked horizontal bars: label | bar | value */
.kpi-bars{display:flex; flex-direction:column; gap:6px;}
.kpi-hrow{display:grid; grid-template-columns:minmax(0,42%) 1fr auto; gap:10px; align-items:center;
  min-height:26px; border-radius:var(--r-sm); padding:2px 4px; margin:0 -4px;}
.kpi-hrow.tap{cursor:pointer;}
.kpi-hrow.tap:hover, .kpi-hrow.tap:focus-visible{background:var(--panel); outline:none;}
/* the chosen technician: a heavy frame and the word "showing" — never a tint alone (owner's rule 8) */
.kpi-hrow.sel{outline:2px solid var(--text); outline-offset:-1px; padding-left:8px; padding-right:8px; margin:0 -8px;}
.kpi-hrow.sel .kpi-hl span{color:var(--text); font-weight:600;}
.kpi-showing{display:inline-block; margin-left:8px; padding:1px 7px; border:1.5px solid var(--text); border-radius:var(--r-pill);
  font-size:10.5px; font-weight:600; letter-spacing:.04em; text-transform:uppercase; color:var(--text); vertical-align:1px;}
/* Machine and department names wrap to two lines instead of being cut
   (QA audit 2026-09-03: names were ellipsised even at 1280 px). */
.kpi-hl{font-size:12.5px; min-width:0; overflow:hidden; display:-webkit-box; -webkit-line-clamp:2;
  -webkit-box-orient:vertical; line-height:1.25; word-break:break-word;}
.kpi-hl b{font-family:var(--mono); font-weight:600; margin-right:6px;}
.kpi-hl span{color:var(--muted);}
.kpi-hb{height:14px; min-width:0;}
.kpi-hbar{display:block; height:100%; background:var(--viz-1); border-radius:0 4px 4px 0; min-width:2px;}
/* hours bars (downtime) wear a hatch of surface-coloured stripes, so a list
   of hours never reads as a list of counts — in colour or in grey (rule 8) */
.kpi-hbar.hatched{background:repeating-linear-gradient(135deg, var(--viz-1) 0 3px, var(--chrome) 3px 5px);}
/* a small heading inside a card, above a second list */
.kpi-h4{margin:12px 0 6px; font-size:12.5px; color:var(--muted); font-weight:600;}
/* "parts only" beside the cost figure — a word, never only a colour */
.kpi-hero .kpi-tag{font-size:12px; font-weight:600; color:var(--muted); letter-spacing:.02em; text-transform:uppercase;
  border:1.5px solid var(--muted); border-radius:var(--r-pill); padding:2px 8px; align-self:center;}
/* the machine screen's one-line summary under the header (mod/asset.js costLine) */
.acost{margin-top:10px; font-size:12.5px; font-family:var(--mono); opacity:.85;}
.acost:empty{display:none;}
/* Admin -> Repair log fields: the failure-code list (mod/admin/repairlog.js) */
.fcodes{display:flex; flex-direction:column;}
.fcode{display:flex; align-items:center; gap:6px; padding:4px 0; border-bottom:1px solid var(--line);}
.fcode:last-child{border-bottom:0;}
.fcode.add{margin-top:4px; padding-top:8px; border-top:1px solid var(--line); border-bottom:0;}
.fcode .n{flex:0 0 22px; font-family:var(--mono); font-size:12px; color:var(--muted); text-align:right;}
.fcode input{flex:1 1 auto; min-width:0; margin:0; padding:7px 10px; font-size:14px;}
.fcode button.small{width:auto; min-height:30px; padding:3px 9px; flex:0 0 auto;}
.fcode button.small:disabled{opacity:.35;}
.kpi-hv{font-family:var(--mono); font-size:12.5px; font-variant-numeric:tabular-nums;
  min-width:28px; text-align:right;}

/* stacked states of open work — a 2px surface gap between segments, no borders */
.kpi-stack{display:flex; gap:2px; height:14px;}
.kpi-stack span{display:block; height:100%; min-width:2px;}
.kpi-stack span:last-child{border-radius:0 4px 4px 0;}
.kpi-o1{background:var(--viz-o1);} .kpi-o2{background:var(--viz-o2);} .kpi-o3{background:var(--viz-o3);}
.kpi-legend{display:flex; gap:14px; flex-wrap:wrap; margin-top:10px; font-size:12px; color:var(--muted);}
.kpi-legend i{display:inline-block; width:10px; height:10px; border-radius:2px; margin-right:6px; vertical-align:-1px;}
.kpi-legend i.lk{width:14px; height:3px; border-radius:2px; vertical-align:2px;}   /* a line key for a line series */
/* the series key (mod/kpi.js kpiKey): a short line with its marker, or a plain / hatched swatch */
.kpi-key{display:inline-block; width:22px; height:12px; overflow:visible; vertical-align:-1px; margin-right:6px; flex:0 0 auto;}

/* series colours: marks only (fills, strokes, keys) — never text */
.kpi-s1{background:var(--viz-1); fill:var(--viz-1); stroke:var(--viz-1);}
.kpi-s2{background:var(--viz-2); fill:var(--viz-2); stroke:var(--viz-2);}
.kpi-s3{background:var(--viz-3); fill:var(--viz-3); stroke:var(--viz-3);}
.kpi-r1{background:var(--viz-o1); fill:var(--viz-o1); stroke:var(--viz-o1);}
.kpi-r2{background:var(--viz-o2); fill:var(--viz-o2); stroke:var(--viz-o2);}   /* the ramp's mid step: its dark end sits under 3:1 on the dark card */

/* how series tell apart without colour (owner's rule 8): the second line is
   dashed, the third dotted, each with its own marker shape; the second and
   third fills wear a hatch of surface-coloured stripes at 45° / 135° */
.kpi-dashed{stroke-dasharray:7 4;}
.kpi-dotted{stroke-dasharray:0.5 5;}       /* round caps turn these into dots */
.kpi-patbase{stroke:none;}                /* the colour under a hatch */
.kpi-hatch{stroke:var(--chrome); stroke-width:1.7;}

/* column and line charts */
.kpi-chart{width:100%; min-width:0; position:relative;}
.kpi-svg{display:block; width:100%; height:auto; overflow:visible;}
.kpi-gl{stroke:var(--viz-gl); stroke-width:1;}
.kpi-axis{stroke:var(--viz-axis); stroke-width:1;}
.kpi-col{fill:var(--viz-1);}
.kpi-tick{fill:var(--muted); font-size:11px; font-family:var(--mono);}
.kpi-val{fill:var(--text); font-size:11.5px; font-family:var(--mono); font-weight:600;}
.kpi-line{fill:none; stroke-width:2; stroke-linejoin:round; stroke-linecap:round;}
.kpi-dot{stroke:var(--chrome); stroke-width:2;}                 /* a 2px surface ring where marks cross */
path.kpi-seg, rect.kpi-seg{stroke:none;}
.kpi-hair{stroke:var(--muted); stroke-width:1; pointer-events:none;}

/* the crosshair tooltip: every series at the bucket under the pointer */
.kpi-tip{position:absolute; z-index:5; pointer-events:none; background:var(--chrome); border:1px solid var(--line);
  border-radius:var(--r-md); padding:8px 10px; box-shadow:var(--shadow-sm); font-size:12px; min-width:130px;}
.kpi-tip .t{color:var(--muted); margin-bottom:5px; font-family:var(--mono);}
.kpi-tip .r{display:flex; align-items:center; gap:7px; line-height:1.6; white-space:nowrap;}
.kpi-tip .r .kpi-key{margin-right:0;}
.kpi-tip .r b{font-family:var(--mono); font-variant-numeric:tabular-nums; color:var(--text);}
.kpi-tip .r span{color:var(--muted);}

/* the three trend sections share the card */
.kpi-trend{padding:12px 0 4px; border-top:1px solid var(--line);}
.kpi-trend:first-of-type{border-top:0; padding-top:0;}
.kpi-trend h4{margin:0 0 3px; font-size:14px;}

/* PM on-time meter: the track is a faint step of the same colour as the fill */
.kpi-meter{height:12px; border-radius:6px; background:rgba(61,220,132,.18); overflow:hidden; margin:6px 0 8px;}
.kpi-meter i{display:block; height:100%; border-radius:6px; background:var(--good);}
.kpi-meter.warn{background:rgba(255,182,72,.18);} .kpi-meter.warn i{background:var(--warn);}
.kpi-meter.bad{background:rgba(255,115,115,.18);} .kpi-meter.bad i{background:var(--bad);}
.kpi-state{font-size:13px; margin:0;}

/* table twin of each chart, folded away */
details.kpi-table{margin-top:8px;}
details.kpi-table summary{color:var(--muted); cursor:pointer; font-size:12px;}
.kpi-table table{width:100%; border-collapse:collapse; margin-top:6px; font-family:var(--mono); font-size:12px;}
.kpi-table td, .kpi-table th{padding:3px 4px; border-bottom:1px solid var(--line);}
.kpi-table th{text-align:left; font-weight:600; color:var(--muted);}
.kpi-table td:not(:first-child), .kpi-table th:not(:first-child){text-align:right; font-variant-numeric:tabular-nums;}
