/* AGS Project Control — shared styles.
   1. Tokens: the light palette on :root, then two equivalent dark blocks (system dark, explicit dark), then the explicit pink block, then a print block that forces light.
   2. Application shell: sidebar, top bar, content column, mobile drawer, print header.
   3. Views: cards, tables, chips, schedule, intake, archive, assistant, auth pages.
   Every colour below is a token so dark mode retunes everything; the on-soft-background text colours are tokens too (--good-ink …). */
:root{
  --bg:#f3f5f8; --surface:#ffffff; --surface2:#f6f8fb; --ink:#14181f; --ink2:#454d57; --muted:#818183; --line:#dfe3e9; --line2:#eceff3;
  --accent:#004989; --accent-ink:#ffffff; --accent-soft:#e4edf6; --live:#00aeef;
  --brand-deep:#000545; --brand-mid:#004989; --brand-light:#00aeef; --brand-grey:#818183; --brand-band:#002b6b;
  --bronze:#9a6128; --bronze-soft:#f5ebdf;
  --good:#0ca30c; --good-soft:#e2f5e2; --warn:#fab219; --warn-soft:#fff1cf; --serious:#ec835a; --gold:#c9a227; --crit:#d03b3b; --crit-soft:#fbe3e3; --info:#2a78d6; --info-soft:#e1edfb;
  --good-ink:#0a6a0a; --warn-ink:#7a5200; --amber-ink:#a86f00; --crit-ink:#9b2020; --info-ink:#1a5aa8;
  --s1:#2a78d6; --s2:#eb6834; --s3:#1baf7a; --grid:#e3e6ec; --axis:#c4c9d3;
  --pm-1:#004989; --pm-2:#00aeef; --pm-3:#1f9e89; --pm-4:#e07a3f; --pm-5:#7b6bc9; --pm-6:#c9a227;
  --est-1:#c62828; --est-2:#1f5fbf; --est-3:#14181f; --est-4:#6a3fb5; --est-ink:#ffffff; --est-edge:transparent;   /* estimators in ESTIMATORS' order (rules.js): Ridge red, Evan blue, Joe black, Schawnette purple — every theme; the edge rings a tag on a dark one */
  --chart-1:#004989; --chart-2:#00aeef; --chart-3:#1f9e89; --chart-4:#e07a3f; --chart-5:#7b6bc9; --chart-6:#c9a227; --chart-7:#818183; --chart-8:#b9c0cc;
  --sidebar-bg:#000545; --sidebar-ink:#dfe6f2; --sidebar-muted:#8f9bb8; --sidebar-active:rgba(0,174,239,.16); --sidebar-hi:#ffffff; --sidebar-line:rgba(255,255,255,.08); --sidebar-hover:rgba(255,255,255,.06);
  --scrim:rgba(0,5,69,.5); --logo-plate:transparent; --paper:#ffffff; --paper-ink:#000000;
  --entry-soft:#e8f6fd; --entry-ink:#005f8a; --rule:#8a8f95;
  --radius:8px; --top-h:52px; --shadow:0 1px 2px rgba(20,24,31,.06),0 4px 14px rgba(20,24,31,.05); --shadow-lg:0 12px 32px rgba(0,5,69,.18);
  color-scheme:light;
}
@media (prefers-color-scheme:dark){
  :root:not([data-theme="light"]):not([data-theme="pink"]){
    --bg:#12151c; --surface:#181c24; --surface2:#1e232c; --ink:#eef2f6; --ink2:#b7c0cc; --muted:#8b95a3; --line:#2a313c; --line2:#232932;
    --accent:#5fb2f2; --accent-ink:#06192b; --accent-soft:#1a2c40; --live:#33c2ff;
    --brand-deep:#000545; --brand-mid:#5fb2f2; --brand-light:#33c2ff; --brand-grey:#9a9b9e; --brand-band:#002b6b;
    --bronze:#d39a5c; --bronze-soft:#2f271d;
    --good:#3ec23e; --good-soft:#173a17; --warn:#fab219; --warn-soft:#3d3110; --serious:#ec835a; --gold:#e0b83a; --crit:#ee5c5c; --crit-soft:#3f1c1c; --info:#5b9de6; --info-soft:#18283c;
    --good-ink:#7ee07e; --warn-ink:#f6c75a; --amber-ink:#fab219; --crit-ink:#ff9c9c; --info-ink:#8dbcf3;
    --s1:#3987e5; --s2:#d95926; --s3:#199e70; --grid:#262c36; --axis:#3a4250;
    --pm-1:#4f8fd6; --pm-2:#33c2ff; --pm-3:#3fc4ac; --pm-4:#f0925c; --pm-5:#a094e6; --pm-6:#e0bb45;
    --est-edge:#b7c0cc;
    --chart-1:#4f8fd6; --chart-2:#33c2ff; --chart-3:#3fc4ac; --chart-4:#f0925c; --chart-5:#a094e6; --chart-6:#e0bb45; --chart-7:#9aa3b0; --chart-8:#5c6572;
    --sidebar-bg:#070c2a; --sidebar-ink:#dfe6f2; --sidebar-muted:#8f9bb8; --sidebar-active:rgba(0,174,239,.18); --sidebar-hi:#ffffff; --sidebar-line:rgba(255,255,255,.08); --sidebar-hover:rgba(255,255,255,.06);
    --scrim:rgba(0,0,0,.6); --logo-plate:#ffffff; --paper:#ffffff; --paper-ink:#000000;
    --entry-soft:#10283a; --entry-ink:#7fd4ff; --rule:#4d5563;
    --radius:8px; --top-h:52px; --shadow:0 1px 2px rgba(0,0,0,.4),0 4px 14px rgba(0,0,0,.3); --shadow-lg:0 12px 32px rgba(0,0,0,.5);
    color-scheme:dark;
  }
}
:root[data-theme="dark"]{
  --bg:#12151c; --surface:#181c24; --surface2:#1e232c; --ink:#eef2f6; --ink2:#b7c0cc; --muted:#8b95a3; --line:#2a313c; --line2:#232932;
  --accent:#5fb2f2; --accent-ink:#06192b; --accent-soft:#1a2c40; --live:#33c2ff;
  --brand-deep:#000545; --brand-mid:#5fb2f2; --brand-light:#33c2ff; --brand-grey:#9a9b9e; --brand-band:#002b6b;
  --bronze:#d39a5c; --bronze-soft:#2f271d;
  --good:#3ec23e; --good-soft:#173a17; --warn:#fab219; --warn-soft:#3d3110; --serious:#ec835a; --gold:#e0b83a; --crit:#ee5c5c; --crit-soft:#3f1c1c; --info:#5b9de6; --info-soft:#18283c;
  --good-ink:#7ee07e; --warn-ink:#f6c75a; --amber-ink:#fab219; --crit-ink:#ff9c9c; --info-ink:#8dbcf3;
  --s1:#3987e5; --s2:#d95926; --s3:#199e70; --grid:#262c36; --axis:#3a4250;
  --pm-1:#4f8fd6; --pm-2:#33c2ff; --pm-3:#3fc4ac; --pm-4:#f0925c; --pm-5:#a094e6; --pm-6:#e0bb45;
  --est-edge:#b7c0cc;
  --chart-1:#4f8fd6; --chart-2:#33c2ff; --chart-3:#3fc4ac; --chart-4:#f0925c; --chart-5:#a094e6; --chart-6:#e0bb45; --chart-7:#9aa3b0; --chart-8:#5c6572;
  --sidebar-bg:#070c2a; --sidebar-ink:#dfe6f2; --sidebar-muted:#8f9bb8; --sidebar-active:rgba(0,174,239,.18); --sidebar-hi:#ffffff; --sidebar-line:rgba(255,255,255,.08); --sidebar-hover:rgba(255,255,255,.06);
  --scrim:rgba(0,0,0,.6); --logo-plate:#ffffff; --paper:#ffffff; --paper-ink:#000000;
  --entry-soft:#10283a; --entry-ink:#7fd4ff; --rule:#4d5563;
  --radius:8px; --top-h:52px; --shadow:0 1px 2px rgba(0,0,0,.4),0 4px 14px rgba(0,0,0,.3); --shadow-lg:0 12px 32px rgba(0,0,0,.5);
  color-scheme:dark;
}
/* Pink: a light theme with a rose identity — blush ground, white surfaces with a faint rose tint, plum-navy ink, raspberry accent, plum sidebar and
   auth band, dusty-rose rules. The semantic colours stay as in light except where the blush ground would swallow them (crit warmed away from rose, the
   entry tint moved to lilac so editable cells still stand out). Chosen explicitly, so it also overrides an OS dark preference (the :not() guard above). */
