/* ============================================================================
   MOSS NOC design system (ADR-0029).

   One stylesheet: tokens, then components. Interface text is IBM Plex Sans in
   sentence case; IBM Plex Mono is kept for data - addresses, numbers, codes and
   timestamps. Surfaces separate by tone and a little elevation, not by lines
   alone. One cobalt accent means "primary action" or "selected". One status
   scale (up, degraded, down, stale/unknown, not monitored, retired) is drawn the
   same way everywhere.

   The palette is declared three times - light, dark by OS preference, dark by
   choice - and moss-admin.css restates it under the admin's names
   (core/tests_palette.py keeps the two files, and every text pair's contrast,
   honest).
   ========================================================================== */

/* ---- palette: light (the default) ------------------------------------------
   Surfaces, lowest to highest: --bg-void (inset tracks, wells) < --bg (the
   canvas) < --bg-raised (card headers, table headers, hover) < --bg-base (cards)
   = --bg-overlay (menus and dialogs, which add a shadow). */
:root,:root[data-theme="light"]{
  --bg-void:#E8ECF1; --bg:#F3F5F8; --bg-base:#FFFFFF; --bg-raised:#F8F9FB; --bg-overlay:#FFFFFF;
  /* borders: row dividers < card edges < button edges; --field-line is the >=3:1 control edge */
  --line-faint:#EEF1F4; --line:#E2E6EB; --line-strong:#CDD3DB; --field-line:#7B8595;
  /* ink */
  --text-hi:#101828; --text:#344054; --text-mut:#5A6474; --text-ghost:#98A1AE;
  /* the accent: primary actions, links, selection */
  --acid:#2B54C9; --acid-dim:#2346AB; --acid-glow:rgba(43,84,201,0.10); --on-acid:#ffffff;
  /* status tones (dots, bars, borders) and their inks (text on a tint of the tone) */
  --ok:#15803D; --info:#2563EB; --warn:#B45309; --crit:#C4302B; --idle:#6B7280;
  --ok-ink:#166534; --info-ink:#1E40AF; --warn-ink:#92400E; --crit-ink:#991B1B; --idle-ink:#475467;
  --tint:12%;
  --scrim:rgba(16,24,40,.42);
  /* the shadow that says a list scrolls on */
  --shade:rgba(16,24,40,.16);
  --shadow-1:0 1px 2px rgba(16,24,40,.05),0 1px 3px rgba(16,24,40,.06);
  --shadow-2:0 2px 4px -1px rgba(16,24,40,.06),0 6px 14px -3px rgba(16,24,40,.10);
  --shadow-3:0 4px 8px -2px rgba(16,24,40,.08),0 14px 28px -6px rgba(16,24,40,.16);
  --shadow-4:0 10px 20px -6px rgba(16,24,40,.12),0 28px 56px -12px rgba(16,24,40,.28);
  color-scheme:light;
}
/* ---- palette: dark, when the OS asks and the user has not chosen light ---- */
@media (prefers-color-scheme:dark){:root:not([data-theme="light"]){
  --bg-void:#0B0D11; --bg:#111418; --bg-base:#171B21; --bg-raised:#1D2229; --bg-overlay:#232932;
  --line-faint:#222831; --line:#2C333D; --line-strong:#3D4652; --field-line:#6B7686;
  --text-hi:#EEF1F5; --text:#C3C9D2; --text-mut:#99A2AE; --text-ghost:#5F6874;
  --acid:#7C95F2; --acid-dim:#95AAF5; --acid-glow:rgba(124,149,242,0.14); --on-acid:#0E1116;
  --ok:#4CC38A; --info:#6AA6F0; --warn:#E0A84E; --crit:#F07167; --idle:#8B94A1;
  --ok-ink:#5FD39B; --info-ink:#8AB8F5; --warn-ink:#EBB866; --crit-ink:#F58B83; --idle-ink:#B4BCC7;
  --tint:16%;
  --scrim:rgba(0,0,0,.6);
  --shade:rgba(0,0,0,.7);
  --shadow-1:0 1px 2px rgba(0,0,0,.35),inset 0 1px 0 rgba(255,255,255,.02);
  --shadow-2:0 4px 12px rgba(0,0,0,.40),inset 0 1px 0 rgba(255,255,255,.03);
  --shadow-3:0 10px 28px rgba(0,0,0,.50),inset 0 1px 0 rgba(255,255,255,.04);
  --shadow-4:0 20px 48px rgba(0,0,0,.60),inset 0 1px 0 rgba(255,255,255,.05);
  color-scheme:dark;
}}
/* ---- palette: dark, chosen with the toggle (identical to the block above) -- */
:root[data-theme="dark"]{
  --bg-void:#0B0D11; --bg:#111418; --bg-base:#171B21; --bg-raised:#1D2229; --bg-overlay:#232932;
  --line-faint:#222831; --line:#2C333D; --line-strong:#3D4652; --field-line:#6B7686;
  --text-hi:#EEF1F5; --text:#C3C9D2; --text-mut:#99A2AE; --text-ghost:#5F6874;
  --acid:#7C95F2; --acid-dim:#95AAF5; --acid-glow:rgba(124,149,242,0.14); --on-acid:#0E1116;
  --ok:#4CC38A; --info:#6AA6F0; --warn:#E0A84E; --crit:#F07167; --idle:#8B94A1;
  --ok-ink:#5FD39B; --info-ink:#8AB8F5; --warn-ink:#EBB866; --crit-ink:#F58B83; --idle-ink:#B4BCC7;
  --tint:16%;
  --scrim:rgba(0,0,0,.6);
  --shade:rgba(0,0,0,.7);
  --shadow-1:0 1px 2px rgba(0,0,0,.35),inset 0 1px 0 rgba(255,255,255,.02);
  --shadow-2:0 4px 12px rgba(0,0,0,.40),inset 0 1px 0 rgba(255,255,255,.03);
  --shadow-3:0 10px 28px rgba(0,0,0,.50),inset 0 1px 0 rgba(255,255,255,.04);
  --shadow-4:0 20px 48px rgba(0,0,0,.60),inset 0 1px 0 rgba(255,255,255,.05);
  color-scheme:dark;
}
/* ---- scales that do not change with the theme ----------------------------- */
:root{
  --mono:'IBM Plex Mono',ui-monospace,'SF Mono',Menlo,Consolas,monospace;
  --sans:'IBM Plex Sans',system-ui,-apple-system,'Segoe UI',sans-serif;
  /* type: 11 is the floor (tiny tags only); 14 is body and table text;
     16-18 section titles; 26 the page title; 30 the KPI figure */
  --fs-1:11px; --fs-2:12px; --fs-3:13px; --fs-4:14px; --fs-5:16px; --fs-6:18px; --fs-7:26px; --fs-8:30px;
  --lh-tight:1.25; --lh:1.5;
  /* spacing: an 8px grid with a 4px half-step */
  --space-1:4px; --space-2:8px; --space-3:12px; --space-4:16px;
  --space-5:24px; --space-6:32px; --space-7:40px; --space-8:48px;
  /* radii: tags, controls, cards, pills */
  --r-sm:4px; --r:6px; --r-lg:10px; --r-full:999px;
  /* one control height, and a compact one for table rows */
  --ctl-h:36px; --ctl-h-sm:28px;
  --strip-h:32px; --topbar-h:56px; --sidebar-w:248px;
  --ring:0 0 0 3px color-mix(in srgb,var(--acid) 25%,transparent);
  --dur-fast:.12s; --dur:.16s; --ease:cubic-bezier(.22,.61,.36,1);
}

/* ---- base ------------------------------------------------------------------ */
*{box-sizing:border-box;margin:0;padding:0;}
html,body{background:var(--bg);color:var(--text);}
/* a #fragment (the row being edited) lands below the sticky strip and header, with room
   above it for its floor's band */
html{scroll-padding-top:calc(var(--strip-h) + var(--topbar-h) + var(--space-8) + var(--space-4));}
/* a signed-out page has no status strip (the sidebar layout zeroes --topbar-h below) */
html:has(> body.no-strip){--strip-h:0px;}
/* `hidden` always wins: a component that sets its own display (the console drawer, a
   menu) must still disappear when its hidden attribute is set */
[hidden]{display:none !important;}
body{
  font-family:var(--sans);font-size:var(--fs-4);line-height:var(--lh);-webkit-font-smoothing:antialiased;
  font-variant-numeric:tabular-nums;padding-top:var(--strip-h);
}
.mono{font-family:var(--mono);font-size:.93em;letter-spacing:0;}
.mono .mono{font-size:inherit;}
.dim{color:var(--text-mut);}
.tiny{font-size:var(--fs-2);}
::selection{background:color-mix(in srgb,var(--acid) 22%,transparent);color:inherit;}
a{color:var(--acid);text-decoration:none;}
a:hover{color:var(--acid-dim);}
b,strong{font-weight:600;}

*::-webkit-scrollbar{width:10px;height:10px;}
*::-webkit-scrollbar-track{background:transparent;}
*::-webkit-scrollbar-thumb{background:var(--line-strong);border:2px solid transparent;background-clip:padding-box;border-radius:var(--r-full);}
*::-webkit-scrollbar-thumb:hover{background-color:var(--text-ghost);}

:focus-visible{outline:none;box-shadow:0 0 0 2px var(--bg-base),0 0 0 4px var(--acid);transition:box-shadow var(--dur-fast) ease;}

/* ---- status dots ------------------------------------------------------------
   Still: a status is read, not watched. Only "down" asks for attention. */
.led{width:8px;height:8px;display:inline-block;border-radius:50%;background:var(--idle);flex:0 0 auto;}
.led.ok{background:var(--ok);}
.led.info{background:var(--info);}
.led.warn{background:var(--warn);}
.led.crit{background:var(--crit);box-shadow:0 0 0 3px color-mix(in srgb,var(--crit) 22%,transparent);}
@keyframes pulse{0%,100%{opacity:.55;}50%{opacity:1;}}

/* ---- status strip -------------------------------------------------------------
   A quiet band of network facts (ADR-0030): grey labels, dark figures, nothing that
   moves but BEAT. Every problem is drawn one way - a dot and an ink beside its figure,
   amber (degraded, spend, audit gap) or red (a silent probe, a recorder down, alerts
   stuck, checks stalled) - and the summary on the right is the one filled red on the
   screen, only while something is down; green only while a recent check vouches that
   every line is up, grey otherwise. The summary never scrolls away; on a narrow screen
   the facts slide under a fade instead, and the problems lead at every width. */
