/* O&M platform shell.
   Neutral by design: the tenant's colours, logo and fonts arrive at runtime from
   config, so nothing here names a customer.

   DEPTH WITHOUT OPACITY. GSG's guidelines forbid changing colour opacity, so
   every surface, border and state colour is a solid value from the palette.
   No rgba, no color-mix, no tints of the primary. */
:root{
  --brand:#3d7a3d;
  --paper:#12151a;
  --surface:#171b21;
  --surface2:#1d222a;
  --surface3:#232933;
  --line:#262d37;
  --line2:#323a46;
  --ink:#eef1f5;
  --ink2:#c3cbd6;
  --muted:#8c96a4;
  --bad:#e05a4f;
  --warn:#d99a2b;
  --ok:#4caf7d;
  --accent1:#255d66; --accent2:#164e6f; --accent3:#3c435c;
  --r:10px; --r2:14px;
  --shadow:0 1px 2px #0d1014, 0 8px 24px #0d1014;
  /* Sampled from the supplied shield artwork: dark forest at the top of the mark
     to leaf at the foot. This is the brand's OWN gradient, lifted from an
     approved asset, not a new combination invented from the palette, which the
     guidelines forbid. Replace with the official toolkit gradient when GSG
     supply it. */
  --grad-from:#3e633f; --grad-to:#629845;
  --grad:linear-gradient(160deg,var(--grad-from),var(--grad-to));

  /* BACKGROUND FIELD.
     Built from the brand's own shield gradient, carried down into the dark end
     so it has real presence rather than being technically-there-and-invisible.
     A radial from the top left in the mark's forest green, over the brand navy,
     plus a cooler foot. Solid colour stops throughout: no rgba, no opacity, so
     no brand colour is being tinted or faded.

     THIS IS A DEVIATION and worth regularising. The guidelines permit only the
     approved gradients from the brand toolkit, which GSG have not supplied.
     Swap this for the official one when the asset pack arrives, alongside the
     Cera Pro webfont and the proper logo variants. */
  --bg-from:#243428; --bg-mid:#181b26; --bg-to:#1a2430;
  --bg-field:
    radial-gradient(120% 85% at 8% -10%, var(--bg-from) 0%, var(--bg-mid) 52%),
    linear-gradient(172deg, var(--bg-mid) 40%, var(--bg-to) 100%);
  --surface-field:linear-gradient(165deg,#1e242c,#171b21 70%);
}
@media (prefers-color-scheme:light){
  :root{
    --paper:#fbfcfd; --surface:#fff; --surface2:#f4f6f9; --surface3:#eceff4;
    --line:#e2e7ee; --line2:#cfd7e2; --ink:#141920; --ink2:#3d4854; --muted:#69737f;
    --shadow:0 1px 2px #e7ebf0, 0 8px 24px #eef1f5;
    --bg-from:#e8f0e6; --bg-mid:#fbfcfd; --bg-to:#eef3f8;
    --bg-field:
      radial-gradient(120% 85% at 8% -10%, var(--bg-from) 0%, var(--bg-mid) 52%),
      linear-gradient(172deg, var(--bg-mid) 40%, var(--bg-to) 100%);
    --surface-field:linear-gradient(165deg,#fff,#f7f9fb 70%);
  }
}
*{box-sizing:border-box}
html{-webkit-text-size-adjust:100%}
body{margin:0;background:var(--paper);background-image:var(--bg-field);background-attachment:fixed;
     color:var(--ink);font-size:15px;line-height:1.55;
     font-family:var(--body,system-ui),system-ui,-apple-system,"Segoe UI",sans-serif;
     -webkit-font-smoothing:antialiased}
a{color:inherit}
::selection{background:var(--brand);color:#fff}

/* ---------------------------------------------------------------- chrome */
/* Part of the column, not a bar across it. It used to be a sticky panel filled
   with var(--surface) - the SAME colour as the rail - with a square corner and a
   hard border, so the two read as one notched shape with a seam down the middle.
   The rail is sticky and always reachable; a site selector and a sign-out button
   do not need to follow you down a table. */
header.top{display:flex;align-items:center;gap:1rem;padding:4px 0 18px;
  background:none;flex-wrap:wrap}
header.top h1{font-size:.95rem;margin:0;font-weight:700;letter-spacing:-.01em}
header.top .sp{flex:1}
/* Dead since the shell landed: #tabs carries .subnav now. Kept out rather than
   left to fight the new rule if anything ever restores the class. */
nav.tabs::-webkit-scrollbar{display:none}
nav.tabs button{background:none;border:0;border-bottom:2px solid transparent;color:var(--muted);
  font:inherit;font-weight:600;font-size:.9rem;padding:.85rem .85rem;cursor:pointer;white-space:nowrap;
  transition:color .12s ease,border-color .12s ease}
nav.tabs button:hover{color:var(--ink2)}
nav.tabs button[aria-selected=true]{color:var(--ink);border-bottom-color:transparent;
  background-image:var(--grad);background-repeat:no-repeat;background-size:100% 2px;background-position:bottom}
.wrap{max-width:74rem;margin:0 auto;padding:26px 22px 72px}

h2{font-size:1.3rem;font-weight:600;margin:0 0 .35rem;letter-spacing:-.015em}
.lede{color:var(--ink2);font-size:.9rem;margin:.3rem 0 1.4rem;max-width:65ch;line-height:1.6}

/* ------------------------------------------------------------------ kpis */
.grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(10.5rem,1fr));gap:.7rem;margin:1.1rem 0 1.5rem}
.kpi{background:var(--surface);background-image:var(--surface-field);
  border:1px solid var(--line);border-radius:var(--r2);padding:1rem 1.1rem}
.kpi .n{font-size:2rem;font-weight:600;font-variant-numeric:tabular-nums;line-height:1.05;letter-spacing:-.02em}
.kpi .l{color:var(--muted);font-size:.8rem;margin-top:.3rem;font-weight:500}
.kpi.alert .n{color:var(--bad)}
.kpi.warn .n{color:var(--warn)}

/* ----------------------------------------------------------------- cards */
.card{background:var(--surface);border:1px solid var(--line);border-radius:var(--r2);padding:1.1rem;margin:1rem 0}
.card.tight{padding:.85rem 1rem}

/* month groups on the maintenance board */
.mgroup{margin:1.4rem 0 0}
.mhead{display:flex;align-items:center;gap:.8rem;padding:.55rem 0;position:sticky;top:105px;z-index:10;
  background:var(--bg-from);border-bottom:1px solid var(--line)}
.mhead .name{font-weight:700;font-size:.95rem;letter-spacing:-.01em}
.mhead .count{color:var(--muted);font-size:.82rem}
.mhead .sp{flex:1}

.ring{width:26px;height:26px;flex:0 0 auto;transform:rotate(-90deg)}
.ring circle{fill:none;stroke-width:3.5}
.ring .bg{stroke:var(--line2)}
.ring .fg{stroke:var(--grad-to);stroke-linecap:round;transition:stroke-dasharray .3s ease}

.task{display:grid;grid-template-columns:auto 1fr auto;gap:.9rem;align-items:start;
  background:var(--surface);border:1px solid var(--line);border-radius:var(--r2);
  padding:.85rem 1rem;margin:.5rem 0;cursor:pointer;
  transition:border-color .12s ease,transform .12s ease,background .12s ease}
.task:hover{border-color:var(--line2);background:var(--surface2);transform:translateY(-1px)}
.task:focus-visible{outline:2px solid var(--brand);outline-offset:2px}
.task.done{cursor:default}
.task.done:hover{transform:none;background:var(--surface)}
.task .ref{font-variant-numeric:tabular-nums;font-weight:700;font-size:.8rem;color:var(--muted);
  background:var(--surface3);border:1px solid var(--line);border-radius:7px;padding:.2rem .45rem;min-width:3.2rem;text-align:center}
.task .act{font-size:.92rem;line-height:1.45}
.task .meta{color:var(--muted);font-size:.79rem;margin-top:.25rem;display:flex;gap:.5rem;flex-wrap:wrap;align-items:center}
.task .right{display:flex;flex-direction:column;align-items:flex-end;gap:.4rem}

/* ----------------------------------------------------------------- atoms */
.pill{display:inline-flex;align-items:center;gap:.3rem;font-size:.74rem;font-weight:500;
  padding:.2rem .5rem;border-radius:999px;border:1px solid currentColor;letter-spacing:.01em;white-space:nowrap}
.pill.solid{border-color:transparent;color:#fff}
.g{color:var(--ok)} .a{color:var(--warn)} .r{color:var(--bad)} .m{color:var(--muted)}
.dot{width:6px;height:6px;border-radius:50%;background:currentColor;flex:0 0 auto}

.seg{display:inline-flex;background:var(--surface2);border:1px solid var(--line);border-radius:999px;padding:2px}
.seg button{background:none;border:0;color:var(--muted);font:inherit;font-weight:600;font-size:.82rem;
  padding:.35rem .8rem;border-radius:999px;cursor:pointer;transition:color .12s ease,background .12s ease}
.seg button[aria-pressed=true]{background:var(--surface3);color:var(--ink)}

:is(button,label).btn{font:inherit;font-weight:600;font-size:.88rem;min-height:38px;padding:.45rem .95rem;
  border-radius:var(--r);border:1px solid var(--line2);background:var(--surface2);color:inherit;cursor:pointer;
  transition:border-color .12s ease,background .12s ease}
:is(button,label).btn:hover:not(:disabled){border-color:var(--muted);background:var(--surface3)}
:is(button,label).btn.primary{background:var(--grad);color:#fff;border-color:transparent}
:is(button,label).btn.primary:hover:not(:disabled){filter:brightness(1.08)}
:is(button,label).btn.danger{color:var(--bad);border-color:var(--bad)}
:is(button,label).btn:disabled{opacity:.45;cursor:default}
:is(button,label).btn:focus-visible{outline:2px solid var(--brand);outline-offset:2px}
label.btn{display:inline-flex;align-items:center;justify-content:center;user-select:none}

input,select,textarea{width:100%;font:inherit;font-size:.92rem;color:inherit;background:var(--surface2);
  border:1px solid var(--line2);border-radius:var(--r);padding:.55rem .7rem;min-height:38px}
input:focus,select:focus,textarea:focus{outline:2px solid var(--brand);outline-offset:1px;border-color:transparent}
textarea{min-height:82px;resize:vertical;line-height:1.5}
label{display:block;font-weight:600;margin:1rem 0 .3rem;font-size:.86rem}
.hint{color:var(--muted);font-size:.82rem;font-weight:400;line-height:1.45}
label .hint{display:block;margin-top:.15rem}
.row{display:flex;gap:.5rem;flex-wrap:wrap;align-items:center}
.between{display:flex;gap:1rem;align-items:flex-start;justify-content:space-between;flex-wrap:wrap;margin-bottom:.4rem}

/* choice cards, replacing radio buttons and native confirms */
.choices{display:grid;gap:.45rem;margin-top:.35rem}
.choice{display:flex;gap:.7rem;align-items:flex-start;padding:.7rem .85rem;border:1px solid var(--line2);
  border-radius:var(--r);cursor:pointer;background:var(--surface2);transition:border-color .12s ease,background .12s ease}
.choice:hover{border-color:var(--muted)}
.choice input{position:absolute;opacity:0;width:0;height:0}
.choice .mark{width:17px;height:17px;border-radius:50%;border:2px solid var(--line2);flex:0 0 auto;margin-top:2px;
  display:grid;place-items:center}
.choice input:checked ~ .mark{border-color:var(--brand)}
.choice input:checked ~ .mark::after{content:"";width:9px;height:9px;border-radius:50%;background:var(--brand)}
.choice:has(input:checked){border-color:var(--brand);background:var(--surface3)}
.choice .txt{display:flex;flex-direction:column;gap:.15rem;min-width:0}
.choice .t{display:block;font-weight:600;font-size:.9rem}
.choice .d{display:block;color:var(--muted);font-size:.8rem;line-height:1.4}

/* ---------------------------------------------------------------- photos */
.shots{display:grid;grid-template-columns:repeat(auto-fill,minmax(84px,1fr));gap:.5rem;margin-top:.5rem}
.shot{position:relative;aspect-ratio:1;border-radius:var(--r);overflow:hidden;border:1px solid var(--line2);background:var(--surface3)}
.shot img{width:100%;height:100%;object-fit:cover;display:block}
.shot .x{position:absolute;top:3px;right:3px;width:22px;height:22px;border-radius:50%;border:0;
  background:var(--bad);color:#fff;font-size:13px;line-height:1;cursor:pointer;display:grid;place-items:center;padding:0}
.shot .bar{position:absolute;left:0;right:0;bottom:0;height:3px;background:var(--line2)}
.shot .bar i{display:block;height:100%;background:var(--grad-to);width:0;transition:width .2s ease}
.addshot{display:flex;flex-direction:column;align-items:center;justify-content:center;gap:.25rem;
  aspect-ratio:1;border-radius:var(--r);border:1px dashed var(--line2);background:var(--surface2);
  color:var(--muted);cursor:pointer;font-size:.72rem;font-weight:600;text-align:center;padding:.3rem}
.addshot:hover{border-color:var(--brand);color:var(--ink2)}
.addshot svg{width:19px;height:19px;stroke:currentColor;fill:none;stroke-width:1.7}
.shotrow{display:grid;grid-template-columns:1fr 1fr;gap:.5rem;margin-top:.5rem}

/* ---------------------------------------------------------------- tables */
.scroll{overflow-x:auto;border:1px solid var(--line);border-radius:var(--r2);background:var(--surface)}
.scroll thead th{position:sticky;top:0;background:var(--surface);z-index:1}
table{width:100%;border-collapse:collapse;font-variant-numeric:tabular-nums}
th,td{text-align:left;padding:.78rem .9rem;border-bottom:1px solid var(--line);vertical-align:top;font-size:.88rem;line-height:1.45}
tbody tr:last-child td{border-bottom:0}
tbody tr:hover td{background:var(--surface2)}
/* A reference, a priority code or a date must never wrap: split over two lines
   they stop reading as one token. The first column of every table here is one
   of those; long prose sits in the middle columns, where wrapping is correct. */
th:first-child,td:first-child{white-space:nowrap}
th{font-size:.71rem;text-transform:uppercase;letter-spacing:.06em;color:var(--muted);font-weight:500;
  background:var(--surface2);position:sticky;top:0}

/* ----------------------------------------------------------------- sheet */
.sheet-bg{position:fixed;inset:0;background:#0b0e12;z-index:40;display:none}
.sheet-bg.on{display:block;animation:fade .16s ease}
@media (prefers-color-scheme:light){ .sheet-bg{background:#2b3440} }
.sheet{position:fixed;top:0;right:0;bottom:0;width:min(30rem,100%);background:var(--surface);
  background-image:var(--surface-field);
  border-left:1px solid var(--line);z-index:41;display:none;flex-direction:column;box-shadow:var(--shadow)}
.sheet.on{display:flex;animation:slide .2s cubic-bezier(.2,.8,.2,1)}
.sheet header{padding:1.1rem 1.3rem .9rem;border-bottom:1px solid var(--line);position:relative}
.sheet header::before{content:"";position:absolute;inset:0 0 auto 0;height:3px;background:var(--grad)}
.sheet header h3{margin:0;font-size:1.02rem;letter-spacing:-.01em}
.sheet header .sub{color:var(--muted);font-size:.83rem;margin-top:.2rem}
.sheet .body{padding:.4rem 1.3rem 1.3rem;overflow-y:auto;flex:1}
.sheet footer{padding:.9rem 1.3rem;border-top:1px solid var(--line);display:flex;gap:.5rem;justify-content:flex-end;
  background:var(--surface2)}
@keyframes slide{from{transform:translateX(18px)}to{transform:none}}
@keyframes fade{from{opacity:0}to{opacity:1}}
@media (max-width:640px){ .sheet{width:100%;top:auto;height:88dvh;border-left:0;border-top:1px solid var(--line);border-radius:var(--r2) var(--r2) 0 0}
  @keyframes slide{from{transform:translateY(18px)}to{transform:none}} }

/* ------------------------------------------------------------- licence bar */
.licbar{padding:.7rem 22px;font-size:.88rem;font-weight:600;display:flex;gap:.8rem;align-items:center;
  border-bottom:1px solid var(--line);background:var(--surface2)}
.licbar .sp{flex:1}
.licbar.warn{color:var(--warn);border-bottom-color:var(--warn)}
.licbar.urgent{color:var(--bad);border-bottom-color:var(--bad)}
.licbar.block{color:#fff;background:var(--bad);border-bottom-color:var(--bad)}
.licbar span{min-width:0}
.licbar button{white-space:nowrap;flex:none;font:inherit;font-weight:700;font-size:.82rem;padding:.3rem .7rem;border-radius:999px;
  border:1px solid currentColor;background:none;color:inherit;cursor:pointer}
.lockscreen{max-width:34rem;margin:14vh auto;text-align:center}
.lockscreen h2{font-size:1.3rem}
.lockscreen p{color:var(--muted);line-height:1.6}

/* --------------------------------------------------------------- notices */
.msg{margin:.8rem 0;padding:.7rem .95rem;border-radius:var(--r);border-left:3px solid var(--bad);
  background:var(--surface2);font-size:.88rem;line-height:1.5}
.msg.ok{border-left-color:var(--ok)}
.msg.warn{border-left-color:var(--warn)}
/* An empty state is an invitation, not an apology. It names the space, says in
   one line what lands here, and leaves the control that fills it on screen. */
.empty{color:var(--muted);padding:2.4rem 1.5rem;text-align:center;font-size:.9rem;line-height:1.6}
.empty strong{display:block;color:var(--ink);font-weight:500;font-size:1rem;margin-bottom:.3rem}
.empty em{font-style:normal;color:var(--ink2)}
code{font-size:.79rem;color:var(--muted);font-variant-numeric:tabular-nums}
[hidden]{display:none !important}

/* ---------------------------------------------------------------- next up
   One thing at the top, everything else quiet beneath it. The old dashboard
   gave a zero and a deadline the same weight, so good news competed with bad
   and the eye had nowhere to land. */
.nextwrap{margin:0 0 1.6rem}
.nextlabel{font-size:.78rem;letter-spacing:.06em;text-transform:uppercase;color:var(--muted);margin:0 0 .6rem}
.hero{background:var(--card);border:1px solid var(--line);border-radius:14px;padding:1.4rem 1.5rem}
.hero.breach{border-color:#b4232a;background:#1d1416}
.hero.urgent{border-color:#c8791b;background:#1d1810}
.heroTitle{font-size:1.45rem;font-weight:600;line-height:1.25;color:var(--fg)}
.heroDetail{margin-top:.5rem;color:var(--muted);font-size:.95rem;line-height:1.5}
.heroBar{height:6px;border-radius:3px;background:rgba(255,255,255,.08);overflow:hidden;margin:1rem 0 0}
.heroBar > i{display:block;height:100%;background:var(--accent);border-radius:3px}
.hero .btn{margin-top:1.1rem}
.rest{margin-top:.9rem;display:flex;flex-direction:column;gap:1px;
      border:1px solid var(--line);border-radius:12px;overflow:hidden}
.restRow{display:flex;align-items:center;gap:.9rem;padding:.85rem 1.1rem;background:var(--card);cursor:pointer;
         border:0;width:100%;text-align:left;font:inherit;color:inherit}
.restRow:hover{background:var(--card-2,rgba(255,255,255,.03))}
.restDot{width:9px;height:9px;border-radius:50%;flex:none;background:#5f5e5a}
.restDot.breach{background:#e24b4a}.restDot.urgent{background:#ef9f27}
.restDot.soon{background:#97c459}.restDot.later{background:#5f5e5a}
.restMain{flex:1;min-width:0}
.restTitle{font-size:.95rem;color:var(--fg);line-height:1.35}
.restDetail{font-size:.82rem;color:var(--muted);margin-top:.15rem;
            overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.restWhen{font-size:.82rem;color:var(--muted);flex:none}
.allclear{padding:1.2rem 0;color:var(--muted);font-size:.95rem}
.detail{margin-top:1.8rem;border-top:1px solid var(--line);padding-top:1rem}
.detail > summary{cursor:pointer;color:var(--muted);font-size:.9rem;list-style:none}
.detail > summary::-webkit-details-marker{display:none}
.detail > summary::before{content:"▸ ";color:var(--muted)}
.detail[open] > summary::before{content:"▾ "}

/* ==================================================================== shell
   The rail. Eleven tabs asked for eleven decisions before any work started;
   four destinations ask for one, and the secondary row only appears once you
   have chosen. Nothing here names a tenant: --brand and the display face both
   arrive at runtime from /api/brand. */
/* No <body> tag in the page, so the browser's implicit one cannot carry a
   class. The grid lives on a wrapper. */
.shell{display:grid;grid-template-columns:74px minmax(0,1fr);min-height:100vh;margin:0}
.rail{background:var(--surface);border-right:1px solid var(--line);
      display:flex;flex-direction:column;align-items:center;gap:6px;padding:22px 0 18px;position:sticky;top:0;height:100vh;height:100dvh;align-self:start}
/* align-self:start: Safari lets a stretched grid item scroll away instead of sticking,
   so the menu left the screen on a long page (16/09/2026). */
/* The rail carries ONE brand moment, and it is the real lockup at the foot.
   A generic shield-in-a-square at the top duplicated the header's lockup with
   artwork that was not even the customer's - three marks on one screen, none of
   them earning its place. */
.railBtn{width:46px;height:46px;border-radius:13px;border:0;background:transparent;cursor:pointer;
      display:grid;place-items:center;color:var(--muted);position:relative;transition:background .16s,color .16s}
.railBtn svg{width:21px;height:21px;display:block}
.railBtn:hover{background:var(--surface2);color:var(--ink2)}
.railBtn[aria-current="page"]{background:var(--surface3);color:var(--brand)}
.railBtn:focus-visible{outline:2px solid var(--brand);outline-offset:2px}
.railBtn .tip{position:absolute;left:calc(100% + 10px);top:50%;transform:translateY(-50%);
      background:var(--surface3);border:1px solid var(--line2);color:var(--ink);padding:5px 11px;
      border-radius:8px;font-size:.82rem;white-space:nowrap;opacity:0;pointer-events:none;transition:opacity .14s;z-index:40}
.railBtn:hover .tip,.railBtn:focus-visible .tip{opacity:1}
.railSpacer{flex:1}
.railDot{position:absolute;top:9px;right:9px;width:7px;height:7px;border-radius:50%;
      background:var(--bad);border:2px solid var(--surface)}

.col{min-width:0;padding:22px 28px 48px;max-width:1220px}
.topline{display:flex;align-items:center;gap:14px;margin-bottom:18px;flex-wrap:wrap}
.topline h1{font-size:1.55rem;margin:0;line-height:1.15;letter-spacing:-.01em}
.topline .meta{font-size:.82rem;color:var(--muted);margin-top:1px}
.topline .sp{flex:1}

/* secondary: only the views inside the chosen destination */
.subnav{display:flex;gap:4px;flex-wrap:wrap;margin:0 0 22px;padding:3px;
      background:var(--surface);border:1px solid var(--line);border-radius:12px;width:fit-content}
.subnav[hidden]{display:none}
.subnav button{border:0;background:transparent;color:var(--muted);font:inherit;font-size:.86rem;
      padding:7px 15px;border-radius:9px;cursor:pointer;transition:background .16s,color .16s}
.subnav button:hover{color:var(--ink2)}
.subnav button[aria-selected="true"]{background:var(--surface3);color:var(--ink)}
.subnav button:focus-visible{outline:2px solid var(--brand);outline-offset:1px}

/* ---- the home screen ---- */
.heroCard{background:var(--surface);border:1px solid var(--line);border-radius:var(--r2);
      padding:26px;display:flex;gap:26px;align-items:center;position:relative;overflow:hidden}
.heroCard::before{content:"";position:absolute;left:0;top:0;bottom:0;width:3px;background:var(--muted)}
.heroCard.urgent::before{background:var(--warn)}
.heroCard.breach::before{background:var(--bad)}
.eyebrow{font-size:.7rem;letter-spacing:.14em;text-transform:uppercase;color:var(--muted);
      display:flex;align-items:center;gap:7px;margin-bottom:11px;white-space:nowrap}
.eyebrow i{width:6px;height:6px;border-radius:50%;background:currentColor;display:block}
.heroCard.urgent .eyebrow{color:var(--warn)}
.heroCard.breach .eyebrow{color:var(--bad)}
.heroBody{flex:1;min-width:0}
.heroH{font-size:1.85rem;font-weight:600;line-height:1.15;letter-spacing:-.015em;margin:0 0 8px;text-wrap:balance}
.heroP{color:var(--ink2);font-size:.95rem;margin:0;max-width:54ch;line-height:1.55}
.heroActs{display:flex;gap:8px;margin-top:18px;flex-wrap:wrap}

/* NOT .ring - that name was already taken by the 26px inline ring above, whose
   transform:rotate(-90deg) sits on the CONTAINER and would rotate this one's
   centred text with it. The arc's rotation belongs on the circle as an SVG
   attribute, where no cascade can reach it. */
.dial{position:relative;width:128px;height:128px;flex:none}
.dial svg{width:128px;height:128px;display:block}
.dialMid{position:absolute;inset:0;display:grid;place-content:center;text-align:center}
.dialNum{font-size:2rem;font-weight:600;line-height:1;font-variant-numeric:tabular-nums}
.dialSub{font-size:.76rem;color:var(--muted);margin-top:4px}

.visits{display:grid;grid-template-columns:repeat(auto-fit,minmax(130px,1fr));gap:10px}
.visit{background:var(--surface2);border:1px solid var(--line);border-radius:var(--r);padding:14px}
.visit.next{border-color:var(--brand);background:var(--surface3)}
.visitWhen{font-size:.7rem;letter-spacing:.1em;text-transform:uppercase;color:var(--muted);margin-bottom:8px}
.visit.next .visitWhen{color:var(--brand)}
.visitNum{font-size:1.7rem;font-weight:600;line-height:1;font-variant-numeric:tabular-nums}
.visitWhat{font-size:.8rem;color:var(--ink2);margin-top:6px;line-height:1.45}
.visitFlag{font-size:.78rem;color:var(--warn);margin-top:5px}

.rows{display:flex;flex-direction:column}
.row2{display:flex;align-items:center;gap:12px;padding:12px 0;border-top:1px solid var(--line);
      background:none;border-left:0;border-right:0;border-bottom:0;width:100%;text-align:left;
      font:inherit;color:inherit;cursor:pointer}
.row2:first-child{border-top:0}
.row2:hover{background:var(--surface2)}
.row2:focus-visible{outline:2px solid var(--brand);outline-offset:-2px}
.sev{width:8px;height:8px;border-radius:50%;flex:none;background:var(--muted)}
.sev.breach{background:var(--bad)}.sev.urgent{background:var(--warn)}
.sev.soon{background:var(--ok)}.sev.later{background:var(--muted)}
.rowMain{flex:1;min-width:0}
/* Both are spans inside a span, so without this they set on one line and the
   muted detail runs straight into the title with no space at all - and the
   margin-top below did nothing, because margins do not apply to inline boxes. */
.rowT{display:block;font-size:.92rem;line-height:1.35}
.rowS{display:block;font-size:.8rem;color:var(--muted);margin-top:3px;
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap}

.side{display:flex;flex-direction:column;gap:16px}
.homeCols{display:grid;grid-template-columns:minmax(0,1.6fr) minmax(0,1fr);gap:16px;align-items:start}
@media(max-width:920px){.homeCols{grid-template-columns:minmax(0,1fr)}
  .shell{grid-template-columns:60px minmax(0,1fr)} .col{padding:18px 16px 40px}}
.stat{display:flex;align-items:baseline;gap:9px;padding:12px 0;border-top:1px solid var(--line)}
.stat:first-of-type{border-top:0}
.statNum{font-size:1.4rem;font-weight:600;line-height:1;font-variant-numeric:tabular-nums}
.statL{font-size:.85rem;color:var(--ink2)}
.statN{margin-left:auto;font-size:.78rem;color:var(--muted)}

/* ================================================================ the expert
   A floating button that pulses UNTIL IT HAS BEEN USED, then stops. A pulse
   that never ends is a pulse people stop seeing, and on a console someone sits
   in all day it becomes an irritation rather than an invitation. */
.askBtn{position:fixed;right:20px;bottom:20px;z-index:60;width:54px;height:54px;border-radius:50%;
  border:1px solid var(--line2);background:var(--brand);color:var(--paper);cursor:pointer;
  display:grid;place-items:center;box-shadow:var(--shadow)}
.askBtn svg{width:23px;height:23px;display:block}
.askBtn:hover{filter:brightness(1.08)}
.askBtn:focus-visible{outline:2px solid var(--ink);outline-offset:3px}
.askBtn.pulse::after{content:"";position:absolute;inset:-4px;border-radius:50%;
  border:2px solid var(--brand);animation:askPulse 2.4s ease-out infinite}
@keyframes askPulse{0%{transform:scale(.9);opacity:.75}70%{transform:scale(1.35);opacity:0}100%{opacity:0}}
@media(prefers-reduced-motion:reduce){.askBtn.pulse::after{animation:none;opacity:.5}}

.askPanel{position:fixed;right:20px;bottom:86px;z-index:61;width:min(390px,calc(100vw - 40px));
  max-height:min(560px,calc(100vh - 130px));display:flex;flex-direction:column;
  background:var(--surface);border:1px solid var(--line2);border-radius:16px;overflow:hidden;box-shadow:var(--shadow)}
.askPanel[hidden]{display:none}
.askHd{display:flex;align-items:center;gap:10px;padding:14px 16px;border-bottom:1px solid var(--line)}
.askHd strong{font-weight:500;font-size:.95rem}
.askHd .hint{margin-left:auto;font-size:.72rem}
.askClose{border:0;background:transparent;color:var(--muted);cursor:pointer;font-size:1.2rem;
  line-height:1;min-width:44px;min-height:44px;border-radius:9px}
.askClose:hover{background:var(--surface2);color:var(--ink)}
.askBody{overflow-y:auto;padding:6px 0 10px}
.askQ{width:100%;text-align:left;border:0;background:transparent;color:var(--ink2);font:inherit;
  font-size:.88rem;padding:11px 16px;cursor:pointer;display:block;border-bottom:1px solid var(--line)}
.askQ:hover{background:var(--surface2);color:var(--ink)}
.askQ:focus-visible{outline:2px solid var(--brand);outline-offset:-2px}
.askA{padding:14px 16px;font-size:.89rem;line-height:1.62;color:var(--ink2);border-bottom:1px solid var(--line)}
.askA h4{margin:0 0 .45rem;font-size:.95rem;font-weight:500;color:var(--ink)}
.askA b{color:var(--ink);font-weight:500}
.askA .src{margin-top:.7rem;font-size:.76rem;color:var(--muted)}
.askFoot{padding:12px 16px;border-top:1px solid var(--line);display:flex;gap:8px}
.askFoot input{flex:1;min-width:0}
.askNone{padding:16px;font-size:.86rem;color:var(--muted);line-height:1.6}

/* ---- feature requests, inside the expert panel ---- */
.askTabs{display:flex;gap:3px;padding:8px 10px;border-bottom:1px solid var(--line)}
.askTabs button{flex:1;border:0;background:transparent;color:var(--muted);font:inherit;font-size:.82rem;
  padding:7px 10px;border-radius:8px;cursor:pointer}
.askTabs button[aria-selected="true"]{background:var(--surface3);color:var(--ink)}
.askTabs button:focus-visible{outline:2px solid var(--brand);outline-offset:-2px}
.reqWrap{padding:14px 16px;display:flex;flex-direction:column;gap:12px}
.reqWrap textarea{min-height:82px;resize:vertical}
.reqQ{border-top:1px solid var(--line);padding-top:11px}
.reqQ label{display:block;font-size:.84rem;color:var(--ink2);margin-bottom:.3rem}
.reqQ .hint{display:block;margin-bottom:.35rem}
.reqMeter{display:flex;align-items:center;gap:9px;font-size:.78rem;color:var(--muted)}
.reqMeter .bar{flex:1;height:5px;border-radius:3px;background:var(--surface3);overflow:hidden}
.reqMeter .bar i{display:block;height:100%;background:var(--warn);border-radius:3px;transition:width .25s ease}
.reqMeter.good .bar i{background:var(--brand)}
.reqSug{background:var(--surface2);border:1px solid var(--line);border-radius:var(--r);padding:12px;font-size:.85rem;line-height:1.55}
.reqSug h5{margin:0 0 .3rem;font-size:.85rem;font-weight:500;color:var(--ink)}
.reqSug ul{margin:.4rem 0 0;padding-left:1.1rem}
.reqSug li{margin:.15rem 0}

/* ---------------------------------------------------- rail, expandable
   Collapsed it is a strip of icons; expanded it names every destination and
   the views inside it. The width is the only thing that animates - sliding
   content in and out of a rail is motion for its own sake. */
.shell{transition:grid-template-columns .2s ease}
.shell.wide{grid-template-columns:216px minmax(0,1fr)}
.rail{overflow:hidden}
.shell.wide .rail{align-items:stretch;padding:18px 12px}
.railLabel{display:none;font-size:.9rem;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.shell.wide .railLabel{display:block}
.shell.wide .railBtn{width:100%;justify-content:flex-start;display:flex;align-items:center;gap:12px;padding:0 12px}
.shell.wide .railBtn .tip{display:none}
.railSub{display:none;flex-direction:column;gap:1px;margin:2px 0 6px 20px;padding-left:12px;border-left:1px solid var(--line)}
.shell.wide .railSub.open{display:flex}
.railSub button{border:0;background:transparent;color:var(--muted);font:inherit;font-size:.82rem;
  text-align:left;padding:6px 10px;border-radius:8px;cursor:pointer;white-space:nowrap;
  overflow:hidden;text-overflow:ellipsis}
.railSub button:hover{background:var(--surface2);color:var(--ink2)}
.railSub button[aria-current="page"]{color:var(--brand)}
.railToggle{width:100%;border:0;background:transparent;color:var(--muted);cursor:pointer;
  display:flex;align-items:center;gap:12px;padding:10px 12px;border-radius:11px;font:inherit;font-size:.82rem}
.railToggle:hover{background:var(--surface2);color:var(--ink2)}
.railToggle svg{width:18px;height:18px;flex:none;transition:transform .2s ease}
.shell.wide .railToggle svg{transform:rotate(180deg)}

/* ---------------------------------------------------------- search anything */
.searchBtn{display:flex;align-items:center;gap:8px;background:var(--surface);border:1px solid var(--line);
  color:var(--muted);border-radius:11px;padding:8px 12px;cursor:pointer;font:inherit;font-size:.86rem}
.searchBtn:hover{border-color:var(--line2);color:var(--ink2)}
.searchBtn kbd{font-family:inherit;font-size:.72rem;border:1px solid var(--line2);border-radius:5px;
  padding:1px 5px;color:var(--muted)}
.sOverlay{position:fixed;inset:0;z-index:80;background:#000a;display:grid;place-items:start center;padding-top:11vh}
.sOverlay[hidden]{display:none}
.sBox{width:min(620px,calc(100vw - 32px));background:var(--surface);border:1px solid var(--line2);
  border-radius:16px;overflow:hidden;box-shadow:var(--shadow);max-height:70vh;display:flex;flex-direction:column}
.sBox input{border:0;border-bottom:1px solid var(--line);border-radius:0;font-size:1rem;padding:16px 18px;background:transparent}
.sBox input:focus{outline:none;box-shadow:none}
.sResults{overflow-y:auto}
.sGroup{font-size:.68rem;letter-spacing:.12em;text-transform:uppercase;color:var(--muted);padding:12px 18px 5px}
.sHit{display:flex;align-items:center;gap:12px;width:100%;border:0;background:transparent;color:inherit;
  font:inherit;text-align:left;padding:9px 18px;cursor:pointer}
.sHit:hover,.sHit.on{background:var(--surface2)}
.sHit .t{flex:1;min-width:0;font-size:.9rem;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.sHit .s{font-size:.78rem;color:var(--muted);flex:none}
.sHit .ic{width:26px;height:26px;border-radius:7px;background:var(--surface3);display:grid;place-items:center;
  flex:none;font-size:.68rem;color:var(--muted);text-transform:uppercase}
.sNone{padding:26px 18px;color:var(--muted);font-size:.88rem;text-align:center}
.sFoot{border-top:1px solid var(--line);padding:9px 18px;font-size:.75rem;color:var(--muted);display:flex;gap:14px}

/* ---- document summary, collapsed by default ----
   Muted and one line of reveal: the table is for scanning, and a summary that
   pushes every other row off the screen stops the table doing its job. */
.docToggle{border:0;background:transparent;color:var(--muted);cursor:pointer;font:inherit;
  padding:0;display:inline-flex;align-items:center;gap:.45rem;text-align:left}
.docToggle:hover{color:var(--ink)}
.docToggle .chev{display:inline-block;transition:transform .16s ease;font-size:.7rem;color:var(--muted);flex:none}
.docToggle[aria-expanded="true"] .chev{transform:rotate(90deg)}
.docToggle:focus-visible{outline:2px solid var(--brand);outline-offset:2px;border-radius:5px}
tr.docSum td{padding-top:0;border-bottom:1px solid var(--line);color:var(--muted);
  font-size:.84rem;line-height:1.55}
tr.docSum .inner{display:flex;gap:1rem;align-items:baseline;max-width:80ch}
tr.docSum .conf{margin-left:auto;flex:none;font-size:.76rem;white-space:nowrap}
tr.docSum .none{font-style:normal;opacity:1}

/* ---- the brand hero, anchoring the foot of the rail ----
   Quiet through SIZE and PLACEMENT, never through opacity: GSG's guidelines
   forbid fading a brand colour, because a tint invents a value outside the
   approved palette. So the shield keeps its full colour and simply sits small,
   low, and apart from the navigation. */
/* Targeted by ID, not class. applyBrand takes the element over completely and
   strips its className - so every .railHero rule silently stopped matching the
   moment the brand loaded, and the wordmark stayed visible in the collapsed
   rail with its left half cut off. */
#railHero{margin:0 0 8px;padding:14px 12px 12px;border-top:1px solid var(--line);
  display:flex;align-items:center;gap:.6rem;min-height:52px}
.shell:not(.wide) #railHero{justify-content:center;padding:14px 0 12px}
/* Collapsed, the wordmark has nowhere to go. applyBrand writes inline styles,
   so these have to win. */
.shell:not(.wide) #railHero span{display:none!important}
.shell:not(.wide) #railHero img{height:26px!important}
.shell.wide #railHero img{height:30px!important}
.shell.wide #railHero span{font-size:.68rem!important;letter-spacing:.09em!important}

/* A sheet is a focused task. The help button sits at a higher z-index than the
   sheet (60 vs 41) and was covering its primary action, so it stands down while
   one is open rather than being re-layered underneath, where a tap on the OK
   button's edge would still have hit it. */
html.sheet-open .askBtn,
html.sheet-open .askPanel{display:none}

/* A download control on every register, and on every row. Quiet: exporting is
   something you do occasionally, not the reason you opened the screen. */
.expBtn{border:1px solid var(--line);background:transparent;color:var(--muted);cursor:pointer;
  font:inherit;font-size:.78rem;padding:4px 9px;border-radius:8px;white-space:nowrap}
.expBtn:hover{border-color:var(--line2);color:var(--ink)}
.expBtn:focus-visible{outline:2px solid var(--brand);outline-offset:1px}
.expBtn[disabled]{opacity:1;color:var(--muted);cursor:default}

/* ---- signing ----
   The declaration sits ABOVE the pen, on the glass. A signature collected under
   a label that says "Signature" asserts nothing; one collected under a sentence
   in the first person asserts that sentence. */
.sigwrap{display:flex;flex-direction:column;gap:.5rem}
.sigdec{background:var(--surface2);border:1px solid var(--line);border-radius:var(--r);
  padding:.7rem .85rem;font-size:.86rem;line-height:1.5;color:var(--ink)}
.sigpad{position:relative;background:#fff;border:1px solid var(--line2);border-radius:var(--r);
  height:150px;touch-action:none;overflow:hidden}
.sigpad canvas{display:block;width:100%;height:100%}
.sigpad .ph{position:absolute;inset:0;display:grid;place-items:center;color:#8b93a0;
  font-size:.86rem;pointer-events:none}
.sigpad.signed .ph{display:none}
.sigrow{display:flex;gap:.5rem;align-items:center}
.sigrow .hint{flex:1}
.sugg{display:flex;gap:.35rem;flex-wrap:wrap;margin-top:.4rem}
.sugg button{border:1px solid var(--line);background:transparent;color:var(--ink2);font:inherit;
  font-size:.8rem;padding:4px 10px;border-radius:999px;cursor:pointer}
.sugg button:hover{border-color:var(--brand);color:var(--ink)}

/* ================================================== the travelling indicator
   ONE element moves between items. Every nav here used to toggle a background
   on and off, which is a cut, not a transition - the eye loses the selection
   and finds it again somewhere else.
   The deformation is the point: during travel the bead compresses across its
   travel axis and lets out along the other, then settles. That is what reads as
   a surface moving rather than a rectangle teleporting. */
.hasBead{position:relative}
.hasBead > .bead{
  position:absolute;top:0;left:0;height:100%;border-radius:9px;background:var(--surface3);
  transform:translate3d(0,0,0);transform-origin:center;pointer-events:none;z-index:0;
  transition:transform .38s cubic-bezier(.22,1,.36,1),
             width .38s cubic-bezier(.22,1,.36,1),
             opacity .18s ease;
  will-change:transform,width;
}
.hasBead > .bead[hidden]{display:none}
.hasBead > *{position:relative;z-index:1}
/* Selected items keep their OWN colour; only the plate beneath them travels. */
.subnav.hasBead button[aria-selected="true"],
.seg.hasBead button[aria-pressed="true"]{background:transparent}
.rail.hasBead .railBtn[aria-current="page"]{background:transparent}
.rail.hasBead > .bead{border-radius:13px;background:var(--surface3)}

@media(prefers-reduced-motion:reduce){
  .hasBead > .bead{transition:none}
}

/* The source's own words, under the finding they belong to. Quieter and
   italic, so the row reads as our summary first and the evidence second -
   and never the other way round, which would make the register look like a
   transcript of somebody else's report. */
.quote{display:block;margin-top:.3rem;color:var(--muted);font-size:.78rem;
  font-style:italic;line-height:1.45;max-width:62ch}
.quoteWhere{display:block;margin-top:.2rem;color:var(--muted);font-size:.72rem;
  letter-spacing:.02em;opacity:.8}

/* SEVERITY ACCENT. A pill states the severity; a row of pills all the same
   shape still has to be read one by one. A coloured bar down the left of the
   row is seen before anything is read, so "immediate" is found by scanning
   rather than by reading. Applied to the row, not the cell, so it reads as a
   property of the finding.

   The bar is the ONLY colour carried - not a tinted row. A red-washed row on a
   register where a third of the entries are high would leave the eye nowhere
   to rest, and the one immediate item would stop standing out at all. */
tr[data-sev]>td:first-child{position:relative;padding-left:1rem}
tr[data-sev]>td:first-child::before{content:"";position:absolute;left:0;top:6px;bottom:6px;
  width:3px;border-radius:2px;background:var(--line)}
tr[data-sev="immediate"]>td:first-child::before{background:var(--bad);width:4px;top:3px;bottom:3px}
tr[data-sev="high"]>td:first-child::before{background:var(--warn)}
tr[data-sev="investigate"]>td:first-child::before{background:color-mix(in srgb,var(--muted) 55%,transparent)}
tr[data-sev="low"]>td:first-child::before{background:transparent}
/* Immediate is the only one that also carries weight in the type: it is the
   category where a delay is a safety matter, not a housekeeping one. */
tr[data-sev="immediate"]>td:first-child{font-weight:600}

/* A staged proposal carries the same severity accent as a register row, and
   for the same reason: the immediate one should be found by scanning. Drawn
   as a left border rather than the table-cell background, because these are
   cards and there is no first cell to paint. */
.inspRow{border-left:3px solid var(--line)}
.inspRow[data-sev="immediate"]{border-left-color:var(--bad);border-left-width:4px}
.inspRow[data-sev="high"]{border-left-color:var(--warn)}
.inspRow[data-sev="investigate"]{border-left-color:color-mix(in srgb,var(--muted) 55%,transparent)}

/* ================================================ the records screens, lifted
   These two arrived built to the plain house components (card, table, pill)
   while the shell next door had already been taken to the reference standard.
   Same vocabulary as the home screen - heroCard, dial, rows, stat - so there is
   one visual language across the console rather than two tiers. */

.mainCol{display:flex;flex-direction:column;gap:16px;min-width:0}

/* A label whose VALUE is long ("Rivington Energy Ltd (asset manager, Jack
   Payne)") cannot sit on the same line as its label: .stat pushes the value
   right with margin-left:auto and the two collide, then wrap into each other.
   Stacked, the value gets the full width and the eye still reads label-first. */
.statStack{padding:11px 0;border-top:1px solid var(--line)}
.statStack:first-of-type{border-top:0}
.statStack .k{display:block;font-size:.74rem;letter-spacing:.06em;text-transform:uppercase;color:var(--muted)}
.statStack .v{display:block;font-size:.9rem;color:var(--ink2);margin-top:4px;line-height:1.45}

/* The state of a row, quietly. Fifteen identical pills stacked down a list is a
   wall that has to be read line by line to learn nothing - the summary belongs
   in the header, and the row only needs to speak when it DIFFERS. So the
   ordinary state is muted text and only an exception gets colour. */
.rowMeta{display:flex;align-items:center;gap:10px;flex:none;font-size:.78rem;color:var(--muted);
  text-align:right;white-space:nowrap}
.rowMeta .on{color:var(--ok)}
.rowMeta .att{color:var(--warn)}

.row2[aria-expanded]{align-items:flex-start}
.row2 .chev{flex:none;width:14px;height:14px;margin-top:3px;color:var(--muted);transition:transform .16s}
.row2[aria-expanded="true"] .chev{transform:rotate(90deg)}
.rowOpen{padding:2px 0 14px 20px;border-top:0}
.rowOpen .quote{margin:0;max-width:70ch}

/* The severity mix, as a bar rather than three numbers. One immediate item
   among fifteen is the fact worth seeing, and a count of "1" set beside a count
   of "9" does not carry it; a red sliver against amber does. */
.sevBar{display:flex;height:6px;border-radius:3px;overflow:hidden;margin:2px 0 12px;background:var(--line)}
.sevBar span{display:block}
.sevBar .s-immediate{background:var(--bad)}
.sevBar .s-high{background:var(--warn)}
.sevBar .s-investigate{background:var(--line2)}
.sevBar .s-low{background:var(--surface3)}
.sevKey{display:flex;flex-wrap:wrap;gap:12px;font-size:.78rem;color:var(--muted)}
.sevKey b{font-weight:600;color:var(--ink2);font-variant-numeric:tabular-nums}
.sevKey i{display:inline-block;width:8px;height:8px;border-radius:2px;margin-right:5px}

/* A 64-character hash is data, not prose: monospaced so it can be compared by
   eye, and allowed to break anywhere because it has no break opportunities. */
.hash{display:block;font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-size:.76rem;
  color:var(--ink2);overflow-wrap:anywhere;line-height:1.5}

/* ---- a proposal awaiting a decision ----
   Not a table row: each one carries a summary, the inspector's own words, the
   reasoning behind the proposal, and two controls. That is a CARD's worth of
   content, and forcing it into a row is what made the first pass read as a
   spreadsheet. The severity accent is a left border here rather than the
   cell-background trick the tables use, because there is no first cell. */
.props{display:flex;flex-direction:column;gap:10px}
.propCard{background:var(--surface2);border:1px solid var(--line);border-left:3px solid var(--line2);
  border-radius:var(--r);padding:15px 16px}
.propCard[data-sev="immediate"]{border-left-color:var(--bad);border-left-width:4px}
.propCard[data-sev="high"]{border-left-color:var(--warn)}
.propCard[data-sev="investigate"]{border-left-color:var(--line2)}
.propTop{display:flex;align-items:center;justify-content:space-between;gap:12px;flex-wrap:wrap}
.propHead{display:flex;align-items:center;gap:8px;flex-wrap:wrap;min-width:0}
.propRef{font-size:.74rem;letter-spacing:.08em;color:var(--muted);font-variant-numeric:tabular-nums}
.propSev{font-size:.72rem;letter-spacing:.06em;text-transform:uppercase;font-weight:600}
.propSev.s-immediate{color:var(--bad)} .propSev.s-high{color:var(--warn)}
.propSev.s-investigate,.propSev.s-low{color:var(--muted)}
.tag{font-size:.7rem;color:var(--ink2);background:var(--surface3);border-radius:999px;padding:2px 8px}
.tag.q{color:var(--muted);background:transparent;border:1px solid var(--line2)}
/* The proposed answer, stated once and plainly. "Needs your call" is the only
   one that gets colour, because it is the only one that stops the page. */
.propAct{font-size:.76rem;font-weight:500;color:var(--muted);white-space:nowrap}
.propAct.a-unclear{color:var(--warn)}
.propSum{font-size:.98rem;line-height:1.4;margin:.6rem 0 0}
/* The REASONING. On screen at full opacity, not folded away: a proposal nobody
   can interrogate is one nobody can responsibly confirm. */
.propWhy{font-size:.82rem;color:var(--ink2);line-height:1.5;margin:.6rem 0 0;
  padding-left:11px;border-left:2px solid var(--line2)}
.propCtl{display:flex;gap:8px;align-items:center;margin-top:.85rem;flex-wrap:wrap}
.propWarn{font-size:.78rem;color:var(--warn);line-height:1.5;margin:.65rem 0 0}
.propWarn b{font-weight:600}

/* ================================================= plain-English hover helper
   Every number, badge and control on these screens is shorthand for something
   with a consequence - "inherited", "not seen", "flagged", a severity, a hash.
   Somebody who did not build it should be able to find out what one means
   without leaving the page or asking.

   ONE floating element, moved and filled on demand, rather than a tooltip per
   trigger: a tooltip nested inside a card is clipped by the card's own
   overflow, and the register is full of scrolling containers.

   It answers to FOCUS as well as hover, so it is reachable from the keyboard
   and does not hide anything from a screen reader - the same text is on the
   trigger's aria-label. It is help, never the only place a fact appears. */
/* --line2 is a border colour: as an underline on a dark ground it is invisible,
   which makes the affordance no affordance at all. Muted reads as a hint
   without competing with the text it sits under. */
/* Drawn as a repeating background rule, not text-decoration. A dotted
   underline at 1px did not render at all in the print/headless path and was
   invisible on screen too, so the affordance was no affordance. This is a
   painted gradient: it always shows, and it sits clear of descenders. */
.hasHelp{cursor:help;padding-bottom:2px;
  background-image:linear-gradient(to right,var(--muted) 0 2px,transparent 2px 5px);
  background-size:5px 1px;background-repeat:repeat-x;background-position:0 100%}
.hasHelp:hover,.hasHelp:focus-visible{color:var(--ink);
  background-image:linear-gradient(to right,var(--ink2) 0 2px,transparent 2px 5px)}
.hasHelp:focus-visible{outline:2px solid var(--brand);outline-offset:2px;border-radius:3px}
button.hasHelp,select.hasHelp,label.hasHelp{background-image:none;padding-bottom:0;cursor:pointer}
#helpTip{position:fixed;z-index:90;max-width:min(30rem,calc(100vw - 32px));
  background:var(--surface3);color:var(--ink2);border:1px solid var(--line2);
  border-radius:10px;padding:9px 12px;font-size:.82rem;line-height:1.5;
  box-shadow:var(--shadow);pointer-events:none;opacity:0;transform:translateY(3px);
  transition:opacity .12s ease,transform .12s ease}
#helpTip[data-on]{opacity:1;transform:translateY(0)}
#helpTip b{color:var(--ink);font-weight:600}
@media(prefers-reduced-motion:reduce){#helpTip{transition:none}}

/* ======================================================= glass surfaces
   Steven, 13/09/2026, choosing between two mock-ups: the restrained one, and
   explicitly NOT the vivid neon ground beside it.

   THE COLOURS ARE DERIVED, NOT INVENTED. The mock-up that was approved used
   three hand-picked hexes; every one of them is expressed here as a mix of
   colours already in the palette, so the lifted ground traces back to the
   brand's own green and its navy accent rather than to my eye. The deviation
   noted on --bg-field above still stands and still wants regularising when GSG
   supply the toolkit - this does not add a second one.

   A raised ground is not decoration here: backdrop-filter blurs what is BEHIND
   an element, so over a near-flat field there is nothing to blur and the whole
   treatment is invisible. The ground is what makes the glass read. */
:root{
  --bg-lift1:color-mix(in srgb, var(--grad-from) 58%, var(--bg-mid));
  --bg-lift2:color-mix(in srgb, var(--accent2)  72%, var(--bg-mid));
  --bg-lift3:color-mix(in srgb, var(--grad-from) 34%, var(--bg-mid));
  --glass:color-mix(in srgb, var(--surface) 54%, transparent);
  --glass2:color-mix(in srgb, var(--surface2) 48%, transparent);
  --glassLine:color-mix(in srgb, #fff 12%, transparent);
  --glassTop:color-mix(in srgb, #fff 8%, transparent);
}
@media (prefers-color-scheme:light){
  :root{
    /* Light mode needs far less transparency: a white card at 54% over a pale
       ground is a grey smear, and the type loses its contrast with it. */
    --glass:color-mix(in srgb, var(--surface) 82%, transparent);
    --glass2:color-mix(in srgb, var(--surface2) 80%, transparent);
    --glassLine:color-mix(in srgb, var(--line2) 80%, transparent);
    --glassTop:color-mix(in srgb, #fff 70%, transparent);
    --bg-lift1:color-mix(in srgb, var(--grad-to) 22%, var(--bg-mid));
    --bg-lift2:color-mix(in srgb, var(--accent2) 14%, var(--bg-mid));
    --bg-lift3:color-mix(in srgb, var(--grad-to) 12%, var(--bg-mid));
  }
}

body{
  background-image:
    radial-gradient(46% 38% at 12% 6%,  var(--bg-lift1) 0%, transparent 62%),
    radial-gradient(40% 34% at 88% 2%,  var(--bg-lift2) 0%, transparent 60%),
    radial-gradient(52% 44% at 72% 88%, var(--bg-lift3) 0%, transparent 62%),
    var(--bg-field);
}

.card,.heroCard,.propCard,.visit,#helpTip{
  background-color:var(--glass);
  -webkit-backdrop-filter:blur(22px) saturate(150%);
  backdrop-filter:blur(22px) saturate(150%);
  border:1px solid var(--glassLine);
  box-shadow:0 1px 0 var(--glassTop) inset, 0 18px 40px rgba(0,0,0,.34);
}
.propCard{background-color:var(--glass2)}
/* The severity accent is the record's meaning and must not be softened into
   the glass: it keeps its own border colour and weight. */
.propCard[data-sev="immediate"]{border-left-color:var(--bad);border-left-width:4px}
.propCard[data-sev="high"]{border-left-color:var(--warn)}
.rail{
  background-color:color-mix(in srgb, var(--surface) 46%, transparent);
  -webkit-backdrop-filter:blur(26px) saturate(150%);
  backdrop-filter:blur(26px) saturate(150%);
  border-right:1px solid var(--glassLine);
}
.row2:hover{background:color-mix(in srgb, #fff 6%, transparent)}
.sevBar{background:color-mix(in srgb, #fff 10%, transparent)}

/* TWO WAYS OUT, both mandatory.
   Without support the cards would render at half opacity over a lifted ground
   with NO blur behind them, which is not a plainer look - it is unreadable
   text. And a reader who has asked their system to reduce transparency has
   usually asked for a reason. Both fall back to the solid surfaces. */
@supports not ((backdrop-filter:blur(1px)) or (-webkit-backdrop-filter:blur(1px))){
  .card,.heroCard,.visit,#helpTip{background-color:var(--surface);border-color:var(--line)}
  .propCard{background-color:var(--surface2);border-color:var(--line)}
  .rail{background-color:var(--surface)}
}
@media (prefers-reduced-transparency:reduce){
  .card,.heroCard,.visit,#helpTip{background-color:var(--surface);backdrop-filter:none;
    -webkit-backdrop-filter:none;border-color:var(--line)}
  .propCard{background-color:var(--surface2);backdrop-filter:none;-webkit-backdrop-filter:none}
  .rail{background-color:var(--surface);backdrop-filter:none;-webkit-backdrop-filter:none}
}

/* ---- quick actions (start page) ---- */
.quick{margin:0 0 18px}
.quickTop{display:flex;align-items:center;justify-content:space-between;gap:12px;margin:0 0 10px;flex-wrap:wrap}
.quickH{font-weight:500;font-size:.95rem}
.seg{display:inline-flex;border:1px solid var(--line2);border-radius:999px;padding:2px;background:var(--surface2)}
.seg button{font:inherit;font-size:.82rem;font-weight:600;border:0;background:transparent;color:var(--muted);padding:.35rem .9rem;border-radius:999px;cursor:pointer;min-height:32px}
.seg button[aria-selected="true"]{background:var(--surface3);color:var(--ink)}
.seg button:focus-visible{outline:2px solid var(--brand);outline-offset:1px}
.quickRow{display:flex;flex-wrap:wrap;gap:8px}
.qbtn{display:inline-flex;align-items:center;gap:8px;font:inherit;font-weight:600;font-size:.88rem;line-height:1;
  min-height:42px;padding:0 14px 0 12px;border-radius:var(--r);cursor:pointer;white-space:nowrap;max-width:100%;
  border:1px solid var(--line2);background:var(--surface3);color:var(--ink);
  box-shadow:0 1px 0 rgba(0,0,0,.25);transition:filter .12s ease,border-color .12s ease,background .12s ease,transform .06s ease}
.qbtn:hover{border-color:var(--muted)}
.qbtn:active{transform:translateY(1px)}
.qbtn:focus-visible{outline:2px solid var(--brand);outline-offset:2px}
.qbtn .qI{width:17px;height:17px;flex:none}
.qbtn .qL{overflow:hidden;text-overflow:ellipsis;text-align:left;min-width:0}
.qbtn{max-width:min(100%,460px)}
.qB{white-space:nowrap;flex:none}
/* the most pressing one */
.qbtn.q-primary{background:var(--grad);color:#fff;border-color:transparent}
.qbtn.q-primary:hover{filter:brightness(1.08)}
/* the icon carries the urgency on the solid buttons */
.qbtn.q-solid.t-breach .qI{color:var(--bad)} .qbtn.q-solid.t-urgent .qI{color:var(--warn)} .qbtn.q-solid.t-soon .qI{color:var(--ok)}
/* standing actions: outlined */
.qbtn.q-ghost{background:transparent;box-shadow:none;color:var(--ink2,var(--ink))}
.qbtn.q-ghost .qI{color:var(--muted)}
/* the badge inside the button */
.qB{font-size:.72rem;font-weight:700;letter-spacing:.02em;padding:3px 7px;border-radius:999px;background:var(--surface2);color:var(--muted)}
.t-breach .qB{background:var(--bad);color:#fff}
.t-urgent .qB{background:var(--warn);color:#1b1407}
.t-soon .qB{background:var(--ok);color:#fff}
.q-primary .qB{background:rgba(255,255,255,.22);color:#fff}
/* OFFICE: pills, tinted by urgency (style B, chosen 15/09/2026). Lighter on a
   desk screen that carries a lot else; the standing actions are plain text. */
.quick[data-mode="office"] .qbtn{border-radius:999px;min-height:38px;padding:0 15px 0 11px;font-size:.86rem;box-shadow:none;border:0;background:rgba(255,255,255,.07);color:var(--ink)}
.quick[data-mode="office"] .qbtn:hover{background:rgba(255,255,255,.11)}
.quick[data-mode="office"] .qbtn.t-breach{background:color-mix(in srgb,var(--bad) 22%,transparent);color:#ffd9d5}
.quick[data-mode="office"] .qbtn.t-urgent{background:color-mix(in srgb,var(--warn) 22%,transparent);color:#ffe7bd}
.quick[data-mode="office"] .qbtn.t-soon{background:color-mix(in srgb,var(--ok) 22%,transparent)}
.quick[data-mode="office"] .qbtn.q-primary{background:var(--grad);color:#fff}
.quick[data-mode="office"] .qbtn .qI{width:16px;height:16px;color:inherit}
.quick[data-mode="office"] .qB{padding:2px 8px;font-size:.7rem;background:rgba(0,0,0,.28);color:inherit}
.quick[data-mode="office"] .qbtn.q-ghost{background:transparent;color:var(--muted)}
.quick[data-mode="office"] .qbtn.q-ghost:hover{background:rgba(255,255,255,.06);color:var(--ink)}

/* ON SITE: icon tiles (style C, chosen 15/09/2026). A tinted icon square leads
   each button, so the job is recognisable at a glance and easy to hit with a
   thumb; a phone stacks them full width. */
.quick[data-mode="field"] .qbtn{padding:7px 16px 7px 7px;min-height:60px;gap:12px;font-size:.98rem;background:var(--surface2);border-color:var(--line);box-shadow:none}
.quick[data-mode="field"] .qbtn .qI{width:44px;height:44px;padding:11px;border-radius:10px;background:var(--surface3);color:var(--ink);box-sizing:border-box}
.quick[data-mode="field"] .qbtn.t-breach .qI{background:color-mix(in srgb,var(--bad) 28%,transparent);color:var(--bad)}
.quick[data-mode="field"] .qbtn.t-urgent .qI{background:color-mix(in srgb,var(--warn) 26%,transparent);color:var(--warn)}
.quick[data-mode="field"] .qbtn.t-soon .qI{background:color-mix(in srgb,var(--ok) 26%,transparent);color:var(--ok)}
.quick[data-mode="field"] .qbtn.q-primary{background:var(--grad);border-color:transparent;color:#fff}
.quick[data-mode="field"] .qbtn.q-primary .qI{background:rgba(255,255,255,.2);color:#fff}
.quick[data-mode="field"] .qbtn.q-ghost{background:transparent}
.quick[data-mode="field"] .qbtn.q-ghost .qI{background:transparent;border:1px dashed var(--line2);color:var(--muted)}
@media (max-width:640px){
  .quickRow{flex-direction:column;align-items:stretch}
  .qbtn{justify-content:flex-start;white-space:normal;line-height:1.25;padding-top:8px;padding-bottom:8px;max-width:100%}
  .qbtn .qL{flex:1 1 auto}
  .qbtn .qB{margin-left:auto}
}

/* Locked account: one column. Hiding the rail inside the two-column shell pushed the
   page into the rail's narrow track. Last in the file so .shell.wide cannot win. */
.shell.locked,.shell.locked.wide{grid-template-columns:minmax(0,1fr)}

/* ---- generation graphs (home page) ----
   Solid colours only: tenant guidelines can forbid opacity. --gen-sun and --gen-fill
   come from the tenant record at runtime; these are neutral defaults. */
:root{--gen-sun:#2f9fb8;--gen-fill:var(--surface3)}
.gen .gKpis{display:grid;grid-template-columns:repeat(auto-fit,minmax(12rem,1fr));gap:12px}
.gen .kpi .n small{font-size:1rem;font-weight:500;color:var(--ink2);margin-left:3px}
.gen .kpi .h{color:var(--muted);font-size:.76rem;margin-top:2px}
.gGrid{display:grid;grid-template-columns:minmax(0,1.35fr) minmax(0,1fr);gap:14px;margin-top:2px}
@media(max-width:900px){.gGrid{grid-template-columns:minmax(0,1fr)}}
.gCard{min-width:0;margin:.7rem 0 0}
.gH{font-weight:500}
.gD{color:var(--muted);font-size:.8rem;margin:.15rem 0 .5rem}
.gChart{position:relative;width:100%;min-width:0}
.gChart svg{display:block;overflow:visible;max-width:100%;height:auto}
.gAxis text{fill:var(--muted);font-size:11px;font-variant-numeric:tabular-nums}
.gAxis line.g{stroke:var(--line);stroke-width:1}
.gAxis line.base{stroke:var(--line2);stroke-width:1}
.gLab{fill:var(--ink2);font-size:11px;font-variant-numeric:tabular-nums}
.gTip{position:absolute;pointer-events:none;background:var(--paper);border:1px solid var(--line2);border-radius:8px;
  padding:6px 9px;font-size:.78rem;white-space:nowrap;color:var(--ink);transform:translate(-50%,-115%);z-index:3}
.gTip b{font-variant-numeric:tabular-nums}
.gMore{margin-top:.4rem}
.gMore summary{color:var(--muted);font-size:.78rem;cursor:pointer}
.gTw{overflow:auto;max-height:14rem}
.gTable{border-collapse:collapse;font-size:.78rem;margin-top:.4rem;font-variant-numeric:tabular-nums}
.gTable td,.gTable th{padding:2px 14px 2px 0;text-align:left;color:var(--ink2)}
.gTable th{color:var(--muted);font-weight:500}

/* ---- print ----
   The screen theme is set partly at runtime (inline brand colours on the root) and
   partly by prefers-color-scheme, over a fixed full-window background and frosted
   glass. A printer honours some of that and not the rest, which printed a black
   block, a green blob and dark text on dark cards (16/09/2026). Print is its own
   flat, light layout: !important beats the runtime inline colours. Brand green and
   the graph colours are kept; they read on white. */
@media print{
  @page{size:A4;margin:12mm}
  :root{--paper:#fff !important;--surface:#fff !important;--surface2:#f3f5f8 !important;--surface3:#e9edf2 !important;
    --line:#d9dee5 !important;--line2:#c3cad4 !important;--ink:#111 !important;--ink2:#333 !important;--muted:#555 !important;
    --bg-field:none !important;--surface-field:none !important;--glass:#fff !important;--glass2:#fff !important;
    --glassLine:#d9dee5 !important;--glassTop:#fff !important}
  html,body{background:#fff !important;background-image:none !important;color:#111 !important}
  *,*::before,*::after{backdrop-filter:none !important;-webkit-backdrop-filter:none !important;box-shadow:none !important;
    text-shadow:none !important;animation:none !important;transition:none !important}
  body{-webkit-print-color-adjust:exact;print-color-adjust:exact}
  .shell,.shell.wide{display:block !important}
  .rail,.subnav,#tabs,.licbar,#licbar,.quick,.askBtn,.askPanel,#searchBtn,#siteSel,#out,.sheet-bg,button.btn,.expBtn,.gMore{display:none !important}
  .col{padding:0 !important}
  .wrap{max-width:none !important;padding:0 !important}
  header.top{padding:0 0 8px !important;border-bottom:1px solid #d9dee5 !important;background:#fff !important}
  .card,.kpi,.heroCard,.gCard{background:#fff !important;background-image:none !important;border:1px solid #d9dee5 !important;
    break-inside:avoid;page-break-inside:avoid}
  .homeCols,.gGrid{grid-template-columns:minmax(0,1fr) minmax(0,1fr) !important}
  .gen{break-before:auto}
  .gTip{display:none !important}
  a{color:inherit;text-decoration:none}
}


/* ---- Focus view (28/10/2026). One thing at a time: same information, less on
   screen. The switch lives in the top bar; html.focus carries the mode. */
.focusSw{display:inline-flex;align-items:center;gap:8px;background:none;border:1px solid var(--line2);border-radius:999px;
  padding:5px 12px 5px 6px;color:var(--ink2);font:inherit;font-size:.82rem;cursor:pointer;white-space:nowrap}
.focusSw .knob{width:30px;height:18px;border-radius:999px;background:var(--line2);position:relative;transition:background .2s}
.focusSw .knob::after{content:"";position:absolute;top:2px;left:2px;width:14px;height:14px;border-radius:50%;background:var(--paper);transition:transform .2s}
.focusSw[aria-checked="true"]{border-color:var(--brand);color:var(--ink)}
.focusSw[aria-checked="true"] .knob{background:var(--brand)}
.focusSw[aria-checked="true"] .knob::after{transform:translateX(12px)}
.focusOnly{display:none}
html.focus .focusOnly{display:inline-flex}
html.focus .homeCols{grid-template-columns:minmax(0,1fr)!important}
html.focus .homeCols .side,html.focus #visitCard,html.focus #genCard{display:none!important}
html.focus #nextHero .heroH{font-size:1.9rem}
html.focus tbody.clamped tr:nth-child(n+6){display:none}
.clampBtn{margin:.5rem 0 0}
.sheet .stepBar{display:flex;align-items:center;gap:4px;margin:0 0 .7rem}
.sheet .stepBar[hidden]{display:none}
.sheet .stepBar i{flex:1;height:4px;border-radius:2px;background:var(--line2)}
.sheet .stepBar i.done{background:var(--brand)}
.sheet .stepBar span{margin-left:8px;color:var(--muted);font-size:.76rem;white-space:nowrap}
.sheet.stepping .stepF{display:none}
.sheet.stepping .stepF.cur{display:block}
.sheet.stepping .stepF.cur .choice{padding-top:.9rem;padding-bottom:.9rem}