:root[data-theme="pink"]{
  --bg:#fff5f8; --surface:#fffbfc; --surface2:#fdf0f4; --ink:#2b1a33; --ink2:#5a4560; --muted:#86737f; --line:#ecd5dd; --line2:#f5e6ec;
  --accent:#c2185b; --accent-ink:#ffffff; --accent-soft:#fbe0ea; --live:#f0508f;
  --brand-deep:#4a1236; --brand-mid:#c2185b; --brand-light:#ff8fb8; --brand-grey:#86737f; --brand-band:#6b1d4f;
  --bronze:#9a6128; --bronze-soft:#f7e9dc;
  --good:#0ca30c; --good-soft:#e2f5e2; --warn:#fab219; --warn-soft:#fff1cf; --serious:#ec835a; --gold:#c9a227; --crit:#cf3a2f; --crit-soft:#ffe2dc; --info:#2a78d6; --info-soft:#e1edfb;
  --good-ink:#0a6a0a; --warn-ink:#7a5200; --amber-ink:#a86f00; --crit-ink:#9b2020; --info-ink:#1a5aa8;
  --s1:#c2185b; --s2:#eb6834; --s3:#1baf7a; --grid:#f0dfe6; --axis:#d9bfc9;
  --pm-1:#c2185b; --pm-2:#f06292; --pm-3:#1f9e89; --pm-4:#e07a3f; --pm-5:#7b6bc9; --pm-6:#c9a227;
  --chart-1:#c2185b; --chart-2:#f06292; --chart-3:#1f9e89; --chart-4:#e07a3f; --chart-5:#7b6bc9; --chart-6:#c9a227; --chart-7:#86737f; --chart-8:#d9bcc8;
  --sidebar-bg:#4a1236; --sidebar-ink:#f3e3ea; --sidebar-muted:#c49bb0; --sidebar-active:rgba(255,143,184,.2); --sidebar-hi:#ffffff; --sidebar-line:rgba(255,255,255,.1); --sidebar-hover:rgba(255,255,255,.07);
  --scrim:rgba(74,18,54,.5); --logo-plate:transparent; --paper:#ffffff; --paper-ink:#000000;
  --entry-soft:#f2e7fb; --entry-ink:#6b2d8f; --rule:#b08a9a;
  --radius:8px; --top-h:52px; --shadow:0 1px 2px rgba(74,18,54,.07),0 4px 14px rgba(74,18,54,.06); --shadow-lg:0 12px 32px rgba(74,18,54,.22);
  color-scheme:light;
}
/* Paper is always light: printing from dark or pink mode gets the light palette back. The last selector repeats the system-dark guard's two
   :not()s so it has the same specificity (0,3,0) and, sitting later in the file, wins over it; the explicit dark and pink selectors match their
   own blocks' specificity for the same reason. */
@media print{
  :root[data-theme="dark"],:root[data-theme="pink"],:root:not([data-theme="light"]):not([data-theme="pink"]){
    --bg:#ffffff; --surface:#ffffff; --surface2:#f6f8fb; --ink:#14181f; --ink2:#454d57; --muted:#818183; --line:#dfe3e9; --line2:#eceff3;
    --accent:#004989; --accent-ink:#ffffff; --accent-soft:#e4edf6; --live:#00aeef;
    --brand-deep:#000545; --brand-mid:#004989; --brand-light:#00aeef; --brand-grey:#818183; --brand-band:#002b6b;
    --bronze:#9a6128; --bronze-soft:#f5ebdf;
    --good:#0ca30c; --good-soft:#e2f5e2; --warn:#fab219; --warn-soft:#fff1cf; --serious:#ec835a; --gold:#c9a227; --crit:#d03b3b; --crit-soft:#fbe3e3; --info:#2a78d6; --info-soft:#e1edfb;
    --good-ink:#0a6a0a; --warn-ink:#7a5200; --amber-ink:#a86f00; --crit-ink:#9b2020; --info-ink:#1a5aa8;
    --s1:#2a78d6; --s2:#eb6834; --s3:#1baf7a; --grid:#e3e6ec; --axis:#c4c9d3;
    --pm-1:#004989; --pm-2:#00aeef; --pm-3:#1f9e89; --pm-4:#e07a3f; --pm-5:#7b6bc9; --pm-6:#c9a227;
    --est-edge:transparent;
    --chart-1:#004989; --chart-2:#00aeef; --chart-3:#1f9e89; --chart-4:#e07a3f; --chart-5:#7b6bc9; --chart-6:#c9a227; --chart-7:#818183; --chart-8:#b9c0cc;
    --sidebar-bg:#000545; --sidebar-ink:#dfe6f2; --sidebar-muted:#8f9bb8; --sidebar-active:rgba(0,174,239,.16); --sidebar-hi:#ffffff; --sidebar-line:rgba(255,255,255,.08); --sidebar-hover:rgba(255,255,255,.06);
    --scrim:rgba(0,5,69,.5); --logo-plate:transparent; --paper:#ffffff; --paper-ink:#000000;
    --entry-soft:#ffffff; --entry-ink:#14181f; --rule:#8a8f95;
    --radius:8px; --top-h:52px; --shadow:none; --shadow-lg:none;
    color-scheme:light;
  }
}

/* ---------- base ---------- */
*{box-sizing:border-box}
html,body{margin:0;background:var(--bg);color:var(--ink);font:14px/1.45 "IBM Plex Sans",system-ui,-apple-system,"Segoe UI",sans-serif}
h1,h2,h3,h4,.cond,th,.tab,.chip,.kpi .v,.brand{font-family:"IBM Plex Sans Condensed","IBM Plex Sans",system-ui,sans-serif}
h1{font-size:22px;font-weight:600;margin:0;text-wrap:balance}
h2{font-size:17px;font-weight:600;margin:0 0 10px}
h3{font-size:14px;font-weight:600;margin:0 0 8px;text-transform:uppercase;letter-spacing:.06em;color:var(--ink2)}
a{color:var(--accent)}
button{font:inherit;cursor:pointer}
input,select,textarea{font:inherit;color:var(--ink);background:var(--surface);border:1px solid var(--line);border-radius:4px;padding:5px 7px;min-width:0}
input:focus,select:focus,textarea:focus{outline:2px solid var(--accent);outline-offset:1px}
button:focus-visible,a:focus-visible,[tabindex]:focus-visible{outline:2px solid var(--accent);outline-offset:2px}
input[type=date]{width:128px} input[type=number]{width:96px;text-align:right;font-variant-numeric:tabular-nums}
textarea{width:100%;resize:vertical}
.btn{border:1px solid var(--line);background:var(--surface);color:var(--ink);border-radius:4px;padding:6px 12px;font-weight:500;text-decoration:none;display:inline-block}
.btn:hover{background:var(--surface2)} .btn.primary{background:var(--accent);color:var(--accent-ink);border-color:var(--accent)} .btn.primary:hover{filter:brightness(1.08)}
.btn.sm{padding:3px 8px;font-size:12px} .btn.danger{color:var(--crit)} .btn.big{padding:16px;font-size:16px;font-weight:600;width:100%;text-align:left}
.btn[disabled]{opacity:.5;cursor:default}
.admin-only{display:none} body.is-admin .admin-only{display:inline-block}
.editor-only{display:none} body.can-edit .editor-only{display:inline-block}
/* Controls by capability: a template writes class="… ${capOnly('po.write')}" (app.js), which is 'nocap' for someone whose roles do not
   hold that section's capability and nothing for someone who does. The rule only ever hides, so the control keeps whatever display it
   has (a button, a flex row, a <details> card) and no "show" rule has to restate it. editor-only above is no longer written by any view:
   body.can-edit now means "may change something somewhere", which is not what any one section's control should ask. */