.nocbar{
  position:fixed;top:0;left:0;right:0;height:var(--strip-h);z-index:60;
  display:flex;align-items:center;gap:var(--space-4);padding:0 var(--space-2) 0 var(--space-5);
  background:var(--bg-void);border-bottom:1px solid var(--line);white-space:nowrap;
  font:600 var(--fs-1)/1 var(--sans);letter-spacing:.06em;color:var(--text-mut);
}
.nocbar.is-crit{border-bottom-color:var(--crit);box-shadow:inset 0 -1px 0 var(--crit);}
.noc-facts{flex:1;min-width:0;display:flex;align-items:center;gap:var(--space-5);height:100%;
  overflow-x:auto;overflow-y:hidden;scrollbar-width:none;
  -webkit-mask-image:linear-gradient(90deg,#000 calc(100% - 28px),transparent);mask-image:linear-gradient(90deg,#000 calc(100% - 28px),transparent);}
.noc-facts::-webkit-scrollbar{display:none;}
.noc-fact{flex:none;display:inline-flex;align-items:center;gap:7px;color:var(--text-mut);border-radius:var(--r-sm);}
.noc-fact b{font:500 var(--fs-2)/1 var(--mono);letter-spacing:0;color:var(--text-hi);}
a.noc-fact[href]:hover{color:var(--text);}
a.noc-fact[href]:hover b{color:var(--acid);}
.noc-fact.is-warn::before,.noc-fact.is-crit::before{content:'';flex:none;width:7px;height:7px;border-radius:50%;background:var(--warn);}
.noc-fact.is-crit::before{background:var(--crit);}
.noc-fact.is-warn b{color:var(--warn-ink);}
.noc-fact.is-crit,.noc-fact.is-crit b{color:var(--crit-ink);}
/* problems lead: the markup already puts them first; this lifts BEAT too once
   deadswitch.js turns it red, so no problem ever sits under the fade */
.noc-fact.is-crit{order:-2;}
.noc-fact.is-warn{order:-1;}
/* below 1280px every problem at once only fits with the facts drawn closer */
@media (max-width:1279.98px){.noc-facts{gap:var(--space-4);}}
.noc-spark{display:block;width:48px;height:14px;margin-left:2px;}
/* the summary: calm green while all is clear, the one filled red while anything is down */
.noc-summary{flex:none;display:inline-flex;align-items:center;gap:7px;height:22px;padding:0 11px 0 9px;border-radius:var(--r-full);
  background:color-mix(in srgb,var(--ok) var(--tint),var(--bg-base));color:var(--ok-ink);}
.noc-summary .led{width:7px;height:7px;box-shadow:none;}
/* grey, not green, while no recent check vouches for ALL CLEAR (base.html says when) */
.noc-summary.is-idle{background:color-mix(in srgb,var(--idle) var(--tint),var(--bg-base));color:var(--idle-ink);}
.noc-sub{font-weight:500;letter-spacing:.02em;color:var(--text-mut);}
.noc-summary.is-clear .noc-sub::before{content:'\00b7';margin:0 6px 0 1px;}
.nocbar.is-crit .noc-summary{background:var(--crit);color:var(--on-acid);font-weight:700;}
.nocbar.is-crit .noc-summary .noc-sub{color:inherit;font-weight:500;}
.nocbar.is-crit .noc-summary .led{background:currentColor;animation:pulse 1.6s ease-in-out infinite;}
.nocbar.is-crit a.noc-summary[href]:hover{color:var(--on-acid);filter:brightness(.94);}

/* ---- the app shell ----------------------------------------------------------------
   One markup, three layouts (ADR-0030; the breakpoints are repeated in shell.js and a
   test keeps them equal):
     from 1600px   a fixed sidebar: every link in sight, grouped, one click to any page;
     1024-1599px   a one-row top bar: Home and four groups that open as menus;
     below 1024px  the same bar; a menu button opens the nav as a drawer from the left.
   The rules below are the list the sidebar and the drawer share; the top bar turns the
   groups into menus further down. */
.sprite{position:absolute;width:0;height:0;overflow:hidden;}
.i{width:18px;height:18px;flex:none;fill:none;stroke:currentColor;stroke-width:1.75;stroke-linecap:round;stroke-linejoin:round;}
.skip-link{position:fixed;left:var(--space-3);top:var(--space-2);z-index:100;transform:translateY(-300%);
  padding:9px 14px;border-radius:var(--r);background:var(--acid);color:var(--on-acid);
  font:600 var(--fs-3)/1.2 var(--sans);box-shadow:var(--shadow-3);}
.skip-link:focus{transform:none;color:var(--on-acid);}
#main:focus,#main:focus-visible{outline:none;box-shadow:none;}

.topbar{
  position:sticky;top:var(--strip-h);z-index:40;
  display:flex;flex-wrap:nowrap;align-items:center;gap:var(--space-2);height:var(--topbar-h);padding:0 var(--space-5);
  background:var(--bg-base);border-bottom:1px solid var(--line);box-shadow:var(--shadow-1);
}
.brand{flex:none;display:inline-flex;align-items:center;gap:10px;height:40px;padding:0 6px;margin-left:-6px;
  border-radius:var(--r);color:var(--text-hi);}
.brand:hover{color:var(--text-hi);}
.brand-mark{flex:none;width:28px;height:28px;border-radius:8px;display:grid;place-items:center;background:var(--acid);
  box-shadow:inset 0 -1px 0 rgba(0,0,0,.18);}
.brand-mark svg{width:18px;height:18px;fill:none;stroke:var(--on-acid);stroke-width:2.4;stroke-linecap:round;stroke-linejoin:round;}
.wordmark{flex:none;font:600 var(--fs-5)/1 var(--mono);letter-spacing:.06em;color:var(--text-hi);white-space:nowrap;}
.wordmark:hover{color:var(--text-hi);}
.wm-acid{color:var(--acid);}
/* the only environment marker: DEBUG is on. Production shows nothing. */
.env-chip{flex:none;padding:4px 7px;border-radius:var(--r-sm);font:700 var(--fs-1)/1 var(--sans);letter-spacing:.08em;
  color:var(--warn-ink);background:color-mix(in srgb,var(--warn) var(--tint),var(--bg-base));
  border:1px solid color-mix(in srgb,var(--warn) 45%,transparent);}

/* the links: one component in the sidebar, the drawer and a group's menu */
.topnav{display:flex;flex-direction:column;align-items:stretch;gap:1px;min-width:0;}
/* a list taller than its column scrolls; it never squeezes a link to fit */
.topnav > *,.nav-items > *{flex-shrink:0;}
.nav-link{display:flex;align-items:center;gap:10px;height:36px;padding:0 10px;border-radius:var(--r);
  font:500 var(--fs-4)/1 var(--sans);color:var(--text);white-space:nowrap;
  transition:background var(--dur-fast) var(--ease),color var(--dur-fast) var(--ease);}
.nav-link .i{color:var(--text-mut);}
.nav-link:hover{background:var(--bg-raised);color:var(--text-hi);}
.nav-link:hover .i{color:var(--text);}
.nav-link.active{background:var(--acid-glow);color:var(--acid);font-weight:600;}
.nav-link.active .i{color:var(--acid);}
/* open outages, on Incidents: a tag, not a second filled red */
.nav-count{margin-left:auto;min-width:20px;height:20px;padding:0 6px;border-radius:var(--r-full);display:inline-grid;place-items:center;
  font:600 var(--fs-1)/1 var(--sans);color:var(--crit-ink);background:color-mix(in srgb,var(--crit) var(--tint),var(--bg-base));
  border:1px solid color-mix(in srgb,var(--crit) 30%,transparent);}
.nav-label{display:block;margin:var(--space-5) 0 6px;padding:0 10px;font:600 var(--fs-2)/1.2 var(--sans);color:var(--text-mut);}
.nav-group-btn{display:none;}
.nav-items{display:flex;flex-direction:column;gap:1px;}
.navtoggle .i-shut,.navtoggle[aria-expanded="true"] .i-open{display:none;}
.navtoggle[aria-expanded="true"] .i-shut{display:block;}
.nav-scrim{display:none;}
.chev{width:16px;height:16px;color:var(--text-mut);transition:transform var(--dur) var(--ease);}

/* theme and account, at the end of the bar (the foot of the sidebar) */
.topbar-right{display:flex;align-items:center;gap:var(--space-1);margin-left:auto;flex:none;}
.topbar .iconbtn{width:36px;height:36px;flex:none;display:inline-grid;place-items:center;padding:0;
  border-radius:var(--r);color:var(--text-mut);}
.topbar .iconbtn:hover{background:var(--bg-raised);color:var(--text-hi);}
/* the drawer's button: only below 1024px */
.topbar .navtoggle{display:none;}
.theme-toggle .i-sun{display:none;}
:root[data-theme="dark"] .theme-toggle .i-sun{display:block;}
:root[data-theme="dark"] .theme-toggle .i-moon{display:none;}
@media (prefers-color-scheme:dark){
  :root:not([data-theme="light"]) .theme-toggle .i-sun{display:block;}
  :root:not([data-theme="light"]) .theme-toggle .i-moon{display:none;}
}
.usermenu{position:relative;min-width:0;}
.usermenu-btn{display:flex;align-items:center;gap:8px;height:40px;max-width:240px;padding:0 8px 0 5px;cursor:pointer;
  border:1px solid transparent;border-radius:var(--r-full);background:none;color:var(--text);font:500 var(--fs-3)/1 var(--sans);}
.usermenu-btn:hover,.usermenu.open .usermenu-btn{background:var(--bg-raised);border-color:var(--line);}
.usermenu.open .usermenu-btn .chev{transform:rotate(180deg);}
.avatar{flex:none;width:28px;height:28px;border-radius:50%;display:grid;place-items:center;
  background:var(--acid-glow);color:var(--acid);font:600 var(--fs-3)/1 var(--sans);}
.user-name{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;}
/* a menu hung off the shell: the account menu, and a nav group's menu in the top bar */
.menu{position:absolute;right:0;top:calc(100% + 8px);z-index:70;min-width:240px;padding:6px;background:var(--bg-overlay);
  border:1px solid var(--line);border-radius:var(--r-lg);box-shadow:var(--shadow-3);}
.menu-head{display:flex;flex-direction:column;gap:3px;padding:8px 10px 10px;margin-bottom:4px;border-bottom:1px solid var(--line-faint);}
.menu-name{font:600 var(--fs-4)/1.3 var(--sans);color:var(--text-hi);}
.menu-meta{font:400 var(--fs-2)/1.4 var(--sans);color:var(--text-mut);overflow-wrap:anywhere;}
.menu form{display:block;}
.menu-item{display:flex;align-items:center;gap:10px;width:100%;height:36px;padding:0 10px;cursor:pointer;
  border:0;border-radius:var(--r);background:none;color:var(--text);font:500 var(--fs-4)/1 var(--sans);text-align:left;white-space:nowrap;}
.menu-item .i{color:var(--text-mut);}
.menu-item kbd{margin-left:auto;}
.menu-item:hover{background:var(--bg-raised);color:var(--text-hi);}
.menu-item:hover .i{color:var(--text);}

/* ---- page frame and page header ------------------------------------------------
   Every page opens the same way: an optional breadcrumb (the list a form or a record
   belongs to), the title, the actions level with the title, and a one-line subtitle
   under both:
     <header class="hero">
       <nav class="crumbs" aria-label="Breadcrumb"><a href="...">Assets</a></nav>
       <h1>Add asset</h1>
       <div class="hero-actions">...</div>
       <p class="hero-sub">...</p>
     </header>
   Every part but the title is optional; the grid keeps each in its place whichever
   are there. */
.wrap{max-width:1440px;margin:0 auto;padding:var(--space-6) var(--space-6) 64px;position:relative;z-index:2;}
.hero{display:grid;grid-template-columns:minmax(0,1fr) auto;grid-template-areas:"crumbs crumbs" "title actions" "sub sub";
  align-items:center;column-gap:var(--space-5);margin-bottom:var(--space-5);}
.hero h1{grid-area:title;min-width:0;font:600 var(--fs-7)/var(--lh-tight) var(--sans);letter-spacing:-.015em;color:var(--text-hi);}
.hero-sub{grid-area:sub;display:block;max-width:80ch;margin-top:6px;font:400 var(--fs-4)/1.45 var(--sans);
  letter-spacing:0;text-transform:none;color:var(--text-mut);}
.hero-actions{grid-area:actions;display:flex;align-items:center;justify-content:flex-end;gap:var(--space-2);flex-wrap:wrap;}
.hero-actions form{display:inline-flex;}
.crumbs{grid-area:crumbs;display:flex;flex-wrap:wrap;align-items:center;gap:2px;margin:0 0 6px -4px;
  font:500 var(--fs-3)/1.3 var(--sans);color:var(--text-mut);}
.crumbs a{display:inline-flex;align-items:center;gap:6px;padding:2px 4px;border-radius:var(--r-sm);color:var(--text-mut);}
.crumbs a:hover{color:var(--acid);}
/* the first crumb points back up the way it goes; later ones are separated by a slash */
.crumbs a:first-child::before{content:'';width:6px;height:6px;margin:0 1px 0 2px;border:solid currentColor;
  border-width:0 0 1.5px 1.5px;transform:rotate(45deg);}
.crumbs a + a::before{content:'/';margin-right:4px;color:var(--text-ghost);}
/* a form's header is as wide as the form, so its Cancel sits over the card's right edge
   and not out over the empty canvas beside it */
.hero:has(+ form.form-card){max-width:880px;}
.inline{display:inline;}

/* ---- buttons -------------------------------------------------------------------
   Primary (.btn-blaze), secondary (.btn-ghost), destructive (.btn-ghost.danger,
   and the one filled .btn-danger on a confirm page), small (.tiny), text
   (.btn-linkish). Same height, radius and type everywhere. */
.btn-blaze,.btn-ghost{
  display:inline-flex;align-items:center;justify-content:center;gap:6px;
  min-height:var(--ctl-h);padding:0 14px;border-radius:var(--r);border:1px solid var(--line-strong);
  font:500 var(--fs-4)/1 var(--sans);letter-spacing:0;text-transform:none;white-space:nowrap;
  cursor:pointer;background:var(--bg-base);color:var(--text-hi);box-shadow:var(--shadow-1);text-decoration:none;
  transition:background var(--dur) var(--ease),border-color var(--dur) var(--ease),color var(--dur) var(--ease),box-shadow var(--dur) var(--ease);
}
.btn-blaze{color:var(--on-acid);background:var(--acid);border-color:var(--acid);font-weight:600;}
.btn-blaze:hover{background:var(--acid-dim);border-color:var(--acid-dim);color:var(--on-acid);}
.btn-ghost:hover{background:var(--bg-raised);border-color:var(--field-line);color:var(--text-hi);}
.btn-ghost.danger{color:var(--crit-ink);border-color:color-mix(in srgb,var(--crit) 40%,var(--bg-base));}
.btn-ghost.danger:hover{background:color-mix(in srgb,var(--crit) 7%,var(--bg-base));border-color:var(--crit);color:var(--crit-ink);}
.btn-ghost.tiny,.btn-blaze.tiny{min-height:var(--ctl-h-sm);padding:0 10px;font-size:var(--fs-3);}
.btn-blaze:focus-visible,.btn-ghost:focus-visible{box-shadow:0 0 0 2px var(--bg-base),0 0 0 4px var(--acid);}
.btn-blaze .i,.btn-ghost .i{width:16px;height:16px;}
/* a text button: a link's colour, a button's target (row actions, "All incidents") */
.btn-linkish{display:inline-flex;align-items:center;gap:4px;background:none;border:none;border-radius:var(--r-sm);
  color:var(--acid);cursor:pointer;font:500 var(--fs-3)/1.2 var(--sans);letter-spacing:0;text-transform:none;
  padding:5px 6px;text-decoration:none;}
.btn-linkish:hover{background:var(--acid-glow);color:var(--acid-dim);}
.btn-linkish .i{width:15px;height:15px;}
.btn-linkish.danger{color:var(--crit-ink);}
.btn-linkish.danger:hover{background:color-mix(in srgb,var(--crit) 9%,transparent);color:var(--crit-ink);}
/* The confirm page's button is the only red *filled* button in the app, so it cannot be
   mistaken for the primary action anywhere else. */
.btn-danger{display:inline-flex;align-items:center;justify-content:center;gap:6px;min-height:var(--ctl-h);
  padding:0 var(--space-4);border:1px solid var(--crit);border-radius:var(--r);
  background:var(--crit);color:var(--on-acid);font:600 var(--fs-4)/1 var(--sans);  /* on-acid, not #fff: it flips with the theme */
  box-shadow:var(--shadow-1);cursor:pointer;transition:filter var(--dur) var(--ease);}
.btn-danger:hover{filter:brightness(.93);}
/* box-shadow:none clears the global :focus-visible ring, which otherwise drew a
   cobalt halo *and* this red outline at once - on an autofocused delete button. */
.btn-danger:focus-visible{outline:2px solid var(--crit);outline-offset:2px;box-shadow:none;}
button[disabled],.btn-ghost[disabled],.btn-blaze[disabled]{opacity:.45;cursor:not-allowed;}
.btn-ghost:active,.btn-linkish:active{transform:translateY(1px);}
.iconbtn{background:none;border:none;color:inherit;cursor:pointer;font:400 var(--fs-4)/1 var(--sans);padding:var(--space-1);}
.iconbtn:hover{color:var(--acid);}

/* ---- alerts ----------------------------------------------------------------------
   Inline and persistent: an operator must not miss one. Info (blue) is the
   default; .ok, .warn and .err colour the same frame. */
.flash{position:relative;padding:11px 16px 11px 44px;border:1px solid color-mix(in srgb,var(--info) 28%,var(--bg-base));
  border-radius:var(--r-lg);background:color-mix(in srgb,var(--info) 7%,var(--bg-base));
  font:400 var(--fs-4)/1.5 var(--sans);color:var(--text-hi);margin-bottom:var(--space-4);}
.flash::before{content:'i';position:absolute;left:14px;top:12px;width:18px;height:18px;border-radius:50%;
  display:grid;place-items:center;background:var(--info);color:var(--on-acid);font:700 11px/1 var(--sans);}
.flash > p{margin:0;}
.flash > p + p{margin-top:var(--space-1);}
.flash b{color:var(--text-hi);}
.flash.ok{border-color:color-mix(in srgb,var(--ok) 30%,var(--bg-base));background:color-mix(in srgb,var(--ok) 7%,var(--bg-base));}
.flash.ok::before{content:'\2713';background:var(--ok);}
.flash.warn{border-color:color-mix(in srgb,var(--warn) 34%,var(--bg-base));background:color-mix(in srgb,var(--warn) 8%,var(--bg-base));}
.flash.warn::before{content:'!';background:var(--warn);}
.flash.err{border-color:color-mix(in srgb,var(--crit) 32%,var(--bg-base));background:color-mix(in srgb,var(--crit) 7%,var(--bg-base));}
.flash.err::before{content:'!';background:var(--crit);}
.flash form,.flash .btn-ghost{margin-top:var(--space-2);}
/* ---- a page that is switched off (page_off.html) ---- */
.page-off-note{color:var(--text);background:color-mix(in srgb,var(--warn) 8%,var(--bg-base));
  border:1px solid color-mix(in srgb,var(--warn) 30%,var(--bg-base));border-radius:var(--r);
  padding:var(--space-2) var(--space-3);margin:0 auto var(--space-3);max-width:46ch;text-align:left;}

/* ---- KPI tiles ------------------------------------------------------------------
   Label above, figure below. A tone class (only rendered when the count is not
   zero) adds a dot to the label; down and degraded also tint the tile, so a
   problem is visible across the room and a quiet board stays quiet. */
.kpis{display:grid;grid-template-columns:repeat(auto-fit,minmax(168px,1fr));gap:var(--space-3);margin-bottom:var(--space-5);}
/* the Infrastructure tab's tiles - seven with the printers (ADR-0039) - stay one row on a laptop */
.infra-kpis{grid-template-columns:repeat(auto-fit,minmax(148px,1fr));}
.kpi{position:relative;min-width:0;display:flex;flex-direction:column-reverse;justify-content:flex-end;gap:10px;
  padding:14px var(--space-4) var(--space-4);background:var(--bg-base);border:1px solid var(--line);
  border-radius:var(--r-lg);box-shadow:var(--shadow-1);color:inherit;text-decoration:none;}
.kpi-num{font:600 var(--fs-8)/1 var(--sans);letter-spacing:-.02em;color:var(--text-hi);font-variant-numeric:tabular-nums;
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap;}
.kpi-lbl{display:flex;align-items:center;gap:7px;font:500 var(--fs-3)/1.3 var(--sans);color:var(--text-mut);}
.kpi.up .kpi-lbl::before,.kpi.ok .kpi-lbl::before,.kpi.down .kpi-lbl::before,.kpi.crit .kpi-lbl::before,
.kpi.degraded .kpi-lbl::before,.kpi.warn .kpi-lbl::before,.kpi.stale .kpi-lbl::before{content:'';flex:none;width:8px;height:8px;border-radius:50%;background:var(--ok);}
.kpi.down .kpi-lbl::before,.kpi.crit .kpi-lbl::before{background:var(--crit);}
.kpi.degraded .kpi-lbl::before,.kpi.warn .kpi-lbl::before{background:var(--warn);}
/* stale = not heard from, so unknown: the grey hollow dot of its badge, and no tint */
.kpi.stale .kpi-lbl::before{background:transparent;box-shadow:inset 0 0 0 1.5px var(--idle);}
.kpi.down,.kpi.crit{background:color-mix(in srgb,var(--crit) 6%,var(--bg-base));border-color:color-mix(in srgb,var(--crit) 32%,var(--bg-base));}
.kpi.down .kpi-num,.kpi.crit .kpi-num{color:var(--crit-ink);}
.kpi.degraded,.kpi.warn{background:color-mix(in srgb,var(--warn) 6%,var(--bg-base));border-color:color-mix(in srgb,var(--warn) 34%,var(--bg-base));}
.kpi.degraded .kpi-num,.kpi.warn .kpi-num{color:var(--warn-ink);}
a.kpi{transition:box-shadow var(--dur) var(--ease),border-color var(--dur) var(--ease);}
a.kpi:hover{box-shadow:var(--shadow-2);color:inherit;}
/* a card's resting shadow is set after the global ring and would hide it: restate it */
a.kpi:focus-visible{box-shadow:0 0 0 2px var(--bg-base),0 0 0 4px var(--acid);}

/* ---- status badges ----------------------------------------------------------------
   One component, one variable. Every class a template emits for a state maps
   onto one tone of the status scale:
     up / ok / done          green     degraded / in progress   amber
     down / failed           red       stale, unknown, open     grey
     not monitored, a task closed without doing it   grey, hollow dot, dotted edge
     retired, suspended      grey, a bar for a dot, dashed edge
   Categories that are not a state (a role, a domain, a system) use .chip. */
.pill{--tone:var(--idle);--tone-ink:var(--idle-ink);
  display:inline-flex;align-items:center;gap:6px;white-space:nowrap;vertical-align:middle;
  padding:0 9px 0 7px;min-height:22px;border-radius:var(--r-full);
  font:600 var(--fs-2)/1 var(--sans);letter-spacing:0;text-transform:none;
  color:var(--tone-ink);background:color-mix(in srgb,var(--tone) var(--tint),var(--bg-base));
  border:1px solid color-mix(in srgb,var(--tone) 26%,transparent);}
.pill::before{content:'';flex:none;width:6px;height:6px;border-radius:50%;background:var(--tone);}
.pill.up,.pill.ok,.pill.completed,.pill.paid,.pill.sub-submitted,.pill.pay-paid,.pill.asset-in_use,.pill.task-done{--tone:var(--ok);--tone-ink:var(--ok-ink);}
.pill.degraded,.pill.warn,.pill.in_progress,.pill.on_hold,.pill.pay-in_process,.pill.pay-on_hold,.pill.sub-on_hold,.pill.asset-repair{--tone:var(--warn);--tone-ink:var(--warn-ink);}
.pill.down,.pill.crit,.pill.sub-rejected,.pill.asset-lost{--tone:var(--crit);--tone-ink:var(--crit-ink);}
.pill.info{--tone:var(--info);--tone-ink:var(--info-ink);}
.pill.stale{border-style:dashed;}
.pill.stale::before{background:transparent;box-shadow:inset 0 0 0 1.5px var(--tone);}
.pill.unmonitored,.pill.task-wont_do,.pill.task-not_required,.pill.task-ignored{background:transparent;border-style:dotted;border-color:var(--line-strong);color:var(--text-mut);}
.pill.unmonitored::before,.pill.task-wont_do::before,.pill.task-not_required::before,.pill.task-ignored::before{background:transparent;box-shadow:inset 0 0 0 1.5px var(--idle);}
.pill.retired,.pill.asset-retired{background:transparent;border-style:dashed;border-color:var(--line-strong);color:var(--text-mut);}
.pill.retired::before,.pill.asset-retired::before{width:8px;height:2px;border-radius:1px;background:var(--text-ghost);}

/* ---- cards ----------------------------------------------------------------------
   ONE bordered surface. `.loc` (a building on the Network board) and `.panel` (any
   other section) are two names for it, kept because the names carry meaning where
   they are used. */
/* min-width:0 - overflow:clip (unlike hidden) does not let a grid or flex item shrink
   below its content, so a card in a grid column would push the page sideways */
.panel,.loc{background:var(--bg-base);border:1px solid var(--line);border-radius:var(--r-lg);
  box-shadow:var(--shadow-1);margin-bottom:var(--space-5);overflow:clip;min-width:0;}
.loc-head,.panel-head{display:flex;align-items:center;justify-content:space-between;
  gap:var(--space-2) var(--space-4);flex-wrap:wrap;padding:14px 20px;border-bottom:1px solid var(--line);
  background:var(--bg-base);}
/* the title, whichever element carries it */
.loc-code,.panel-head h2{margin:0;font:600 var(--fs-5)/1.3 var(--sans);
  letter-spacing:-.005em;text-transform:none;color:var(--text-hi);}
/* and the quiet half beside it */
.loc-name,.panel-head .dim{font:400 var(--fs-3)/1.3 var(--sans);letter-spacing:0;
  text-transform:none;color:var(--text-mut);}
/* a title with a quiet line beside it; the tools (a toggle, a link, a count) at the end */
.loc-id,.panel-title{display:flex;align-items:baseline;gap:10px;flex-wrap:wrap;min-width:0;}
.panel-tools{display:flex;align-items:center;gap:var(--space-2) var(--space-4);flex-wrap:wrap;}
.panel-head > .btn-linkish{margin-right:-6px;}
.panel-foot{margin:0;padding:10px 20px;border-top:1px solid var(--line-faint);font:400 var(--fs-3)/1.4 var(--sans);color:var(--text-mut);}
/* how many: a card's head, a filter bar's end, a pager */
.loc-summary,.count{font:500 var(--fs-3)/1.3 var(--sans);color:var(--text-mut);white-space:nowrap;}
/* A floor inside a building: lighter than the card's title, heavier than a row. */
.floor-head{display:flex;align-items:center;flex-wrap:wrap;gap:6px 10px;padding:9px 20px;background:var(--bg-raised);
  border-top:1px solid var(--line);border-bottom:1px solid var(--line-faint);
  font:600 var(--fs-3)/1.3 var(--sans);color:var(--text-hi);}
.loc-head + .floor-head,.loc-head + .floor-group > .floor-head{border-top:0;}
.floor-head .floor-count{white-space:nowrap;font:500 var(--fs-2)/1 var(--sans);color:var(--text-mut);background:var(--bg-base);
  border:1px solid var(--line);padding:4px 9px;border-radius:var(--r-full);}
/* A table whose floors are <tbody>s (the Subnets page): each floor's first row is this
   header. The cell draws the band; the label inside it keeps its place when a phone
   scrolls the table sideways. */
table.lines tr.floor-row > th.floor-cell{padding:0;background:var(--bg-raised);box-shadow:none;
  border-top:1px solid var(--line);border-bottom:1px solid var(--line-faint);
  font:600 var(--fs-3)/1.3 var(--sans);letter-spacing:0;color:var(--text-hi);}
table.lines > tbody:first-of-type > tr.floor-row > th.floor-cell{border-top:0;}   /* the headings' rule is above it */
th.floor-cell > .floor-head{border:0;background:none;position:sticky;left:0;width:max-content;}
/* a floor's internal subnets (ADR-0027), after its name and count: each network in mono,
   its purpose in the quiet sans beside it, the whole run a link to the Subnets page */
.floor-subnets{display:inline-flex;flex-wrap:wrap;align-items:baseline;gap:2px 14px;margin-left:4px;padding:1px 0 1px 12px;
  border-left:1px solid var(--line-strong);border-radius:0;font:500 var(--fs-2)/1.4 var(--mono);color:var(--text);}
.floor-subnets i{font:400 var(--fs-2)/1.4 var(--sans);font-style:normal;color:var(--text-mut);}
a.floor-subnets:hover,a.floor-subnets:hover i{color:var(--acid);}
/* ...on the Leased Lines tab, on a line of their own under the floor's heading, not in it:
   the heading is the <summary> that folds the floor, and a link inside it took a tap meant
   for the fold to the Subnets page (ADR-0032). They fold away with the floor. */
.floor-nets{display:flex;flex-wrap:wrap;align-items:baseline;margin:0;padding:7px 20px;
  border-bottom:1px solid var(--line-faint);font:500 var(--fs-2)/1.4 var(--sans);color:var(--text-mut);}
.floor-nets .floor-subnets{margin-left:10px;}
/* a floor's ISP redundancy on the Leased Lines tab (ADR-0032), after its line count: quiet
   while two ISPs carry the floor, amber with a dot when one failure takes it offline */
.floor-cover{display:inline-flex;align-items:center;gap:6px;white-space:nowrap;
  font:500 var(--fs-2)/1.3 var(--sans);color:var(--text-mut);}
.floor-cover.warn{color:var(--warn-ink);}
.floor-cover.warn::before{content:'';flex:none;width:7px;height:7px;border-radius:50%;background:var(--warn);}
/* the Subnets page: a floor's "Add subnet" at the end of its band */
table.lines tr.floor-row > th.floor-cell-end{padding:0 14px 0 0;text-align:right;white-space:nowrap;}

/* ---- data tables -------------------------------------------------------------------
   Sentence-case headers, 14px rows with room to breathe, data in mono, a hover
   row, numbers right-aligned (.num). A long table is as long as it is: it scrolls
   with the page, never inside a box of its own that would catch the mouse wheel. */
table.lines{width:100%;border-collapse:separate;border-spacing:0;}
table.lines th{text-align:left;padding:10px 14px;white-space:nowrap;
  background:var(--bg-base);box-shadow:inset 0 -1px 0 var(--line);
  font:600 var(--fs-2)/1.3 var(--sans);letter-spacing:.01em;text-transform:none;color:var(--text-mut);}
table.lines td{padding:11px 14px;border-bottom:1px solid var(--line-faint);font-size:var(--fs-4);
  vertical-align:middle;color:var(--text);}
table.lines th:first-child,table.lines td:first-child{padding-left:20px;}
table.lines th:last-child,table.lines td:last-child{padding-right:20px;}
table.lines td.mono,table.lines td .mono{font-family:var(--mono);font-size:var(--fs-3);color:var(--text-hi);}
/* data and names never break; a long free-text column (a circuit id) opts into it */
table.lines td.mono,table.lines td.nowrap,table.lines .num{white-space:nowrap;}
table.lines td.wrap{white-space:normal;}
table.lines .num{text-align:right;}
/* .dim is (0,1,0) and `table.lines td` is (0,1,2): whole-row states - paused
   recipients, suspended accounts, retired lines - need the stronger selector. */
table.lines tr.dim td,table.lines tr.dim td.mono,
table.lines td.dim,table.lines td.dim.mono,table.lines td .dim{color:var(--text-mut);}
table.lines tbody tr{transition:background var(--dur-fast);}
table.lines tbody tr:last-child td{border-bottom:none;}
table.lines tbody tr:hover{background:var(--bg-raised);}
table.lines td b{color:var(--text-hi);font-weight:600;}
/* plain links in a cell; a button that happens to sit in a table keeps its own colours */
table.lines a:where(:not(.btn-blaze,.btn-ghost,.btn-danger)){color:var(--acid);}
table.lines a:where(:not(.btn-blaze,.btn-ghost,.btn-danger)):hover{color:var(--acid-dim);}
/* a cell's title with a quieter line under it (a device and its address) */
.cell-title{display:block;color:var(--text-hi);}
.cell-sub{display:block;margin-top:2px;font-size:var(--fs-2);}
/* where a reading came from, after a device's name: "· Central · 14 clients", "· Ping" */
.via{font:400 var(--fs-2)/1.4 var(--sans);color:var(--text-mut);}
table.lines.compact td{padding-top:9px;padding-bottom:9px;}
/* a column as narrow as its content (a hop number), leaving the rest to the others */
table.lines .fit{width:1%;}
/* a name someone typed (a device, a line, a vendor, an item): each line of it as wide as
   its text, up to a cap, so a short one ("Airtel / ILL") takes no more room than it needs
   and never breaks, and a long one wraps at the cap - never word by word, and never
   pushing the rest of the row out of sight. A run with no space to break at (an
   underscored circuit ref, a dotted FQDN) breaks at the cap too, instead of printing
   over the next column. */
table.lines .name-cell>*{display:block;width:max-content;max-width:14rem;overflow-wrap:anywhere;}
table.lines .name-cell.short>*{max-width:9rem;}
/* an empty table is its empty state alone: no column headings over nothing */
table.lines:has(>tbody>tr>td>.empty)>thead{display:none;}
/* a wide table scrolls sideways inside its card, at every width. position:relative makes
   it the containing block of anything absolutely positioned in the table (a .sr-only
   label), which would otherwise escape the scroller and widen the page. */
.tablewrap{position:relative;overflow-x:auto;container-type:inline-size;}
.tablewrap table{margin:0;}
/* an empty state inside a table that scrolls sideways (a phone) stays in view */
.tablewrap td > .empty{position:sticky;left:0;width:100cqw;}
table.lines tbody td:has(> .empty){padding:0;}
/* A header that sorts (the Assets list): its name is a link, as quiet as the other
   headers until pointed at, 24px tall to hit; the column the list is in the order of
   reads in the text colour with a small arrow - up A to Z, down Z to A. */
table.lines th .sort-link{display:inline-flex;align-items:center;gap:4px;min-height:24px;margin:-4px 0;
  color:inherit;text-decoration:none;border-radius:var(--r-sm);}
table.lines th .sort-link:hover{color:var(--text-hi);}
table.lines th .sort-link:focus-visible{outline:none;box-shadow:0 0 0 2px var(--acid);}
table.lines th.is-sorted{color:var(--text-hi);}
table.lines th .sort-arrow{width:13px;height:13px;color:var(--acid);stroke-width:2.25;}
table.lines th .sort-arrow.up{transform:rotate(180deg);}
/* Row actions - one baseline, quiet until the row is pointed at, so a column of
   "edit / retire" does not compete with the status column. */
.row-actions{white-space:nowrap;text-align:right;}
.row-actions form{display:inline;}
.row-actions>*+*{margin-left:var(--space-1);}
/* Alerting: each group's table on one grid (the operator, 14 Oct 2026: "intendation"),
   not sized to its own names and addresses, so the columns line up from group to group */
table.lines.recipients{table-layout:fixed;}
table.lines.recipients col.rc-name{width:24%;}
table.lines.recipients col.rc-email{width:40%;}
table.lines.recipients col.rc-status{width:14%;}
table.lines.recipients col.rc-act{width:22%;}
table.lines.recipients td{overflow-wrap:anywhere;}
table.lines .row-actions .btn-linkish,table.lines .row-actions > a{color:var(--text-mut);}
table.lines tbody tr:hover .row-actions .btn-linkish,table.lines tbody tr:hover .row-actions > a,
table.lines .row-actions .btn-linkish:focus-visible{color:var(--acid);}
table.lines tbody tr:hover .row-actions .btn-linkish.danger,table.lines .row-actions .btn-linkish.danger:focus-visible{color:var(--crit-ink);}
table.lines .row-actions .btn-linkish[disabled]{color:var(--text-ghost);}
table.lines .row-actions > a:not(.btn-linkish){display:inline-flex;padding:5px 6px;border-radius:var(--r-sm);font:500 var(--fs-3)/1.2 var(--sans);}
table.lines .row-actions > a:not(.btn-linkish):hover{background:var(--acid-glow);}

/* ---- filter bar and search -------------------------------------------------------- */
.filters{display:flex;align-items:center;gap:var(--space-2);flex-wrap:wrap;margin-bottom:var(--space-4);
  padding:10px;background:var(--bg-base);border:1px solid var(--line);border-radius:var(--r-lg);box-shadow:var(--shadow-1);}
/* the "N shown" count sits at the far end */
.filters > .count{margin-left:auto;padding:0 6px;}
.filters input[type=text],.filters input[type=search],.filters input[type=date]{
  min-height:var(--ctl-h);padding:0 12px;font:400 var(--fs-4)/1 var(--sans);color:var(--text-hi);
  background:var(--bg-base);border:1px solid var(--field-line);border-radius:var(--r);
  transition:border-color var(--dur) var(--ease),box-shadow var(--dur) var(--ease);}
/* a search field grows into the room left over but asks for little, so a dense bar
   (Activity: search, three selects, two dates, Filter) still fits one row at 1280px */
.filters input[type=text],.filters input[type=search]{flex:1 1 180px;min-width:160px;max-width:380px;}
.filters input[type=date]{flex:none;width:150px;padding:0 10px;}
/* a search field (and only a search field) carries the magnifier */
.filters input[type=search],.filters input[name=q],.filters input#prjSearch{padding-left:34px;
  background:var(--bg-base) no-repeat 11px 50%/16px url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%237B8595' stroke-width='2.2' stroke-linecap='round'%3E%3Ccircle cx='11' cy='11' r='7'/%3E%3Cpath d='m20 20-3.5-3.5'/%3E%3C/svg%3E");}
.filters input:hover{border-color:var(--text-mut);}
.filters input:focus{border-color:var(--acid);box-shadow:var(--ring);outline:none;}
.filters input::placeholder{color:var(--text-mut);}
.filters input::-webkit-search-cancel-button{cursor:pointer;}
.chk{display:inline-flex;align-items:center;gap:var(--space-2);font:500 var(--fs-3)/1.3 var(--sans);
  text-transform:none;letter-spacing:0;color:var(--text);cursor:pointer;}
.chk input{width:16px;height:16px;accent-color:var(--acid);}
.filters input[type=file],.form-grid input[type=file]{font:400 var(--fs-3)/1 var(--sans);color:var(--text-mut);}
.filters input[type=file]::file-selector-button,.form-grid input[type=file]::file-selector-button{font:500 var(--fs-3)/1 var(--sans);margin-right:var(--space-2);
  padding:7px 12px;border:1px solid var(--line-strong);border-radius:var(--r);background:var(--bg-base);color:var(--text-hi);cursor:pointer;}
.filters form{display:inline-flex;}
.filters:not(:has(input:not([type=hidden]),select,textarea)){padding:0;background:none;border:0;box-shadow:none;}

/* ---- forms -------------------------------------------------------------------------- */
.form-card{max-width:880px;padding:var(--space-5) var(--space-6) var(--space-6);background:var(--bg-base);
  border:1px solid var(--line);border-radius:var(--r-lg);box-shadow:var(--shadow-1);margin-bottom:var(--space-5);}
/* minmax(0,...): a long value in a field (a vendor, an uplink, a person) is cut with an
   ellipsis inside its column; a bare 1fr let it widen the column and push the form
   past its card */
.form-grid{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:20px var(--space-5);}
.field{display:flex;flex-direction:column;gap:6px;min-width:0;}
.field-wide{grid-column:1 / -1;}
.field label{display:flex;align-items:baseline;gap:3px;font:500 var(--fs-3)/1.35 var(--sans);
  text-transform:none;letter-spacing:0;color:var(--text-hi);}
.form-grid input[type=text],.form-grid input[type=number],.form-grid input[type=date],.form-grid input[type=email],
.form-grid input[type=password],.form-grid input[type=search],.form-grid input[type=url],.form-grid input[type=tel],
.form-grid select,.form-grid textarea,.qc-body input[type=text],.qc-body input[type=number],.qc-body input[type=email],
.qc-body select,.qc-body textarea{
  width:100%;min-height:var(--ctl-h);padding:7px 12px;font:400 var(--fs-4)/1.4 var(--sans);color:var(--text-hi);
  background:var(--bg-base);border:1px solid var(--field-line);border-radius:var(--r);
  transition:border-color var(--dur) var(--ease),box-shadow var(--dur) var(--ease);}
.form-grid input:hover,.form-grid select:hover,.form-grid textarea:hover{border-color:var(--text-mut);}
.form-grid input:focus,.form-grid select:focus,.form-grid textarea:focus,
.qc-body input:focus,.qc-body select:focus,.qc-body textarea:focus{border-color:var(--acid);box-shadow:var(--ring);outline:none;}
.form-grid input::placeholder,.form-grid textarea::placeholder{color:var(--text-mut);}
.form-grid input[disabled],.form-grid select[disabled],.form-grid textarea[disabled]{background:var(--bg-raised);color:var(--text-mut);cursor:not-allowed;}
/* each message on its own line — |striptags used to glue them into one sentence */
.field-err{display:flex;flex-direction:column;gap:2px;font:500 var(--fs-2)/1.4 var(--sans);color:var(--crit-ink);}
.field-help{font:400 var(--fs-2)/1.45 var(--sans);color:var(--text-mut);}
/* Django renders password rules as a <ul> inside help_text */
.field-help ul{margin:var(--space-1) 0 0;padding-left:1.1em;}
.field-help li{margin:2px 0;}
.req{color:var(--crit);font-weight:600;}
.field .req{font-size:var(--fs-3);line-height:1;}
.field.has-error input,.field.has-error select,.field.has-error textarea{border-color:var(--crit);}
.field.has-error input:focus,.field.has-error select:focus,.field.has-error textarea:focus{
  border-color:var(--crit);box-shadow:0 0 0 3px color-mix(in srgb,var(--crit) 18%,transparent);}
.ctl-area textarea{min-height:104px;resize:vertical;}
/* A checkbox reads as "box + label", not as a stack with a floating caption. It
   spans the grid so the label never wraps inside a half-width column, and its help
   text sits under the pair rather than beside it. */
.ctl-check{grid-column:1 / -1;flex-direction:row;align-items:center;
  flex-wrap:wrap;gap:var(--space-1) var(--space-2);}
.ctl-check input{width:16px;height:16px;accent-color:var(--acid);order:-1;flex:none;}
.ctl-check label{font-size:var(--fs-4);font-weight:400;color:var(--text-hi);white-space:nowrap;}
.ctl-check .field-help{flex-basis:100%;margin-left:calc(16px + var(--space-2));}
/* the destructive action sits apart from the one you meant to press */
.form-actions{margin-top:var(--space-5);padding-top:var(--space-4);border-top:1px solid var(--line-faint);
  display:flex;align-items:center;gap:var(--space-2);justify-content:flex-end;}
.form-actions .danger{margin-right:auto;}
/* a form nested inside a panel supplies its own frame */
.form-card-flush{border:none;background:none;box-shadow:none;padding:var(--space-4) 20px 20px;margin:0;max-width:none;}
/* what follows a form (its status, password, history) is as wide as the form */
.wrap:has(> form.form-card) > .panel{max-width:880px;}
/* the native date icon follows color-scheme on its own */
input[type=date]::-webkit-calendar-picker-indicator{opacity:.55;cursor:pointer;}
input[type=date]:hover::-webkit-calendar-picker-indicator{opacity:1;}

/* ---- dropdowns: the select, combobox and datepicker are one component, styled
   in static/css/mss.css (ADR-0024) ------------------------------------------ */

/* ---- segmented tabs ----------------------------------------------------------------
   An inset track with the current tab lifted out of it. */
.segbar{display:flex;width:max-content;max-width:100%;gap:2px;padding:3px;margin-bottom:var(--space-4);
  background:var(--bg-void);border:1px solid var(--line);border-radius:calc(var(--r) + 3px);
  overflow-x:auto;overflow-y:hidden;-webkit-overflow-scrolling:touch;scrollbar-width:none;}
.segbar::-webkit-scrollbar{display:none;}
.segbar .seg{flex:none;display:inline-flex;align-items:center;min-height:30px;padding:0 14px;
  border:none;border-radius:var(--r);background:transparent;cursor:pointer;text-decoration:none;
  font:500 var(--fs-3)/1 var(--sans);letter-spacing:0;text-transform:none;color:var(--text-mut);
  transition:background var(--dur-fast) var(--ease),color var(--dur-fast) var(--ease);}
.segbar .seg:hover:not(.active){color:var(--text-hi);background:color-mix(in srgb,var(--bg-base) 55%,transparent);}
.segbar .seg.active{background:var(--bg-base);color:var(--text-hi);font-weight:600;box-shadow:var(--shadow-1);}
/* the track scrolls sideways on a phone, so an outside ring would be cut off: draw it inside */
.segbar .seg:focus-visible{box-shadow:inset 0 0 0 2px var(--acid);}
.segbar .seg.active:focus-visible{box-shadow:inset 0 0 0 2px var(--acid),var(--shadow-1);}
.hidden{display:none !important;}
.empty-note{padding:var(--space-6) var(--space-4);text-align:center;color:var(--text-mut);font:400 var(--fs-3)/1.5 var(--sans);}
/* One quiet line (ADR-0041): what a panel, tile or table says when it has nothing to show
   yet, or when what it would show is said on another page - never empty headings over a
   "nothing here". In a panel it sits where the table would; on the page, under the tabs. */
.quiet-line{margin:0;padding:12px 20px;font:400 var(--fs-3)/1.5 var(--sans);color:var(--text-mut);}
.quiet-line .mono{color:var(--text-hi);}
.quiet-line > .led{margin-right:8px;transform:translateY(-1px);}
.quiet-line.it-items-note{margin:0 0 var(--space-4);padding:0 2px;}
.nowrap{white-space:nowrap;}

/* ---- Home: the estate at a glance, then the pages you can open (ADR-0031) ------------
   A health card is one figure from the page it links to: a head (icon, name, the status
   badge), the figure, a meter drawn from the same counts, one quiet line under it. It
   tints red or amber only while its badge does - the KPI tile's rule. */
/* five cards: one row of five from 1180px (each at least 212px), three over two below
   that - auto-fit laid them four and one, the probes card alone on a second row - and
   two a row on a phone (the phone block, below) */
.health-grid{display:grid;grid-template-columns:repeat(6,minmax(0,1fr));gap:var(--space-3);margin-bottom:var(--space-5);}
.health-grid > .health-card{grid-column:span 2;}
.health-grid > .health-card:nth-child(n+4){grid-column:span 3;}
@media (min-width:1180px){
  .health-grid{grid-template-columns:repeat(5,minmax(0,1fr));}
  .health-grid > .health-card,.health-grid > .health-card:nth-child(n+4){grid-column:auto;}
}
.health-card{display:flex;flex-direction:column;gap:10px;min-width:0;padding:14px var(--space-4) var(--space-4);
  background:var(--bg-base);border:1px solid var(--line);border-radius:var(--r-lg);box-shadow:var(--shadow-1);color:var(--text);
  transition:box-shadow var(--dur) var(--ease),border-color var(--dur) var(--ease);}
a.health-card[href]:hover{border-color:color-mix(in srgb,var(--acid) 45%,var(--line));box-shadow:var(--shadow-2);color:var(--text);}
.health-card.down{background:color-mix(in srgb,var(--crit) 5%,var(--bg-base));border-color:color-mix(in srgb,var(--crit) 32%,var(--bg-base));}
.health-card.degraded{background:color-mix(in srgb,var(--warn) 5%,var(--bg-base));border-color:color-mix(in srgb,var(--warn) 34%,var(--bg-base));}
a.health-card.down[href]:hover{border-color:var(--crit);}
a.health-card.degraded[href]:hover{border-color:var(--warn);}
.hc-head{display:flex;align-items:center;gap:8px;min-width:0;min-height:22px;}
.hc-head > .i{color:var(--text-mut);}
.hc-title{flex:1;min-width:0;font:600 var(--fs-3)/1.3 var(--sans);color:var(--text-hi);overflow:hidden;text-overflow:ellipsis;white-space:nowrap;}
.hc-figure{display:block;font:400 var(--fs-3)/1.2 var(--sans);color:var(--text-mut);overflow:hidden;text-overflow:ellipsis;white-space:nowrap;}
.hc-figure b{margin-right:2px;font:600 var(--fs-8)/1 var(--sans);letter-spacing:-.02em;color:var(--text-hi);font-variant-numeric:tabular-nums;}
.health-card.down .hc-figure b{color:var(--crit-ink);}
.health-card.degraded .hc-figure b{color:var(--warn-ink);}
.hc-foot{display:flex;flex-wrap:wrap;align-items:center;gap:6px 10px;margin-top:auto;padding-top:2px;font:400 var(--fs-2)/1.4 var(--sans);color:var(--text-mut);}
.hc-agent{display:inline-flex;align-items:center;gap:6px;}
.hc-agent::before{content:'';width:6px;height:6px;border-radius:50%;background:var(--ok);}
.hc-agent.off{color:var(--crit-ink);}
.hc-agent.off::before{background:var(--crit);}
/* silent with nothing to check (every device at its site paused): grey, not down, not up */
.hc-agent.idle{color:var(--text-mut);}
.hc-agent.idle::before{background:transparent;box-shadow:inset 0 0 0 1.5px var(--idle);}
/* a meter: one segment per state, as wide as its count */
.meter{display:flex;gap:2px;height:6px;min-width:0;border-radius:var(--r-full);overflow:hidden;background:var(--bg-void);}
.meter > i{display:block;flex:1 1 0;min-width:3px;background:var(--idle);}
/* up is the board's softer green (viz.css --vz-up), as on the building tiles and the
   24-hour strips one click away: one fact, one colour on every bar */
.meter > .m-ok{background:var(--vz-up,var(--ok));}
.meter > .m-warn{background:var(--warn);}
.meter > .m-crit{background:var(--crit);}
.meter > .m-idle{background:color-mix(in srgb,var(--idle) 55%,var(--bg-void));}
.meter > .m-off{background:transparent;box-shadow:inset 0 0 0 1px var(--line-strong);}
/* the two panels under the cards: open incidents, and the lines building by building */
.home-cols{display:grid;grid-template-columns:minmax(0,1.5fr) minmax(0,1fr);gap:var(--space-4);align-items:start;margin-bottom:var(--space-6);}
.home-cols > .panel{margin:0;}
.bldg-list{list-style:none;margin:0;padding:0;}
.bldg-list li{display:grid;grid-template-columns:minmax(0,1fr) minmax(64px,120px) 104px;align-items:center;gap:var(--space-4);
  padding:12px 20px;border-bottom:1px solid var(--line-faint);}
.bldg-list li:last-child{border-bottom:0;}
.bl-name{display:flex;align-items:baseline;gap:8px;min-width:0;}
.bl-name b{flex:none;white-space:nowrap;font:600 var(--fs-4)/1.3 var(--sans);color:var(--text-hi);}
.bl-name span{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font:400 var(--fs-3)/1.3 var(--sans);color:var(--text-mut);}
.bl-count{justify-self:end;font:400 var(--fs-3)/1.3 var(--sans);color:var(--text-mut);white-space:nowrap;}
.bl-count .mono{color:var(--text-hi);}
/* the pages this person can open, in the nav's order: one tile each, never grouped by
   department. Neutral until pointed at - the accent means an action. */
.page-links{margin-bottom:var(--space-5);}
.section-title{margin:0 2px var(--space-3);font:600 var(--fs-6)/1.3 var(--sans);letter-spacing:-.005em;color:var(--text-hi);}
/* a tile is wide enough for its one-line description ("Leased lines · access control"):
   four to a row at 1280px, five beside the sidebar at 1920px */
.page-grid{list-style:none;margin:0;padding:0;display:grid;grid-template-columns:repeat(auto-fill,minmax(264px,1fr));gap:var(--space-3);}
.page-grid > li{min-width:0;}
.page-link{display:flex;align-items:center;gap:12px;height:100%;min-height:64px;padding:12px 14px;
  background:var(--bg-base);border:1px solid var(--line);border-radius:var(--r-lg);box-shadow:var(--shadow-1);color:var(--text);
  transition:box-shadow var(--dur) var(--ease),border-color var(--dur) var(--ease);}
.page-link:hover{border-color:color-mix(in srgb,var(--acid) 45%,var(--line));box-shadow:var(--shadow-2);color:var(--text);}
.pl-icon{flex:none;display:grid;place-items:center;width:36px;height:36px;border-radius:var(--r);
  background:var(--bg-raised);border:1px solid var(--line-faint);color:var(--text-mut);
  transition:background var(--dur) var(--ease),color var(--dur) var(--ease);}
.page-link:hover .pl-icon{background:var(--acid-glow);border-color:transparent;color:var(--acid);}
.pl-text{flex:1;min-width:0;display:flex;flex-direction:column;gap:2px;}
.pl-name{font:600 var(--fs-4)/1.3 var(--sans);color:var(--text-hi);overflow:hidden;text-overflow:ellipsis;white-space:nowrap;}
.page-link:hover .pl-name{color:var(--acid);}
.pl-desc{font:400 var(--fs-2)/1.35 var(--sans);color:var(--text-mut);overflow:hidden;text-overflow:ellipsis;white-space:nowrap;}
.pl-go{width:16px;height:16px;color:var(--text-ghost);transition:transform var(--dur) var(--ease),color var(--dur) var(--ease);}
.page-link:hover .pl-go{color:var(--acid);transform:translateX(2px);}
/* the cards' resting shadow comes after the global :focus-visible ring and would replace
   it, leaving a keyboard user no sign of where they are (WCAG 2.4.7): restate the ring */
a.health-card:focus-visible,.page-link:focus-visible{box-shadow:0 0 0 2px var(--bg-base),0 0 0 4px var(--acid);}
@media (max-width:1099.98px){.home-cols{grid-template-columns:minmax(0,1fr);}}
/* a phone: two cards a row, each only its figure, meter and badge (the notes beside
   the badge are on the pages the cards open); an odd last card takes the whole row */
@media (max-width:640px){
  .health-grid{grid-template-columns:repeat(2,minmax(0,1fr));gap:var(--space-2);}
  .health-grid > .health-card,.health-grid > .health-card:nth-child(n+4){grid-column:auto;}
  .health-card{gap:8px;padding:12px;}
  .health-grid > .health-card:last-child:nth-child(odd){grid-column:1 / -1;}
  .hc-figure b{font-size:24px;}
  .hc-foot > :not(.pill){display:none;}
  .health-card:last-child:nth-child(odd) .hc-foot > .hc-agent{display:inline-flex;}
  .bldg-list li{grid-template-columns:minmax(0,1fr) auto;padding:10px var(--space-4);}
  .bldg-list .meter{grid-column:1 / -1;grid-row:2;}
  .page-grid{grid-template-columns:repeat(2,minmax(0,1fr));gap:var(--space-2);}
  .page-link{gap:10px;min-height:56px;padding:10px 12px;}
  .pl-icon{width:32px;height:32px;}
  .pl-go{display:none;}
  /* two lines, not one cut mid-word ("Traceroute · loss...", ADR-0041) */
  .pl-desc{white-space:normal;display:-webkit-box;-webkit-line-clamp:2;line-clamp:2;-webkit-box-orient:vertical;}
}

/* ---- projects: building / cards / table ----------------------------------------- */
.buildings-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(300px,1fr));gap:var(--space-4);}
.building{border:1px solid var(--line);padding:var(--space-5);background:var(--bg-base);border-radius:var(--r-lg);box-shadow:var(--shadow-1);}
.bname{font:600 var(--fs-6)/1.3 var(--sans);text-transform:none;letter-spacing:0;color:var(--text-hi);margin-bottom:14px;}
.bname .dim{margin-left:4px;font:400 var(--fs-4)/1.3 var(--sans);}
.bmeta{display:flex;gap:var(--space-6);margin-bottom:18px;}
.bmeta > div{display:flex;flex-direction:column;}
.bmeta b{font:600 26px/1 var(--sans);letter-spacing:-.02em;color:var(--text-hi);}
.bmeta span{font:500 var(--fs-2)/1.3 var(--sans);text-transform:none;letter-spacing:0;color:var(--text-mut);margin-top:6px;}
.towers{display:flex;gap:var(--space-3);align-items:flex-end;}
.tower{display:flex;flex-direction:column;align-items:center;gap:7px;flex:1;min-width:0;}
.tstack{display:flex;flex-direction:column;gap:4px;width:100%;}
.floor{height:20px;border:1px solid var(--line);background:var(--bg-raised);display:flex;align-items:center;justify-content:center;border-radius:var(--r-sm);
  font:600 var(--fs-1)/1 var(--mono);color:transparent;transition:transform .1s;}
