/* ==========================================================================
   QPeak-Modern design system.

   Carries forward the language of the Q-Peak V1 prototypes in
   ../QPeak Live Platform/Version Initial - Front End Only/shared/styles.css —
   dark operator console, 244px sidebar shell, Inter + JetBrains Mono — retuned
   to the live platform's own theme colour (#0f1923) and tightened up.

   THEME PASS 2026-07-26, halfway to `theme influence.png` (Peak Power pTrack).
   Mert asked to sit between this console and that reference, so the identity stays
   (dark by default, teal/amber data colours) and the *surface language* moves:

     - surfaces lifted off pure black and given more air; borders softened so a card
       reads as a plane rather than an outlined box
     - a distinct CONTROL accent (blue) for buttons, focus and the active nav, kept
       separate from the DATA accents (teal/amber/red/green). The reference does this
       and it stops a primary button competing with a chart series
     - status pills go pastel: tinted fill, saturated text, no hard border
     - bigger, tighter numerals with a small grey unit — the reference's "22,405 MW"
     - light theme moved much closer to the reference: #f7f8fa page, white cards,
       hairline borders, one soft shadow
   ========================================================================== */
:root{
  --bg:#0d131b;
  --panel:#141d28;
  --panel-2:#1a2431;
  --panel-3:#22303f;
  --line:rgba(255,255,255,.07);
  --line-2:rgba(255,255,255,.13);
  --ink:#eef2f7;
  --ink-2:#9daaba;
  --ink-3:#7f8d9d;   /* 5.02:1 on --panel; .sub and .k are 12px body text */
  --teal:#2cbaac;
  --teal-2:#23968b;
  --amber:#f59e0b;
  --red:#ef4444;
  --green:#10b981;
  --info:#60a5fa;
  --violet:#8b7dff;
  /* control accent, deliberately not a data colour */
  --ctl:#2f6bd0;      /* white label clears 5.08:1; 3.25:1 was not enough */
  --ctl-ink:#ffffff;
  --ctl-soft:rgba(77,141,247,.16);
  --shadow:0 1px 2px rgba(0,0,0,.35);
  --r:14px;
  --r-s:10px;
  --sans:"Inter",system-ui,-apple-system,"Segoe UI",Roboto,sans-serif;
  --mono:"JetBrains Mono",ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;
  --brand-hi:#ffffff;
  --brand-lo:#8fa4bd;
}
*{box-sizing:border-box}
html,body{margin:0;padding:0}
body{
  font-family:var(--sans);font-size:14px;line-height:1.55;
  color:var(--ink);background:var(--bg);-webkit-font-smoothing:antialiased;
}
a{color:var(--teal);text-decoration:none}
a:hover{text-decoration:underline}
h1,h2,h3,h4,p{margin:0}
table{border-collapse:collapse;width:100%}
button,input,select,textarea{font:inherit;color:inherit}

/* ---------- shell ---------- */
.app{display:grid;grid-template-columns:246px 1fr;min-height:100vh}
.side{background:#0a1017;border-right:1px solid var(--line);display:flex;
  flex-direction:column;padding:20px 0}
.brand{display:flex;align-items:center;gap:11px;padding:0 20px 18px;
  border-bottom:1px solid var(--line)}
/* The mark is the landing page's: a ring with the dispatch arrow through it. Drawn,
   not an image, so it stays sharp and picks up the theme through --brand-hi/--brand-lo. */
.brand__mark{width:34px;height:34px;flex:none}
.brand__txt{display:grid;line-height:1}
.brand__txt b{font-weight:800;font-size:15px;letter-spacing:.2px}
.brand__txt span{font:600 9.5px/1 var(--mono);letter-spacing:.11em;text-transform:uppercase;
  color:var(--ink-3);margin-top:5px}
.brand:hover{text-decoration:none}
.brand:hover .brand__txt b{color:var(--teal)}
.nav{padding:14px 12px;display:grid;gap:2px}
.nav__h{font:700 9.5px/1 var(--mono);letter-spacing:.15em;text-transform:uppercase;
  color:var(--ink-3);padding:14px 10px 6px}
.nav a{display:flex;align-items:center;gap:10px;padding:9px 11px;border-radius:var(--r-s);
  color:var(--ink-2);font-weight:500;font-size:13.5px}