.nocap{display:none!important}
.spacer{flex:1}

/* ---------- application shell: sidebar + content column ---------- */
body.app{display:grid;grid-template-columns:232px minmax(0,1fr);min-height:100vh;transition:grid-template-columns .18s ease}
html.sidebar-collapsed body.app{grid-template-columns:60px minmax(0,1fr)}
.content{min-width:0}
.sidebar{background:var(--sidebar-bg);color:var(--sidebar-ink);align-self:stretch;min-width:0}
.sbin{position:sticky;top:0;height:100vh;height:100dvh;display:flex;flex-direction:column;overflow:hidden auto}
.sbrand{display:flex;align-items:center;justify-content:center;min-height:72px;padding:14px 16px 12px;flex:none;border-bottom:1px solid var(--sidebar-line)}
.sblogo{display:flex;flex-direction:column;align-items:center;text-align:center;gap:4px;color:inherit;text-decoration:none;min-width:0;border-radius:6px}
.sblogo:focus-visible{outline:2px solid var(--brand-light);outline-offset:4px}
.sblogo img{width:132px;height:auto;display:block}
.sblogo .sbprod{font:600 11px/1 "IBM Plex Sans Condensed",sans-serif;text-transform:uppercase;letter-spacing:.12em;color:var(--sidebar-muted);white-space:nowrap}
.sblogo .mono{display:none;width:32px;height:32px;border-radius:8px;background:var(--sidebar-active);color:var(--brand-light);font:700 13px/1 "IBM Plex Sans Condensed",sans-serif;letter-spacing:.04em;place-items:center}
#nav{display:flex;flex-direction:column;flex:1;gap:0;margin:0;padding:14px 8px 10px;overflow:hidden auto;scrollbar-width:thin}
.navgrp{display:block;margin-top:12px} .navgrp:first-child{margin-top:0}
.navh{margin:0 0 4px;padding:0 12px;font:600 11px/1.6 "IBM Plex Sans Condensed",sans-serif;text-transform:uppercase;letter-spacing:.12em;color:var(--sidebar-muted);white-space:nowrap;overflow:hidden}
#nav a{position:relative;display:flex;align-items:center;gap:12px;height:36px;margin:2px 0;padding:0 12px;border-radius:6px;color:var(--sidebar-ink);text-decoration:none;font-weight:500;font-size:14px;white-space:nowrap;overflow:hidden}
#nav a svg{width:20px;height:20px;flex:none;opacity:.85}
#nav a .lbl{overflow:hidden;text-overflow:ellipsis}
#nav a:hover{background:var(--sidebar-hover);color:var(--sidebar-hi)}
#nav a.on{background:var(--sidebar-active);color:var(--sidebar-hi)} #nav a.on svg{opacity:1}
#nav a.on:before{content:"";position:absolute;left:0;top:7px;bottom:7px;width:3px;border-radius:0 2px 2px 0;background:var(--brand-light)}
#nav a:focus-visible{outline:2px solid var(--brand-light);outline-offset:-2px}
/* Admin-only nav items (Agents, Sync, Admin) need hide rules of their own: .navgrp{display:block} above (same specificity, later)
   and #nav a{display:flex} (an id) both outrank the plain .admin-only{display:none} at the top, so without these everyone would see them. */
.navgrp.admin-only,#nav a.admin-only{display:none}
body.is-admin .navgrp.admin-only{display:block} body.is-admin #nav a.admin-only{display:flex}
/* Sections by role: a section's link carries data-view-cap="<section>.view" (index.html) and is shown only once app.js has marked it
   cap-ok — /api/auth/me said this person's roles open that section (applyIdentity). Until then, and for every section outside their
   roles, it is not shown; the rule only hides, so #nav a{display:flex} above still draws the ones that stay. QuickBooks is one of them
   now (an admin, accounting, Management) rather than admin-only. Hiding is a courtesy; the router and the server each refuse on their own. */
#nav a[data-view-cap]:not(.cap-ok){display:none}
/* Management (the private section): mgmt-only marks what only its people see — body.can-manage is set in Store.init from /api/auth/me's
   can.management (admins signed in, and whoever an admin ticked on the Admin page). The nav link needs the same two rules as admin-only
   above, for the same reason: #nav a{display:flex} outranks a plain class. Hiding is a courtesy; the server refuses on its own. */
.mgmt-only{display:none} body.can-manage .mgmt-only{display:inline-block}
#nav a.mgmt-only{display:none} body.can-manage #nav a.mgmt-only{display:flex}
.sbfoot{flex:none;padding:8px;border-top:1px solid var(--sidebar-line)}
.navcollapse{display:flex;align-items:center;gap:10px;width:100%;height:34px;padding:0 10px;border:0;border-radius:6px;background:transparent;color:var(--sidebar-muted);font:inherit;font-size:13px;white-space:nowrap}
.navcollapse:hover{background:var(--sidebar-hover);color:var(--sidebar-hi)}
.navcollapse:focus-visible{outline:2px solid var(--brand-light);outline-offset:-2px}
.navcollapse svg{width:18px;height:18px;flex:none;transition:transform .18s}
@media (min-width:761px){
  html.sidebar-collapsed .sblogo img,html.sidebar-collapsed .sblogo .sbprod{display:none}
  html.sidebar-collapsed .sblogo .mono{display:grid}
  html.sidebar-collapsed .sbrand{padding:0;justify-content:center}
  html.sidebar-collapsed .sblogo{align-items:center}
  html.sidebar-collapsed #nav a{justify-content:center;padding:0;gap:0}
  html.sidebar-collapsed #nav .lbl,html.sidebar-collapsed .navh{display:none}
  html.sidebar-collapsed .navgrp{margin-top:6px;padding-top:6px;border-top:1px solid var(--sidebar-line)}
  html.sidebar-collapsed .navgrp:first-child{margin-top:0;padding-top:0;border-top:0}
  html.sidebar-collapsed .navcollapse{justify-content:center;padding:0}
  html.sidebar-collapsed .navcollapse .lbl{display:none}
  html.sidebar-collapsed .navcollapse svg{transform:rotate(180deg)}
}
/* top bar */
.top{position:sticky;top:0;z-index:20;background:var(--surface);border-bottom:1px solid var(--line);display:flex;align-items:center;gap:10px;padding:0 16px;height:var(--top-h,52px);min-width:0}
.hamb{display:none;width:36px;height:36px;padding:0;border:0;border-radius:6px;background:transparent;color:var(--ink);align-items:center;justify-content:center;flex:none}
.hamb:hover{background:var(--surface2)} .hamb svg{width:22px;height:22px}
.gsearch{flex:1;max-width:560px;min-width:0}
.conn{font-size:12px;color:var(--muted);display:flex;align-items:center;gap:6px;white-space:nowrap;flex:none}
.conn i{width:8px;height:8px;border-radius:50%;background:var(--muted);display:inline-block} .conn.live i{background:var(--live)} .conn.connecting i{background:var(--warn)}
.presence{display:flex;align-items:center;flex:none}
.presence .av{width:26px;height:26px;border-radius:50%;background:var(--accent-soft);color:var(--accent);font-size:11px;font-weight:700;display:grid;place-items:center;border:2px solid var(--surface);margin-left:-8px;font-family:"IBM Plex Sans Condensed",sans-serif}
.presence .av:first-child{margin-left:0} .presence .av.more{background:var(--surface2);color:var(--muted)}
.askbtn{display:inline-flex;align-items:center;gap:6px;border:1px solid var(--accent);color:var(--accent);background:var(--surface);border-radius:20px;padding:5px 12px;font-weight:600;font-size:13px;white-space:nowrap;flex:none}
.askbtn:hover{background:var(--accent-soft)} .askbtn svg{width:15px;height:15px;flex:none}
body.assist-open .askbtn{background:var(--accent);color:var(--accent-ink)}
.userchip{display:inline-flex;align-items:center;gap:8px;border:1px solid var(--line);border-radius:20px;padding:2px 10px 2px 2px;background:var(--surface);color:var(--ink);font-weight:500;white-space:nowrap;flex:none;max-width:200px}
.userchip:hover{background:var(--surface2)}
.userchip .uav{width:28px;height:28px;border-radius:50%;background:var(--accent);color:var(--accent-ink);display:grid;place-items:center;font:700 12px/1 "IBM Plex Sans Condensed",sans-serif;letter-spacing:.02em;flex:none}
.userchip .uname{overflow:hidden;text-overflow:ellipsis;font-size:13px}
main{max-width:1480px;min-width:0;margin:0 auto;padding:18px}
/* mobile: off-canvas menu */
.navbackdrop{display:none;position:fixed;inset:0;background:var(--scrim);z-index:55}
@media (max-width:760px){
  body.app,html.sidebar-collapsed body.app{grid-template-columns:minmax(0,1fr)}
  .sidebar{position:fixed;top:0;left:0;bottom:0;width:260px;max-width:88vw;z-index:60;transform:translateX(-100%);transition:transform .2s ease;box-shadow:none}
  .sbin{height:100%}
  body.nav-open .sidebar{transform:none;box-shadow:var(--shadow-lg)}
  body.nav-open .navbackdrop{display:block}
  body.nav-open{overflow:hidden}
  .sbfoot{display:none}
  .hamb{display:inline-flex}
  .top{padding:0 10px;gap:8px}
  .conn span{display:none} .presence{display:none}
  .userchip{padding:2px} .userchip .uname{display:none}
  main{padding:10px} .kpi .v{font-size:22px} h1{font-size:19px} .search{width:100%} .gantt{grid-template-columns:180px 1fr}
}
@media (max-width:480px){.askbtn .lbl{display:none} .askbtn{padding:6px 9px}}
/* print header (screen: hidden) */
.printhdr{display:none}