.floor.on{background:var(--acid);border-color:var(--acid);color:var(--on-acid);cursor:pointer;}
.floor.on:hover{transform:scale(1.06);}
.floor.on.soon{background:var(--warn);border-color:var(--warn);}
.tlabel{font:600 var(--fs-2)/1 var(--sans);color:var(--text-mut);}
.blegend{display:flex;gap:var(--space-4);margin-top:14px;padding-top:var(--space-3);border-top:1px solid var(--line-faint);
  font:500 var(--fs-2)/1 var(--sans);color:var(--text-mut);}
.blegend span{display:flex;align-items:center;gap:6px;}
.blegend .sw{width:11px;height:11px;display:inline-block;background:var(--acid);border-radius:3px;}
.blegend .sw.vac{border:1px dashed var(--text-ghost);background:transparent;}
.cards-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(300px,1fr));gap:var(--space-4);}
.pcard{display:block;border:1px solid var(--line);padding:var(--space-5);background:var(--bg-base);border-radius:var(--r-lg);
  box-shadow:var(--shadow-1);color:var(--text);transition:border-color var(--dur),box-shadow var(--dur);}
.pcard:hover{border-color:color-mix(in srgb,var(--acid) 45%,var(--line));box-shadow:var(--shadow-2);color:var(--text);}
.pcard-top{display:flex;align-items:flex-start;justify-content:space-between;gap:var(--space-3);margin-bottom:14px;}
.pcard .nm{font:600 var(--fs-6)/1.25 var(--sans);text-transform:none;letter-spacing:-.005em;color:var(--text-hi);}
.where{display:flex;flex-wrap:wrap;gap:6px;margin-bottom:var(--space-4);}
/* a category or attribute, not a state: square-ish, no status colour */
.chip{display:inline-flex;align-items:center;gap:5px;vertical-align:middle;min-height:22px;padding:0 8px;
  font:500 var(--fs-2)/1 var(--sans);color:var(--text);white-space:nowrap;
  background:var(--bg-raised);border:1px solid var(--line);border-radius:var(--r-sm);}