.nav a:hover{background:var(--panel-2);color:var(--ink);text-decoration:none}
.nav a.on{background:var(--ctl-soft);color:#bcd6fe;font-weight:650}
.nav .pill{margin-left:auto;font:700 10px/1 var(--mono);background:var(--panel-3);
  color:var(--ink-2);padding:3px 7px;border-radius:99px}
.side__foot{margin-top:auto;padding:14px 20px 0;border-top:1px solid var(--line);
  font-size:12px;color:var(--ink-3)}

.main{min-width:0;display:flex;flex-direction:column}
.top{display:flex;align-items:center;gap:16px;padding:16px 26px;
  border-bottom:1px solid var(--line);background:rgba(11,16,23,.86);
  position:sticky;top:0;z-index:20;backdrop-filter:blur(10px)}
.top h1{font-size:18px;font-weight:700;letter-spacing:-.01em}
.top .sp{margin-left:auto}
.who{display:flex;align-items:center;gap:10px;font-size:12.5px;color:var(--ink-2)}
.who b{color:var(--ink);font-weight:600}
.wrap{padding:24px 26px 60px;max-width:1400px}

/* ---------- bits ---------- */
/* Pastel status pills, as in the reference: tinted fill, saturated text, no ring.
   An outlined pill at 10px reads as clutter once there are several in a table row. */
.badge{display:inline-flex;align-items:center;gap:6px;padding:3px 10px;border-radius:99px;
  font:700 10px/1.7 var(--mono);letter-spacing:.07em;text-transform:uppercase;
  border:1px solid transparent}
.badge--ok{color:#5eead4;background:rgba(16,185,129,.16)}
.badge--warn{color:#fcd34d;background:rgba(245,158,11,.16)}
.badge--bad{color:#fca5a5;background:rgba(239,68,68,.16)}
.badge--info{color:#a8ccfd;background:rgba(96,165,250,.16)}
.badge--mute{color:var(--ink-3);background:rgba(255,255,255,.06)}
.role{font:700 9.5px/1.6 var(--mono);letter-spacing:.06em;text-transform:uppercase;
  padding:2px 7px;border-radius:5px;background:var(--panel-3);color:var(--ink-2)}
.role--admin{background:rgba(139,125,255,.16);color:#b9b0ff}
.role--owner{background:rgba(44,186,172,.16);color:#8ee9df}
.role--pm{background:rgba(96,165,250,.14);color:#a8ccfd}

.grid{display:grid;gap:14px}
.g2{grid-template-columns:repeat(2,minmax(0,1fr))}
.g3{grid-template-columns:repeat(3,minmax(0,1fr))}
.g4{grid-template-columns:repeat(4,minmax(0,1fr))}
@media (max-width:1100px){.g4{grid-template-columns:repeat(2,minmax(0,1fr))}
  .g3{grid-template-columns:repeat(2,minmax(0,1fr))}}
@media (max-width:760px){.app{grid-template-columns:1fr}.side{display:none}
  .g2,.g3,.g4{grid-template-columns:minmax(0,1fr)}}

.card{background:var(--panel);border:1px solid var(--line);border-radius:var(--r);
  padding:20px 22px;box-shadow:var(--shadow)}
.card h3{font-size:14.5px;font-weight:650;margin-bottom:12px;letter-spacing:-.01em}
.card--pad0{padding:0;overflow:hidden}
.k{font:700 9.5px/1 var(--mono);letter-spacing:.13em;text-transform:uppercase;
  color:var(--ink-3);margin-bottom:9px}
/* The reference's headline treatment: a big tight numeral with a small grey unit. */
.v{font-size:29px;font-weight:780;letter-spacing:-.025em;font-variant-numeric:tabular-nums;
  line-height:1.1}
.v small{font-size:12px;font-weight:600;color:var(--ink-3);margin-left:5px;
  letter-spacing:0}
.sub{font-size:12px;color:var(--ink-3);margin-top:6px}

table.t{font-size:13px}
table.t th{text-align:left;padding:11px 15px;border-bottom:1px solid var(--line);
  font:700 9.5px/1.4 var(--mono);letter-spacing:.09em;text-transform:uppercase;
  color:var(--ink-3);background:var(--panel-2);white-space:nowrap}
table.t td{padding:12px 15px;border-bottom:1px solid var(--line);vertical-align:middle}
table.t tbody tr:last-child td{border-bottom:0}
table.t tbody tr:hover{background:rgba(255,255,255,.025)}
.num{font-family:var(--mono);font-variant-numeric:tabular-nums;white-space:nowrap}
.muted{color:var(--ink-3)}
.wide{width:100%}

.btn{display:inline-flex;align-items:center;gap:7px;padding:8px 14px;border-radius:var(--r-s);
  border:1px solid var(--line-2);background:var(--panel-2);color:var(--ink);
  font-weight:600;font-size:13px;cursor:pointer;transition:.18s}
.btn:hover{border-color:var(--ctl);text-decoration:none}
.btn:focus-visible{outline:2px solid var(--ctl);outline-offset:1px}
.btn--p{background:var(--ctl);border-color:var(--ctl);color:var(--ctl-ink)}
.btn--p:hover{background:#255ab4;border-color:#255ab4}
.btn--d{border-color:rgba(239,68,68,.4);color:#ffb4b4}
.btn--d:hover{border-color:var(--red);background:rgba(239,68,68,.1)}
.btn--s{padding:5px 10px;font-size:12px}
.row{display:flex;gap:9px;align-items:center;flex-wrap:wrap}

label.f{display:block;font-size:12px;color:var(--ink-2);margin-bottom:5px;font-weight:600}
input.i,select.i,textarea.i{width:100%;padding:9px 11px;border-radius:var(--r-s);
  background:var(--panel-2);border:1px solid var(--line);color:var(--ink)}
input.i:focus,select.i:focus,textarea.i:focus{outline:none;border-color:var(--ctl);
  box-shadow:0 0 0 3px var(--ctl-soft)}
.fset{display:grid;gap:13px}

.flash{padding:11px 15px;border-radius:10px;margin-bottom:16px;font-size:13px;
  border:1px solid var(--line-2);background:var(--panel-2)}
.flash--ok{border-color:rgba(16,185,129,.4);background:rgba(16,185,129,.08)}
.flash--bad{border-color:rgba(239,68,68,.4);background:rgba(239,68,68,.08)}
.flash--warn{border-color:rgba(245,158,11,.4);background:rgba(245,158,11,.08)}

.note{font-size:12px;color:var(--ink-3);border-left:2px solid var(--line-2);
  padding-left:12px;margin-top:14px;line-height:1.6}
.bar{height:6px;border-radius:99px;background:var(--panel-3);overflow:hidden}
.bar i{display:block;height:100%;background:linear-gradient(90deg,var(--teal),var(--green));
  transition:width .18s ease,background .18s ease}
/* Comfort-stress bands, same thresholds as the prototype: <30 Low, <55 Moderate,
   <78 Elevated, else High. */
.bar i.bar--lo{background:var(--green)}
.bar i.bar--mo{background:var(--teal)}
.bar i.bar--el{background:var(--amber)}
.bar i.bar--hi{background:var(--red)}

/* Banner: the prototype's notice strip, used on the planner and the demo walkthrough. */
.banner{display:flex;gap:14px;align-items:flex-start;padding:14px 16px;border-radius:12px;
  border:1px solid var(--line-2);background:var(--panel);font-size:13.5px}
.banner b{font-size:14.5px}
.banner--info{border-color:rgba(96,165,250,.35);background:rgba(96,165,250,.07)}
.banner--warn{border-color:rgba(245,158,11,.32);background:rgba(245,158,11,.07)}

/* Curtailment slider. Snaps to the asset's own ramp_steps in JS; styled in both themes
   because the native control ignores colour otherwise. */
input[type=range].rng{-webkit-appearance:none;appearance:none;width:100%;height:22px;
  background:transparent;cursor:pointer}
input[type=range].rng::-webkit-slider-runnable-track{height:5px;border-radius:99px;
  background:var(--panel-3)}
input[type=range].rng::-webkit-slider-thumb{-webkit-appearance:none;appearance:none;
  width:15px;height:15px;border-radius:50%;background:var(--teal);margin-top:-5px;
  border:2px solid var(--bg)}
input[type=range].rng::-moz-range-track{height:5px;border-radius:99px;background:var(--panel-3)}
input[type=range].rng::-moz-range-thumb{width:13px;height:13px;border:2px solid var(--bg);
  border-radius:50%;background:var(--teal)}
input[type=range].rng:disabled{opacity:.45;cursor:not-allowed}
.empty{padding:34px;text-align:center;color:var(--ink-3);font-size:13px}
.mutebar{background:rgba(245,158,11,.1);border-bottom:1px solid rgba(245,158,11,.3);
  padding:8px 26px;font-size:12.5px;color:#f8d38a}

/* ---------- login ---------- */
.login{min-height:100vh;display:grid;place-items:center;padding:24px;
  background:radial-gradient(1100px 560px at 50% -10%,rgba(44,186,172,.13),transparent),
             var(--bg)}
.login__box{width:100%;max-width:396px}
.login__card{background:var(--panel);border:1px solid var(--line);border-radius:16px;
  padding:28px}
.login h1{font-size:21px;margin-bottom:4px}

/* ==========================================================================
   LIGHT THEME
   The original Q-Peak ships both, and the feedback asks for the same. Every
   colour above is already a token, so the light theme is a token override on
   :root[data-theme="light"] rather than a second stylesheet. The accent shifts
   to the amber the real platform uses in its light mode.
   ========================================================================== */
:root[data-theme="light"]{
  /* This is the half of the pass that moves furthest toward `theme influence.png`:
     a near-white page, white cards, hairline borders and one soft shadow. The data
     colours stay dark enough for text on white (all of these clear 4.5:1 on #fff);
     the control accent is the reference's blue. */
  --bg:#f7f8fa;
  --panel:#ffffff;
  --panel-2:#f4f6f8;
  --panel-3:#e9edf2;
  --line:rgba(16,24,40,.08);
  --line-2:rgba(16,24,40,.15);
  --ink:#101828;
  --ink-2:#48546a;
  --ink-3:#69748a;
  --teal:#b25a08;          /* the real platform's light-mode accent is amber */
  --teal-2:#8f4706;
  --amber:#b45309;
  --red:#c2321f;
  --green:#0b7a5a;
  --info:#1d63c4;
  --violet:#5b4bd6;
  --ctl:#1f6feb;
  --ctl-ink:#ffffff;
  --ctl-soft:rgba(31,111,235,.09);
  --shadow:0 1px 2px rgba(16,24,40,.05),0 1px 3px rgba(16,24,40,.04);
}
:root[data-theme="light"] .side{background:#fff;border-right:1px solid var(--line)}
:root[data-theme="light"] .brand__mark{--brand-hi:#1f2937;--brand-lo:#64748b}
:root[data-theme="light"] .top{background:rgba(255,255,255,.9)}
:root[data-theme="light"] .nav a.on{background:var(--ctl-soft);color:#1552b8}
:root[data-theme="light"] table.t tbody tr:hover{background:rgba(16,24,40,.02)}
:root[data-theme="light"] .btn--p{color:#fff}
:root[data-theme="light"] .side{box-shadow:1px 0 0 rgba(16,24,40,.04)}
/* Pastel pills need darker text on white to stay readable. */
:root[data-theme="light"] .badge--ok{color:#07603f;background:rgba(11,122,90,.11)}
:root[data-theme="light"] .badge--warn{color:#8a4406;background:rgba(180,83,9,.12)}
:root[data-theme="light"] .badge--bad{color:#982616;background:rgba(194,50,31,.11)}
:root[data-theme="light"] .badge--info{color:#134a9c;background:rgba(29,99,196,.1)}
:root[data-theme="light"] .badge--mute{color:var(--ink-3);background:rgba(16,24,40,.05)}
:root[data-theme="light"] .role--admin{background:rgba(91,75,214,.1);color:#413397}
:root[data-theme="light"] .role--owner{background:rgba(178,90,8,.12);color:#8a4406}
:root[data-theme="light"] .role--pm{background:rgba(29,99,196,.1);color:#134a9c}
:root[data-theme="light"] .role{background:rgba(16,24,40,.055);color:var(--ink-2)}
:root[data-theme="light"] table.t th{background:#fafbfc}
:root[data-theme="light"] .banner{box-shadow:var(--shadow)}
:root[data-theme="light"] .login{background:
  radial-gradient(1100px 560px at 50% -10%,rgba(31,111,235,.07),transparent),var(--bg)}
:root[data-theme="light"] .role--admin{background:rgba(91,75,214,.12);color:#4a3cc0}
:root[data-theme="light"] .role--owner{background:rgba(194,98,10,.13);color:#8a4406}
:root[data-theme="light"] .role--pm{background:rgba(29,99,196,.12);color:#1a56ad}

/* ---------- header furniture the real platform has ---------- */
.crumb{display:flex;align-items:center;gap:8px;font-size:13px;color:var(--ink-3)}
.crumb b{color:var(--ink);font-weight:650}
.clock{font:600 12.5px/1 var(--mono);color:var(--ink-2);letter-spacing:.02em;
  white-space:nowrap}
.clock b{font-size:15px;color:var(--ink);font-weight:700}
.tbtn{display:grid;place-items:center;width:34px;height:34px;border-radius:9px;
  border:1px solid var(--line-2);background:var(--panel-2);cursor:pointer;flex:none}
.tbtn:hover{border-color:var(--teal)}
.tbtn svg{width:17px;height:17px}
.asclient{display:inline-flex;align-items:center;gap:8px;padding:5px 11px;border-radius:99px;
  background:rgba(245,158,11,.14);border:1px solid rgba(245,158,11,.4);
  color:var(--amber);font-size:12.5px;font-weight:650}
.asclient a{color:inherit;opacity:.8}
.evpill{display:inline-flex;align-items:center;gap:7px;padding:5px 12px;border-radius:99px;
  border:1px solid var(--line-2);background:var(--panel-2);font-size:12.5px;color:var(--ink-2)}
.evpill i{width:7px;height:7px;border-radius:50%;background:var(--ink-3);display:block}
.evpill.on i{background:var(--green)}
.side__as{margin:0 12px 6px;padding:12px 13px;border-radius:10px;
  background:rgba(44,186,172,.1);border:1px solid rgba(44,186,172,.28)}
.side__as .k{margin-bottom:4px}
.side__as b{display:block;font-size:15px}
.side__as span{font-size:12px;color:var(--ink-3)}
.side__as a{display:inline-block;margin-top:8px;font-size:12.5px}

/* ---------- peak forecast ---------- */
.hero{display:grid;grid-template-columns:1.25fr .95fr;gap:0;overflow:hidden}
@media (max-width:900px){.hero{grid-template-columns:1fr}}
.hero__l{padding:26px 28px}
.hero__r{padding:26px 28px;border-left:1px solid var(--line);text-align:center;
  background:var(--panel-2)}
.hero h2{font-size:30px;font-weight:780;letter-spacing:-.03em;margin:8px 0 8px}
.big{font:800 46px/1 var(--sans);letter-spacing:-.03em;color:var(--amber)}
.days{display:grid;grid-template-columns:repeat(6,minmax(0,1fr));gap:10px}
@media (max-width:1000px){.days{grid-template-columns:repeat(3,minmax(0,1fr))}}
@media (max-width:620px){.days{grid-template-columns:repeat(2,minmax(0,1fr))}}
.day{border:1px solid var(--line);border-radius:var(--r-s);padding:15px 10px;
  text-align:center;background:var(--panel);box-shadow:var(--shadow)}
/* Risk reads by colour, as in the reference: red high, amber elevated, green low. */
.day--hi{background:rgba(239,68,68,.11);border-color:rgba(239,68,68,.3)}
.day--el{background:rgba(245,158,11,.11);border-color:rgba(245,158,11,.3)}
.day--mo{background:rgba(251,191,36,.08);border-color:rgba(251,191,36,.24)}
.day--lo{background:rgba(16,185,129,.08);border-color:rgba(16,185,129,.22)}
.day--we{background:var(--panel-2)}
/* the reference puts the weekday in a pale pill above the number */
.day__d{display:inline-block;font:700 10.5px/1 var(--mono);letter-spacing:.09em;
  text-transform:uppercase;color:var(--ink-2);background:var(--panel-2);
  padding:4px 9px;border-radius:99px}
.day__dt{font-size:11.5px;color:var(--ink-3);margin-top:3px}
.day__p{font:800 27px/1 var(--sans);margin:11px 0 3px;letter-spacing:-.02em}
.day__b{font:700 10px/1.35 var(--mono);letter-spacing:.06em;text-transform:uppercase}
.day__mw{font:600 11.5px/1.4 var(--mono);color:var(--ink-3);margin-top:9px;
  padding-top:9px;border-top:1px solid var(--line)}
.hi{color:#f87171}.el{color:var(--amber)}.mo{color:#d8a412}.lo{color:#34d399}
:root[data-theme="light"] .hi{color:var(--red)}
:root[data-theme="light"] .mo{color:#8a5a06}
:root[data-theme="light"] .lo{color:var(--green)}
.wx{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:10px}
.wx > div{border:1px solid var(--line);border-radius:var(--r-s);padding:16px;
  text-align:center;background:var(--panel);box-shadow:var(--shadow)}
/* `.wx div` (no >) boxed every descendant, so the label, icon, temp and caption each
   drew their own border - four nested boxes per day. */
.wx .t{font:800 24px/1 var(--sans);color:var(--amber);margin-top:8px}

/* ---------- nav icons ---------- */
.nvi{width:17px;height:17px;flex:none;opacity:.8}
.nav a.on .nvi{opacity:1}
.nav a span{flex:1;min-width:0}

/* ---------- building cards (Portfolio > Buildings) ---------- */
.blds{display:grid;grid-template-columns:repeat(auto-fill,minmax(232px,1fr));gap:14px}
.bld{background:var(--panel);border:1px solid var(--line);border-radius:var(--r);
  overflow:hidden;display:flex;flex-direction:column;transition:.18s}
.bld:hover{border-color:var(--teal);transform:translateY(-2px);text-decoration:none}
.bld__vis{height:104px;position:relative;display:grid;place-items:end center;
  background:linear-gradient(180deg,var(--panel-3),var(--panel-2));overflow:hidden}
.bld__vis svg{width:100%;height:100%;display:block}
.bld__code{position:absolute;top:9px;left:10px}
.bld__kw{position:absolute;top:9px;right:10px;font:700 10px/1.6 var(--mono);
  padding:2px 7px;border-radius:99px;background:rgba(44,186,172,.16);color:#8ee9df}
:root[data-theme="light"] .bld__kw{background:rgba(194,98,10,.13);color:#8a4406}
.bld__b{padding:13px 15px 15px;display:flex;flex-direction:column;gap:3px;flex:1}
.bld__a{font-weight:650;font-size:13.5px;line-height:1.35;color:var(--ink)}
.bld__c{font-size:11.5px;color:var(--ink-3)}
.bld__m{margin-top:auto;padding-top:11px;display:flex;gap:14px;
  border-top:1px solid var(--line);font:600 11px/1 var(--mono);color:var(--ink-3)}
.bld__m b{color:var(--ink);font-size:13px;font-weight:700}

/* ---------- future-release notice ---------- */
.future{border:1px dashed var(--line-2);border-radius:var(--r);padding:16px 18px;
  background:var(--panel-2);margin-bottom:14px}
.future b{color:var(--amber)}

/* Outlier marker on the demand chart: IESO occasionally publishes a single hour far
   from both neighbours. The value is drawn as published and ringed, never smoothed. */
.odd{fill:none;stroke:var(--red);stroke-width:1.6;opacity:.9}


/* ---------- charts ---------- */
.chart{position:relative}
.cax{font:500 10px var(--mono);fill:var(--ink-3)}
.dhit{cursor:crosshair}
/* Tooltip sits above the plot, follows the hovered hour horizontally. */
.ctip{position:absolute;top:4px;pointer-events:none;z-index:5;display:grid;gap:3px;
  padding:9px 11px;border-radius:9px;border:1px solid var(--line-2);background:var(--panel);
  box-shadow:0 8px 24px rgba(0,0,0,.35);font-size:12px;white-space:nowrap}
.ctip b{font-family:var(--mono)}
.ctip span{display:flex;align-items:center;gap:6px;color:var(--ink-2)}
:root[data-theme="light"] .ctip{box-shadow:0 8px 24px rgba(16,24,40,.12)}
/* Legend swatches, so the key is a line sample rather than an em dash. */
.lgnd{gap:14px;font-size:11.5px;color:var(--ink-3)}
.lgnd span{display:flex;align-items:center;gap:6px}
/* The swatch is an SVG line, not a CSS border. A dashed border-top on a 16px-wide,
   zero-height box renders inconsistently - often as a solid stub - so the forecast and the
   actual looked identical in the key while the chart drew one of them dashed. Giving the
   swatch the SAME stroke-dasharray as the chart means the key cannot disagree with the
   thing it describes. */
.sw{width:20px;height:8px;flex:none;overflow:visible}
.sw line{stroke-linecap:round}
.sw--f line{stroke:var(--amber);stroke-width:2;stroke-dasharray:6 4}
.sw--a line{stroke:var(--teal);stroke-width:2.8}
.sw--t line{stroke:var(--red);stroke-width:1.6;stroke-dasharray:5 4}
@media print{
  .sw--f line{stroke:#8a4406}
  .sw--a line{stroke:#0f7d72}
  .sw--t line{stroke:#982616}
}

.wx--none{opacity:.55;border-style:dashed !important}


/* ---------- preview (a page reserved for a future release) ---------- */
/* Obscured, and it STAYS obscured. Mert, 2026-07-27: "live dispatch is still visible when
   mouse goes on that, make it really unvisible inside that blur part". It used to lift the
   blur on hover, which defeated the point - the whole reason the page is blurred is that
   its numbers are not live, and a number you can reveal by resting the mouse on it is a
   number someone will read and quote.

   Three layers, because a blur alone is soft enough to decipher at large font sizes:
     1. blur + desaturate, permanently, with no hover or focus rule to undo it;
     2. `color:transparent` with a text-shadow, so every glyph is a smudge of its own
        colour rather than a legible shape - this survives even if filter() is unsupported;
     3. a scrim over the whole block, which flattens what contrast is left.
   The layout stays reviewable, which is the only thing this page is for. */
.preview{position:relative}
.preview__body{position:relative;filter:blur(7px) saturate(.55);opacity:.6;
  pointer-events:none;user-select:none;-webkit-user-select:none}
/* Glyphs become smudges. Scoped to text nodes so borders, bars and cards keep their shape. */
.preview__body,.preview__body *{color:transparent !important;
  text-shadow:0 0 9px rgba(140,150,170,.85)}
.preview__body::after{content:"";position:absolute;inset:0;z-index:3;
  background:var(--panel);opacity:.28;pointer-events:none}
.preview__tag{position:absolute;top:50%;left:50%;transform:translate(-50%,-50%);
  z-index:4;padding:9px 16px;border-radius:99px;pointer-events:none;
  background:var(--panel);border:1px solid var(--line-2);box-shadow:0 6px 22px rgba(0,0,0,.35);
  font:700 11px/1 var(--mono);letter-spacing:.1em;text-transform:uppercase;
  color:var(--ink-2);white-space:nowrap}
:root[data-theme="light"] .preview__tag{box-shadow:0 6px 22px rgba(16,24,40,.14)}
:root[data-theme="light"] .preview__body,
:root[data-theme="light"] .preview__body *{text-shadow:0 0 9px rgba(80,92,112,.8)}


/* ---------- client report (printable) ---------- */
.rep{background:var(--panel);border:1px solid var(--line);border-radius:var(--r);
  padding:30px 34px;box-shadow:var(--shadow)}
.rep h2{font-size:23px;font-weight:750;letter-spacing:-.02em;margin:4px 0 6px}
.rep h3{font-size:15px;font-weight:700;margin:0 0 8px;padding-bottom:7px;
  border-bottom:1px solid var(--line)}
.rep p{margin:0 0 10px;font-size:13px}
.rep__head{padding-bottom:18px;border-bottom:2px solid var(--line-2)}
.rep__client{font:700 11px/1 var(--mono);letter-spacing:.16em;text-transform:uppercase;
  color:var(--teal)}
.rep__sub{font-size:12.5px;color:var(--ink-2);margin-top:3px}
.rep__ul{margin:0 0 12px;padding-left:20px;font-size:13px;color:var(--ink-2)}
.rep__ul li{margin-bottom:7px}
.rep__tot td{border-top:2px solid var(--line-2);background:var(--panel-2)}
.rep__foot{margin-top:24px;padding-top:14px;border-top:1px solid var(--line);
  font-size:11.5px;color:var(--ink-3);line-height:1.7}
@media print{
  .side,.top,.noprint,.mutebar{display:none !important}
  .app{display:block}.wrap{padding:0;max-width:none}
  body{background:#fff;color:#000}
  .rep{border:0;box-shadow:none;padding:0}
  .card{box-shadow:none;break-inside:avoid}
  table.t{break-inside:avoid}
  .rep h3{break-after:avoid}
}


/* ---------- BAS checklist phases ---------- */
/* Three phases, three colours, so an operator can see at a glance which block they are in
   during an event: blue to prepare, amber while holding the curtailment, green to recover.
   The tint is carried on a left edge and the header rather than the whole table, so the
   step text keeps full contrast. */
.phase{border-left:3px solid var(--line-2);margin:14px 0 0}
.phase:last-of-type{margin-bottom:4px}
.phase__hd{display:flex;align-items:center;gap:9px;padding:9px 20px;font-size:13px}
.phase__dot{width:9px;height:9px;border-radius:50%;background:currentColor;flex:none}
.phase--before{border-left-color:var(--info)}
.phase--before .phase__hd{background:rgba(96,165,250,.09);color:#a8ccfd}
.phase--during{border-left-color:var(--amber)}
.phase--during .phase__hd{background:rgba(245,158,11,.1);color:#fcd34d}
.phase--after{border-left-color:var(--green)}
.phase--after .phase__hd{background:rgba(16,185,129,.09);color:#5eead4}
.phase__hd b{color:var(--ink)}
:root[data-theme="light"] .phase--before .phase__hd{background:rgba(29,99,196,.07);color:#134a9c}
:root[data-theme="light"] .phase--during .phase__hd{background:rgba(180,83,9,.08);color:#8a4406}
:root[data-theme="light"] .phase--after .phase__hd{background:rgba(11,122,90,.08);color:#07603f}


/* ---------- report figures ---------- */
/* SVG, server-rendered, so a printed report is never half-drawn and never rasterised. */
.fig{margin:18px 0 4px;padding:0}
.fig svg{display:block;height:auto;max-width:100%}
.fig figcaption{font-size:11.5px;color:var(--ink-3);margin-top:7px;line-height:1.55}
.fig__bar{fill:var(--teal)}
.fig__bar--alt{fill:var(--info)}
.fig__val{fill:var(--ink-2)}
.fig__lbl{fill:var(--ink-2)}
.fig__win{fill:rgba(245,158,11,.13)}
.fig__bl{stroke:var(--amber);stroke-width:1.6;stroke-dasharray:5 4}
.fig__bl-t{fill:var(--amber)}
.fig__line{fill:none;stroke:var(--teal);stroke-width:1.8;stroke-linejoin:round}

/* Row sparklines: shape only. The number beside them carries the magnitude. */
.spark{width:64px;height:18px;display:block}
.spark__l{fill:none;stroke:var(--teal);stroke-width:1.5;stroke-linejoin:round}
.spark__d{fill:var(--teal)}
.spark__zero{stroke:var(--line-2);stroke-width:1;stroke-dasharray:2 2}

/* Print: figures must not break across pages, and nothing may animate. */
@media print{
  .fig{break-inside:avoid;page-break-inside:avoid}
  .fig svg,.spark{animation:none !important;transition:none !important}
  .fig__bar{fill:#0f7d72}
  .fig__bar--alt{fill:#1d63c4}
  .fig__line,.spark__l{stroke:#0f7d72}
  .spark__d{fill:#0f7d72}
  .fig__win{fill:rgba(180,83,9,.14)}
  .fig__bl,.fig__bl-t{stroke:#8a4406;fill:#8a4406}
  .fig__lbl,.fig__val,.cax{fill:#333}
}


/* ---------- report tables are dense ---------- */
/* The by-building table carries up to ten columns: the building, one per Event, a trend,
   an average, the best event, the commitment and the comparison. At the console's 13px
   with 15px cell padding that is ~300px of padding alone, so it overflowed its card and
   numbers were clipped. Scoped to .rep so the console's own tables are untouched. */
.rep table.t{font-size:11.5px}
.rep table.t th{padding:8px 9px;letter-spacing:.05em;white-space:normal}
.rep table.t td{padding:8px 9px}
.rep table.t .sub{font-size:10px;margin-top:1px}
.rep .spark{width:54px}
/* The event columns hold four digits at most; keep them narrow so the building name gets
   the room instead. */
.rep table.t th.num,.rep table.t td.num{padding-left:7px;padding-right:7px}

@media print{
  /* Print cannot scroll, so a scrolling wrapper must not hide the right-hand columns. */
  .rep div[style*="overflow-x"]{overflow:visible !important}
  .rep table.t{font-size:8.6pt;width:100%}
  .rep table.t th,.rep table.t td{padding:4px 5px}
  .rep table.t .sub{font-size:7.4pt}
  .rep .spark{width:44px}
}


/* ---------- checklist ticks ---------- */
/* A real checkbox, visually replaced, so keyboard and screen readers keep working and the
   printed sheet still shows a box an operator can tick by hand. */
.ck{display:inline-flex;align-items:center;cursor:pointer;position:relative}
.ck__i{position:absolute;opacity:0;width:20px;height:20px;margin:0;cursor:pointer}
.ck__b{width:20px;height:20px;border-radius:6px;border:1.8px solid var(--line-2);
  background:var(--panel-2);display:inline-block;position:relative;transition:.15s}
.ck__i:checked + .ck__b{background:var(--green);border-color:var(--green)}
.ck__i:checked + .ck__b::after{content:"";position:absolute;left:6px;top:2px;width:5px;
  height:10px;border:solid #06231a;border-width:0 2.2px 2.2px 0;transform:rotate(45deg)}
.ck__i:focus-visible + .ck__b{outline:2px solid var(--ctl);outline-offset:2px}
.ck__sr{position:absolute;width:1px;height:1px;overflow:hidden;clip:rect(0 0 0 0)}
.ckl__t{line-height:1.5}
.ckl tr.is-done .ckl__t{color:var(--ink-3);text-decoration:line-through;
  text-decoration-color:var(--line-2)}
.ckl__by{font-size:11px;color:var(--green)}
:root[data-theme="light"] .ck__i:checked + .ck__b::after{border-color:#fff}

@media print{
  /* An unticked box must print as an empty square so the sheet is usable on paper. */
  .ck__b{border-color:#555;background:#fff;-webkit-print-color-adjust:exact;
    print-color-adjust:exact}
  .ck__i:checked + .ck__b{background:#fff;border-color:#111}
  .ck__i:checked + .ck__b::after{border-color:#111}
  .ckl tr.is-done .ckl__t{color:#000;text-decoration:none}
  .ckl__by{color:#444}
  .phase{break-inside:avoid}
}

/* Program demos (/programs): answer cards and the three-step header. */
.opts{display:grid;gap:10px;grid-template-columns:repeat(auto-fill,minmax(210px,1fr))}
.opt{position:relative;display:block;padding:12px 14px;border:1px solid var(--line-2);
  border-radius:var(--r-s);background:var(--panel-2);cursor:pointer}
.opt input{position:absolute;opacity:0;pointer-events:none}
.opt b{display:block;font-size:13.5px}
.opt .sub{margin-top:2px}
.opt:hover{border-color:var(--ctl)}
.opt:has(input:checked){border-color:var(--ctl);background:var(--ctl-soft)}
.opt:has(input:focus-visible){outline:2px solid var(--ctl);outline-offset:2px}
.opt--off{opacity:.55;cursor:not-allowed}
.qh{font-size:13px;font-weight:650;margin:18px 0 8px}
.qh:first-child{margin-top:0}
.steps3{display:flex;gap:0;margin:0 0 14px;overflow-x:auto}
.steps3 a,.steps3 span{flex:1;min-width:150px;padding:10px 14px;border:1px solid var(--line);
  background:var(--panel);font-size:13px;color:var(--ink-2)}
.steps3 > :first-child{border-radius:10px 0 0 10px}
.steps3 > :last-child{border-radius:0 10px 10px 0}
.steps3 .on{background:var(--ctl-soft);color:var(--ink);font-weight:650}
.kv{display:grid;grid-template-columns:120px 1fr;gap:6px 14px;font-size:13px}
.kv dt{color:var(--ink-3)}
.kv dd{margin:0}
.tl{list-style:none;margin:0;padding:0;font-size:13px}
.tl li{display:grid;grid-template-columns:170px 1fr;gap:10px;padding:6px 0;border-top:1px solid var(--line)}
.tl li:first-child{border-top:0}
.tl b{font-family:var(--mono);font-size:12px;font-weight:600}
@media (max-width:760px){.kv{grid-template-columns:1fr}.tl li{grid-template-columns:1fr}}