/* ---------- layout primitives ---------- */
.row{display:flex;gap:12px;align-items:center;flex-wrap:wrap}
.hdr{display:flex;align-items:flex-end;justify-content:space-between;gap:16px;flex-wrap:wrap;margin-bottom:14px}
.sub{color:var(--muted);font-size:13px}
.card{background:var(--surface);border:1px solid var(--line);border-radius:var(--radius);padding:14px 16px}
.grid{display:grid;gap:12px}
.kpis{grid-template-columns:repeat(auto-fit,minmax(150px,1fr));margin-bottom:14px}
.kpi{background:var(--surface);border:1px solid var(--line);border-radius:var(--radius);padding:10px 12px;cursor:pointer}
.kpi:hover{border-color:var(--accent)}
/* a tile whose page this person cannot open is a figure, not a link (kpi() in js/views/dash.js leaves data-href out) */
div.kpi:not([data-href]){cursor:default} div.kpi:not([data-href]):hover{border-color:var(--line)}
.kpi .l{font-size:11px;color:var(--muted);text-transform:uppercase;letter-spacing:.06em}
.kpi .v{font-size:26px;font-weight:600;line-height:1.15;font-variant-numeric:tabular-nums}
.kpi.crit .v{color:var(--crit)} .kpi.warn .v{color:var(--amber-ink)} .kpi.good .v{color:var(--good)}
.two{grid-template-columns:1fr 1fr} .three{grid-template-columns:repeat(3,1fr)}
@media (max-width:900px){.two,.three{grid-template-columns:1fr}}
.chips{display:flex;gap:6px;flex-wrap:wrap}
.pill{border:1px solid var(--line);border-radius:20px;padding:3px 11px;background:var(--surface);color:var(--ink2);font-weight:500;font-size:13px}
.pill.on{background:var(--accent);color:var(--accent-ink);border-color:var(--accent)}
.chip{display:inline-flex;align-items:center;gap:5px;border-radius:3px;padding:1px 7px;font-size:12px;font-weight:600;letter-spacing:.02em;white-space:nowrap;line-height:1.5}
.chip i{font-style:normal;font-weight:700}
.chip.ok{background:var(--good-soft);color:var(--good-ink)} .chip.warning{background:var(--warn-soft);color:var(--warn-ink)} .chip.critical{background:var(--crit-soft);color:var(--crit-ink)} .chip.info{background:var(--info-soft);color:var(--info-ink)} .chip.neutral{background:var(--surface2);color:var(--ink2)}
.tw{overflow-x:auto;border:1px solid var(--line);border-radius:var(--radius);background:var(--surface)}
table{border-collapse:collapse;width:100%;font-size:13px}
th{position:sticky;top:0;background:var(--surface2);text-align:left;font-weight:600;font-size:12px;letter-spacing:.05em;text-transform:uppercase;color:var(--ink2);padding:8px 10px;border-bottom:1px solid var(--line);white-space:nowrap;z-index:1}
th.sort{cursor:pointer} th.sort:hover{color:var(--accent)}
td{padding:6px 10px;border-bottom:1px solid var(--line2);vertical-align:middle}
tr:last-child td{border-bottom:0}
tr.link{cursor:pointer} tr.link:hover td{background:var(--surface2)}
td.num,th.num{text-align:right;font-variant-numeric:tabular-nums}
td input,td select{padding:3px 6px;font-size:13px;background:transparent;border-color:transparent;width:100%}
td input:hover,td select:hover{border-color:var(--line)} td input:focus,td select:focus{background:var(--surface);border-color:var(--accent)}
td input[type=date]{width:118px} td input[type=number]{width:84px}
td input[type=checkbox]{width:auto}
.bar{height:6px;background:var(--line2);border-radius:3px;overflow:hidden;min-width:70px} .bar b{display:block;height:100%;background:var(--s1)} .bar b.warn{background:var(--warn)} .bar b.crit{background:var(--crit)}
.attn{display:grid;gap:6px}
.attn .it{display:grid;grid-template-columns:auto 1fr auto;gap:10px;align-items:center;padding:7px 10px;border:1px solid var(--line2);border-radius:4px;background:var(--surface)}
.attn .it .t{font-size:13px} .attn .it .p{font-weight:600} .attn .it .p small{color:var(--muted);font-weight:400}
.fields{display:grid;grid-template-columns:repeat(auto-fill,minmax(210px,1fr));gap:10px 16px}
.f{display:flex;flex-direction:column;gap:3px} .f label{font-size:11px;text-transform:uppercase;letter-spacing:.06em;color:var(--muted);font-weight:600}
.f input,.f select{width:100%} .f.wide{grid-column:1/-1}
.sw{display:inline-flex;align-items:center;gap:8px;cursor:pointer;padding:5px 0}
.sw input{width:18px;height:18px;margin:0;accent-color:var(--accent)}
/* Admin → People: a person's roles as a row of tick boxes (admin.js roleBoxes; the invite form's row too) — the seven roles, then Mgmt set a little apart, since it is the Management grant and not a stored role. Wraps on a phone. */
.roleboxes{display:flex;flex-wrap:wrap;align-items:center;gap:2px 12px}
.roleboxes label{display:inline-flex;align-items:center;gap:4px;font-size:13px;white-space:nowrap;cursor:pointer}
.roleboxes input[type=checkbox]{width:auto;margin:0;accent-color:var(--accent)}
.roleboxes label.mgmt{padding-left:12px;border-left:1px solid var(--line)}
/* Admin → People, how a person signs in (admin.js emailCell / signinCell / pwCell): the e-mail is edited in place, so its box keeps a width an
   address can be read in; the Sign-in words and Unlink Microsoft stay on one line; "Password sign-in (test account)" is a tick box in a cell
   of its OWN — never one of .roleboxes' eight — faded while this session may not give the exception. On a phone the rows are cards
   (tables.css), where a cell wraps again. Admin → Sign-in (#signinCard, admin.js signinCard): the list of who has not signed in with Microsoft
   yet, in columns where there is room, and "Changes to sign-in" — a .signinblock with its own .signinlog table (data-list); "The last
   25 sign-ins" and the one line about anonymous refusals (.signinanon) with its Show / Hide button are Activity → Sign In Activity's
   (#siCard, views/activity.js) since 2026-09-28, in the same classes — whose last column is a sentence and wraps. While Microsoft sign-in is required and the session came in with a password, the
   People rows, the invite form and the API keys form are drawn `disabled` (admin.js frontDoorShut): the browser's own look for a locked
   control, and the reason in a .banner above them. Nothing here asks for a width on a
   phone — a minimum width inside a card would push the page sideways — and what Microsoft called an account may break anywhere. Tokens only. */