/* a person's Microsoft 365 licences (Users, ADR-0027): a chip each; a free or trial one
   - which does not count as a licence - hollow, dashed and quiet, and says so */
td.licences{white-space:normal;min-width:13rem;}
td.licences .lic{display:inline-flex;align-items:center;gap:6px;max-width:19rem;min-height:22px;margin:2px 4px 2px 0;padding:2px 8px;
  font:500 var(--fs-2)/1.3 var(--sans);color:var(--text);background:var(--bg-raised);border:1px solid var(--line);border-radius:var(--r-sm);}
td.licences .lic.free{background:transparent;border-style:dashed;border-color:var(--line-strong);color:var(--text-mut);}
td.licences .lic-tag{flex:none;padding:2px 6px;border-radius:var(--r-full);background:var(--bg-void);
  font:600 var(--fs-1)/1 var(--sans);color:var(--text-mut);}
.countdown{display:flex;align-items:center;gap:14px;border:1px solid var(--line);background:var(--bg-raised);padding:var(--space-3) var(--space-4);
  border-radius:var(--r);font:500 var(--fs-2)/1.3 var(--sans);text-transform:none;letter-spacing:0;color:var(--text-mut);}
.countdown .days{font:600 28px/1 var(--sans);color:var(--ok-ink);}
.countdown.soon .days{color:var(--warn-ink);}
.countdown.past .days{color:var(--crit-ink);}
.countdown .cd-date{color:var(--text-mut);text-transform:none;}
.projtable th.sortable{cursor:pointer;}
.projtable th.sorted{color:var(--acid);}
.projtable .arr{color:var(--acid);font-size:var(--fs-1);margin-left:3px;}
.tiny.soon{color:var(--warn-ink);}.tiny.past{color:var(--crit-ink);}.tiny.ok{color:var(--ok-ink);}
.cs-tag{font-size:var(--fs-1);padding:0 6px 0 5px;min-height:18px;}

/* ---- roles matrix ----------------------------------------------------------------- */
.dept-panel{margin-bottom:var(--space-5);}

/* ---- invoices board bits ---------------------------------------------------------- */
.stage-tag{display:inline-block;margin-left:2px;font:600 var(--fs-1)/1 var(--sans);letter-spacing:.02em;text-transform:none;
  border:1px solid var(--line);background:var(--bg-raised);color:var(--text-mut);padding:3px 6px;border-radius:var(--r-sm);vertical-align:1px;}
.tag-fetch{display:inline-block;margin-left:6px;font:600 var(--fs-1)/1 var(--sans);letter-spacing:.02em;text-transform:none;
  background:var(--acid-glow);color:var(--acid);border:1px solid color-mix(in srgb,var(--acid) 35%,transparent);padding:3px 7px;border-radius:var(--r-full);vertical-align:1px;}
.docs{white-space:nowrap;}
.doclink{display:inline-flex;align-items:center;min-height:24px;font:500 var(--fs-2)/1 var(--sans);text-transform:none;letter-spacing:0;
  border:1px solid var(--line-strong);border-radius:var(--r-sm);color:var(--text-hi);background:var(--bg-base);padding:0 9px;margin-right:5px;}
.doclink:hover{border-color:var(--acid);color:var(--acid);}
.doclink.ack{border-color:color-mix(in srgb,var(--ok) 40%,var(--bg-base));color:var(--ok-ink);background:color-mix(in srgb,var(--ok) 6%,var(--bg-base));}
.rowform{display:flex;align-items:center;gap:6px;margin:0;}
.filebtn{display:inline-flex;align-items:center;min-height:24px;font:500 var(--fs-2)/1 var(--sans);text-transform:none;letter-spacing:0;
  border:1px dashed var(--line-strong);color:var(--text-mut);padding:0 9px;cursor:pointer;white-space:nowrap;border-radius:var(--r-sm);}
.filebtn:hover{border-color:var(--acid);color:var(--acid);}
.note{margin-top:var(--space-4);font:400 var(--fs-3)/1.5 var(--sans);color:var(--text-mut);}

/* ---- pricing ---------------------------------------------------------------------- */
/* a total is a figure, not a link: cobalt is for actions and selection */
.ratecard .total{color:var(--text-hi);font-weight:600;}
.ratecard .pct{font:500 var(--fs-1)/1 var(--mono);color:var(--text-mut);}
/* the period a figure is for (ADR-0042): under a heading that says it for the column,
   beside a figure in a panel that mixes periods */
.ratecard .per{font:400 var(--fs-1)/1.2 var(--sans);color:var(--text-mut);white-space:nowrap;}
.ratecard th .per{display:block;margin-top:2px;}
/* every category's table on one grid (ADR-0035): each money column has one share of the
   width, the edit link what it needs, the plan the rest - so the panels' columns line up
   down the page while there is room; a phone scrolls each table sideways as before. The
   total has the widest share - in a panel that mixes periods it says "one-time" beside
   six figures - the month and the one-time charge less (measured in Chrome on the rate
   card with its periods: one grid from 1,280px up) */
table.ratecard > thead th.num{width:11.5%;}
table.ratecard > thead th.rc-total{width:13.5%;}
table.ratecard > thead th.rc-month{width:10%;}
table.ratecard > thead th.rc-once{width:9%;}
table.ratecard > thead th:last-child{width:1%;}

kbd{font:500 var(--fs-1)/1 var(--sans);background:var(--bg-base);border:1px solid var(--line-strong);border-bottom-width:2px;
  padding:2px 5px;color:var(--text);border-radius:var(--r-sm);}

/* ---- console drawer (Ctrl+`) ---------------------------------------------------- */
.console{position:fixed;left:0;right:0;bottom:0;z-index:70;height:240px;background:var(--bg-overlay);border-top:1px solid var(--line-strong);
  display:flex;flex-direction:column;box-shadow:0 -8px 28px -8px var(--shade);}
.console-head{display:flex;align-items:center;gap:var(--space-2);padding:9px var(--space-4);border-bottom:1px solid var(--line);
  font:600 var(--fs-3)/1 var(--sans);letter-spacing:0;text-transform:none;color:var(--text-hi);background:var(--bg-raised);}
.console-head .led{margin-right:2px;}
.console-head .x{margin-left:auto;display:grid;place-items:center;width:26px;height:26px;border:0;border-radius:var(--r);background:none;cursor:pointer;color:var(--text-mut);font:400 var(--fs-3)/1 var(--sans);}
.console-head .x:hover{background:var(--bg-base);color:var(--crit-ink);}
.console-body{flex:1;overflow:auto;padding:10px var(--space-4);font:400 var(--fs-2)/1.7 var(--mono);}
.logline{color:var(--text);white-space:pre-wrap;}
.logline .t{color:var(--text-mut);}
.logline .lv-ok{color:var(--ok-ink);}.logline .lv-info{color:var(--info-ink);}.logline .lv-warn{color:var(--warn-ink);}.logline .lv-crit{color:var(--crit-ink);}
.logline.fresh{animation:slidein .22s ease;}
@keyframes slidein{from{opacity:0;transform:translateX(-8px);}to{opacity:1;transform:translateX(0);}}

/* ---- the on-site probe bar (Infrastructure tab) ------------------------------------ */
.probe-bar{display:block;padding:12px var(--space-4) 10px;
  margin-bottom:var(--space-4);border-radius:var(--r-lg);border:1px solid var(--line);background:var(--bg-base);
  box-shadow:var(--shadow-1);font:400 var(--fs-3)/1.45 var(--sans);color:var(--text);}
.probe-bar > b{display:inline-flex;align-items:center;gap:7px;margin-right:4px;font-weight:600;color:var(--ok-ink);}
.probe-bar > b::before{content:'';width:8px;height:8px;border-radius:50%;background:var(--ok);}
.probe-bar.down{background:color-mix(in srgb,var(--crit) 6%,var(--bg-base));border-color:color-mix(in srgb,var(--crit) 32%,var(--bg-base));}
.probe-bar.down > b{color:var(--crit-ink);}
.probe-bar.down > b::before{background:var(--crit);box-shadow:0 0 0 3px color-mix(in srgb,var(--crit) 22%,transparent);}
.probe-bar.warn{background:color-mix(in srgb,var(--warn) 6%,var(--bg-base));border-color:color-mix(in srgb,var(--warn) 34%,var(--bg-base));}
.probe-bar.warn > b{color:var(--warn-ink);}
.probe-bar.warn > b::before{background:var(--warn);}
/* nothing is being checked - every device paused: the probes have nothing to do, and the
   bar says so in no colour (amended 2026-10-08) */
.probe-bar.idle > b{color:var(--text-hi);}
.probe-bar.idle > b::before{background:transparent;box-shadow:inset 0 0 0 1.5px var(--idle);}
/* the Microsoft 365 sync's last run (Users): its state, when, and what it did */
.sync-bar{display:flex;flex-wrap:wrap;align-items:baseline;gap:4px var(--space-4);padding-bottom:12px;}
.sync-bar > b{margin-right:0;}
.sync-what{color:var(--text-mut);}
.probe-bar .agent{display:inline-flex;align-items:center;gap:7px;margin:2px 6px 2px 0;padding:3px 10px;border-radius:var(--r-full);
  background:var(--bg-raised);border:1px solid var(--line);font:400 var(--fs-2)/1.3 var(--mono);color:var(--text);}
.probe-bar > b + .agent,.probe-bar .agent:first-of-type{margin-left:10px;}
.probe-bar .agent.off{color:var(--crit-ink);border-color:color-mix(in srgb,var(--crit) 30%,var(--bg-base));}
/* silent, with nothing to check: grey, not down */
.probe-bar .agent.idle{color:var(--text-mut);border-style:dotted;}
/* a site whose checked devices no probe reads (ADR-0039): said under the probes, in no colour */
.probe-bar .probe-gap{display:block;margin-top:6px;color:var(--text-mut);}
/* on a phone a chip's words wrap as words, not as three boxes side by side */
@media (max-width:640px){.probe-bar .agent{display:inline-block;max-width:100%;}.probe-bar .agent .led{margin-right:4px;}}
/* the probe's id, site and version are data; how long ago it was seen is words */
.probe-bar .agent-age{font-family:var(--sans);}
/* ---- the checks bar (Infrastructure tab, ADR-0036, amended 2026-10-08) ---------------
   Each group's one control - the network gear, then CCTV - under the tiles: a group whose
   checks are paused is a line of the one notice, with Resume under it; a group being
   checked is a row of its own, its name and its buttons. */
.checks-bar-lbl{padding:0 4px 0 2px;font:600 var(--fs-3)/1 var(--sans);color:var(--text-hi);}
.checks-line > p{margin:0;}
.checks-line + .checks-line{margin-top:var(--space-3);padding-top:var(--space-3);
  border-top:1px solid color-mix(in srgb,var(--info) 20%,var(--bg-base));}
/* a row of its own, never the filter bar's two columns on a narrow screen (a button half
   a phone wide ran off its edge): on a phone the name takes a line and each button the
   width, so the page never scrolls sideways */
.checks-group .filters{display:flex;}
@media (max-width:640px){
  .checks-bar-lbl{flex-basis:100%;padding:2px 2px 0;}
  .checks-group .filters > form{flex:1 1 auto;}
  .checks-group .filters .btn-ghost{width:100%;}
  .checks-line .btn-ghost{width:100%;}
}
/* the floor heading's count says up to five things: on a narrow screen it wraps between
   them, never inside one (each part is .nowrap), and squares off to hold two lines */
.floor-head .floor-count.infra-count{white-space:normal;line-height:1.35;}
@media (max-width:640px){.floor-head .floor-count.infra-count{border-radius:var(--r);}}

/* ---- motion, all of it small ------------------------------------------------------ */
/* a line whose status flipped on the last recheck gets one accent flash, then settles */
tbody tr.flash-row{animation:rowflash 1.6s ease-out;}
@keyframes rowflash{from{background-color:var(--acid-glow);}}
/* SLA-24h uptime bar shown on hovering a line's status pill (sla-hover.js) */
.pill[data-uptime24]{cursor:help;}
.sla-tip{z-index:200;background:var(--bg-overlay);border:1px solid var(--line);border-radius:var(--r);padding:8px 10px;
  box-shadow:var(--shadow-3);pointer-events:none;display:none;}
.sla-tip-bars{display:flex;gap:1px;height:18px;align-items:stretch;}
.sla-tip-bars i{width:3px;border-radius:1px;display:block;}
.sla-tip-lbl{font:500 var(--fs-1)/1.3 var(--sans);color:var(--text-mut);margin-top:6px;letter-spacing:0;text-transform:none;white-space:nowrap;}
/* loading: a button that has been pressed for a slow job, and a placeholder block */
[aria-busy="true"]{cursor:progress;}
.btn-blaze[aria-busy="true"],.btn-ghost[aria-busy="true"]{pointer-events:none;opacity:.85;}
.btn-blaze[aria-busy="true"]::before,.btn-ghost[aria-busy="true"]::before,.spinner{content:'';display:inline-block;flex:none;
  width:14px;height:14px;border-radius:50%;border:2px solid currentColor;border-right-color:transparent;animation:spin .7s linear infinite;}
@keyframes spin{to{transform:rotate(360deg);}}
/* the spinner takes the place of the button's own icon */
.btn-blaze[aria-busy="true"] .i,.btn-ghost[aria-busy="true"] .i{display:none;}

/* ---- reduced motion ---------------------------------------------------------------- */
@media (prefers-reduced-motion:reduce){
  *,*::before,*::after{animation:none !important;transition:none !important;}
}

/* ===========================================================================
   Inline quick-create - the "+" beside a foreign-key dropdown, and its dialog.
   Creates a Location/Floor/Vendor without leaving the form that needs it.
   =========================================================================== */
.qc-row{display:flex;gap:6px;align-items:stretch;}
.qc-row > select{flex:1 1 auto;min-width:0;}
/* the same box as the dropdown it sits beside: field fill, field edge, control height */
.qc-add{flex:0 0 auto;width:var(--ctl-h);min-height:var(--ctl-h);display:inline-flex;align-items:center;justify-content:center;
  background:var(--bg-base);border:1px solid var(--field-line);color:var(--acid);
  border-radius:var(--r);font:500 var(--fs-5)/1 var(--sans);cursor:pointer;
  transition:background var(--dur-fast) var(--ease),border-color var(--dur-fast) var(--ease),color var(--dur-fast) var(--ease);}
.qc-add:hover{background:var(--acid-glow);border-color:var(--acid);color:var(--acid);}
.qc-add:active{transform:translateY(1px);}
/* the picture of the button in a sentence (Reference) is text-sized */
.qc-add-inline{width:auto;min-height:0;padding:1px 5px;font-size:var(--fs-2);display:inline-flex;vertical-align:1px;}

/* ---- modal dialog ------------------------------------------------------------------ */
.qc-backdrop{position:fixed;inset:0;z-index:1000;display:flex;align-items:center;justify-content:center;
  padding:var(--space-5);background:var(--scrim);backdrop-filter:blur(2px);}
.qc-backdrop[hidden]{display:none;}
.qc-dialog{width:min(460px,100%);max-height:86vh;overflow:auto;background:var(--bg-overlay);
  border:1px solid var(--line);border-radius:12px;box-shadow:var(--shadow-4);}
.qc-head{display:flex;align-items:center;justify-content:space-between;gap:var(--space-3);
  padding:var(--space-4) 20px;border-bottom:1px solid var(--line);}
.qc-head h2{margin:0;font:600 var(--fs-5)/1.3 var(--sans);letter-spacing:-.005em;text-transform:none;color:var(--text-hi);}
.qc-close{display:grid;place-items:center;width:30px;height:30px;background:none;border:none;border-radius:var(--r);
  color:var(--text-mut);font-size:20px;line-height:1;cursor:pointer;}
.qc-close:hover{background:var(--bg-raised);color:var(--text-hi);}
.qc-body{padding:20px;display:flex;flex-direction:column;gap:var(--space-4);}
.qc-actions{display:flex;justify-content:flex-end;gap:var(--space-2);padding:14px 20px;
  border-top:1px solid var(--line);background:var(--bg-raised);border-radius:0 0 12px 12px;}

/* ---- Reference: buildings and floors side by side, vendors under them; each card is a
   panel holding a table.lines. Two columns, not auto-fill: from 1320px auto-fill made a
   third, empty one and squeezed the floors table into a sideways scroll. ---- */
.ref-grid{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:var(--space-4);align-items:start;}
.ref-grid > .panel{margin:0;}
/* vendors are the long list with the long names: a card the width of the grid */
.ref-grid > .ref-wide{grid-column:1 / -1;}

/* ---- internal subnets (ADR-0027): a row that overlaps another floor's is marked at its
   edge, as a deleted audit row is, and the overlaps are listed in the warning above ---- */
table.subnet-table tr.clash td:first-child{box-shadow:inset 3px 0 0 var(--crit);}
table.subnet-table .pill{margin-left:6px;}
.clash-list{margin:var(--space-2) 0 0;padding-left:1.2em;}
.clash-list li{margin:2px 0;}

/* Global message region - every page shows what it tells you. */
.flash-region{display:flex;flex-direction:column;gap:var(--space-2);margin:0 0 var(--space-5);}
.flash-region:empty{display:none;}
.flash-region > .flash{margin:0;}

/* ---- pagination --------------------------------------------------------------------- */
.pager{display:flex;align-items:center;justify-content:space-between;gap:var(--space-4);flex-wrap:wrap;
  padding:0 2px;margin:calc(var(--space-2) * -1) 0 var(--space-5);
  font:400 var(--fs-3)/1 var(--sans);color:var(--text-mut);}
.pager-links{display:flex;align-items:center;gap:6px;flex-wrap:wrap;}
.pager-links > a,.pager-links > .dim{display:inline-flex;align-items:center;height:32px;padding:0 12px;border-radius:var(--r);
  font:500 var(--fs-3)/1 var(--sans);border:1px solid var(--line-strong);background:var(--bg-base);}
.pager-links > a{color:var(--text-hi);box-shadow:var(--shadow-1);text-decoration:none;}
.pager-links > a:hover{background:var(--bg-raised);border-color:var(--field-line);color:var(--text-hi);}
.pager-links > a:focus-visible{box-shadow:0 0 0 2px var(--bg-base),0 0 0 4px var(--acid);}   /* its shadow outranks the ring */
.pager-links > .dim{color:var(--text-ghost);border-color:var(--line);background:transparent;}
.pager-at{padding:0 var(--space-2);font:500 var(--fs-3)/1 var(--sans);color:var(--text);white-space:nowrap;}

code{font-family:var(--mono);font-size:.9em;padding:1px 5px;border-radius:var(--r-sm);
  background:var(--bg-raised);border:1px solid var(--line);color:var(--text-hi);}
/* ---- empty and error states --------------------------------------------------------
   One pattern: an icon in a soft circle, a title, one sentence, at most one action.
   The glyph span is empty in the markup; the icon is drawn here. A span that does
   hold text (an error code) shows the text instead. */
.empty{padding:var(--space-8) var(--space-5);text-align:center;}
.empty .empty-glyph{display:inline-grid;place-items:center;width:48px;height:48px;margin-bottom:14px;border-radius:50%;
  background:var(--bg-raised);border:1px solid var(--line);color:var(--text-mut);
  font:600 var(--fs-3)/1 var(--mono);letter-spacing:0;}