@media (min-width:641px){
  .people td.uemail input{min-width:190px}
  .people td.usignin{white-space:nowrap}
  .people td.usignin .btn{margin-left:6px}
  .signinlog td.signindetail{min-width:240px}
}
.signinhow{overflow-wrap:anywhere}
.pwlogin{display:inline-flex;align-items:center;gap:6px;white-space:nowrap;cursor:pointer}
.pwlogin input[type=checkbox]{width:auto;margin:0;accent-color:var(--accent)}
.pwlogin input[type=checkbox]:disabled{opacity:.45;cursor:default}
.signinout,.signinblock{margin-top:14px;padding-top:12px;border-top:1px solid var(--line2)}
.signinout h4,.signinblock h4{margin:0 0 6px;font-size:14px;font-weight:600;color:var(--ink)}
.signinout ul{margin:0;padding-left:18px;columns:2 260px}
.signinout li{margin:2px 0;break-inside:avoid}
.signinlog td.signindetail{white-space:normal;color:var(--ink2)}
.signinanon .btn{margin-left:4px}
#siCard .signinblock{margin-top:0;padding-top:0;border-top:0}   /* Activity → Sign In Activity: the sign-ins are the card's first and only block */
.signinmoved a{font-weight:600}
.signinanon + .signinlog{margin-top:8px}
.roleboxes input[type=checkbox]:disabled,.people input:disabled{cursor:default}
.people input[type=email]:disabled,.people input:not([type]):disabled{opacity:.6}
@media (max-width:640px){.signinlog td{overflow-wrap:anywhere}}
#signinCard .row > .sub{flex:1 1 320px;min-width:0}
/* Admin → Rollout, "Who sees each section, by role" (admin.js accessBlock): a row per section — the pages nested in it indented under it — and a
   tick box per role. The table opts out of the phone cards (data-cards="off", tables.css): it stays a grid and scrolls sideways INSIDE .accessgrid
   — the page never does — with the row names held in sight by a sticky first column. A box that differs from the role's built-in access carries a
   dot (.adot); a locked box (its section is unticked for that role) is faded. Every colour is a token, so dark and pink follow. */
.accessblock{margin-top:14px;padding-top:12px;border-top:1px solid var(--line2)}
.accessblock h4{margin:0 0 4px;font-size:14px;font-weight:600;color:var(--ink)}
.tw.accessgrid{overflow-x:auto;margin-top:8px;border:1px solid var(--line);background:var(--surface)}
.accessgrid thead th{text-align:center}
.accessgrid thead th:first-child{text-align:left;left:0;z-index:2}
.accessgrid tbody th{position:sticky;left:0;top:auto;z-index:1;background:var(--surface);min-width:150px;padding:6px 10px;border-bottom:1px solid var(--line2);text-align:left;white-space:normal;font:inherit;font-size:13px;font-weight:600;letter-spacing:0;text-transform:none;color:var(--ink)}
.accessgrid tbody tr:last-child th{border-bottom:0}
.accessgrid tr.nested th{padding-left:26px;font-weight:400;color:var(--ink2)}
.accessgrid tbody th .chip{white-space:normal;vertical-align:middle}
.accessgrid td{position:relative;text-align:center}
.accessgrid td input[type=checkbox]{width:18px;height:18px;margin:0;vertical-align:middle;accent-color:var(--accent);cursor:pointer}
.accessgrid td input[type=checkbox]:disabled{opacity:.45;cursor:default}
.accessgrid .adot{position:absolute;top:50%;left:calc(50% + 13px);width:6px;height:6px;margin-top:-3px;border-radius:50%;background:var(--bronze)}
/* The line under the pointer — or holding the keyboard's focus — is lit the whole way across (the owner, 2026-09-20: "so that it is easier
   to see which section the mouse is over and I am editing"): the section's name, which has a background of its own because it sticks, and every box. */
.accessgrid tbody tr:hover>th,.accessgrid tbody tr:hover>td,.accessgrid tbody tr:focus-within>th,.accessgrid tbody tr:focus-within>td{background:var(--accent-soft)}
.accessgrid tbody tr:hover>th,.accessgrid tbody tr:focus-within>th{color:var(--ink);box-shadow:inset 3px 0 0 var(--accent)}
@media print{.accessgrid tbody tr:hover>th,.accessgrid tbody tr:hover>td{background:none;box-shadow:none}}
@media (max-width:640px){.accessgrid tbody th,.accessgrid thead th:first-child{min-width:0;max-width:128px}}
/* Admin → Rollout, "Tabs on a job's page" (admin.js tabsBlock): the same sub-section shape as the grid above it and the same light-blue line
   under the pointer, but a table of its own (a class of its own too: the grid is asked about by name, and there must be only one of it).
   Overview's box is drawn ticked and disabled — it is the landing tab — and a switch that is not saved yet says so beside it. */
.tabblock{margin-top:14px;padding-top:12px;border-top:1px solid var(--line2)}
.tabblock h4{margin:0 0 4px;font-size:14px;font-weight:600;color:var(--ink)}
.tw.tabgrid{margin-top:8px;border:1px solid var(--line);background:var(--surface)}
.tabgrid tbody th{padding:6px 10px;border-bottom:1px solid var(--line2);text-align:left;white-space:normal;font:inherit;font-size:13px;font-weight:600;letter-spacing:0;text-transform:none;color:var(--ink)}
.tabgrid tbody tr:last-child th{border-bottom:0}
.tabgrid td.tabon{width:70px;text-align:center}
.tabgrid td input[type=checkbox]{width:18px;height:18px;margin:0;vertical-align:middle;accent-color:var(--accent);cursor:pointer}
.tabgrid td input[type=checkbox]:disabled{opacity:.45;cursor:default}
.tabgrid tbody tr:hover>th,.tabgrid tbody tr:hover>td,.tabgrid tbody tr:focus-within>th,.tabgrid tbody tr:focus-within>td{background:var(--accent-soft)}
.tabgrid tbody tr:hover>th,.tabgrid tbody tr:focus-within>th{color:var(--ink);box-shadow:inset 3px 0 0 var(--accent)}
@media print{.tabgrid tbody tr:hover>th,.tabgrid tbody tr:hover>td{background:none;box-shadow:none}}
.tabs{display:flex;gap:2px;border-bottom:1px solid var(--line);margin:14px 0;overflow-x:auto}
.tab{padding:8px 12px;border:0;background:none;color:var(--ink2);font-weight:600;font-size:14px;border-bottom:2px solid transparent;white-space:nowrap;text-decoration:none}
.tab.on{color:var(--accent);border-bottom-color:var(--accent)} .tab b{background:var(--surface2);border-radius:10px;padding:0 6px;margin-left:4px;font-size:11px;color:var(--muted)}
.gate{display:flex;align-items:center;gap:10px;padding:7px 0;border-bottom:1px solid var(--line2)} .gate:last-child{border:0}
.gate .dot{width:10px;height:10px;border-radius:50%;background:var(--line);flex:none} .gate .dot.on{background:var(--good)} .gate .dot.no{background:var(--crit)} .gate .dot.na{background:var(--line)}
.gate .n{flex:1}
.stat{display:grid;grid-template-columns:repeat(auto-fit,minmax(130px,1fr));gap:10px;margin-bottom:12px}
.stat .s{background:var(--surface2);border-radius:4px;padding:8px 10px} .stat .s .l{font-size:11px;color:var(--muted);text-transform:uppercase;letter-spacing:.06em} .stat .s .v{font-size:20px;font-weight:600;font-variant-numeric:tabular-nums;font-family:"IBM Plex Sans Condensed",sans-serif}
svg.chart{width:100%;height:auto;display:block}
.legend{display:flex;gap:14px;font-size:12px;color:var(--ink2);margin:6px 0} .legend i{display:inline-block;width:12px;height:3px;vertical-align:middle;margin-right:5px;border-radius:2px}
.toast{position:fixed;bottom:18px;left:50%;transform:translateX(-50%);background:var(--ink);color:var(--bg);padding:9px 16px;border-radius:6px;font-weight:500;box-shadow:var(--shadow);z-index:50;opacity:0;transition:opacity .2s;pointer-events:none;max-width:90vw}
.toast.show{opacity:1}
.modal{position:fixed;inset:0;background:var(--scrim);display:flex;align-items:center;justify-content:center;z-index:40;padding:16px}
.modal .box{background:var(--surface);border-radius:8px;padding:20px;max-width:440px;width:100%;box-shadow:var(--shadow);max-height:92vh;overflow:auto}
.modal .box.wide{max-width:900px}
.names{display:grid;grid-template-columns:1fr 1fr;gap:6px;margin:12px 0}
.banner{background:var(--warn-soft);border:1px solid var(--warn);border-radius:var(--radius);padding:8px 12px;margin-bottom:12px;font-size:13px}
.banner.info{background:var(--info-soft);border-color:var(--info)}
.empty{color:var(--muted);padding:18px;text-align:center}
.mono{font-variant-numeric:tabular-nums}
.muted{color:var(--muted)}
.search{width:260px}
.nowrap{white-space:nowrap}
.srh{display:flex;gap:8px;align-items:center;flex-wrap:wrap;margin-bottom:10px}
code,kbd,pre{font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;font-size:12px}
pre{background:var(--surface2);border:1px solid var(--line2);border-radius:4px;padding:8px 10px;overflow:auto;white-space:pre-wrap;word-break:break-word}
code{background:var(--surface2);padding:1px 4px;border-radius:3px}
/* schedule */
.gwrap{overflow:auto;max-height:calc(100vh - 150px);border:1px solid var(--line);border-radius:var(--radius);background:var(--surface)}
.gantt{display:grid;grid-template-columns:260px 1fr}
.glabel{padding:7px 10px;border-bottom:1px solid var(--line2);border-right:1px solid var(--line);position:sticky;left:0;background:var(--surface);z-index:2;font-size:13px}
.glabel a{color:inherit;text-decoration:none;font-weight:600} .glabel .m{color:var(--muted);font-size:12px}
.glabel.ghead{font-size:11px;text-transform:uppercase;letter-spacing:.06em;color:var(--ink2);background:var(--surface2);font-weight:600;z-index:5;top:0}
.glabel.ghead.h2{top:30px}
.glabel.ggrp{background:var(--surface2);font-weight:700;font-family:"IBM Plex Sans Condensed",sans-serif;letter-spacing:.04em;font-size:14px}
.gtl{position:relative;border-bottom:1px solid var(--line2);min-height:34px}
.gtl.ghead{height:30px;background:var(--surface2);position:sticky;top:0;z-index:4;border-bottom:1px solid var(--line)} .gtl.ghead.h2{top:30px}
.gtl.ggrp{background:var(--surface2);min-height:26px}
@media print{.gwrap{max-height:none;overflow:visible}}
.gwk{position:absolute;top:0;height:100%;border-left:1px solid var(--line);padding:7px 6px;font-size:11px;color:var(--ink2);white-space:nowrap;overflow:hidden;font-variant-numeric:tabular-nums}
.gwk.wk-today{background:var(--accent-soft)}
.gneed{font-weight:700;font-size:13px;font-family:"IBM Plex Sans Condensed",sans-serif} .gneed.ok{color:var(--good-ink)} .gneed.over{color:var(--crit);background:var(--crit-soft)}
.gbar{position:absolute;top:5px;height:24px;border-radius:4px;background:var(--surface2);border:1px solid var(--line);color:var(--ink);font-size:12px;line-height:22px;padding:0 7px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;box-sizing:border-box}
.gbar.active{background:var(--info-soft);border-color:var(--info)} .gbar.punch{background:var(--warn-soft);border-color:var(--warn)} .gbar.late{background:var(--crit-soft);border-color:var(--crit)} .gbar.done{background:var(--good-soft);border-color:var(--good)} .gbar.notready{border-style:dashed;border-color:var(--warn)}
.gtoday{position:absolute;top:0;bottom:0;width:2px;background:var(--live);z-index:1}
.gtl .gwk:first-child{border-left:0}
.gflag{display:inline-block;width:8px;height:8px;border-radius:50%;background:var(--warn);margin-right:5px;vertical-align:middle}
/* intake */
.dz{border:2px dashed var(--line);border-radius:var(--radius);background:var(--surface2);padding:14px 16px;margin-bottom:12px;display:flex;align-items:center;gap:12px;flex-wrap:wrap;transition:border-color .15s,background .15s}
.dz.over{border-color:var(--accent);background:var(--accent-soft)}
.dz .dzi{width:34px;height:34px;border-radius:6px;background:var(--surface);border:1px solid var(--line);display:grid;place-items:center;font-size:17px;flex:none}
.dz .dzt{flex:1;min-width:200px}
.dz .dzt b{font-family:"IBM Plex Sans Condensed",sans-serif;font-size:14px}
.dz .dzt div{font-size:12px;color:var(--muted)}
.dz.busy{border-style:solid;border-color:var(--accent)}
.ib{position:fixed;inset:0;background:var(--scrim);display:flex;align-items:flex-start;justify-content:center;z-index:45;padding:16px;overflow:auto}
.ib .box{background:var(--surface);border-radius:8px;padding:18px;max-width:1100px;width:100%;box-shadow:var(--shadow);margin:auto}
.ib h2{display:flex;align-items:center;gap:8px;flex-wrap:wrap}
.ev{background:var(--surface2);border:1px solid var(--line2);border-radius:4px;padding:8px 10px;font-size:12px;color:var(--ink2);margin-bottom:10px}
.ev b{font-family:"IBM Plex Sans Condensed",sans-serif;text-transform:uppercase;letter-spacing:.05em;font-size:11px;color:var(--muted);display:block;margin-bottom:3px}
.ev ul{margin:0;padding-left:16px} .ev li{margin:1px 0}
.prow{border:1px solid var(--line);border-radius:5px;padding:10px;margin-bottom:8px;background:var(--surface)}
.prow.off{opacity:.45}
.prow .ph{display:flex;align-items:center;gap:8px;margin-bottom:8px}
.prow .ph .n{font-weight:600;flex:1}
.spin{display:inline-block;width:13px;height:13px;border:2px solid var(--line);border-top-color:var(--accent);border-radius:50%;animation:sp .7s linear infinite;vertical-align:-2px}
@keyframes sp{to{transform:rotate(360deg)}}
@media (prefers-reduced-motion:reduce){.spin{animation-duration:2s}}
.progress{height:6px;background:var(--line2);border-radius:3px;overflow:hidden;margin:6px 0} .progress b{display:block;height:100%;background:var(--accent);transition:width .2s}
/* activity feed */
.feed{display:grid;gap:4px;max-height:420px;overflow:auto}
.feed .fi{display:grid;grid-template-columns:auto 1fr auto;gap:8px;align-items:baseline;padding:5px 8px;border-radius:4px;font-size:13px}
.feed .fi:hover{background:var(--surface2)}
.feed .fi .who{font-weight:600;white-space:nowrap} .feed .fi .when{color:var(--muted);font-size:12px;white-space:nowrap}
.feed .fi.new{animation:fade 1.2s}
@keyframes fade{from{background:var(--accent-soft)}to{background:transparent}}
.feed .fi .k{display:inline-block;width:8px;height:8px;border-radius:50%;background:var(--line);margin-right:6px;vertical-align:middle} .feed .fi .k.file{background:var(--bronze)} .feed .fi .k.doc{background:var(--s1)} .feed .fi .k.agent,.feed .fi .k.ai{background:var(--s3)} .feed .fi .k.admin,.feed .fi .k.auth{background:var(--muted)}
/* Admin → Activity (views/activity.js): the full change log — the filter row, then a table When · Who · What changed · Job */
.avfilters{flex-wrap:wrap;gap:8px;align-items:flex-end;margin-bottom:10px} .avfilters .search{flex:1 1 220px;min-width:180px}
.avlab{display:flex;flex-direction:column;gap:2px;font-size:12px;color:var(--muted)} .avlab select,.avlab input{min-width:0}
.avtable td{vertical-align:top} .avwhen{font-size:12px;white-space:nowrap} .avwhen .sub{color:var(--muted)}
.avwho{font-weight:600;white-space:nowrap} .avwhat{min-width:260px} .avjob{white-space:nowrap}
.avrow.new td{animation:fade 1.2s}
.avwho .k{display:inline-block;width:8px;height:8px;border-radius:50%;background:var(--line);margin-right:6px;vertical-align:middle} .avwho .k.file{background:var(--bronze)} .avwho .k.doc{background:var(--s1)} .avwho .k.agent,.avwho .k.ai{background:var(--s3)} .avwho .k.admin,.avwho .k.auth{background:var(--muted)}
.avmore{margin-top:10px;gap:10px;align-items:center}
@media (max-width:640px){.avwhat{min-width:0}}
/* archive */
.files{display:grid;gap:8px}
.filerow{display:grid;grid-template-columns:34px 1fr auto;gap:10px;align-items:center;padding:8px 10px;border:1px solid var(--line2);border-radius:5px;background:var(--surface)}
.filerow:hover{border-color:var(--line)}
.filerow .ico{width:34px;height:34px;border-radius:6px;background:var(--surface2);border:1px solid var(--line2);display:grid;place-items:center;font-size:11px;font-weight:700;color:var(--ink2);font-family:"IBM Plex Sans Condensed",sans-serif;text-transform:uppercase}
.filerow .nm{font-weight:600;overflow:hidden;text-overflow:ellipsis;white-space:nowrap} .filerow .nm a{color:inherit;text-decoration:none}
.filerow .meta{font-size:12px;color:var(--muted);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.filerow .acts{display:flex;gap:4px;flex-wrap:wrap;justify-content:flex-end}
.tag{display:inline-block;background:var(--surface2);border-radius:3px;padding:0 6px;font-size:11px;color:var(--ink2);margin-right:4px}
.tag.warn{background:var(--warn-soft)} .tag.auto{background:var(--good-soft)}
.preview{position:fixed;inset:0;background:var(--scrim);z-index:46;display:flex;flex-direction:column;padding:12px}
.preview .ph{display:flex;align-items:center;gap:10px;color:var(--paper);padding:0 4px 8px;flex-wrap:wrap}
.preview .ph b{flex:1;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.preview .pb{flex:1;background:var(--surface);border-radius:6px;overflow:hidden;display:grid;place-items:center}
.preview iframe{width:100%;height:100%;border:0;background:var(--paper)} .preview img{max-width:100%;max-height:100%;object-fit:contain}
.preview pre{max-height:100%;width:100%;overflow:auto;margin:0;border:0;border-radius:0}
/* assistant drawer */
.assist{position:fixed;top:var(--top-h,52px);right:0;bottom:0;width:440px;max-width:100vw;background:var(--surface);border-left:1px solid var(--line);box-shadow:var(--shadow);z-index:30;display:flex;flex-direction:column}
.assist[hidden]{display:none}
.assist .ah{display:flex;align-items:center;gap:8px;padding:10px 12px;border-bottom:1px solid var(--line)} .assist .ah b{font-family:"IBM Plex Sans Condensed",sans-serif;font-size:15px}
.assist .am{flex:1;overflow:auto;padding:12px;display:flex;flex-direction:column;gap:10px}
.assist .af{border-top:1px solid var(--line);padding:10px 12px;display:grid;gap:6px}
.assist .af textarea{min-height:56px;font-size:14px}
.msg{max-width:100%;padding:8px 11px;border-radius:8px;font-size:13.5px;line-height:1.45}
.msg.user{background:var(--accent-soft);align-self:flex-end;white-space:pre-wrap}
.msg.ai{background:var(--surface2);align-self:stretch}
.msg.sys{color:var(--muted);font-size:12px;align-self:center;text-align:center}
.msg .tools{font-size:12px;color:var(--muted);margin-bottom:4px} .msg .tools span{display:inline-block;margin-right:8px}
.sugg{display:grid;gap:6px} .sugg button{text-align:left;border:1px solid var(--line);background:var(--surface);border-radius:6px;padding:8px 10px;color:var(--ink2)} .sugg button:hover{border-color:var(--accent);color:var(--accent)}
body.assist-open main{margin-right:440px}
@media (max-width:1100px){body.assist-open main{margin-right:0}.assist{width:100vw;top:var(--top-h,52px)}}
/* markdown */
.md{line-height:1.5} .md h1{font-size:20px;margin:14px 0 8px} .md h2{font-size:16px;margin:14px 0 6px} .md h3{font-size:14px;margin:12px 0 6px;text-transform:none;letter-spacing:0;color:var(--ink)}
.md p{margin:6px 0} .md ul,.md ol{margin:6px 0;padding-left:22px} .md li{margin:2px 0}
.md table{width:auto;min-width:50%;margin:8px 0;border:1px solid var(--line)} .md th{position:static} .md td,.md th{padding:5px 9px;border:1px solid var(--line2)}
.md blockquote{border-left:3px solid var(--line);margin:8px 0;padding:2px 10px;color:var(--ink2)}
.md hr{border:0;border-top:1px solid var(--line);margin:12px 0}
/* job status timeline */
.timeline{display:grid;grid-template-columns:repeat(6,1fr);gap:0;margin:2px 0 12px;background:var(--surface);border:1px solid var(--line);border-radius:var(--radius);overflow:hidden}
.timeline .stg{position:relative;padding:10px 12px 10px 30px;border-right:1px solid var(--line2);min-width:0}
.timeline .stg:last-child{border-right:0}
.timeline .stg i{position:absolute;left:12px;top:14px;width:11px;height:11px;border-radius:50%;background:var(--line);box-shadow:0 0 0 3px var(--surface)}
.timeline .stg b{display:block;font-family:"IBM Plex Sans Condensed",sans-serif;font-size:13px;letter-spacing:.02em;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.timeline .stg span{display:block;font-size:12px;color:var(--muted);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.timeline .stg.done i{background:var(--good)} .timeline .stg.active i{background:var(--info);box-shadow:0 0 0 3px var(--info-soft)} .timeline .stg.warn i{background:var(--warn);box-shadow:0 0 0 3px var(--warn-soft)}
.timeline .stg.active{background:var(--info-soft)} .timeline .stg.warn{background:var(--warn-soft)}
.timeline .stg.todo b,.timeline .stg.todo span{color:var(--muted)}
/* A service job's timeline has five stages, a warranty call's two (service.js → serviceStages); the project timeline keeps six.
   On a phone every timeline wraps to three columns (two stages keep two); .n5 is named in the media query as well because it outranks the bare .timeline rule. */
.timeline.n5{grid-template-columns:repeat(5,1fr)} .timeline.n2{grid-template-columns:repeat(2,1fr)}
@media (max-width:900px){.timeline,.timeline.n5{grid-template-columns:repeat(3,1fr)}.timeline.n2{grid-template-columns:repeat(2,1fr)}.timeline .stg{border-bottom:1px solid var(--line2)}}
/* message and report actions */
.msgacts{display:flex;gap:4px;margin-top:6px;flex-wrap:wrap} .msgacts .btn{padding:2px 7px;font-size:11px}
/* agents */
.agent{display:grid;grid-template-columns:1fr auto;gap:10px;align-items:start}
.status{display:inline-block;padding:1px 7px;border-radius:3px;font-size:12px;font-weight:600}
.status.queued{background:var(--surface2);color:var(--ink2)} .status.running{background:var(--info-soft);color:var(--info-ink)} .status.done{background:var(--good-soft);color:var(--good-ink)} .status.failed{background:var(--crit-soft);color:var(--crit-ink)}
/* Sync → EquipmentShare (T3) tile (public/js/sync.js esCard): four figures, the two folds, the days-left cells. Tokens only. */
.t3figs{display:grid;grid-template-columns:repeat(auto-fit,minmax(120px,1fr));gap:8px;margin:10px 0 2px}
.t3fig{border:1px solid var(--line);border-radius:10px;padding:8px 10px;background:var(--surface2);display:flex;flex-direction:column;gap:2px}
.t3fig b{font-size:20px;line-height:1.1;font-variant-numeric:tabular-nums}
.t3fig span{font-size:12px;color:var(--ink2)}
.t3fig.warn{border-color:var(--warn);background:var(--warn-soft)}
.t3fold{margin-top:10px}.t3fold>summary{cursor:pointer;padding:4px 0}
.t3left{font-variant-numeric:tabular-nums}.t3left.warn{color:var(--warn-ink);font-weight:600}.t3left.crit{color:var(--crit-ink);font-weight:600}
/* auth pages: deep-blue band with the card overlapping it */
.authwrap{min-height:100vh;display:flex;justify-content:center;align-items:flex-start;padding:max(24px,calc(38vh - 120px)) 20px 40px;background:linear-gradient(180deg,var(--brand-deep) 0,var(--brand-band) 38vh,var(--bg) 38vh)}
.authbox{width:100%;max-width:440px;background:var(--surface);border:1px solid var(--line);border-radius:12px;padding:28px 28px 24px;box-shadow:var(--shadow-lg)}
.authbox .brand{display:flex;flex-direction:column;align-items:center;gap:8px;margin-bottom:18px}
.authbox .brand img{width:200px;max-width:100%;height:auto;display:block;background:var(--logo-plate);border-radius:8px;padding:4px 8px}
.authbox .brand span{font:600 13px/1 "IBM Plex Sans Condensed",sans-serif;text-transform:uppercase;letter-spacing:.2em;color:var(--brand-mid);text-align:center}
.authbox h2{text-align:center}
.authbox .f{margin-bottom:12px}
.authbox input{padding:10px}
.authbox .btn.primary{width:100%;padding:10px;font-size:15px;margin-top:4px}
.authbox .sub{margin:0 0 14px} .authbox .sub.after{margin:12px 0 0;text-align:center}
/* Sign in with Microsoft (login.html, js/auth-pages.js). The blocks of the sign-in card are shown and folded with the `hidden` attribute —
   and .btn, .f and .orline set a display of their own, which would beat the browser's [hidden] rule: without the first line the Microsoft
   link would show on a server that has no Microsoft sign-in. The link is a plain <a class="btn primary">: centred, since an <a> is not a
   <button>. "Use a password instead" is a button that reads as a link (.linkbtn). Every colour is a token, so dark and pink follow. */
.authbox [hidden]{display:none!important}
.authbox a.btn.primary{text-align:center}
.authbox #msbox{margin-bottom:4px}
.authbox .linkbtn{border:0;background:none;padding:0;color:var(--accent);text-decoration:underline;font:inherit}
.authbox .linkbtn:hover{filter:brightness(1.15)}
.authbox .orline{display:flex;align-items:center;gap:10px;margin:16px 0 14px;color:var(--muted);font-size:12px;text-transform:uppercase;letter-spacing:.08em}
.authbox .orline::before,.authbox .orline::after{content:"";flex:1;border-top:1px solid var(--line)}
.authbox .banner{margin:0 0 12px}
.err{background:var(--crit-soft);border:1px solid var(--crit);color:var(--crit-ink);border-radius:4px;padding:8px 10px;font-size:13px;margin-bottom:10px}
div.ok{background:var(--good-soft);border:1px solid var(--good);border-radius:4px;padding:8px 10px;font-size:13px;margin-bottom:10px}
/* print: no chrome, full-width page, branded header */
@media print{
  .sidebar,.top,.noprint,.assist,.navbackdrop,.toast,#modal{display:none!important}
  body,body.app{display:block;background:var(--paper);color:var(--paper-ink)}
  .content{display:block}
  .printhdr{display:flex;align-items:center;gap:14px;padding:0 0 10px;margin:0 0 14px;border-bottom:2px solid var(--brand-deep)}
  .printhdr img{height:44px;width:auto}
  .printhdr b{display:block;font:700 16px/1.2 "IBM Plex Sans Condensed",sans-serif;color:var(--brand-deep)}
  .printhdr span{display:block;font-size:12px;color:var(--ink2)}
  main{max-width:none;width:auto;padding:0;margin:0!important}
  .tw{border:0;overflow:visible} th{position:static}
}
@media (prefers-reduced-motion:reduce){*{transition:none!important}}
/* KPI strips: five cards per row from tablet width up, two per row on a phone (measured against the content column, not the window); the dashboard's eight cards sit as two rows of four */
main{container-type:inline-size}
@container (min-width:720px){.kpis{grid-template-columns:repeat(5,minmax(0,1fr))} .kpis.dashkpis{grid-template-columns:repeat(4,minmax(0,1fr))}}
@container (max-width:719.98px){.kpis{grid-template-columns:repeat(2,minmax(0,1fr))}}
@media (max-width:760px){.top .spacer{display:none} .gsearch{flex:1 1 auto}}
/* Sync page: a tile minimized to its heading (sync.js foldHead / data-shut); on paper every tile prints whole */
@media screen{[data-syncfold][data-shut]>*:not(:first-child){display:none}}
.sfh{gap:2px;align-items:center;flex-wrap:nowrap}.sfh-own{margin-bottom:8px}[data-shut]>.sfh-own{margin-bottom:0}
.syncfold{background:none;border:0;padding:0 6px 0 0;margin:0;font:inherit;font-size:15px;color:var(--muted);cursor:pointer;line-height:1;min-width:20px}
.syncfold:hover{color:var(--ink)}
.syncfold::before{content:'▾'}.syncfold[aria-expanded=false]::before{content:'▸'}
.syncfold:focus-visible{outline:2px solid var(--accent);outline-offset:2px;border-radius:4px}
@media print{.syncfold{display:none}}
/* Admin page: a card minimized to its heading (admin.js foldHead / data-shut); on paper every card prints whole */
@media screen{[data-admfold][data-shut]>*:not(:first-child){display:none}}
.admfh{gap:2px;align-items:center;flex-wrap:nowrap;margin-bottom:8px}.admfh h3{margin:0}
[data-admfold][data-shut]>.admfh,[data-admfold][data-shut]>.row>.admfh{margin-bottom:0}
.row>.admfh{margin-bottom:0}
.admfold{background:none;border:0;padding:0 6px 0 0;margin:0;font:inherit;font-size:15px;color:var(--muted);cursor:pointer;line-height:1;min-width:20px}
.admfold:hover{color:var(--ink)}
.admfold::before{content:'▾'}.admfold[aria-expanded=false]::before{content:'▸'}
.admfold:focus-visible{outline:2px solid var(--accent);outline-offset:2px;border-radius:4px}
@media print{.admfold{display:none}}