.empty .empty-glyph:empty::before{content:'';width:22px;height:22px;background:currentColor;
  -webkit-mask:no-repeat center/contain url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='1.8' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M3 13h5l1.5 3h5L16 13h5'/%3E%3Cpath d='M5.5 5.5h13L21 13v5a1.5 1.5 0 0 1-1.5 1.5h-15A1.5 1.5 0 0 1 3 18v-5z'/%3E%3C/svg%3E");
  mask:no-repeat center/contain url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='1.8' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M3 13h5l1.5 3h5L16 13h5'/%3E%3Cpath d='M5.5 5.5h13L21 13v5a1.5 1.5 0 0 1-1.5 1.5h-15A1.5 1.5 0 0 1 3 18v-5z'/%3E%3C/svg%3E");}
.empty h3{margin:0 0 6px;font:600 var(--fs-5)/1.35 var(--sans);color:var(--text-hi);}
.empty p{margin:0 auto var(--space-4);max-width:52ch;font:400 var(--fs-4)/1.55 var(--sans);color:var(--text-mut);}
.empty p:last-child{margin-bottom:0;}
.empty .btn-blaze,.empty .btn-ghost{display:inline-flex;}
/* a smaller one, for a panel that shares its row or a card of a few rows */
.empty.compact{padding:var(--space-6) var(--space-5);}
.empty.compact .empty-glyph{width:40px;height:40px;margin-bottom:10px;}
.empty.is-error .empty-glyph,.empty.is-off .empty-glyph{background:color-mix(in srgb,var(--crit) 8%,var(--bg-base));
  border-color:color-mix(in srgb,var(--crit) 28%,var(--bg-base));color:var(--crit-ink);}
.empty.is-off .empty-glyph{background:color-mix(in srgb,var(--warn) 9%,var(--bg-base));
  border-color:color-mix(in srgb,var(--warn) 30%,var(--bg-base));color:var(--warn-ink);}
.empty .empty-actions{display:flex;justify-content:center;gap:var(--space-2);flex-wrap:wrap;}
/* a page that is switched off gets a pause mark, not an empty tray */
.empty.is-off .empty-glyph:empty::before{
  -webkit-mask-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2' stroke-linecap='round'%3E%3Ccircle cx='12' cy='12' r='9'/%3E%3Cpath d='M10 9v6M14 9v6'/%3E%3C/svg%3E");
  mask-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2' stroke-linecap='round'%3E%3Ccircle cx='12' cy='12' r='9'/%3E%3Cpath d='M10 9v6M14 9v6'/%3E%3C/svg%3E");}

/* ---- Internet spend (ADR-0034) ---------------------------------------------------
   What the internet costs, for a manager in thirty seconds: five tiles, then four
   tables whose money lines up on the right, a bar beside every share, totals that read
   as totals, and "not recorded" in amber wherever a cost is missing - never a zero.
   Printed, it is one A4 landscape document (the print block at the end). */
/* the headline figure is the widest: a crore in lakh grouping is twelve characters */
.spend-kpis{grid-template-columns:minmax(0,1.4fr) repeat(4,minmax(0,1fr));}
.kpi-sub{font:400 var(--fs-2)/1.35 var(--sans);color:var(--text-mut);}
.kpi-sub .mono{font-size:inherit;color:var(--text);}
.spend-unpriced-list{display:flex;flex-wrap:wrap;gap:4px 16px;margin-top:6px;font:500 var(--fs-3)/1.5 var(--sans);}
.spend-unpriced-list a span{font-weight:400;color:var(--text-mut);}
.spend-none{font:italic 400 var(--fs-3)/1.3 var(--sans);color:var(--warn-ink);white-space:nowrap;}
.cell-sub.spend-none{font-size:var(--fs-2);}
/* what a total's per Mbps is over, where that is less than the row's bandwidth (ARC and speed both recorded) */
table.lines td .spend-basis{display:block;margin-top:1px;font:400 var(--fs-2)/1.3 var(--sans);color:var(--text-mut);white-space:normal;text-wrap:balance;}
/* a share: a bar as long as its part of the whole, then the figure */
.spend-share{display:flex;align-items:center;gap:10px;min-width:170px;}
.spend-bar{flex:1 1 auto;display:block;min-width:72px;height:8px;border-radius:var(--r-full);background:var(--bg-void);overflow:hidden;}
.spend-bar > i{display:block;height:100%;border-radius:var(--r-full);background:var(--acid);}
.spend-share .mono{flex:none;min-width:3.6em;text-align:right;font-size:var(--fs-3);color:var(--text-hi);}
table.lines th.spend-share-h{min-width:190px;}
.panel-head > .spend-more{margin-right:-6px;}
/* By building: a building opens to its floors */
.spend-toggle{display:inline-flex;align-items:baseline;gap:8px;margin:-2px -4px;padding:2px 4px;background:none;border:0;
  border-radius:var(--r-sm);font:inherit;color:var(--text-hi);text-align:left;cursor:pointer;}
.spend-toggle::before{content:'';flex:none;align-self:center;width:7px;height:7px;border:solid var(--text-mut);
  border-width:0 1.75px 1.75px 0;transform:rotate(-45deg);transition:transform var(--dur) var(--ease);}
.spend-toggle[aria-expanded="true"]::before{transform:translateY(-2px) rotate(45deg);}
.spend-toggle:hover::before{border-color:var(--text-hi);}
.spend-toggle b{white-space:nowrap;}
.spend-toggle .dim{font-size:var(--fs-3);}
table.lines tr.spend-floor-row td{background:var(--bg-raised);padding-top:8px;padding-bottom:8px;font-size:var(--fs-3);}
table.lines tr.spend-floor-row td:first-child{padding-left:43px;}
/* Every line: a floor is named once, on the first of its lines */
table.lines td.spend-floor{font:600 var(--fs-3)/1.3 var(--sans);color:var(--text-hi);}
table.lines tr.spend-floor-first > td{border-top:1px solid var(--line);}
.spend-bldg-name{font-weight:400;color:var(--text-mut);}
table.lines td.spend-worked{font-size:var(--fs-2);white-space:nowrap;}
/* a circuit breaks at its spaces ("LSI-241224100098578 / RA 2116422"), not after its
   hyphen; the two long headings give it the room */
table.lines td.spend-circuit{min-width:11.5rem;}
table.lines th.spend-wrap-h{min-width:5.5rem;white-space:normal;}
/* subtotals and totals read as sums */
table.lines tr.spend-subtotal td{background:var(--bg-raised);border-top:1px solid var(--line);font-weight:600;color:var(--text-hi);}
table.lines tr.spend-total td{background:var(--bg-raised);border-top:2px solid var(--line-strong);border-bottom:0;font-weight:700;color:var(--text-hi);}
/* Leased Lines: a building's yearly total opens its lines on Internet spend */
.loc-spend{color:inherit;border-bottom:1px dotted var(--text-ghost);}
.loc-spend:hover{color:var(--acid);border-bottom-color:var(--acid);}
/* Including GST: a vendor whose ARC is not confirmed to exclude GST is named above its
   table, inside the card */
.spend-gst-warn{margin:var(--space-3) 20px;font-size:var(--fs-3);}
@media (min-width:820.02px) and (max-width:1179.98px){
  .spend-kpis,.it-kpis,.ov-kpis{grid-template-columns:repeat(3,minmax(0,1fr));}
  .spend-kpis .kpi-wide,.it-kpis .kpi-wide,.ov-kpis .kpi-wide{grid-column:span 2;}
}

/* ---- IT spend, Licences, IT overview (ADR-0038) ------------------------------------
   Internet spend's components, for every IT cost: the same tiles, the same ruled tables
   with money on the right and a bar beside every share, "not recorded" in amber where a
   price is missing. The overview is the management page: five tiles, then a grid of
   cards that prints as one A4 landscape sheet (the print block at the end). */
.it-kpis,.ov-kpis{grid-template-columns:minmax(0,1.4fr) repeat(4,minmax(0,1fr));}
.it-missing p + p{margin-top:6px;}
/* a table's paise (|inr_paise): there so a column adds to its total, quieter than the rupees */
.paise{opacity:.6;}
.it-derived,.it-source{border-bottom:1px dotted var(--text-ghost);cursor:help;}
table.lines td .it-change{color:var(--warn-ink);}
table.lines td.it-what{min-width:14rem;max-width:30rem;white-space:normal;font-size:var(--fs-3);}
/* IT spend's quantity and price share a cell; on its row editor, the two inputs stack */
table.lines td.it-qty{white-space:nowrap;}
table.lines td.it-qty-edit .cell-input{margin-top:4px;}
.it-events{list-style:none;margin:0;padding:4px 20px 10px;}
.it-event{display:flex;gap:16px;padding:8px 0;border-bottom:1px solid var(--line-faint);font:400 var(--fs-3)/1.45 var(--sans);color:var(--text);}
.it-event:last-child{border-bottom:0;}
.it-event b{color:var(--text-hi);}
.it-when{flex:none;min-width:7.5em;color:var(--text-mut);}
.it-event.warn .it-when{color:var(--warn-ink);}
.it-event.off{color:var(--text-mut);}
/* Licences */
.lic-idle{color:var(--warn-ink);}
/* the licence panel on Users (ADR-0038, amended 2026-10-09): one compact row per paid
   licence - its name, then the figures as a row of small label-over-value pairs that wraps
   on a phone - so the directory stays the page */
.lic-note{margin:0;padding:10px 20px;border-bottom:1px solid var(--line-faint);font:400 var(--fs-3)/1.45 var(--sans);color:var(--warn-ink);}
.lic-rows{list-style:none;margin:0;padding:0;}
.lic-row{display:flex;flex-wrap:wrap;align-items:center;gap:8px 24px;padding:12px 20px;}
.lic-row + .lic-row{border-top:1px solid var(--line-faint);}
.lic-name{flex:1 1 15rem;min-width:0;font:400 var(--fs-4)/1.35 var(--sans);color:var(--text-hi);}
.lic-name b{font-weight:600;}
.lic-flag{display:block;margin-top:2px;font-size:var(--fs-2);color:var(--warn-ink);}
.lic-figs{display:flex;flex-wrap:wrap;gap:6px 22px;margin:0;}
.lic-figs > div{display:flex;flex-direction:column;gap:1px;min-width:3.5rem;}
.lic-figs dt{font:500 var(--fs-1)/1.3 var(--sans);letter-spacing:.04em;text-transform:uppercase;color:var(--text-mut);}
.lic-figs dd{margin:0;font-size:var(--fs-4);color:var(--text-hi);}
.lic-figs dd a{color:inherit;text-decoration:underline;text-decoration-color:var(--line-strong);text-underline-offset:3px;}
.lic-sub{display:block;font:400 var(--fs-1)/1.3 var(--sans);color:var(--text-mut);}
.lic-who{margin-left:auto;}
.lic-none{color:var(--text-mut);font:400 var(--fs-3)/1.45 var(--sans);}
/* IT overview: twelve columns - the money wide beside the network, then three cards */
.ov-grid{display:grid;grid-template-columns:repeat(12,minmax(0,1fr));gap:var(--space-4);}
.ov-grid > .panel{min-width:0;margin-bottom:0;}
.ov-money{grid-column:span 7;}
.ov-network{grid-column:span 5;}
.ov-estate,.ov-licences,.ov-items{grid-column:span 4;}
/* a bar per area and per vendor, on one scale - the share of the whole - with its figure
   and its share written beside it, so nothing is read from a length alone */
.ov-bars{display:grid;gap:12px;padding:14px 20px;}
.ov-bars-tight{gap:8px;padding-top:8px;}
.ov-bar{display:grid;grid-template-columns:minmax(8rem,12.5rem) minmax(0,1fr) minmax(6.5rem,auto) 3.6em;align-items:center;gap:12px;}
.ov-bar-name{min-width:0;font:500 var(--fs-3)/1.3 var(--sans);color:var(--text-hi);}
.ov-bar-what{display:block;font:400 var(--fs-2)/1.35 var(--sans);color:var(--text-mut);}
.ov-bar-track{display:block;height:12px;border-radius:2px;background:var(--bg-void);overflow:hidden;}
.ov-bars-tight .ov-bar-track{height:8px;}
.ov-bar-track > i{display:block;height:100%;min-width:2px;border-radius:0 4px 4px 0;background:var(--acid);}
.ov-bar-rest .ov-bar-track > i{background:color-mix(in srgb,var(--acid) 45%,var(--bg-void));}
.ov-bar-val{font-size:var(--fs-3);color:var(--text-hi);text-align:right;white-space:nowrap;}
.ov-bar-share{font-size:var(--fs-3);color:var(--text-mut);text-align:right;}
.ov-sub{margin:0;padding:6px 20px 0;border-top:1px solid var(--line-faint);font:600 var(--fs-2)/2 var(--sans);color:var(--text-mut);}
.ov-facts{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:12px 16px;margin:0;padding:14px 20px;}
.ov-facts dt{font:400 var(--fs-2)/1.3 var(--sans);color:var(--text-mut);}
.ov-facts dd{margin:3px 0 0;font-size:var(--fs-5);color:var(--text-hi);}
.ov-crit{color:var(--crit-ink) !important;}
.ov-warn{color:var(--warn-ink);}
table.lines.ov-table{border-top:1px solid var(--line-faint);}
.ov-kinds{list-style:none;display:flex;flex-wrap:wrap;gap:6px 18px;margin:0;padding:14px 20px 8px;font:400 var(--fs-3)/1.4 var(--sans);color:var(--text);}
.ov-kinds .mono{color:var(--text-hi);font-weight:600;}
.ov-note{margin:0;padding:8px 20px 0;font:400 var(--fs-2)/1.45 var(--sans);color:var(--text-mut);}
.ov-list{list-style:none;margin:0;padding:6px 20px 12px;}
.ov-item{display:flex;align-items:baseline;gap:10px;padding:7px 0;border-bottom:1px solid var(--line-faint);font:400 var(--fs-3)/1.45 var(--sans);color:var(--text);}
.ov-item:last-child{border-bottom:0;}
.ov-item .led{transform:translateY(-1px);}
.ov-item a{color:inherit;border-bottom:1px dotted var(--text-ghost);}
.ov-item a:hover{color:var(--acid);border-bottom-color:var(--acid);}
/* ---- Billing (ADR-0040) ------------------------------------------------------------
   IT spend's tiles and ruled tables; a period's status is a pill on the one status scale -
   paid green, received blue, awaited amber, not received and overdue red, upcoming with a
   dashed edge, not billed dotted - and the year is a calendar: a row per subscription, a
   cell per month, a period's pill in the month it starts and a rule through the months a
   longer one runs on. The calendar scrolls inside its card on a narrow screen. */
.pill.bill-paid{--tone:var(--ok);--tone-ink:var(--ok-ink);}
.pill.bill-received{--tone:var(--info);--tone-ink:var(--info-ink);}
.pill.bill-awaiting{--tone:var(--warn);--tone-ink:var(--warn-ink);}
.pill.bill-missing,.pill.bill-overdue{--tone:var(--crit);--tone-ink:var(--crit-ink);}
.pill.bill-upcoming{border-style:dashed;}
.pill.bill-upcoming::before{background:transparent;box-shadow:inset 0 0 0 1.5px var(--tone);}
.pill.bill-skipped{background:transparent;border-style:dotted;border-color:var(--line-strong);color:var(--text-mut);}
.pill.bill-skipped::before{background:transparent;box-shadow:inset 0 0 0 1.5px var(--idle);}
table.lines tr.bill-look td{background:color-mix(in srgb,var(--warn) 6%,var(--bg-base));}
table.lines td .bill-why{color:var(--warn-ink);white-space:normal;}
table.lines td .bill-note{white-space:normal;max-width:36rem;}
/* a figure billed in another currency, under its rupees (ADR-0040): "USD 23.54 · ₹95.3364 a
   dollar, the invoice's rate" wraps under the amount rather than widen its column */
table.lines td .it-foreign{white-space:normal;min-width:10rem;max-width:14rem;color:var(--text-mut);
  font:400 var(--fs-2)/1.35 var(--sans);}
table.lines td.num .it-foreign{margin-left:auto;}
table.lines td.bill-act{width:17.5rem;min-width:15rem;white-space:normal;}
table.lines td.bill-act .bill-form{display:flex;flex-wrap:wrap;align-items:center;justify-content:flex-end;gap:6px;}
table.lines td.bill-act .bill-form>*+*{margin-left:0;}
table.lines td.bill-act .bill-form+.bill-form{margin:4px 0 0;}
.cell-input.bill-on{width:7.4em;}
.bill-nav{display:flex;flex-wrap:wrap;align-items:center;gap:6px 16px;font-size:var(--fs-3);}
table.lines.bill-cal{min-width:1100px;table-layout:fixed;}
table.lines.bill-cal .bill-cal-name{width:16rem;text-align:left;vertical-align:top;font-weight:400;white-space:normal;}
table.lines.bill-cal .bill-name{display:block;font:600 var(--fs-3)/1.3 var(--sans);color:var(--text-hi);}
table.lines.bill-cal .bill-how{color:var(--text);}
table.lines.bill-cal th.bill-cal-m{text-align:center;padding-left:3px;padding-right:3px;}
.bill-m{display:block;}
.bill-y{display:block;font-size:var(--fs-1);font-weight:400;color:var(--text-ghost);}
table.lines.bill-cal td.bill-cell{padding:7px 3px;text-align:center;vertical-align:top;}
table.lines.bill-cal .bill-now-m{background:var(--acid-glow);}
.pill.bill-chip{display:inline-flex;flex-direction:column;align-items:center;gap:2px;width:100%;max-width:6.6rem;
  min-height:0;padding:4px 3px;border-radius:var(--r);white-space:normal;line-height:1.15;}
.pill.bill-chip::before{display:none;}
.bill-st{font-size:var(--fs-1);}
.bill-amt{font-size:var(--fs-1);font-weight:500;color:var(--text-hi);}
.bill-extra{font-size:10px;font-weight:400;color:var(--text-mut);}
.bill-cover{display:block;height:2px;margin:16px 0 0;border-radius:1px;background:var(--line-strong);}
table.lines.bill-cal tr.bill-off .bill-name{color:var(--text-mut);}
.bill-legend{margin:0;padding:10px 20px 14px;font:400 var(--fs-2)/2.1 var(--sans);color:var(--text-mut);}
@media (max-width:1179.98px){
  .ov-money,.ov-network,.ov-items{grid-column:1 / -1;}
  .ov-estate,.ov-licences{grid-column:span 6;}
}

/* Floors fold away (Leased Lines, Infrastructure): the summary is the floor header, with a chevron
   that says so - down while open, turned to point right while folded. (The bar is
   display:flex, so the browser draws no disclosure marker of its own.) */
details.floor-group > summary.floor-head{list-style:none;cursor:pointer;user-select:none;}
details.floor-group > summary.floor-head::-webkit-details-marker{display:none;}
details.floor-group > summary.floor-head::before{content:'';flex:none;width:7px;height:7px;margin:0 3px 0 1px;
  border:solid var(--text-mut);border-width:0 1.75px 1.75px 0;transform:translateY(-2px) rotate(45deg);
  transition:transform var(--dur) var(--ease);}
details.floor-group:not([open]) > summary.floor-head::before{transform:rotate(-45deg);}
details.floor-group > summary.floor-head:hover{background:color-mix(in srgb,var(--bg-void) 45%,var(--bg-raised));}
details.floor-group > summary.floor-head:hover::before{border-color:var(--text-hi);}
details.floor-group > summary.floor-head:focus-visible{box-shadow:inset 0 0 0 2px var(--acid);}
details.floor-group:not([open]) > summary.floor-head{border-bottom-color:transparent;}

/* --- Editing a line in its own row (Network board) -------------------------
   A wrong WAN IP is spotted on the board, so it is corrected on the board. The
   open row keeps its measured columns as text and turns the typed ones into
   inputs; the <form> itself sits outside the table (HTML forbids one inside). */
table.lines tr.row-edit{background:color-mix(in srgb,var(--acid) 5%,var(--bg-base));}
table.lines tr.row-edit:hover{background:color-mix(in srgb,var(--acid) 5%,var(--bg-base));}
table.lines tr.row-edit td{padding:var(--space-2) 6px;vertical-align:top;border-bottom-color:color-mix(in srgb,var(--acid) 25%,var(--bg-base));}
table.lines tr.row-edit td > .pill{margin-top:3px;}
/* a row of inputs must still fit a laptop: the open table tightens up */
table.lines:has(tr.row-edit) :is(th,td):not(:first-child):not(:last-child){padding-left:8px;padding-right:8px;}
table.lines tr.row-edit td:first-child{box-shadow:inset 3px 0 0 var(--acid);padding-left:20px;}
table.lines tr.row-edit td:last-child{padding-right:20px;}
.cell-input{min-height:var(--ctl-h-sm);font:400 var(--fs-2)/1.3 var(--mono);background:var(--bg-base);color:var(--text-hi);
  border:1px solid var(--field-line);border-radius:var(--r);padding:4px 6px;max-width:100%;box-sizing:border-box;}
.cell-input:focus{border-color:var(--acid);box-shadow:var(--ring);outline:none;}
.cell-input[type=number]{width:4.5em;}
.cell-input[name="annual_cost"]{width:6em;}   /* rupees a year: seven digits */
/* the line's name is a name, not an address: the interface face, like the cell it
   replaces, and as wide as the Line column the other rows have made (never under 7.5rem) */
.cell-input[name="label"]{font-family:var(--sans);font-size:var(--fs-3);width:100%;min-width:7.5rem;}
/* The circuit fills its column (at size="14" an id lost its end at every width). It is free
   text of any length, so where the table is tight (KP at 1280px) it gives up width first,
   and on a wide screen it asks for as much as it holds, up to 22rem (field-sizing would
   make it that wide at 1280px too, pushing DD's table 53px sideways). The LAN pool that
   stood beside it left the board with ADR-0027; a floor's subnets are on its band. */
.cell-input[name="circuit_id"]{width:100%;min-width:6rem;}
@media (min-width:1800px){.cell-input[name="circuit_id"]{field-sizing:content;max-width:22rem;}}
.cell-err{display:block;margin-top:var(--space-1);font:500 var(--fs-2)/1.35 var(--sans);
  text-transform:none;letter-spacing:0;color:var(--crit-ink);white-space:normal;max-width:24ch;}
.cell-input[aria-invalid]{border-color:var(--crit);}   /* Django marks the field; colour it too */
/* Save, then the two ways out, stacked: a row of inputs and three controls side by side
   pushed the board into a horizontal scroll. */
.row-edit .row-actions .row-edit-links{display:block;margin:var(--space-1) 0 0;}
.row-edit .row-actions .row-edit-links>a{display:flex;justify-content:flex-end;margin:0;}
table.lines .row-edit .row-actions .btn-linkish{color:var(--acid);}

/* --- Task board ---------------------------------------------------------------
   The board is the one screen people run the day from, so a row has to carry
   its instructions without a round trip to a detail page. */
.status-row{display:flex;flex-wrap:wrap;gap:var(--space-2);padding:var(--space-4);}
.status-row .btn-ghost.active{border-color:var(--acid);color:var(--acid);background:var(--acid-glow);}
.row-detail{margin-top:var(--space-1);}
.row-detail summary{display:inline-flex;align-items:center;gap:5px;font:500 var(--fs-2)/1.3 var(--sans);
  text-transform:none;letter-spacing:0;color:var(--text-mut);cursor:pointer;list-style:none;}
.row-detail summary::-webkit-details-marker{display:none;}
.row-detail summary::before{content:'';width:5px;height:5px;border:solid currentColor;border-width:0 1.5px 1.5px 0;
  transform:rotate(-45deg);transition:transform var(--dur) var(--ease);}
.row-detail[open] > summary::before{transform:rotate(45deg);}
.row-detail summary:hover{color:var(--acid);}
.row-detail p{margin:var(--space-2) 0 0;max-width:70ch;font-size:var(--fs-3);line-height:1.55;color:var(--text);}
/* priority is a word with a mark, not a status badge: high is the only loud one, and it
   is amber - urgent, not an outage - like the High priority tile above the rows (red is
   for something that is down) */
.prio{display:inline-flex;align-items:center;gap:6px;font:500 var(--fs-3)/1.2 var(--sans);color:var(--text);white-space:nowrap;}
.prio::before{content:'';flex:none;width:8px;height:8px;border-radius:2px;background:var(--line-strong);}
.prio-high{color:var(--warn-ink);font-weight:600;}
.prio-high::before{background:var(--warn);}
/* the task's title and its instructions: wide enough to read on a phone's scrolled table */
.task-cell{min-width:16rem;}
.prio-low{color:var(--text-mut);}
.prio-low::before{background:transparent;box-shadow:inset 0 0 0 1.5px var(--line-strong);}

/* An explanatory note above a board - why something is deliberately absent. */
.callout{margin:0 0 var(--space-5);padding:var(--space-3) var(--space-4);
  border:1px solid var(--line);border-left:3px solid var(--line-strong);border-radius:var(--r);background:var(--bg-base);
  font:400 var(--fs-3)/1.55 var(--sans);color:var(--text-mut);max-width:80ch;}
.callout b{color:var(--text);}

/* Capabilities that are not part of the None/View/Manage ladder (the two invoice
   stages), shown under the module they belong to. */
.extras{display:flex;flex-wrap:wrap;gap:var(--space-1) var(--space-4);margin-top:var(--space-2);}
.extras .chk{font-size:var(--fs-2);color:var(--text-mut);}
.extras .chk:hover{color:var(--text);}
.extras input{width:14px;height:14px;accent-color:var(--acid);}

/* --- Destructive-action interstitial (templates/_confirm.html) -------------
   Deliberately not styled like an ordinary form: a page that deletes something
   should not look like a page that saves something. */
.confirm{position:relative;max-width:640px;background:var(--bg-base);border:1px solid color-mix(in srgb,var(--crit) 30%,var(--line));
  border-radius:var(--r-lg);box-shadow:var(--shadow-1);padding:var(--space-5) var(--space-5) var(--space-5) 72px;overflow:clip;}
.confirm::before{content:'!';position:absolute;left:var(--space-5);top:var(--space-5);width:32px;height:32px;border-radius:50%;
  display:grid;place-items:center;font:700 var(--fs-5)/1 var(--sans);
  background:color-mix(in srgb,var(--crit) 12%,var(--bg-base));color:var(--crit-ink);}
.confirm-subject{margin:0;font:600 var(--fs-5)/1.4 var(--sans);color:var(--text-hi);word-break:break-word;}
.confirm-detail{margin:var(--space-1) 0 0;font:400 var(--fs-4)/1.5 var(--sans);color:var(--text-mut);}
.confirm-list{margin:var(--space-4) 0 0;padding-left:1.2em;font:400 var(--fs-4)/1.6 var(--sans);color:var(--text);}
.confirm-list .blocking{color:var(--crit-ink);font-weight:600;}
.confirm-actions{display:flex;align-items:center;justify-content:flex-end;gap:var(--space-2);margin:var(--space-5) 0 0 -52px;
  padding-top:var(--space-4);border-top:1px solid var(--line-faint);flex-wrap:wrap;}
.confirm-actions .dim{margin-right:auto;font-size:var(--fs-3);}
/* --- small utilities ----------------------------------------------------- */
/* sits directly under a filter bar, so it pulls up into the bar's own gap */
.hero-note{margin:calc(var(--space-2) * -1) 0 var(--space-5) 2px;font:400 var(--fs-3)/1.4 var(--sans);color:var(--text-mut);}
/* wide enough for a hostname, but never wider than the screen */
.filters .wide-input{min-width:360px;max-width:100%;flex:0 1 480px;}
.flush{margin:0;}
/* one fact in two places, one of them shown: a column a phone has no room for (.ph-hide)
   and the same fact folded into a neighbouring cell there (.ph-only). display:none takes
   the hidden one out of the accessibility tree too, so nothing is read twice. */
@media (max-width:640px){.ph-hide{display:none;}}
@media (min-width:640.02px){.ph-only{display:none;}}

/* --- the shell's three layouts (ADR-0030) ------------------------------------------
   Sixteen links need about 1,250px of bar, so they never sit in one flat row: that is
   what wrapped the header onto two and three rows. The breakpoints are repeated in
   shell.js, and core/tests_shell.py keeps the two equal. */

/* -- sidebar, from 1600px. The Network board (the start page) needs 1,265px for its
   widest building with a row's editor open; beside a sidebar it gets 1600-248-64-2 =
   1,286px here, never less than the 1,214px the top bar leaves it at 1280px. At 1440px
   it would get 1,126px and the KP table would scroll sideways, its edit links off the
   card. core/tests_shell.py keeps the sum. */
@media (min-width:1600px){
  html:has(> body.has-nav){--topbar-h:0px;}
  body.has-nav{padding-left:var(--sidebar-w);}
  body.has-nav .wrap{max-width:1600px;}
  body.has-nav .topbar{position:fixed;top:var(--strip-h);left:0;bottom:0;width:var(--sidebar-w);height:auto;
    flex-direction:column;align-items:stretch;gap:0;padding:0;border-bottom:0;border-right:1px solid var(--line);box-shadow:none;}
  body.has-nav .brand{height:60px;margin:0;padding:0 var(--space-5);border-radius:0;}
  body.has-nav .env-chip{position:absolute;top:20px;right:var(--space-4);}
  /* all seventeen links fit a 1080px screen; on a shorter one the list scrolls, with a
     shadow at whichever end has more (the backgrounds scroll with the list and cover
     the shadows once an end is reached) */
  body.has-nav .topnav{flex:1;min-height:0;overflow-y:auto;overscroll-behavior:contain;scrollbar-width:thin;
    padding:var(--space-1) var(--space-3) var(--space-4);
    background:
      linear-gradient(var(--bg-base) 30%,transparent) center top/100% 36px no-repeat local,
      linear-gradient(transparent,var(--bg-base) 70%) center bottom/100% 36px no-repeat local,
      radial-gradient(farthest-side at 50% 0,var(--shade),transparent) center top/100% 10px no-repeat scroll,
      radial-gradient(farthest-side at 50% 100%,var(--shade),transparent) center bottom/100% 10px no-repeat scroll;
    background-color:var(--bg-base);}
  body.has-nav .nav-link{height:34px;}
  body.has-nav .nav-label{margin-top:var(--space-4);}
  body.has-nav .nav-link.active{box-shadow:inset 3px 0 0 var(--acid);}
  body.has-nav .topbar-right{margin:0;padding:var(--space-3);gap:var(--space-2);border-top:1px solid var(--line);}
  body.has-nav .usermenu{flex:1;order:-1;}
  body.has-nav .usermenu-btn{width:100%;max-width:none;border-radius:var(--r);padding:0 10px 0 6px;}
  body.has-nav .usermenu-btn .chev{margin-left:auto;transform:rotate(180deg);}
  body.has-nav .usermenu.open .usermenu-btn .chev{transform:none;}
  body.has-nav .menu{top:auto;bottom:calc(100% + 8px);left:0;right:auto;width:calc(var(--sidebar-w) - 2 * var(--space-3));min-width:0;}
  /* the console drawer opens beside the sidebar, not over the account menu */
  body.has-nav .console{left:var(--sidebar-w);}
}

/* -- top bar, 1024-1599px: Home, then the four groups, each a menu under its name ----- */
@media (min-width:1024px) and (max-width:1599.98px){
  .topnav{flex:1;flex-direction:row;align-items:center;gap:2px;margin-left:var(--space-5);}
  .topnav > .nav-link{padding:0 12px;}
  .topnav > .nav-link .i,.nav-label{display:none;}
  .nav-group{position:relative;}
  .nav-group-btn{display:flex;align-items:center;gap:4px;height:36px;padding:0 8px 0 12px;cursor:pointer;position:relative;
    border:0;border-radius:var(--r);background:none;color:var(--text);font:500 var(--fs-4)/1 var(--sans);white-space:nowrap;}
  .nav-group-btn:hover,.nav-group.open .nav-group-btn{background:var(--bg-raised);color:var(--text-hi);}
  .nav-group:has(.nav-link.active) .nav-group-btn{background:var(--acid-glow);color:var(--acid);font-weight:600;}
  .nav-group:has(.nav-link.active) .nav-group-btn .chev{color:var(--acid);}
  .nav-group.open .nav-group-btn .chev{transform:rotate(180deg);}
  /* a group holding open outages says so while it is shut */
  .nav-group:has(.nav-count) .nav-group-btn::after{content:'';position:absolute;top:7px;right:5px;width:7px;height:7px;
    border-radius:50%;background:var(--crit);box-shadow:0 0 0 2px var(--bg-base);}
  .nav-items{display:none;}
  .nav-group.open .nav-items{display:flex;position:absolute;left:0;top:calc(100% + 10px);z-index:70;min-width:232px;
    padding:6px;background:var(--bg-overlay);border:1px solid var(--line);border-radius:var(--r-lg);box-shadow:var(--shadow-3);}
  /* the tint over a menu's lighter surface is lighter too: in dark, --acid on it is
     4.1:1, so the page you are on reads in the deeper accent (5.2:1; darker in light) */
  .nav-items .nav-link.active{color:var(--acid-dim);}
}
@media (min-width:1024px) and (max-width:1199.98px){
  .user-name,.usermenu-btn .chev{display:none;}
  .usermenu-btn{padding:0 5px;}
}

/* -- drawer, below 1024px: the menu button opens the same list from the left -------- */
@media (max-width:1023.98px){
  .topbar{gap:var(--space-1);padding:0 var(--space-3) 0 var(--space-2);}
  .topbar .navtoggle{display:inline-grid;}
  .topbar .navtoggle[aria-expanded="true"]{background:var(--acid-glow);color:var(--acid);}
  .brand{margin-left:0;}
  .topnav{position:fixed;top:calc(var(--strip-h) + var(--topbar-h));left:0;bottom:0;z-index:45;width:min(304px,86vw);
    padding:var(--space-2) var(--space-3) var(--space-7);overflow-y:auto;overscroll-behavior:contain;
    background:var(--bg-base);border-right:1px solid var(--line);box-shadow:var(--shadow-4);
    visibility:hidden;transform:translateX(-100%);transition:transform var(--dur) var(--ease),visibility 0s linear var(--dur);}
  .topnav.open{visibility:visible;transform:none;transition:transform var(--dur) var(--ease);}
  .topnav .nav-link{height:42px;}
  /* under the bar (whose stacking context holds the drawer), over the page */
  .nav-scrim{display:block;position:fixed;inset:calc(var(--strip-h) + var(--topbar-h)) 0 0 0;z-index:35;background:var(--scrim);}
  body.nav-open{overflow:hidden;}
}
@media (max-width:640px){
  .user-name,.usermenu-btn .chev{display:none;}
  .usermenu-btn{padding:0 5px;}
  .wordmark{font-size:var(--fs-4);}
}

/* --- sign-in ---------------------------------------------------------------
   The only page an unauthenticated visitor sees, so it carries the wordmark and
   nothing else. */
.signin{max-width:26rem;margin:var(--space-7) auto;}
.signin-mark{display:grid;place-items:center;width:44px;height:44px;margin-bottom:var(--space-4);border-radius:var(--r-lg);
  background:var(--acid-glow);color:var(--acid);}
.signin-mark .i{width:22px;height:22px;}
.signin h1{font:600 var(--fs-7)/1.2 var(--sans);letter-spacing:-.015em;color:var(--text-hi);margin:0;}
.signin-brand{margin:0 0 var(--space-1);font:600 var(--fs-3)/1.4 var(--sans);letter-spacing:.01em;color:var(--text-mut);}
.signin-sub{font:400 var(--fs-4)/1.4 var(--sans);text-transform:none;letter-spacing:0;color:var(--text-mut);
  margin:var(--space-1) 0 var(--space-5);}
.signin .form-card{max-width:none;padding:var(--space-5);}
.signin .form-actions .btn-blaze{flex:1;}
.signin-help{margin-top:var(--space-4);font:400 var(--fs-3)/1.5 var(--sans);color:var(--text-mut);text-align:center;}

/* --- activity (ADR-0020) ----------------------------------------------------
   Who changed what. A change reads "field  old -> new"; a delete folds its last
   known state away so a long list of deletes stays scannable. */
.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap;border:0;}
.audit-table td{vertical-align:top;}
.audit-noun{display:block;font:500 var(--fs-2)/1.3 var(--sans);color:var(--text-mut);}
.audit-what{min-width:9rem;}
.audit-detail{min-width:18rem;}
.audit-lines{list-style:none;margin:0;padding:0;font-size:var(--fs-3);line-height:1.55;}
.audit-lines li{overflow-wrap:anywhere;}
.audit-field{font:500 var(--fs-2)/1.4 var(--mono);color:var(--text-mut);margin-right:var(--space-1);}
.audit-old{color:var(--text-mut);text-decoration-color:var(--crit);}
.audit-note{display:block;margin-top:var(--space-1);font:400 var(--fs-2)/1.45 var(--sans);color:var(--text-mut);}
a.audit-note{color:var(--acid);}
.audit-state{display:grid;grid-template-columns:max-content 1fr;gap:var(--space-1) var(--space-3);
  margin:var(--space-2) 0 0;font-size:var(--fs-3);}
.audit-state dt{font:500 var(--fs-2)/1.45 var(--mono);color:var(--text-mut);}
.audit-state dd{margin:0;overflow-wrap:anywhere;}
.audit-deleted td:first-child{box-shadow:inset 3px 0 0 var(--crit);}
.audit-panel{margin-top:var(--space-5);}
.audit-card{margin-bottom:var(--space-5);}
.audit-card-title{margin:0;font:600 var(--fs-3)/1.3 var(--sans);text-transform:none;letter-spacing:0;color:var(--text-hi);}
.audit-gap{display:flex;align-items:center;justify-content:space-between;gap:var(--space-3);flex-wrap:wrap;}
.audit-gap form,.audit-gap .btn-ghost{margin-top:0;}
.audit-gaps{font-size:var(--fs-3);}
.audit-set{display:inline;}
.audit-set summary{display:inline;cursor:pointer;color:var(--text);}
.audit-items{display:block;margin-top:var(--space-1);font:400 var(--fs-2)/1.6 var(--mono);color:var(--text-mut);}

/* --- error pages (404, 403, 500) --------------------------------------------- */
.error-page{max-width:640px;margin:var(--space-7) auto;}
.error-page .empty{padding:var(--space-7) var(--space-6);}
.error-page .empty-glyph:not(:empty){width:auto;min-width:64px;height:40px;padding:0 14px;border-radius:var(--r-full);font-size:var(--fs-4);}
body.bare{padding-top:0;}
.error-standalone{min-height:100vh;display:grid;place-items:center;padding:var(--space-5);}
.error-standalone .error-page{width:100%;margin:0 auto;}
.error-standalone .wordmark{display:block;text-align:center;margin-bottom:var(--space-5);}

/* ---- Add assets in bulk (ADR-0037) ----------------------------------------------
   A grid of rows in a card. Each column is named in the interface face with a dim line
   on what it takes; the cells are drawn as a spreadsheet's - edge to edge, a hairline
   between them, the field's ring only where the cursor is - so twelve columns read as one
   sheet and not as twelve stacks of boxes. The dropdowns and typeaheads are the one
   component, and how they sit in a cell is in mss.css with the rest of it. The grid
   scrolls sideways in its own box at every width and the page never does, with a shade
   at its right edge while there are columns past it. On a laptop or wider the footer,
   with what is ready and the Add buttons, stays at the bottom of the screen while a long
   batch scrolls past it; on a phone it would cover a third of the screen, so it stays
   under the grid. */
.bulk-import{margin-bottom:var(--space-4);}
.bulk-import > summary{list-style:none;cursor:pointer;display:flex;align-items:baseline;flex-wrap:wrap;gap:4px 12px;padding:14px 20px;}
.bulk-import > summary::-webkit-details-marker{display:none;}
.bulk-import > summary::before{content:'';flex:none;align-self:center;width:7px;height:7px;margin:0 2px 2px 1px;
  border:solid var(--text-mut);border-width:0 1.5px 1.5px 0;transform:rotate(-45deg);transition:transform var(--dur) var(--ease);}
.bulk-import[open] > summary::before{transform:rotate(45deg);margin-bottom:5px;}
.bulk-import > summary:hover{background:var(--bg-raised);}
.bulk-import > summary:focus-visible{box-shadow:inset 0 0 0 2px var(--acid);}
.bulk-import-title{font:600 var(--fs-4)/1.3 var(--sans);color:var(--text-hi);}
.bulk-import > summary .dim{font:400 var(--fs-3)/1.3 var(--sans);}
.bulk-import-body{display:grid;gap:var(--space-3);padding:14px 20px 18px;border-top:1px solid var(--line-faint);}
.bulk-import-label{font:500 var(--fs-3)/1.35 var(--sans);color:var(--text-hi);}
.bulk-paste{width:100%;min-height:96px;resize:vertical;padding:9px 12px;font:400 var(--fs-3)/1.45 var(--mono);color:var(--text-hi);
  background:var(--bg-base);border:1px solid var(--field-line);border-radius:var(--r);}
.bulk-paste:hover{border-color:var(--text-mut);}
.bulk-paste:focus{border-color:var(--acid);box-shadow:var(--ring);outline:none;}
.bulk-paste::placeholder{color:var(--text-mut);font-family:var(--sans);}
.bulk-import-actions{display:flex;flex-wrap:wrap;align-items:center;gap:var(--space-2) var(--space-3);}
/* the file input covers its label, so a click anywhere on it opens the picker */
.bulk-file{position:relative;cursor:pointer;}
.bulk-file input{position:absolute;inset:0;width:100%;height:100%;opacity:0;cursor:pointer;}
.bulk-file:focus-within{box-shadow:0 0 0 2px var(--bg-base),0 0 0 4px var(--acid);}
.bulk-import-status{font:500 var(--fs-3)/1.4 var(--sans);color:var(--text);}
.bulk-import-note{margin:0;max-width:100ch;font:400 var(--fs-3)/1.5 var(--sans);color:var(--text-mut);}

.bulk-scroll-wrap{position:relative;}
.bulk-scroll-wrap::after{content:'';position:absolute;top:0;right:0;bottom:0;z-index:5;width:28px;pointer-events:none;
  background:linear-gradient(to left,var(--shade),transparent);opacity:0;transition:opacity var(--dur) var(--ease);}
.bulk-scroll-wrap.more-right::after{opacity:1;}
.bulk-scroll{position:relative;overflow-x:auto;overscroll-behavior-x:contain;}
.bulk-grid{border-collapse:separate;border-spacing:0;width:max-content;min-width:100%;}
.bulk-grid thead th{padding:10px 12px 9px;text-align:left;vertical-align:bottom;background:var(--bg-raised);
  border-bottom:1px solid var(--line);border-right:1px solid var(--line-faint);}
.bulk-name{display:block;font:600 var(--fs-3)/1.3 var(--sans);color:var(--text-hi);white-space:nowrap;}
.bulk-hint{display:block;margin-top:2px;font:400 var(--fs-2)/1.35 var(--sans);color:var(--text-mut);}
/* each column as wide as what it holds, with room for its hint on two lines at most */
.bulk-grid .bulk-c-category,.bulk-grid .bulk-c-make{width:164px;min-width:164px;}
.bulk-grid .bulk-c-model,.bulk-grid .bulk-c-serial{width:176px;min-width:176px;}
.bulk-grid .bulk-c-assigned_to{width:212px;min-width:212px;}
.bulk-grid .bulk-c-status{width:136px;min-width:136px;}
.bulk-grid .bulk-c-location,.bulk-grid .bulk-c-condition{width:120px;min-width:120px;}
.bulk-grid .bulk-c-assigned_on{width:156px;min-width:156px;}
.bulk-grid .bulk-c-purchase_date,.bulk-grid .bulk-c-warranty_end{width:140px;min-width:140px;}
.bulk-grid .bulk-c-purchase_price{width:132px;min-width:132px;}
.bulk-grid .bulk-c-notes{width:248px;min-width:248px;border-right:0;}
/* the row's number and its menu stay at the left while the grid scrolls */
.bulk-grid .bulk-rowhead{position:sticky;left:0;z-index:2;width:92px;min-width:92px;padding:6px 4px 0 14px;text-align:left;
  white-space:nowrap;vertical-align:top;background:var(--bg-base);border-right:1px solid var(--line);
  border-bottom:1px solid var(--line-faint);font:500 var(--fs-2)/1 var(--sans);color:var(--text-mut);}
.bulk-grid thead .bulk-rowhead{z-index:3;background:var(--bg-raised);border-bottom-color:var(--line);}
.bulk-rowno{display:inline-block;min-width:3.6em;vertical-align:middle;}
.bulk-rowmenu{display:inline-grid;place-items:center;width:28px;height:28px;margin:0;padding:0;vertical-align:middle;
  border:0;border-radius:var(--r-sm);background:none;color:var(--text-mut);cursor:pointer;}
.bulk-rowmenu > span{display:block;width:3px;height:3px;border-radius:50%;background:currentColor;
  box-shadow:-5px 0 0 currentColor,5px 0 0 currentColor;}
.bulk-rowmenu:hover,.bulk-rowmenu[aria-expanded="true"]{background:var(--bg-raised);color:var(--text-hi);}
.bulk-cell{padding:0;vertical-align:top;background:var(--bg-base);border-right:1px solid var(--line-faint);border-bottom:1px solid var(--line-faint);}
.bulk-grid .bulk-input{width:100%;min-width:0;min-height:40px;padding:0 10px;border:0;border-radius:0;background:transparent;
  font:400 var(--fs-4)/1.3 var(--sans);color:var(--text-hi);}
.bulk-grid .bulk-serial,.bulk-grid .bulk-date,.bulk-grid .bulk-money{font-family:var(--mono);font-size:var(--fs-3);}
.bulk-grid .bulk-input::placeholder{color:var(--text-ghost);opacity:1;}
.bulk-grid .bulk-input:hover{background:color-mix(in srgb,var(--bg-raised) 70%,transparent);}
/* the cell the cursor is in: the accent's ring inside its edges (mss.css draws the same
   for a dropdown or a typeahead in a cell) */
.bulk-grid .bulk-input:focus{outline:none;background:var(--bg-base);box-shadow:inset 0 0 0 2px var(--acid);}
/* what is wrong is marked by the cell itself: a tint, a rule along its foot, a message */
.bulk-cell.has-error{background:color-mix(in srgb,var(--crit) 6%,var(--bg-base));box-shadow:inset 0 -2px 0 var(--crit);}
.bulk-cell.has-warning{background:color-mix(in srgb,var(--warn) 7%,var(--bg-base));box-shadow:inset 0 -2px 0 var(--warn);}
.bulk-msg{display:block;padding:0 10px 8px;font:400 var(--fs-2)/1.4 var(--sans);color:var(--text-mut);white-space:normal;}
.bulk-msg:empty{display:none;}
.bulk-msg.is-error{color:var(--crit-ink);font-weight:500;}
.bulk-msg.is-warning{color:var(--warn-ink);}
/* a block picked with Shift and the arrows */
.bulk-cell.is-picked{background:color-mix(in srgb,var(--acid) 11%,var(--bg-base));
  box-shadow:inset 0 0 0 1px color-mix(in srgb,var(--acid) 40%,transparent);}
.bulk-tools{display:flex;flex-wrap:wrap;align-items:center;gap:var(--space-2) var(--space-3);padding:12px 20px;border-top:1px solid var(--line);}
.bulk-help{flex:1 1 340px;margin:0 0 0 var(--space-2);font:400 var(--fs-3)/1.5 var(--sans);color:var(--text-mut);}
.bulk-note{flex:1 1 100%;order:3;margin:0;font:500 var(--fs-3)/1.45 var(--sans);color:var(--text);}
.bulk-foot{display:flex;flex-wrap:wrap;align-items:center;justify-content:space-between;
  gap:var(--space-3) var(--space-5);padding:14px 20px;background:var(--bg-raised);border-top:1px solid var(--line);}
@media (min-width:820.02px){.bulk-foot{position:sticky;bottom:0;z-index:6;}}
.bulk-verdict{display:flex;flex-direction:column;gap:2px;flex:1 1 360px;min-width:0;}
.bulk-verdict-title{font:600 var(--fs-4)/1.35 var(--sans);color:var(--text-hi);}
.bulk-verdict-detail{font:400 var(--fs-3)/1.45 var(--sans);color:var(--text-mut);}
.bulk-actions{display:flex;flex-wrap:wrap;gap:var(--space-2);}
/* a row's menu: clear, duplicate, remove (in <body>, like the dropdowns' menus) */
.bulk-menu{position:fixed;z-index:1100;display:flex;flex-direction:column;min-width:188px;padding:4px;background:var(--bg-overlay);
  border:1px solid var(--line-strong);border-radius:var(--r);box-shadow:var(--shadow-3);}
.bulk-menu-item{display:flex;align-items:center;min-height:34px;padding:0 10px;border:0;border-radius:var(--r-sm);background:none;
  font:500 var(--fs-3)/1.2 var(--sans);color:var(--text-hi);text-align:left;cursor:pointer;}
.bulk-menu-item:hover,.bulk-menu-item:focus{background:var(--acid-glow);outline:none;}
.bulk-menu-item.danger{color:var(--crit-ink);}
.bulk-menu-item.danger:hover,.bulk-menu-item.danger:focus{background:color-mix(in srgb,var(--crit) 9%,transparent);}
@media (pointer:coarse){.bulk-menu-item{min-height:44px;}}
/* the Assets list after a bulk add: the new rows flash once and keep a mark at their edge */
table.lines tbody tr.is-new > td:first-child{box-shadow:inset 3px 0 0 var(--acid);}

/* ---- small screens -------------------------------------------------------------
   Last, so these win over everything above. */
@media(max-width:820px){
  .wrap{padding:var(--space-5) var(--space-4) var(--space-7);}
  .hero{grid-template-columns:minmax(0,1fr);grid-template-areas:"crumbs" "title" "sub" "actions";margin-bottom:var(--space-4);}
  .hero h1{font-size:22px;}
  .hero-actions{justify-content:flex-start;margin-top:var(--space-3);}
  .hero-actions:empty{display:none;}
  /* figures two to a row, as short as they can be: the table is what the page is for */
  .kpis{grid-template-columns:repeat(2,minmax(0,1fr));gap:var(--space-2);}
  .kpi{min-width:0;gap:6px;padding:10px var(--space-3) var(--space-3);}
  /* an odd last tile takes the whole row, as Home's last card does, not half of it */
  .kpi:last-child:nth-child(odd){grid-column:1 / -1;}
  .kpi-num{font-size:22px;}
  /* Internet spend: the annual figure across the top, the other four two by two */
  .spend-kpis{grid-template-columns:repeat(2,minmax(0,1fr));}
  .spend-kpis .kpi-wide{grid-column:1 / -1;}
  .spend-kpis .kpi:last-child:nth-child(odd){grid-column:auto;}
  /* and its summary tables keep vendor, annual and share (.ph-hide folds the rest), a
     building's name under its code, and fit the screen */
  .spend-share,table.lines th.spend-share-h{min-width:0;}
  .spend-share{gap:6px;}
  .spend-share .mono{min-width:0;}
  .spend-bar{min-width:28px;}
  table.spend-table.compact :is(th,td):not(:first-child):not(:last-child){padding-left:8px;padding-right:8px;}
  table.spend-table.compact .cell-sub.spend-none{white-space:normal;}
  .spend-gst-warn{margin:var(--space-3) var(--space-4);}
  .spend-toggle{flex-wrap:wrap;row-gap:0;}
  .spend-toggle .dim{flex-basis:100%;padding-left:15px;}
  /* a wide table keeps the width its columns need and scrolls inside its card; a
     compact one (three or four short columns) fits the screen, its dropdowns giving up
     width before it scrolls, and so does an empty one (its empty state alone) */
  table.lines{min-width:760px;}
  table.lines.compact,table.lines:has(>tbody>tr>td>.empty){min-width:0;}
  table.lines.compact{--mss-min:7rem;}
  /* and a name in one wraps at 9rem, not 14, so the columns after it stay on screen */
  table.lines.compact .name-cell>*{max-width:9rem;}
  /* and its row actions (Reference's edit and delete) stack rather than stand in a row */
  table.lines.compact .row-actions>*{display:block;}
  table.lines.compact .row-actions>*+*{margin:2px 0 0;}
  /* Two columns inside a padded card leave ~131px each at 375px: one column. */
  .form-grid{grid-template-columns:minmax(0,1fr);}
  .form-card{padding:var(--space-4);}
  /* a filter bar: a search or text field takes a row of its own, the selects and
     dates sit two to a row, so six filters are three rows and not seven */
  .filters{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));}
  .filters > *{min-width:0;}
  .filters input[type=text],.filters input[type=search],.filters .wide-input{min-width:0;max-width:none;grid-column:1 / -1;}
  /* a text field the dropdown component wrapped (a combobox: Diagnostics, Brochures) */
  .filters > :has(input[list],input[data-mss-list],input[data-mss-combo]){grid-column:1 / -1;}
  .filters input[type=date]{width:auto;}
  .filters > .count{margin-left:0;}
  .loc-head,.panel-head{padding:12px var(--space-4);}
  .floor-head{padding:9px var(--space-4);}
  .floor-nets{padding:7px var(--space-4);}
  table.lines th:first-child,table.lines td:first-child,table.lines tr.row-edit td:first-child{padding-left:var(--space-4);}
  table.lines th:last-child,table.lines td:last-child,table.lines tr.row-edit td:last-child{padding-right:var(--space-4);}
  .segbar .seg{padding:0 11px;}
  .confirm{padding:var(--space-4);}
  .confirm::before{position:static;margin-bottom:var(--space-3);}
  .confirm-actions{margin-left:0;}
  .ref-grid{grid-template-columns:1fr;}
  .audit-detail{min-width:0;}
  .audit-state{grid-template-columns:1fr;}
  /* the strip: the summary stays put, the facts slide under a fade */
  .nocbar{gap:var(--space-3);padding:0 var(--space-2) 0 var(--space-4);}
  .noc-spark{display:none;}
  /* Add assets in bulk (ADR-0037): the gutters of the rest of the page, a narrower row
     number, and the footer's buttons across the screen under what is ready */
  .bulk-import > summary{padding:12px var(--space-4);}
  .bulk-import-body{padding:12px var(--space-4) var(--space-4);}
  .bulk-tools,.bulk-foot{padding:12px var(--space-4);}
  .bulk-help{flex-basis:100%;margin:2px 0 0;}
  .bulk-grid .bulk-rowhead{width:76px;min-width:76px;padding-left:10px;}
  .bulk-rowno{min-width:3.2em;}
  .bulk-verdict{flex-basis:100%;}
  .bulk-actions{width:100%;}
  .bulk-actions > *{flex:1 1 auto;}
  /* IT spend, Licences, the IT overview (ADR-0038): the tiles two to a row, every card
     full width, and on a bar the name, its figure and share on one row, the bar under them */
  .it-kpis,.ov-kpis{grid-template-columns:repeat(2,minmax(0,1fr));}
  .it-kpis .kpi-wide,.ov-kpis .kpi-wide{grid-column:1 / -1;}
  .it-kpis .kpi:last-child:nth-child(odd),.ov-kpis .kpi:last-child:nth-child(odd){grid-column:auto;}
  .ov-grid{gap:var(--space-3);}
  .ov-grid > .panel{grid-column:1 / -1;}
  /* a phone: the name, its figure and share on one row, the bar under them */
  .ov-bar{grid-template-columns:minmax(0,1fr) auto 3.4em;grid-template-areas:"name val share" "track track track";row-gap:5px;}
  .ov-bar-name{grid-area:name;}
  .ov-bar-track{grid-area:track;}
  .ov-bar-val{grid-area:val;}
  .ov-bar-share{grid-area:share;}
  .ov-bars,.ov-facts,.ov-list,.ov-kinds,.lic-row,.lic-note,.it-events,.ov-sub,.ov-note{padding-left:var(--space-4);padding-right:var(--space-4);}
  .quiet-line{padding-left:var(--space-4);padding-right:var(--space-4);}
  .it-event{flex-direction:column;gap:2px;}
  table.lines td.it-what{min-width:0;}
  /* Billing (ADR-0040): this month's marks under the figures; the calendar keeps its width
     and scrolls in its card, the subscription's name narrower */
  .bill-legend{padding-left:var(--space-4);padding-right:var(--space-4);}
  /* this month's list as cards: the charge across, its invoice and figure, its due day and
     status, then the marks - nothing to scroll sideways for */
  table.lines.bill-now{min-width:0;}
  table.lines.bill-now>thead{display:none;}
  table.lines.bill-now>tbody>tr{display:grid;grid-template-columns:minmax(0,1fr) auto;gap:4px 12px;
    padding:10px var(--space-4);border-bottom:1px solid var(--line-faint);}
  table.lines.bill-now>tbody>tr>td{display:block;padding:0;border:0;}
  table.lines.bill-now>tbody>tr>td.ph-hide{display:block;}
  table.lines.bill-now>tbody>tr>td:first-child{padding-left:0;grid-column:1 / -1;}
  table.lines.bill-now>tbody>tr>td.bill-st-c,table.lines.bill-now>tbody>tr>td.bill-due{text-align:right;}
  table.lines.bill-now>tbody>tr>td.num{text-align:left;}
  table.lines.bill-now>tbody>tr>td.num .it-foreign{margin-left:0;min-width:0;}
  table.lines.bill-now>tbody>tr>td.bill-due::before{content:"due ";font-family:var(--sans);color:var(--text-mut);}
  table.lines.bill-now>tbody>tr>td.bill-act{grid-column:1 / -1;width:auto;min-width:0;padding-top:4px;}
  table.lines.bill-now>tbody>tr>td:last-child{padding-right:0;}
  table.lines td.bill-act .bill-form{justify-content:flex-start;}
  table.lines.bill-cal{min-width:980px;}
  table.lines.bill-cal .bill-cal-name{width:11.5rem;}
}
@media(max-width:480px){
  .noc-summary .noc-sub{display:none;}
}

/* ---- print ------------------------------------------------------------------------
   Internet spend is printed for management (ADR-0034), and any page prints the same
   way: the page alone on A4 landscape - no strip, no nav, no buttons or row actions -
   in the light palette whatever the screen's theme (a dark page would print light text
   on white paper), with cards as plain ruled boxes and every table at full width. */
@media print{
  @page{size:A4 landscape;margin:10mm 10mm 12mm;}
  :root:not([data-theme="light"]),:root[data-theme="dark"]{
    --bg-void:#E8ECF1; --bg:#F3F5F8; --bg-base:#FFFFFF; --bg-raised:#F8F9FB; --bg-overlay:#FFFFFF;
    --line-faint:#EEF1F4; --line:#E2E6EB; --line-strong:#CDD3DB; --field-line:#7B8595;
    --text-hi:#101828; --text:#344054; --text-mut:#5A6474; --text-ghost:#98A1AE;
    --acid:#2B54C9; --acid-dim:#2346AB; --on-acid:#ffffff;
    --ok:#15803D; --info:#2563EB; --warn:#B45309; --crit:#C4302B; --idle:#6B7280;
    --ok-ink:#166534; --info-ink:#1E40AF; --warn-ink:#92400E; --crit-ink:#991B1B; --idle-ink:#475467;
    color-scheme:light;
  }
  html,body{background:var(--bg-base);}
  body{padding-top:0;}
  .nocbar,.topbar,.skip-link,.nav-scrim,.console,.hero-actions,.flash-region,.row-actions,.row-edit-form,
  .spend-edit-h,.spend-edit-c,.spend-more,.spend-tabs{display:none !important;}
  .spend-screen,.spend-toggle::before{display:none !important;}
  .wrap{max-width:none;margin:0;padding:0;}
  .hero{margin-bottom:8px;}
  .hero h1{font-size:20px;}
  .hero-sub{margin-top:2px;font-size:12px;}
  .flash{margin-bottom:8px;padding:6px 10px 6px 36px;font-size:11px;}
  .flash::before{top:7px;left:10px;}
  /* Chrome matches the width queries against its default paper, not this @page: the
     phone and laptop rules may apply here, so print states every layout it relies on */
  .kpis,.spend-kpis{grid-template-columns:minmax(0,1.4fr) repeat(4,minmax(0,1fr));gap:8px;margin-bottom:8px;}
  .spend-kpis .kpi-wide,.spend-kpis .kpi:last-child:nth-child(odd){grid-column:auto;}
  .hero{grid-template-columns:minmax(0,1fr);grid-template-areas:"crumbs" "title" "sub";}
  table.lines,table.lines.compact{min-width:0;}
  .ph-hide{display:table-cell !important;}
  .spend-toggle{flex-wrap:nowrap;}
  .spend-toggle .dim{flex-basis:auto;padding-left:0;}
  .ph-only{display:none !important;}
  .kpi{gap:4px;padding:8px 10px;box-shadow:none;break-inside:avoid;}
  .kpi-num{font-size:19px;}
  .loc,.panel{margin-bottom:8px;box-shadow:none;}
  .panel:not(.spend-every){break-inside:avoid;}
  .panel-head,.loc-head{padding:6px 10px;}
  .panel-head h2{font-size:13px;}
  .tablewrap{overflow:visible;}
  table.lines th,table.lines td{padding:2px 7px;font-size:10px;line-height:1.35;}
  table.lines td.mono,table.lines td .mono{font-size:10px;}
  table.lines th:first-child,table.lines td:first-child{padding-left:10px;}
  table.lines th:last-child,table.lines td:last-child{padding-right:10px;}
  table.lines tr{break-inside:avoid;}
  /* a building's lines stay on one page with their band and subtotal; the grand total is
     printed once, at the end - a repeated footer read as a total of the page above it */
  table.spend-lines > tbody{break-inside:avoid;}
  table.lines > tfoot{display:table-row-group;}
  table.lines .name-cell>*{max-width:none;}
  .floor-head{padding:3px 10px;font-size:10px;}
  .floor-head .floor-count{padding:1px 6px;font-size:9px;}
  table.lines .spend-none,table.lines .cell-sub,table.lines td .spend-basis,table.lines td.spend-floor,.spend-toggle,.spend-toggle .dim{font-size:10px;}
  table.lines tr.spend-floor-row td:first-child{padding-left:10px;}
  .spend-share{min-width:120px;}
  .spend-bar{height:6px;-webkit-print-color-adjust:exact;print-color-adjust:exact;}
  .spend-gst-warn{margin:6px 10px;}
  /* IT spend and the IT overview (ADR-0038): the overview is one A4 landscape sheet - the
     tiles; the money, the network and the licences; the estate and the open items */
  .it-kpis,.ov-kpis{grid-template-columns:minmax(0,1.4fr) repeat(4,minmax(0,1fr));gap:8px;margin-bottom:8px;}
  .it-kpis .kpi-wide,.ov-kpis .kpi-wide,.it-kpis .kpi:last-child:nth-child(odd),.ov-kpis .kpi:last-child:nth-child(odd){grid-column:auto;}
  .it-events{padding:2px 10px 4px;}
  .it-event{flex-direction:row;padding:3px 0;font-size:10px;}
  .quiet-line{padding:4px 10px;font-size:10px;}
  /* the cards' places, stated as strongly as the phone block's ".ov-grid > .panel", which
     Chrome may apply here: the money, the network and the licences across, then the
     estate beside the open items, which read best wide (dense: the licences fill the
     first row's end) */
  .ov-grid{grid-template-columns:repeat(12,minmax(0,1fr));grid-auto-flow:row dense;gap:8px;}
  .ov-grid > .panel{margin:0;}
  .ov-grid > .ov-money{grid-column:span 6;}
  .ov-grid > .ov-network,.ov-grid > .ov-licences{grid-column:span 3;}
  .ov-grid > .ov-estate{grid-column:span 5;}
  .ov-grid > .ov-items{grid-column:span 7;}
  .ov-kpis{margin-bottom:6px;}
  .ov-kpis .kpi{padding:6px 10px;}
  .ov-kpis .kpi-num{font-size:17px;}
  .ov-kpis .kpi-sub,.ov-kpis .kpi-lbl{font-size:9.5px;}
  .ov-grid .panel-head{padding:5px 10px;}
  .ov-grid table.lines.compact :is(th,td){padding-top:2px;padding-bottom:2px;}
  .ov-bars{gap:3px;padding:5px 10px;}
  .ov-bar{grid-template-columns:minmax(7rem,10rem) minmax(0,1fr) minmax(5.2rem,auto) 3.2em;grid-template-areas:none;gap:8px;}
  .ov-bar-name,.ov-bar-track,.ov-bar-val,.ov-bar-share{grid-area:auto;}
  .ov-bar-name,.ov-bar-val,.ov-bar-share{font-size:10px;line-height:1.2;}
  .ov-bar-what{font-size:9px;line-height:1.2;}
  .ov-bar-track,.ov-bar-track > i{-webkit-print-color-adjust:exact;print-color-adjust:exact;}
  .ov-bar-track{height:8px;}
  .ov-bars-tight .ov-bar-track{height:6px;}
  .ov-sub{padding:2px 10px 0;font-size:9px;line-height:1.6;}
  .ov-facts{gap:4px 10px;padding:6px 10px;}
  .ov-facts dt{font-size:9px;}
  .ov-facts dd{font-size:12px;}
  .ov-kinds{gap:2px 10px;padding:6px 10px 2px;font-size:10px;}
  .ov-note{padding:3px 10px 0;font-size:9px;}
  .ov-list{padding:2px 10px 6px;}
  .ov-item{gap:6px;padding:2px 0;font-size:9.5px;line-height:1.3;}
  .ov-item a{border-bottom:0;}
  a{color:inherit;}
  /* Billing (ADR-0040): no marks or date fields on paper; the calendar fits the sheet's
     width, its pills in colour */
  .bill-act,.bill-act-h,.bill-nav{display:none !important;}
  table.lines.bill-cal{min-width:0;}
  table.lines.bill-cal .bill-cal-name{width:12rem;}
  table.lines.bill-cal td.bill-cell{padding:2px 1px;}
  .pill.bill-chip{padding:1px 2px;}
  .bill-st,.bill-amt,.bill-y,.bill-extra{font-size:8px;}
  table.lines.bill-cal .bill-name{font-size:10px;}
  .pill,.bill-cover{-webkit-print-color-adjust:exact;print-color-adjust:exact;}
  .bill-legend{padding:4px 10px;font-size:9px;line-height:1.8;}
}
