@font-face{font-family:"Inter";font-style:normal;font-weight:400;font-display:swap;src:url(/fonts/inter-latin-400-normal.woff2) format("woff2");unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD;}
@font-face{font-family:"Inter";font-style:normal;font-weight:500;font-display:swap;src:url(/fonts/inter-latin-500-normal.woff2) format("woff2");unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD;}
@font-face{font-family:"Inter";font-style:normal;font-weight:600;font-display:swap;src:url(/fonts/inter-latin-600-normal.woff2) format("woff2");unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD;}
@font-face{font-family:"Inter";font-style:normal;font-weight:700;font-display:swap;src:url(/fonts/inter-latin-700-normal.woff2) format("woff2");unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD;}
@font-face{font-family:"Inter";font-style:normal;font-weight:400;font-display:swap;src:url(/fonts/inter-latin-ext-400-normal.woff2) format("woff2");unicode-range:U+0100-02BA,U+02BD-02C5,U+02C7-02CC,U+02CE-02D7,U+02DD-02FF,U+0304,U+0308,U+0329,U+1D00-1DBF,U+1E00-1E9F,U+1EF2-1EFF,U+2020,U+20A0-20AB,U+20AD-20C0,U+2113,U+2C60-2C7F,U+A720-A7FF;}
@font-face{font-family:"Inter";font-style:normal;font-weight:500;font-display:swap;src:url(/fonts/inter-latin-ext-500-normal.woff2) format("woff2");unicode-range:U+0100-02BA,U+02BD-02C5,U+02C7-02CC,U+02CE-02D7,U+02DD-02FF,U+0304,U+0308,U+0329,U+1D00-1DBF,U+1E00-1E9F,U+1EF2-1EFF,U+2020,U+20A0-20AB,U+20AD-20C0,U+2113,U+2C60-2C7F,U+A720-A7FF;}
@font-face{font-family:"Inter";font-style:normal;font-weight:600;font-display:swap;src:url(/fonts/inter-latin-ext-600-normal.woff2) format("woff2");unicode-range:U+0100-02BA,U+02BD-02C5,U+02C7-02CC,U+02CE-02D7,U+02DD-02FF,U+0304,U+0308,U+0329,U+1D00-1DBF,U+1E00-1E9F,U+1EF2-1EFF,U+2020,U+20A0-20AB,U+20AD-20C0,U+2113,U+2C60-2C7F,U+A720-A7FF;}
@font-face{font-family:"Inter";font-style:normal;font-weight:700;font-display:swap;src:url(/fonts/inter-latin-ext-700-normal.woff2) format("woff2");unicode-range:U+0100-02BA,U+02BD-02C5,U+02C7-02CC,U+02CE-02D7,U+02DD-02FF,U+0304,U+0308,U+0329,U+1D00-1DBF,U+1E00-1E9F,U+1EF2-1EFF,U+2020,U+20A0-20AB,U+20AD-20C0,U+2113,U+2C60-2C7F,U+A720-A7FF;}
@font-face{font-family:"Inter";font-style:normal;font-weight:400;font-display:swap;src:url(/fonts/inter-greek-400-normal.woff2) format("woff2");unicode-range:U+0370-0377,U+037A-037F,U+0384-038A,U+038C,U+038E-03A1,U+03A3-03FF;}
@font-face{font-family:"Inter";font-style:normal;font-weight:500;font-display:swap;src:url(/fonts/inter-greek-500-normal.woff2) format("woff2");unicode-range:U+0370-0377,U+037A-037F,U+0384-038A,U+038C,U+038E-03A1,U+03A3-03FF;}
@font-face{font-family:"Inter";font-style:normal;font-weight:600;font-display:swap;src:url(/fonts/inter-greek-600-normal.woff2) format("woff2");unicode-range:U+0370-0377,U+037A-037F,U+0384-038A,U+038C,U+038E-03A1,U+03A3-03FF;}
@font-face{font-family:"Inter";font-style:normal;font-weight:700;font-display:swap;src:url(/fonts/inter-greek-700-normal.woff2) format("woff2");unicode-range:U+0370-0377,U+037A-037F,U+0384-038A,U+038C,U+038E-03A1,U+03A3-03FF;}
@font-face{font-family:"Roboto Mono";font-style:normal;font-weight:400;font-display:swap;src:url(/fonts/roboto-mono-latin-400-normal.woff2) format("woff2");unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD;}
@font-face{font-family:"Roboto Mono";font-style:normal;font-weight:500;font-display:swap;src:url(/fonts/roboto-mono-latin-500-normal.woff2) format("woff2");unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD;}
@font-face{font-family:"Roboto Mono";font-style:normal;font-weight:400;font-display:swap;src:url(/fonts/roboto-mono-latin-ext-400-normal.woff2) format("woff2");unicode-range:U+0100-02BA,U+02BD-02C5,U+02C7-02CC,U+02CE-02D7,U+02DD-02FF,U+0304,U+0308,U+0329,U+1D00-1DBF,U+1E00-1E9F,U+1EF2-1EFF,U+2020,U+20A0-20AB,U+20AD-20C0,U+2113,U+2C60-2C7F,U+A720-A7FF;}
@font-face{font-family:"Roboto Mono";font-style:normal;font-weight:500;font-display:swap;src:url(/fonts/roboto-mono-latin-ext-500-normal.woff2) format("woff2");unicode-range:U+0100-02BA,U+02BD-02C5,U+02C7-02CC,U+02CE-02D7,U+02DD-02FF,U+0304,U+0308,U+0329,U+1D00-1DBF,U+1E00-1E9F,U+1EF2-1EFF,U+2020,U+20A0-20AB,U+20AD-20C0,U+2113,U+2C60-2C7F,U+A720-A7FF;}
@font-face{font-family:"Roboto Mono";font-style:normal;font-weight:400;font-display:swap;src:url(/fonts/roboto-mono-greek-400-normal.woff2) format("woff2");unicode-range:U+0370-0377,U+037A-037F,U+0384-038A,U+038C,U+038E-03A1,U+03A3-03FF;}
@font-face{font-family:"Roboto Mono";font-style:normal;font-weight:500;font-display:swap;src:url(/fonts/roboto-mono-greek-500-normal.woff2) format("woff2");unicode-range:U+0370-0377,U+037A-037F,U+0384-038A,U+038C,U+038E-03A1,U+03A3-03FF;}
@font-face{font-family:"Geist";font-style:normal;font-weight:400;font-display:swap;src:url(/fonts/geist-latin-400-normal.woff2) format("woff2");unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD;}
@font-face{font-family:"Geist";font-style:normal;font-weight:500;font-display:swap;src:url(/fonts/geist-latin-500-normal.woff2) format("woff2");unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD;}
@font-face{font-family:"Geist";font-style:normal;font-weight:600;font-display:swap;src:url(/fonts/geist-latin-600-normal.woff2) format("woff2");unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD;}
@font-face{font-family:"Geist";font-style:normal;font-weight:700;font-display:swap;src:url(/fonts/geist-latin-700-normal.woff2) format("woff2");unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD;}
@font-face{font-family:"Geist";font-style:normal;font-weight:400;font-display:swap;src:url(/fonts/geist-latin-ext-400-normal.woff2) format("woff2");unicode-range:U+0100-02BA,U+02BD-02C5,U+02C7-02CC,U+02CE-02D7,U+02DD-02FF,U+0304,U+0308,U+0329,U+1D00-1DBF,U+1E00-1E9F,U+1EF2-1EFF,U+2020,U+20A0-20AB,U+20AD-20C0,U+2113,U+2C60-2C7F,U+A720-A7FF;}
@font-face{font-family:"Geist";font-style:normal;font-weight:500;font-display:swap;src:url(/fonts/geist-latin-ext-500-normal.woff2) format("woff2");unicode-range:U+0100-02BA,U+02BD-02C5,U+02C7-02CC,U+02CE-02D7,U+02DD-02FF,U+0304,U+0308,U+0329,U+1D00-1DBF,U+1E00-1E9F,U+1EF2-1EFF,U+2020,U+20A0-20AB,U+20AD-20C0,U+2113,U+2C60-2C7F,U+A720-A7FF;}
@font-face{font-family:"Geist";font-style:normal;font-weight:600;font-display:swap;src:url(/fonts/geist-latin-ext-600-normal.woff2) format("woff2");unicode-range:U+0100-02BA,U+02BD-02C5,U+02C7-02CC,U+02CE-02D7,U+02DD-02FF,U+0304,U+0308,U+0329,U+1D00-1DBF,U+1E00-1E9F,U+1EF2-1EFF,U+2020,U+20A0-20AB,U+20AD-20C0,U+2113,U+2C60-2C7F,U+A720-A7FF;}
@font-face{font-family:"Geist";font-style:normal;font-weight:700;font-display:swap;src:url(/fonts/geist-latin-ext-700-normal.woff2) format("woff2");unicode-range:U+0100-02BA,U+02BD-02C5,U+02C7-02CC,U+02CE-02D7,U+02DD-02FF,U+0304,U+0308,U+0329,U+1D00-1DBF,U+1E00-1E9F,U+1EF2-1EFF,U+2020,U+20A0-20AB,U+20AD-20C0,U+2113,U+2C60-2C7F,U+A720-A7FF;}
:root {
  /* OUI, the OpenSearch theme Wazuh's dashboard is built on: a grey canvas,
     white panels with a cool grey border, one blue, and its severity colours. */
  --bg:#f4f5f9; --panel:#fff; --panel-2:#f6f7fb; --panel-3:#eceef5;
  --line:#dfe2ec; --line-2:#c8ccda; --ink:#1d2030; --ink-2:#464b5e; --muted:#5f6478;
  /* Vardion indigo: the one brand colour. Distinct from every severity,
     including low's blue, so an accent never reads as a rating. */
  --accent:#4a4bd6; --accent-2:#0f8a7e; --accent-3:#8d5fd3;
  --accent-weak:#eeeefd; --accent-ink:#fff;
  /* The text on a danger fill: white on the deep red of light, dark on the coral of dark. */
  --bad-ink:#fff;
  /* Severity in the order a reader expects: red, orange, yellow, blue, grey.
     Wazuh colours low in green, and green reads as all clear, so low is blue.
     OUI's warning is for a warning that is not a severity. */
  --crit:#BD271E; --high:#E8730C; --med:#F5C518; --low:#6092C0; --info:#646A77;
  --warn:#F5A700; --sev-ink:#FFFFFF; --high-ink:#1A1C21;
  --good:#017d73; --bad:#bd271e;
  --shadow:0 1px 2px rgba(0,0,0,.04), 0 2px 6px -1px rgba(0,0,0,.06);
  --shadow-lg:0 6px 20px rgba(0,0,0,.1);
  --radius:8px; --radius-lg:12px;
  /* Vertical rhythm. Four steps, because the console had a dozen arbitrary
     values (4, 6, 10, 12, 13, 14, 16, 18, 20, 22, 26, 32) and the gaps between
     two blocks on one page disagreed with the gaps between the same two blocks
     on another. sp-1 separates rows inside a group, sp-2 one control row from
     the next, sp-3 one block from the next, sp-4 a new section from what is
     above it. */
  --sp-1:8px; --sp-2:14px; --sp-3:22px; --sp-4:34px;
  /* The same ladder continued below sp-1, for space inside one component
     rather than between two. The component rules were written in raw pixels
     and reached 20 distinct values (1 to 28), so two chips, two cards or two
     table cells written months apart were spaced differently for no reason
     anybody could state. gap-1 separates a glyph from its label, gap-2 one
     control from the next in a row. */
  --gap-1:3px; --gap-2:6px;
  /* Type scale. Same argument as the spacing one, and the same failure: the
     console had fifteen sizes (10, 10.5, 11, 11.5, 12, 12.5, 13, 13.5, 14, 15,
     15.5, 17, 19, 21, 25), several of them half a pixel apart, which is a
     difference nobody can see and a decision every new rule had to make again.
     fs-0 is a micro label, fs-1 secondary text, fs-2 data and controls, fs-3
     body and section headings, fs-4 the one line a page leads with, fs-5 a
     page title, fs-6 the single large number on a card. */
  --fs-0:12px; --fs-1:13px; --fs-2:14px; --fs-3:15px; --fs-4:16px; --fs-5:21px; --fs-6:25px;
  /* One height for every control that sits in a row with others: buttons,
     button-like links, text inputs and selects were 36, 38 and 37 pixels, so
     an inline row of them did not line up. */
  --ctl-h:36px;
  /* The menu is a dark rail in both themes: the console's one large brand
     surface, as Datadog, Linear and Vercel carry theirs. */
  --nav:#0f1020; --nav-ink:#e4e6f2; --nav-muted:#9094ad; --nav-hover:#1b1c32;
  --nav-on:#ffffff; --nav-line:#22243a;
  --radius-sm:6px; --radius-md:8px; --radius-xl:12px;
  --shadow-sm:0 1px 2px rgba(16,18,40,.05);
  /* The cue on a phone table that scrolls sideways. */
  --scroll-shade:rgba(16,18,40,.2);
  --display:"Geist","Inter","Inter UI",-apple-system,BlinkMacSystemFont,"Segoe UI",sans-serif;
  --mono:"Roboto Mono",ui-monospace,SFMono-Regular,Menlo,monospace;
}
* { box-sizing:border-box; }
/* The HTML hidden attribute must always hide, even on an element whose class sets
   an explicit display; without this an authored display:flex/grid/block wins over
   the user-agent [hidden]{display:none} and the element stays visible. */
[hidden] { display:none !important; }
html,body { height:100%; }
/* Inter, as OUI sets it, served by the console from src/fonts (fonts.ts), so
   nothing is fetched from anywhere else. The platform face is the fallback. */
body { margin:0; color:var(--ink); font:var(--fs-3)/1.5 "Geist","Inter","Inter UI",-apple-system,BlinkMacSystemFont,"Segoe UI",Helvetica,Arial,sans-serif;
  -webkit-font-smoothing:antialiased; text-rendering:optimizeLegibility;
  font-variant-numeric:tabular-nums; overflow:hidden;
  background:var(--bg); }
/* Uppercase mono for small labels. System mono (SF Mono, Cascadia, DejaVu) has
   far more character than the UI face and reads as instrumentation, which is
   what this is. No webfont, so nothing is fetched. */
/* Labels in the UI face, as OUI sets them. Monospace is for identifiers. */
:focus-visible { outline:2px solid var(--accent); outline-offset:2px; border-radius:6px; }

/* Shell ------------------------------------------------------------------ */
/* dvh so a mobile browser's collapsing toolbar cannot leave the last rows of a
   long page unreachable; the vh line above it is the fallback for browsers
   without dvh, which simply ignore the second declaration. */
.shell { display:flex; height:100vh; height:100dvh; overflow:hidden; }
aside { width:236px; flex:0 0 236px; color:var(--nav-ink);
  background:var(--nav);
  border-right:1px solid var(--nav-line);
  display:flex; flex-direction:column; height:100vh; height:100dvh; overflow-y:auto; z-index:40; }
aside::-webkit-scrollbar { width:8px; } aside::-webkit-scrollbar-thumb { background:var(--line); border-radius:var(--radius); }
aside .brand { display:flex; align-items:center; gap:var(--sp-1); padding:var(--sp-2) var(--sp-2) var(--sp-2); }
.logo { width:27px; height:27px; flex:0 0 auto; display:inline-flex;
  align-items:center; justify-content:center; color:var(--accent); }
.logo .icon { vertical-align:0; }
aside .brand .name { font-weight:700; color:var(--ink); font-size:var(--fs-4); letter-spacing:.2px; line-height:1.15; }
aside .brand .name small { display:block; font-weight:500; color:var(--nav-muted); font-size:var(--fs-0);
  letter-spacing:.7px; text-transform:uppercase; margin-top:var(--gap-1); }
aside .brand .x { display:none; margin-left:auto; background:none; border:0; color:var(--nav-muted);
  cursor:pointer; padding:var(--gap-1); border-radius:6px; }
aside .brand .x:hover { color:var(--ink); background:var(--nav-hover); }
aside nav { flex:1; padding:var(--gap-1) 0 var(--sp-2); }
aside nav { padding-top:var(--gap-2); }
aside nav a { display:flex; align-items:center; gap:var(--sp-1); color:var(--nav-ink); text-decoration:none;
  margin:var(--gap-1) var(--sp-1); padding:var(--gap-2) var(--sp-1); font-size:var(--fs-2); border-radius:var(--radius); line-height:1.3; }
aside nav a:hover { background:var(--nav-hover); color:var(--ink); }
/* The active item is a background and a weight. No bar, no accent fill: the
   sidebar should read as one surface with one item currently selected. */
aside nav a.on { background:var(--accent-weak); color:var(--nav-on); font-weight:600; }
aside nav a .navlabel { display:inline-flex; align-items:center; gap:var(--sp-1); min-width:0; }
aside nav .navhead { padding:var(--sp-2) var(--sp-2) var(--gap-2); font-size:var(--fs-0); font-weight:700;
  letter-spacing:.06em; text-transform:uppercase; color:var(--nav-muted); }
.tb-title .crumb { color:var(--muted); font-weight:500; text-decoration:none; }
.tb-title a.crumb:hover { color:var(--ink); text-decoration:underline; }
.tb-title .sep { color:var(--muted); margin:0 var(--gap-2); }
.tb-title .here { color:var(--ink); }
aside nav a .icon { opacity:.75; } aside nav a.on .icon,aside nav a:hover .icon { opacity:1; }
aside .badge { margin-left:auto; background:var(--bad); color:var(--bad-ink); border-radius:999px; min-width:19px;
  text-align:center; padding:var(--gap-1) var(--gap-2); font-size:var(--fs-0); font-weight:700; line-height:1.5; }
aside nav a.on .badge { background:var(--bad); color:var(--bad-ink); }
/* A destination that needs attention: a dot, quieter than a count. */
aside .navdot { margin-left:auto; flex:0 0 8px; width:8px; height:8px; border-radius:50%; background:var(--warn); }
aside .navdot.bad { background:var(--bad); }
/* The colours' meaning under the menu; hidden when the menu is collapsed to icons. */
aside .navlegend { display:flex; flex-wrap:wrap; gap:var(--gap-1) var(--sp-2); padding:var(--gap-2) var(--sp-2); font-size:var(--fs-0); color:var(--nav-muted); }
aside .navlegend span { display:inline-flex; align-items:center; gap:var(--gap-1); }
aside .navlegend .navdot { margin:0; display:inline-block; }
:root[data-nav="collapsed"] aside .navlegend { display:none; }
/* A tab carries the mark of what it holds, as the menu entry above it does. */
.tabs .tabcount, .subtabs .tabcount { display:inline-block; min-width:18px; padding:0 5px; margin-left:var(--gap-2); border-radius:9px; background:var(--bad); color:var(--bad-ink); font-size:var(--fs-0); font-weight:700; line-height:18px; text-align:center; vertical-align:middle; }
.tabs .tabdot, .subtabs .tabdot { display:inline-block; width:7px; height:7px; border-radius:50%; background:var(--warn); margin-left:var(--gap-1); vertical-align:middle; }
.tabs .tabdot.bad, .subtabs .tabdot.bad { background:var(--bad); }
aside .navfoot nav.footnav { flex:none; padding:0 0 var(--gap-1); }

/* The collapse control, and the menu collapsed to its icons. Wide screens
   only: below 900px the menu is a drawer and is hidden until opened anyway.
   A label is hidden visually and kept as the link's accessible name, and each
   link carries it as a tooltip while collapsed. */
/* The foot row carries the version at the left and the collapse control at the
   right of one line. */
.navfootrow { display:flex; align-items:center; gap:var(--sp-1); }
.navfootrow .buildid { flex:1; min-width:0; }
/* The collapse control sits beside the version as a plain icon, so the version
   stays fully legible; its accessible name stays on the aria-label, and the
   rail below keeps it icon-only too. */
.navfootrow .navcollapse .navtext { position:absolute; width:1px; height:1px; overflow:hidden;
  clip:rect(0 0 0 0); clip-path:inset(50%); white-space:nowrap; }
.navcollapse { display:flex; align-items:center; gap:var(--sp-1); flex:none; margin:var(--gap-1) var(--sp-1);
  padding:var(--gap-2) var(--sp-1); background:none; border:0; border-radius:var(--radius); color:var(--nav-muted);
  font:inherit; font-size:var(--fs-1); cursor:pointer; text-align:left; box-sizing:border-box; }
.navcollapse:hover { background:var(--nav-hover); color:var(--ink); }
.navcollapse .ic-open { display:none; }
.navcollapse > span { display:inline-flex; }
@media (min-width:901px) {
  aside { transition:width .15s ease, flex-basis .15s ease; }
  :root[data-nav="collapsed"] aside { width:64px; flex-basis:64px; overflow-x:hidden; }
  :root[data-nav="collapsed"] aside .brand { justify-content:center; padding-left:0; padding-right:0; }
  :root[data-nav="collapsed"] aside .brand .name { display:none; }
  :root[data-nav="collapsed"] aside nav a { justify-content:center; position:relative; padding:var(--gap-2) 0; }
  :root[data-nav="collapsed"] aside .navtext { position:absolute; width:1px; height:1px; overflow:hidden;
    clip:rect(0 0 0 0); clip-path:inset(50%); white-space:nowrap; }
  :root[data-nav="collapsed"] aside nav .navhead { font-size:0; padding:0; height:0; margin:var(--sp-1) var(--sp-2);
    border-top:1px solid var(--nav-line); }
  :root[data-nav="collapsed"] aside .navdot { position:absolute; top:5px; right:14px; box-shadow:0 0 0 2px var(--nav); }
  :root[data-nav="collapsed"] aside .badge { position:absolute; top:1px; right:6px; min-width:16px; padding:0 var(--gap-1);
    font-size:10px; line-height:16px; }
  :root[data-nav="collapsed"] .navcollapse { justify-content:center; width:calc(100% - 2 * var(--sp-1)); }
  :root[data-nav="collapsed"] .navcollapse .ic-close { display:none; }
  :root[data-nav="collapsed"] .navcollapse .ic-open { display:inline-flex; }
  /* No room for the version on the icon rail, so it is hidden rather than
     shortened; the tooltip on the build page still carries it. */
  :root[data-nav="collapsed"] .buildid { display:none; }
  :root[data-nav="collapsed"] .wsswitch summary { justify-content:center; padding:var(--gap-2) 0; border-color:transparent; }
  :root[data-nav="collapsed"] .wsmenu { left:calc(100% + 6px); right:auto; top:0; width:240px; }
  /* The menu keeps scrolling on a short window; only while the switcher is
     open may its list spill out beside the icons. */
  :root[data-nav="collapsed"] aside:has(#wsswitch[open]) { overflow:visible; }
}

.col { flex:1; min-width:0; min-height:0; display:flex; flex-direction:column; overflow:hidden; }

/* Top bar ---------------------------------------------------------------- */
/* Which build is loaded. At the foot of the nav: on every page, out of the way,
   and not competing with the page title. Monospace because it is an identifier
   to compare, not prose to read. */
.buildid { display:block; padding:var(--sp-1) var(--sp-3) var(--sp-2); color:var(--muted); text-decoration:none;
  font-family:"Roboto Mono",ui-monospace,SFMono-Regular,Menlo,monospace; font-size:var(--fs-0); letter-spacing:.2px;
  white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }
.buildid:hover { color:var(--ink-2); background:var(--panel-2); }
/* Copy control. Attached to a value rather than a page, so an identifier
   anywhere gets one without its own script. */
.copy { background:transparent; border:0; color:var(--muted); cursor:pointer; padding:var(--gap-1) var(--gap-2);
  border-radius:5px; font-size:var(--fs-0); font-family:"Roboto Mono",ui-monospace,SFMono-Regular,Menlo,monospace;
  vertical-align:middle; opacity:0; transition:opacity .12s,color .12s; }
code:hover + .copy, .copy:hover, .copy:focus-visible, td:hover .copy, .copy.done { opacity:1; }
.copy:hover { color:var(--ink); background:var(--panel-2); }
.copy.done { color:var(--good); }
.snippet .copy { opacity:1; }
td .btnrow { margin:0; }
.inlineedit { display:inline-block; }
/* Evidence proposed for a control from a verified fix or a passing check (evidenceitems.ts), under its evidence badge. */
.proposed { margin-top:6px; padding:6px 8px; border-left:2px solid var(--accent); background:var(--panel-2); font-size:12px; }
.proposed .k { display:block; font-weight:600; color:var(--ink-2); }
.proposed ul { margin:4px 0; padding-left:16px; }
.inlineedit > summary { list-style:none; }
.inlineedit > summary::-webkit-details-marker { display:none; }
.inlineedit[open] > summary { display:none; }
/* A one-field edit (an owner, an assignee) sits in its row. An edit of several
   fields is a stack form and stacks label over field under its summary: forced
   into one row it was a strip of cramped fields running past the table. */
.inlineedit form:not(.stack) { display:inline-flex; gap:var(--gap-2); align-items:center; }
/* An incident card: the significance assessment, set apart from the procedure line under it. */
.incsig { margin:0 0 var(--sp-2); } .incsig h3 { margin:0 0 var(--gap-1); } .incsig p { margin:0 0 var(--gap-1); }
.inlineedit:not(:has(> form.stack)) input { max-width:180px; }
.inlineedit[open]:has(> form.stack) { display:block; }
.inlineedit > form.stack { display:flex; flex-direction:column; align-items:stretch; gap:var(--gap-2); max-width:420px; margin-top:var(--gap-2); }
/* Row controls written side by side with no space between them, such as Mark done, Edit and Remove on a duty. */
td > .inlineedit:has(+ .inlineedit, + form.inline), td > form.inline:has(+ .inlineedit, + form.inline) { margin:0 var(--gap-2) var(--gap-1) 0; }
/* The gap of the form spaces its fields, so the bottom margin of a stacked label
   is taken off. The selector carries the weight of the stacked-label rule, or it loses. */
main .inlineedit > form.stack:not(.inline):not(.btnrow) > label:not(.check):not(.inlinelabel):not(.choice):has(> input:not([type=checkbox]):not([type=radio]), > select, > textarea) { margin:0; }
.demobanner { padding:var(--gap-2) var(--sp-2); margin:0 0 var(--sp-2);
  border:1px solid var(--accent); border-radius:var(--radius); background:var(--accent-weak); font-size:var(--fs-1); }
.demobanner svg { vertical-align:-3px; }
.shots { display:grid; grid-template-columns:repeat(auto-fill, minmax(min(240px,100%),1fr)); gap:var(--sp-2); margin:var(--sp-2) 0; }
.shot { display:flex; flex-direction:column; border:1px solid var(--line); border-radius:var(--radius); overflow:hidden; background:var(--panel); color:inherit; text-decoration:none; min-width:0; }
.shot:hover { border-color:var(--accent); }
.shot img { display:block; width:100%; height:auto; aspect-ratio:16/10; object-fit:cover; object-position:top; background:var(--panel-2); }
.shotcap { display:flex; flex-direction:column; gap:2px; padding:var(--gap-2) var(--sp-1); font-size:var(--fs-1); min-width:0; }
.shotcap > * { overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
.snippet p.muted { margin-bottom:var(--gap-1); }
.topbar { display:flex; align-items:center; gap:var(--sp-2); padding:0 var(--sp-3); height:56px; flex:0 0 auto;
  background:var(--panel); border-bottom:1px solid var(--line); z-index:30; }
.topbar .menubtn { display:none; background:transparent; border:1px solid var(--line); border-radius:7px;
  color:var(--ink); cursor:pointer; padding:var(--gap-2) var(--sp-1); align-items:center; box-shadow:none; }
.topbar .menubtn:hover { background:var(--panel-2); }
.topbar .tb-brand { display:none; align-items:center; gap:var(--sp-1); font-weight:700; font-size:var(--fs-4); }
.topbar .tb-title { font-weight:650; font-size:var(--fs-4); letter-spacing:-.1px; white-space:nowrap;
  overflow:hidden; text-overflow:ellipsis; }
.topbar .spacer { flex:1; }
.topbar .tb-actions { display:flex; align-items:center; gap:var(--sp-1); }
.tb-user { display:inline-flex; align-items:center; gap:var(--gap-2); color:var(--ink-2); text-decoration:none; font-size:var(--fs-2);
  max-width:140px; overflow:hidden; white-space:nowrap; }
.tb-user span { overflow:hidden; text-overflow:ellipsis; }
.tb-signout { margin:0; }
.tb-signout button { padding:var(--gap-2) var(--sp-1); font-size:var(--fs-2); }
@media (max-width:560px) { .tb-user span { display:none; } }
.tb-search { position:relative; display:flex; align-items:center; }
/* Fixed rather than a spacing token: the icon is a fixed 15px at 9px in, and
   compact density shrinks the tokens. The selector carries the type so it
   outranks the generic input rule, which reset the padding and hid the icon. */
.tb-search-icon { position:absolute; left:9px; display:flex; color:var(--muted); pointer-events:none; }
.tb-search input[type="search"] { width:210px; padding:var(--gap-2) var(--sp-1) var(--gap-2) 32px; font:inherit; font-size:var(--fs-2);
  color:var(--fg); background:var(--panel-2); border:1px solid var(--line); border-radius:7px; }
.tb-search input::placeholder { color:var(--muted); }
.tb-search input:focus { outline:none; border-color:var(--accent); background:var(--panel); }
.tb-search input::-webkit-search-cancel-button { -webkit-appearance:none; appearance:none; }
.searchhit { display:block; padding:var(--sp-1) var(--sp-2); border:1px solid var(--line); border-radius:8px;
  margin-bottom:var(--gap-2); text-decoration:none; color:var(--fg); }
.searchhit:hover { background:var(--panel-2); }
.searchhit .sub { display:block; color:var(--muted); font-size:var(--fs-1); font-weight:400; }
.iconbtn { background:transparent; border:1px solid var(--line); border-radius:7px; color:var(--ink-2);
  cursor:pointer; padding:var(--gap-2); display:inline-flex; align-items:center; justify-content:center; gap:var(--gap-2);
  font-size:var(--fs-1); font-weight:600; box-shadow:none; }
/* Show the mode the button switches TO. The selectors deliberately mirror the
   theme token selectors above, so the glyph can never disagree with the theme
   actually in force, including when no choice has been made and the OS decides. */
#themetoggle .sun { display:none; }
#themetoggle .moon { display:inline-flex; }
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) #themetoggle .moon { display:none; }
  :root:not([data-theme="light"]) #themetoggle .sun { display:inline-flex; }
}
:root[data-theme="dark"] #themetoggle .moon { display:none; }
:root[data-theme="dark"] #themetoggle .sun { display:inline-flex; }
:root[data-theme="light"] #themetoggle .moon { display:inline-flex; }
:root[data-theme="light"] #themetoggle .sun { display:none; }
.iconbtn.textbtn { padding:var(--gap-2) var(--sp-1) var(--gap-2) var(--sp-1); gap:var(--gap-2); }
.iconbtn.textbtn span { font-size:var(--fs-1); font-weight:650; letter-spacing:-.1px; }
@media (max-width:1100px) { .iconbtn.textbtn span { display:none; } .iconbtn.textbtn { padding:var(--gap-2); } }
.iconbtn:hover { background:var(--panel-2); color:var(--ink); border-color:var(--line-2); }
/* A toggle that is on says so. Without it the only evidence the density button
   had done anything was the row padding, which is the thing being changed and
   so is not available as confirmation that the click landed. */
.iconbtn[aria-pressed="true"] { background:var(--accent-weak); color:var(--accent);
  border-color:color-mix(in srgb,var(--accent) 40%,var(--line)); }
.runchip { display:none; align-items:center; gap:var(--sp-1); text-decoration:none; font-size:var(--fs-1); font-weight:650;
  padding:var(--gap-2) var(--sp-1); border-radius:999px; border:1px solid color-mix(in srgb,var(--accent) 35%,var(--line));
  background:var(--accent-weak); color:var(--accent); white-space:nowrap; flex:0 0 auto; }
.runchip.show { display:inline-flex; }
/* The chip says that a run is going and for how long. What the run is goes in
   its tooltip: the full mode ("full scan, 100 most common ports, one attempt
   per port") wrapped onto three lines and covered the search box. */
.runchip .rt { font-variant-numeric:tabular-nums; }
@media (max-width:700px) { .runchip #runchiptext { display:none; } }
.tl-row { display:grid; grid-template-columns:110px 1fr 70px; align-items:center; gap:var(--sp-2); margin:var(--gap-1) 0; font-size:var(--fs-1); }
.tl-tool { font-family:var(--mono, monospace); color:var(--ink-2); }
.tl-track { position:relative; height:12px; background:var(--panel-2); border-radius:4px; }
.tl-bar { position:absolute; top:0; bottom:0; background:var(--accent); border-radius:4px; }
.tl-bar.open { background:var(--warn); }
.tl-dur { text-align:right; color:var(--muted); }
.toggle { position:relative; display:inline-block; width:34px; height:20px; margin:0; cursor:pointer; vertical-align:middle; }
label.toggle input { position:absolute; inset:0; opacity:0; width:100%; height:100%; margin:0; cursor:pointer; z-index:1; }
.toggle .track { position:absolute; inset:0; background:var(--line-2); border-radius:10px; transition:background .15s; }
.toggle .track::after { content:""; position:absolute; top:2px; left:2px; width:16px; height:16px; border-radius:50%; background:#fff; box-shadow:0 1px 2px rgba(0,0,0,.3); transition:transform .15s; }
label.toggle input:checked + .track, .toggle .track.on { background:var(--accent); }
label.toggle input:checked + .track::after, .toggle .track.on::after { transform:translateX(14px); }
label.toggle input:disabled { cursor:not-allowed; } label.toggle input:disabled + .track { opacity:.55; }
label.toggle input:focus-visible + .track { outline:2px solid var(--accent); outline-offset:2px; }
.helptip.bare { width:auto; height:auto; min-width:0; border:0; border-radius:0; margin:0; cursor:help; vertical-align:middle; }
.helptip.bare .toggle { cursor:help; } .helptip.bare .track { opacity:.55; }
.helptip.bare:focus-visible .track { outline:2px solid var(--accent); outline-offset:2px; }
table.pipeline tr.off td:not(:first-child), table.pipeline tr.planned td:not(:first-child) { opacity:.6; }
table.pipeline td:first-child, table.pipeline th:first-child { width:1%; white-space:nowrap; }
table.pipeline tr.stagehead th { padding-top:var(--sp-3); color:var(--muted); font-size:var(--fs-0); text-transform:uppercase; letter-spacing:.05em; border-bottom:1px solid var(--line); }
.runprog[hidden] { display:none; }
.runprog { display:flex; flex-direction:column; gap:var(--gap-2); margin:var(--gap-1) 0 var(--gap-2); font-size:var(--fs-1); color:var(--ink-2); }
.runprog .prow { display:flex; flex-direction:column; gap:4px; }
.runprog .plrow { display:flex; align-items:baseline; justify-content:space-between; gap:var(--sp-2); }
.runprog .plrow .rpct, .runprog .plrow .phpct { flex:0 0 auto; font-variant-numeric:tabular-nums; }
.runprog .bar { height:8px; border-radius:999px; background:var(--panel-3); overflow:hidden; }
.runprog .bar span { display:block; height:100%; width:0; background:var(--accent); transition:width .6s ease; }
.runprog .prow-phase .pf { opacity:.6; }
.runprog .prow-phase.nobar .bar { visibility:hidden; }
.nextchip { display:inline-flex; align-items:center; gap:var(--gap-1); max-width:320px; height:calc(var(--ctl-h) - 4px); padding:0 var(--sp-2);
  border:1px solid var(--accent); border-radius:999px; text-decoration:none; font-size:var(--fs-1); font-weight:600; color:var(--ink); }
.nextchip .k { color:var(--accent); text-transform:uppercase; letter-spacing:.04em; font-size:var(--fs-0); }
.nextchip .t { overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
.nextchip:hover { background:var(--panel-2); }
/* Below 900px the top bar has no room for the step: it moves into the menu
   drawer, where it has a row of its own, instead of sitting under the search. */
.navnext { display:none; }
@media (max-width:900px) {
  .tb-actions .nextchip { display:none; }
  .navnext { display:block; padding:var(--gap-2) var(--sp-1); }
  .navnext .nextchip { max-width:none; width:100%; box-sizing:border-box; height:auto; padding:var(--gap-2) var(--sp-1); white-space:normal; }
  .navnext .nextchip .t { white-space:normal; }
}
/* The short label keeps the size of the switch: the .sm utility had made it 13px. */
.surfacebar .sm { display:none; font-size:inherit; }
/* Between a phone and a wide screen the heading row is crowded: the switch
   takes its short labels and the Export menu its icon, so neither is cut off. */
@media (max-width:1100px) {
  .surfacebar .lg { display:none; } .surfacebar .sm { display:inline; }
  .exlabel { display:none; }
}
/* A tab head shares its row with the menu, so it is crowded at a wider window
   than a page head: the switch and Export need about 1180px beside the tabs,
   which is 1484px of window with the menu open (236px of menu and 68px of side
   padding) and 1312px with it collapsed to its icons (64px). */
@media (max-width:1484px) {
  :root:not([data-nav="collapsed"]) .tabhead .surfacebar .lg { display:none; }
  :root:not([data-nav="collapsed"]) .tabhead .surfacebar .sm { display:inline; }
  :root:not([data-nav="collapsed"]) .tabhead .exlabel { display:none; }
}
@media (max-width:1312px) {
  .tabhead .surfacebar .lg { display:none; } .tabhead .surfacebar .sm { display:inline; }
  .tabhead .exlabel { display:none; }
}
/* The next setup step, with its one control. */
.nextstep { display:flex; align-items:center; justify-content:space-between; gap:var(--sp-3); flex-wrap:wrap;
  padding:var(--sp-3); margin:0 0 var(--sp-3); border:1px solid var(--accent); border-radius:var(--radius); background:var(--accent-weak); }
.nextstep .k { display:block; color:var(--accent); text-transform:uppercase; letter-spacing:.04em; font-size:var(--fs-0); font-weight:700; }
.nextstep h3 { margin:var(--gap-1) 0; font-size:var(--fs-3); }
.nextstep p { margin:0; color:var(--ink-2); }
.nextstep .ns-text { flex:1 1 320px; }
.palette { position:fixed; inset:0; z-index:60; background:color-mix(in srgb,#000 35%,transparent); display:flex; justify-content:center; align-items:flex-start; padding-top:12vh; }
.palette[hidden] { display:none; }
.palettebox { width:min(640px, calc(100vw - 32px)); background:var(--panel); border:1px solid var(--line); border-radius:var(--radius); box-shadow:var(--shadow); padding:var(--sp-2); }
.palettebox input { width:100%; }
.palettebox ul { list-style:none; margin:var(--sp-1) 0; padding:0; max-height:50vh; overflow:auto; }
.palettebox li a { display:block; padding:var(--gap-2) var(--sp-1); border-radius:4px; color:var(--ink); text-decoration:none; }
.palettebox li.on a, .palettebox li a:hover { background:var(--panel-2); }
tr.kbcur > td { background:color-mix(in srgb,var(--accent) 10%,transparent); }
tr.kbcur > td:first-child { box-shadow:inset 3px 0 0 var(--accent); }
.runchip .dot { width:8px; height:8px; border-radius:50%; background:currentColor; animation:pulse 1.2s ease-in-out infinite; }
@keyframes pulse { 0%,100%{opacity:1;transform:scale(1)} 50%{opacity:.3;transform:scale(.65)} }

/* The content area is the only scroll container, so the scrollbar stays below
   the top bar and beside the content rather than running the full height next
   to the menus. */
main { flex:1; min-width:0; min-height:0; overflow:auto; }
/* The content area uses the screen. A cap of 1200px left a third of a wide
   screen empty beside a table squeezed into the rest; 2400px only stops a line
   of a table from becoming unreadably long on the widest displays. */
.mainwrap { padding:var(--sp-4) var(--sp-4) var(--sp-4); max-width:2400px; }

/* Scrollbars. The platform default renders a bright overlay bar that sits hard
   against the tab strip and reads as part of it. These are thin, themed and
   quiet, and the gutter is reserved so content does not shift when one appears. */
main { scrollbar-gutter:stable; }
main, pre, .scrollx, aside, select, textarea { scrollbar-width:thin; scrollbar-color:var(--line-2) transparent; }
main::-webkit-scrollbar, pre::-webkit-scrollbar, .scrollx::-webkit-scrollbar { width:11px; height:11px; }
main::-webkit-scrollbar-track, pre::-webkit-scrollbar-track, .scrollx::-webkit-scrollbar-track { background:transparent; }
main::-webkit-scrollbar-thumb, pre::-webkit-scrollbar-thumb, .scrollx::-webkit-scrollbar-thumb {
  background:var(--line-2); border-radius:var(--radius); border:3px solid transparent; background-clip:content-box; }
main::-webkit-scrollbar-thumb:hover, pre::-webkit-scrollbar-thumb:hover, .scrollx::-webkit-scrollbar-thumb:hover {
  background:var(--muted); background-clip:content-box; }
main::-webkit-scrollbar-corner, pre::-webkit-scrollbar-corner { background:transparent; }

/* Typography ------------------------------------------------------------- */
h1 { font-size:var(--fs-5); margin:0 0 var(--sp-1); letter-spacing:-.3px; font-weight:700;
  display:flex; align-items:center; gap:var(--gap-1); }
h2 { font-size:var(--fs-3); margin:var(--sp-4) 0 var(--sp-2); font-weight:700; letter-spacing:.1px;
  display:flex; align-items:center; gap:var(--gap-1); color:var(--ink);
  padding-bottom:var(--sp-1); border-bottom:1px solid var(--line); }
h1 .icon { margin-right:var(--sp-1); color:var(--accent); }
h2 .icon { margin-right:var(--gap-2); color:var(--muted); }
/* A heading immediately after the tab bar or the surface note already has that
   block's gap above it, so it does not add a section gap on top. */
.tabs + h2, .surfacenote + h2, .pagehead + h2 { margin-top:0; }
/* Running text spans the column it sits in, as the tables and panels beside it
   do. A measure in characters made every paragraph stop at its own width, short
   of the table above it on a wide screen and different from its neighbours. */
p.hint { color:var(--muted); margin:0 0 var(--sp-3); font-size:var(--fs-2); }
  .limits { color:var(--muted); font-size:var(--fs-2); padding-left:var(--sp-3); }
  .limits li { margin:var(--gap-2) 0; }
/* The browser's 1em default differed from every spacing value the console
   uses, so a bare paragraph between two blocks was a gap nobody chose. */
p { margin:0 0 var(--sp-2); }
a { color:var(--accent); text-underline-offset:2px; }
.muted { color:var(--muted); }
/* The architecture drawing. Zones by where they sit, links by whether they are encrypted. */
.archwrap { overflow-x:auto; }
.archsvg { max-width:100%; height:auto; }
.archsvg .arch-zone { fill:var(--panel-2); stroke:var(--accent); stroke-width:1.5; }
.archsvg .k-internet, .archsvg .k-partner, .archsvg .k-saas { stroke:var(--high); }
.archsvg .k-internal, .archsvg .k-office { stroke:var(--low); }
.archsvg .arch-name { font-weight:600; font-size:13px; fill:var(--ink); }
.archsvg .arch-kind { font-size:11px; fill:var(--muted); }
.archsvg .arch-link { fill:none; stroke:var(--muted); stroke-width:1.5; }
.archsvg .arch-link.plain { stroke:var(--crit); stroke-dasharray:6 4; }
.archsvg .arch-linktext { font-size:10px; fill:var(--ink); paint-order:stroke; stroke:var(--panel); stroke-width:3px; }
.archsvg .arch-arrow { fill:var(--muted); }
/* The five by five grid of the risk register, each cell in the colour of its band. */
.gridpair { display:flex; flex-wrap:wrap; gap:var(--sp-3); align-items:flex-start; }
/* Visible, not the clip every table has, which cut the first pixel off the caption. */
table.riskgrid { border-collapse:separate; border-spacing:3px; width:auto; overflow:visible; }
figure.rgfig { margin:0; }
table.riskgrid caption { text-align:left; font-weight:600; padding-bottom:var(--gap-2); }
table.riskgrid td, table.riskgrid th { width:2.4em; height:2.4em; text-align:center; padding:0; border:0; font-variant-numeric:tabular-nums; }
table.riskgrid th { color:var(--muted); font-weight:500; background:none; }
/* Dark ink on the tinted bands, white only on the solid critical red: white on
   the low and medium tints read at about 1.3:1. */
table.riskgrid td { border-radius:4px; font-weight:600; color:var(--high-ink); }
table.riskgrid td.rg-low { background:color-mix(in srgb, var(--low) 80%, transparent); }
table.riskgrid td.rg-medium { background:color-mix(in srgb, var(--med) 60%, transparent); }
table.riskgrid td.rg-high { background:color-mix(in srgb, var(--high) 75%, transparent); }
table.riskgrid td.rg-critical { background:var(--crit); color:var(--sev-ink); }
/* The registered country of an address, drawn by the emoji font of the system. See ipcountry.ts. */
.ipflag { margin-left:.35em; font-family:"Apple Color Emoji","Segoe UI Emoji","Noto Color Emoji",sans-serif; font-size:1.1em; line-height:1; cursor:default; font-style:normal; white-space:nowrap; }
img.ipflag { width:16px; height:12px; vertical-align:-1px; border-radius:2px; box-shadow:0 0 0 1px var(--border); object-fit:cover; }
/* Sized from the text around it rather than fixed, so an address in a
   sentence, a table or a heading matches its line. */
code { background:var(--panel-2); padding:var(--gap-1) var(--gap-2); border-radius:5px; font-size:.95em;
  border:1px solid var(--line); font-family:"Roboto Mono",ui-monospace,SFMono-Regular,Menlo,monospace; }
pre { background:#0b0f14; color:#cfd8e3; padding:var(--sp-2) var(--sp-2); border-radius:var(--radius); overflow:auto;
  margin:0 0 var(--sp-2);
  font-size:var(--fs-1); line-height:1.55; border:1px solid #1b232e;
  font-family:"Roboto Mono",ui-monospace,SFMono-Regular,Menlo,monospace; }

/* Tables ----------------------------------------------------------------- */
table { border-collapse:separate; border-spacing:0; width:100%; background:var(--panel); font-size:var(--fs-2);
  /* clip and not hidden: hidden makes the table a scroll container, which both
     cut a wide table off at its right edge and stopped a sticky header. */
  border:1px solid var(--line); border-radius:var(--radius); overflow:clip; box-shadow:var(--shadow);
  /* A table had no bottom margin at all, so whatever followed it sat against
     it or was held off only by its own top margin, which differed per page. */
  margin:0 0 var(--sp-3); }
th,td { padding:var(--sp-1) var(--sp-2); text-align:left; vertical-align:top; border-bottom:1px solid var(--line); }
/* Compact density. A long findings list is read by scanning, and 11px of
   padding per row is 40% of the screen on a table of 20 rows. */
/* Compact density. It used to restyle table rows, the body font and the cards
   and nothing else, so a page of panels and headings looked identical before
   and after and the control read as broken. It moves the spacing scale now, so
   it reaches every gap on every page, and then tightens the components whose
   padding is their own. */
:root[data-density="compact"] { --sp-1:5px; --sp-2:9px; --sp-3:14px; --sp-4:22px; --gap-2:5px; --ctl-h:32px; }
:root[data-density="compact"] body { font-size:var(--fs-2); }
:root[data-density="compact"] .why { margin-top:var(--gap-1); font-size:var(--fs-0); }
:root[data-density="compact"] .cards { gap:var(--sp-1); }
:root[data-density="compact"] .card { padding:var(--sp-1) var(--sp-2) var(--sp-1); }
:root[data-density="compact"] .panel { padding:var(--sp-1) var(--sp-2); }
:root[data-density="compact"] .score { padding:var(--sp-2) var(--sp-2); gap:var(--sp-2) var(--sp-3); }
:root[data-density="compact"] .hero { gap:var(--sp-1); }
:root[data-density="compact"] .mainwrap { padding:var(--sp-2) var(--sp-3) var(--sp-4); }
:root[data-density="compact"] h1 { font-size:19px; }
:root[data-density="compact"] h2 { padding-bottom:var(--gap-2); }
:root[data-density="compact"] .fold .foldbody { padding:var(--gap-1) var(--sp-2) var(--sp-1); }
:root[data-density="compact"] .empty { padding:var(--sp-2); }
:root[data-density="compact"] pre { padding:var(--sp-1) var(--sp-2); }
th { background:var(--panel); font-weight:600; color:var(--ink); font-size:var(--fs-1);
  white-space:nowrap; border-bottom:1px solid var(--line-2); }
tr:last-child td { border-bottom:0; }
/* A row label on the last row loses the header rule with its cells. A header
   row, which holds no cells, keeps it. */
tr:last-child:has(> td) > th { border-bottom:0; }
/* A long list keeps its column headings in view, on every table of records:
   a fact sheet's headings are its row labels and stay where they are. Only a row
   of headings sticks: a first row that opens with a label (KEV, or the 5 of the
   heat map) pinned that label over the rows below it. */
table:not(.kv) tr:first-child:not(:has(> td)) > th { position:sticky; top:0; z-index:2; }
table tr:hover td { background:var(--panel-2); }
/* A table of label/value pairs is a different thing from a table of records and
   shared its style, so the label column took half the page and its uppercase
   heading read as a column header over one cell. The label column is as wide as
   its label, and a hover highlight means nothing on a fact sheet. */
/* Fixed layout, because a value cell decides its own width otherwise and one
   of them always wins. The evidence cell holds a <pre>, whose white-space is
   "pre" and whose intrinsic width is therefore its longest line: a certificate
   name list made the table 108px wider than the content area and put a
   horizontal scrollbar across the foot of every finding page. Overflow on the
   <pre> does not help, because an auto-layout table sizes to content before
   the scroll container ever applies. */
table.kv { table-layout:fixed; }
table.kv.narrowkv th { width:96px; }
/* A Greek label runs longer: "Προγραμματισμένες" alone is wider than the
   English column, and a fixed layout drew it over the value beside it. So the
   column is wider in Greek, and a word that still does not fit is hyphenated. */
:lang(el) table.kv.narrowkv th { hyphens:auto; }
@media (min-width:701px) { :lang(el) table.kv.narrowkv th { width:120px; } }
table.kv th { width:152px; white-space:normal; vertical-align:top;
  background:var(--panel-2); border-right:1px solid var(--line); }
table.kv td > pre { max-width:100%; margin:0; }
table.kv tr:hover td { background:transparent; }
/* A value cell holds whatever the scan returned, and some of it is one token
   with nowhere to break: a finding id, a URL, a certificate's name list. An
   auto-layout table cannot shrink below its widest unbreakable token, so one
   of those stretched the table past the content area and put a horizontal
   scrollbar across the foot of the page. The cell breaks instead. */
table.kv td { width:auto; overflow-wrap:anywhere; }

td a { text-decoration:none; font-weight:550; }
td a:hover { text-decoration:underline; }
/* A code element inside a block is part of the block, not a chip of its own. */
pre code { background:none; border:0; padding:0; font-size:inherit; color:inherit; border-radius:0; }
pre.updlog, .updlog pre { max-height:16rem; overflow:auto; }
td code { background:transparent; border:0; padding:0; color:var(--ink-2); overflow-wrap:anywhere; }
/* The issue is what a row is read for, so it keeps room for a title on one or
   two lines; the owner and its edit control sit on one line. */
td.issuecell { min-width:12rem; }
/* A free-text cell in a table that scrolls keeps the width of a phrase: the
   table shrank every wrappable cell to its longest word, one word per line. */
td.prose { min-width:12rem; }
/* One published check fires once per service, so a risk-sorted list stacks rows
   whose title and template id are identical and differ only by host. The title
   on a row that repeats the one above it is dimmed so the eye lands on the host
   that distinguishes it; the text stays in place for a reader and for copy. */
td.issuecell.rep a { opacity:.42; }
td.issuecell.rep .sm code { opacity:.42; }
/* The title and its preview control are one row, so the control pins to the
   first line of the title rather than orphaning onto a line of its own when the
   title wraps on a narrow screen. */
td.issuecell .titlerow { display:flex; align-items:flex-start; gap:var(--gap-1); }
td.issuecell .titlerow a { min-width:0; }
td.issuecell .titlerow .peek { flex:none; }
td.ownercell { white-space:nowrap; } td.ownercell details.inlineedit { display:inline-block; vertical-align:middle; margin-left:var(--gap-1); }
/* An opened owner edit drops under the name inside its cell, instead of running
   the unbreakable line on over the next column. */
td.ownercell:has(> details.inlineedit[open]) { white-space:normal; }
td.ownercell > details.inlineedit[open] { display:block; margin:var(--gap-1) 0 0; }
td.num { text-align:right; font-weight:650; color:var(--ink-2); white-space:nowrap; }
/* A heading sits over its column, so it aligns the way the column does. */
th.num { text-align:right; }
.nowrap { white-space:nowrap; }

/* Sort control for the findings list: a light segmented row, not a dropdown,
   so the current order is visible without opening anything. */
/* A section folded until it is wanted. The marker is drawn by the rule rather
   than the browser default, so it is the same glyph in every engine. */
.fold { border:1px solid var(--line); border-radius:var(--radius); background:var(--panel);
  margin:0 0 var(--sp-1); }
.fold > summary { cursor:pointer; list-style:none; padding:var(--sp-1) var(--sp-2); font-weight:650; font-size:var(--fs-3);
  display:flex; align-items:center; gap:var(--sp-1); color:var(--ink); }
.fold > summary::-webkit-details-marker { display:none; }
.fold > summary::before { content:"›"; display:inline-block; color:var(--muted); font-size:var(--fs-4);
  line-height:1; transition:transform .15s ease; }
.fold[open] > summary::before { transform:rotate(90deg); }
.fold > summary:hover { background:var(--panel-2); border-radius:var(--radius); }
.fold .foldbody { padding:var(--gap-1) var(--sp-2) var(--sp-2); border-top:1px solid var(--line); }
.fold .foldbody > h2:first-child { margin-top:var(--sp-2); }

/* The surface switch: a segmented control, above the tabs, because it changes
   what every tab below it means. */
/* The heading band. One row of fixed height, so the tabs below it are at the
   same place on every view of a destination. */
.pagehead { display:flex; align-items:center; justify-content:space-between; gap:var(--sp-2);
  flex-wrap:wrap; min-height:var(--ctl-h); }
.pagehead h1 { margin:0; }
.pagehead:not(.tabbed) { margin-bottom:var(--sp-2); }
.pagehead.tabbed { height:var(--ctl-h); flex-wrap:nowrap; }
.pagehead.tabbed h1 { white-space:nowrap; overflow:hidden; min-width:0; }
.pagehead.tabbed .pageactions { flex-wrap:nowrap; flex:0 0 auto; }
.surfacebar { display:inline-flex; border:1px solid var(--line); border-radius:999px; height:var(--ctl-h);
  background:var(--panel-2); padding:var(--gap-1); gap:var(--gap-1); flex:0 0 auto; }
.surfacebar a { display:inline-flex; align-items:center; gap:var(--gap-2); padding:0 var(--sp-2); border-radius:999px;
  text-decoration:none; color:var(--ink-2); font-size:var(--fs-2); font-weight:650; }
.surfacebar a:hover { color:var(--ink); }
.surfacebar a.on { background:var(--panel); color:var(--ink); box-shadow:var(--shadow-lg); }
.surfacebar a b { font-size:var(--fs-0); font-weight:700; color:var(--muted);
  background:var(--panel-3); border-radius:999px; padding:var(--gap-1) var(--gap-2); }
.surfacebar a.on b { color:var(--accent); background:var(--accent-weak); }
/* Sits directly under the tabs, so it pulls back against the tabs' own gap and
   then gives the standard one below itself. */
.cveverdict { font-size:var(--fs-3); margin:0 0 var(--sp-2); }
.cveevidence li { margin-bottom:var(--gap-2); }
.surfacenote { color:var(--muted); font-size:var(--fs-1); margin:calc(var(--sp-3) * -1 + var(--gap-2)) 0 var(--sp-3); }
/* A form the signed-in role cannot send: its values stay readable, its buttons go. See withRole. */
form[data-ro] button, form[data-ro] input[type=submit] { display:none; }
form[data-ro] input, form[data-ro] select, form[data-ro] textarea { opacity:.75; }
.rolenote { margin:0 0 var(--sp-3); }
main table.wide { display:block; overflow-x:auto; max-width:100%; }

/* Sortable columns. The whole heading is the control, so the hit area is the
   column label. The indicator is on the header cell itself through aria-sort,
   which is also what a screen reader reads, so the two cannot disagree. */
table.sortable th[data-sort] { cursor:pointer; user-select:none; white-space:nowrap; }
/* A table of many counted columns lets its headings wrap, so it fits the page
   instead of hiding its last columns past the edge. */
table.sortable.wraphead th[data-sort] { white-space:normal; }
table.wraphead th { white-space:normal; }
table.sortable th[data-sort]:hover,
table.sortable th[data-sort]:focus-visible { color:var(--ink); }
table.sortable th[data-sort]::after { content:"↕"; margin-left:var(--gap-2); font-size:var(--fs-0); opacity:.6; }
table.sortable th[aria-sort] { color:var(--accent); }
table.sortable th[aria-sort="ascending"]::after { content:"↑"; opacity:1; }
table.sortable th[aria-sort="descending"]::after { content:"↓"; opacity:1; }
.sortbar { display:flex; align-items:center; gap:var(--gap-1); margin:0 0 var(--sp-2); flex-wrap:wrap; }
.sortbar .k { color:var(--muted); font-size:var(--fs-0); letter-spacing:.5px; text-transform:uppercase; margin-right:var(--gap-2); }
.sortbar a { color:var(--muted); text-decoration:none; padding:var(--gap-1) var(--sp-1); border-radius:var(--radius); font-size:var(--fs-1); font-weight:600; }
.sortbar a:hover { color:var(--ink); background:var(--panel-2); }
.sortbar a.on { color:var(--accent); background:var(--accent-weak); }
/* The count a filter chip carries. It sits beside a value that is itself a
   number, so "80" and its count of 5 rendered as "80 5", which reads as 805.
   The chip's own background is what separates the two. */
.sortbar .cnt { margin-left:var(--gap-2); font-weight:700; font-size:var(--fs-0); color:var(--muted);
  background:var(--panel-3); border-radius:999px; padding:var(--gap-1) var(--gap-2); }
.sortbar a.on .cnt { background:var(--panel); }
.sortbar a.on .cnt { color:var(--accent); }

/* Saved views: a named filter per chip, carrying the count it matches, with a
   forget control that only shows on hover so the row stays quiet. */
.viewbar { display:flex; align-items:center; gap:var(--gap-2); margin:0 0 var(--sp-2); flex-wrap:wrap; }
.viewbar .k { color:var(--muted); font-size:var(--fs-0); letter-spacing:.5px; text-transform:uppercase; margin-right:var(--gap-1); }
.viewbar .muted { font-size:var(--fs-1); }
.chip { display:inline-flex; align-items:center; background:var(--panel-2); border:1px solid var(--line);
  border-radius:999px; overflow:hidden; }
/* A chip is written two ways. A saved view is a container with the link inside
   it, because it also carries a forget control. A plan's finding is a bare
   link. Both spellings are in use, and the plan's inherited the container's
   border and none of the link rules, so it rendered as an underlined link
   crammed into a pill. The rules apply to both. */
/* A run of chips wraps between chips and never inside one, so an address
   does not break across two lines and a chip does not wrap into an oval. */
.chips a.chip { margin:0 var(--gap-2) var(--gap-1) 0; }
/* A row of chips as a nav of its own is held off the table under it. */
nav.chips { display:flex; flex-wrap:wrap; align-items:center; margin:0 0 var(--sp-2); }
a.chip code, .chip code { white-space:nowrap; }
.chip > a, a.chip { display:inline-flex; align-items:center; gap:var(--gap-2); padding:var(--gap-1) var(--sp-1); text-decoration:none;
  color:var(--ink-2); font-size:var(--fs-1); font-weight:600; line-height:1.5; }
.chip > a:hover, a.chip:hover { color:var(--ink); background:var(--panel-3); }
.chip > a b, a.chip b { color:var(--muted); font-weight:650; font-size:var(--fs-0); }
/* Bare chips sit in a paragraph, so they need their own rhythm. */
.chiprow { display:flex; flex-wrap:wrap; gap:var(--gap-2); margin:0 0 var(--sp-2); }
.chip.on { border-color:var(--accent); background:var(--accent-weak); }
.chip.on > a, .chip.on > a b { color:var(--accent); }
.chip form { display:inline; }
.chip .x { background:transparent; border:0; color:var(--muted); padding:var(--gap-1) var(--sp-1) var(--gap-1) var(--gap-1); font-size:var(--fs-3);
  line-height:1; cursor:pointer; opacity:0; }
.chip:hover .x, .chip .x:focus { opacity:1; }
.chip .x:hover { color:var(--bad); }
.saveview { display:flex; gap:var(--gap-2); align-items:center; margin-left:auto; }
.saveview input { width:170px; }
@media (max-width:760px) { .saveview { margin-left:0; width:100%; } .saveview input { flex:1; width:auto; } }

/* The fan: one address, the names that resolve to it. */
.fanwrap { overflow-x:auto; }
.fan { display:block; }
.fan .fanedge path { fill:none; stroke:var(--line-2); stroke-width:1.1; }
.fan .fannode { fill:var(--accent-weak); stroke:var(--accent); stroke-width:1; }
.fan .fanaddr { fill:var(--accent); font-size:var(--fs-0); font-weight:700;
  font-family:"Roboto Mono",ui-monospace,SFMono-Regular,Menlo,monospace; }
.fan .fanname { fill:var(--ink-2); font-size:var(--fs-0); }
.fan a:hover .fanname { fill:var(--ink); text-decoration:underline; }
.fan a:hover .fannode { fill:color-mix(in srgb,var(--accent) 26%,var(--panel));
  stroke-width:1.6; }
.fan a:hover .fanaddr { fill:var(--ink); }
.fanwrap > .k b { margin-left:var(--sp-1); font-size:var(--fs-0); font-weight:700; color:var(--muted);
  background:var(--panel-3); border-radius:999px; padding:var(--gap-1) var(--gap-2); text-transform:none;
  letter-spacing:0; }
/* A head that carries a risk disc is the word beside the disc, not a 22px pill
   around a 31px disc. */
.fanwrap > .k b:has(> .rdisc) { display:inline-flex; align-items:center; gap:var(--gap-1); padding:0; background:none; }

/* Paths: one column per node type, read left to right as the way in. */
.pathwrap { overflow-x:auto; max-width:100%; }
.pathsvg { display:block; }
.pathsvg .pedge path { fill:none; stroke:var(--line-2); stroke-width:1.1; }
.pathsvg .pedge path.cred { stroke:var(--high); stroke-dasharray:4 3; }
/* An edge that skips a column is a step the graph does not know: dashed, so it
   does not read as passing through the node it crosses. */
.pathsvg .pedge path.skip { stroke-dasharray:3 3; }
.pathsvg .pnode { fill:var(--panel-3); stroke:var(--line-2); stroke-width:1; }
.pathsvg .phead { fill:var(--muted); font-size:var(--fs-0); font-weight:700; }
.pathsvg .plabel { fill:var(--ink-2); font-size:var(--fs-0); }
.pathsvg a:hover .pnode { stroke:var(--accent); stroke-width:1.6; }
.pathsvg a:hover .plabel { fill:var(--ink); text-decoration:underline; }

/* A run of queue rows that are one decision. */
tr.clusterhead td { background:var(--panel-2); border-top:1px solid var(--line-2);
  font-size:var(--fs-1); padding-top:var(--sp-1); padding-bottom:var(--sp-1); }
tr.clusterhead td .why { margin-top:var(--gap-1); }
/* An address reads as one token: broken at its dots it read as three numbers. */
td > code[data-hostcard] { white-space:nowrap; }
/* A name a person gave a run, under its type in History. */
.runlabel { margin-top:var(--gap-1); font-weight:600; overflow-wrap:anywhere; }
/* A DNS chain wraps between steps, never inside a name. */
.dnschain { display:inline-flex; flex-wrap:wrap; gap:var(--gap-1); align-items:baseline; }
.evfold > summary { cursor:pointer; color:var(--accent); font-size:var(--fs-1); margin:var(--gap-1) 0; }
table tr.clusterhead:hover td { background:var(--panel-2); }

/* A risk score as a coloured disc with the number inside, on the 0 to 10
   scale every risk number in the tool is read on. The colour is the rating's
   band, which uses the severity palette, so an 8.1 is orange wherever it is. */
td.risk { white-space:nowrap; }
/* 2.6em with a little tracking, so 10.0 keeps a margin inside its circle. */
.rdisc { display:inline-flex; align-items:center; justify-content:center; width:2.6em; height:2.6em;
  border-radius:50%; font-size:var(--fs-0); font-weight:650; font-variant-numeric:tabular-nums; letter-spacing:-.02em;
  background:var(--info); color:var(--sev-ink); flex:none; }
.rdisc.rl-critical { background:var(--crit); color:var(--sev-ink); }
.rdisc.rl-high { background:var(--high); color:var(--high-ink); }
.rdisc.rl-medium { background:var(--med); color:var(--high-ink); }
.rdisc.rl-low { background:var(--low); color:var(--high-ink); }

/* The one thing a page is opened to find, said first and said large. */
.lead { background:var(--panel); border:1px solid var(--line); border-radius:var(--radius);
  padding:var(--sp-2) var(--sp-2); margin:0 0 var(--sp-2); }
.lead > p { margin:0 0 var(--sp-1); }
.lead > p:last-child { margin:0; }
.lead .leadaction { font-size:var(--fs-4); font-weight:650; line-height:1.45; color:var(--ink);
  letter-spacing:-.1px; }
.lead .leadverify { color:var(--ink-2); font-size:var(--fs-2); }
.lead .leadverify .k { color:var(--muted); font-size:var(--fs-0); letter-spacing:.5px;
  text-transform:uppercase; margin-right:var(--gap-2); }

/* Cards ------------------------------------------------------------------ */
.cards { display:grid; grid-template-columns:repeat(auto-fit,minmax(172px,1fr)); gap:var(--sp-2); margin:0 0 var(--sp-3); }
.card { background:var(--panel); border:1px solid var(--line); border-radius:var(--radius); padding:var(--sp-2) var(--sp-2) var(--sp-2);
  box-shadow:var(--shadow);
  color:inherit; text-decoration:none; display:block; position:relative;
  transition:background-color .12s ease,border-color .12s ease; }
a.card:hover { background:var(--panel-2); border-color:var(--line-2); }
.card .k { color:var(--muted); font-size:var(--fs-0); font-weight:550; letter-spacing:.2px; }
.card .s { color:var(--muted); font-size:var(--fs-1); margin-top:var(--gap-1); }
.card .v { font-size:var(--fs-6); font-weight:600; line-height:1.2; margin-top:var(--gap-1); letter-spacing:-.4px;
  font-variant-numeric:tabular-nums; }
.card.hot .v { color:var(--bad); }
.card .go { position:absolute; right:12px; bottom:11px; color:var(--muted); opacity:0; transition:opacity .12s; }
a.card:hover .go { opacity:.75; }

/* Panels ----------------------------------------------------------------- */
.panel { background:var(--panel); border:1px solid var(--line); border-radius:var(--radius-lg);
  padding:var(--sp-2) var(--sp-3); margin:0 0 var(--sp-2); }
/* A panel inside the hero grid is a grid item, so the grid's gap is its spacing
   and a margin would add to it unevenly. */
.hero > .panel, .hero > .chart, .hero > .score { margin:0; }
.panel > .k, .chart > .k { color:var(--muted); font-size:var(--fs-0); font-weight:650; letter-spacing:.3px;
  text-transform:uppercase; margin-bottom:var(--sp-2); display:block; }

/* A method note folded away: available on the page that shows the number, and
   not in the way of it. */
details.explain { margin-top:var(--sp-2); border-top:1px solid var(--line); padding-top:var(--sp-1); margin-bottom:var(--sp-2); }
details.explain > summary { cursor:pointer; color:var(--muted); font-size:var(--fs-1); font-weight:600;
  list-style:none; }
details.explain > summary::-webkit-details-marker { display:none; }
details.explain > summary::before { content:"+ "; }
details.explain[open] > summary::before { content:"- "; }
details.explain > summary:hover { color:var(--ink-2); }
details.explain p { color:var(--ink-2); font-size:var(--fs-1); margin:var(--sp-1) 0 0; }

/* A version next to its product: readable as a set, clickable individually. */
.verlink { display:inline-block; font-family:"Roboto Mono",ui-monospace,SFMono-Regular,Menlo,monospace;
  font-size:var(--fs-0); padding:var(--gap-1) var(--gap-2); margin:var(--gap-1) var(--gap-1) var(--gap-1) 0; border:1px solid var(--line);
  border-radius:5px; text-decoration:none; color:var(--ink-2); }
.verlink:hover { border-color:var(--accent); color:var(--accent); }

/* Pills and badges ------------------------------------------------------- */
.pill { display:inline-block; padding:var(--gap-1) var(--gap-2); border-radius:5px; font-size:var(--fs-0); font-weight:600;
  letter-spacing:.1px; white-space:nowrap; line-height:1.4; }
/* Severity badges are filled, as Wazuh's are: red, orange, yellow, blue, grey.
   Green is kept for good news, so no severity wears it. Orange and yellow take
   dark text. */
.pill.critical { background:var(--crit); color:var(--sev-ink); }
.pill.high { background:var(--high); color:var(--high-ink); }
.pill.medium { background:var(--med); color:var(--high-ink); }
/* Dark ink on the blue of low: white on it was 3.3:1. */
.pill.low { background:var(--low); color:var(--high-ink); }
.pill.info { background:color-mix(in srgb,var(--info) 15%,transparent); color:var(--info); }

/* Forms and buttons ------------------------------------------------------ */
form.inline { display:inline; }
/* Flat fill, one accent, no gradient and no inset highlight. A glossed button
   is a 2010 control: the only state change on hover is the fill. */
/* A label never wraps. "Save view" sat in a flex row beside a fixed-width
   input, broke over two lines and made that one control half as tall again as
   everything next to it. */
button,a.btnlink,summary.btnlike { white-space:nowrap; }
button { cursor:pointer; color:var(--accent-ink); border:1px solid transparent;
  background:var(--accent); border-radius:7px; padding:var(--gap-2) var(--sp-2); font-size:var(--fs-2);
  font-weight:600; font-family:inherit; line-height:1.55;
  transition:background-color .12s ease,border-color .12s ease,color .12s ease; }
button:hover { background:color-mix(in srgb,var(--accent) 86%,#000); }
button:active { background:color-mix(in srgb,var(--accent) 76%,#000); }
/* Secondary is an outline, which is what most controls on a page should be:
   one primary action per view, everything else quiet. */
button.sec,a.btnlink,summary.btnlike { background:transparent; color:var(--ink-2); border-color:var(--line-2); }
a.btnlink,summary.btnlike { display:inline-flex; align-items:center; border:1px solid var(--line-2); cursor:pointer; border-radius:7px;
  padding:var(--gap-2) var(--sp-2); font-size:var(--fs-2); font-weight:600; text-decoration:none; line-height:1.55;
  transition:background-color .12s ease,border-color .12s ease,color .12s ease; }
a.btnlink:hover,button.sec:hover,summary.btnlike:hover { background:var(--panel-2); border-color:var(--muted); color:var(--ink); }
button.warn { background:var(--bad); color:var(--bad-ink); }
button.warn:hover { background:color-mix(in srgb,var(--bad) 86%,#000); }
button, a.btnlink, summary.btnlike { height:var(--ctl-h); padding-top:0; padding-bottom:0; }
/* Small controls keep their own size: a copy glyph, a preset chip, the menu's
   own buttons and the pager under a table. */
button.copy, button.preset, button.iconbtn, .chip button.x, button.navcollapse, .wsmenu button, aside button.x, button.menubtn,
.pager button, .pager select, .btnrow.presets .preset { height:auto; }
/* A disabled primary keeps the accent fill so hover cannot darken it; every
   other kind keeps its own look, faded. A help tip, a copy glyph or a danger
   button painted indigo read as a primary action that was switched off. */
button:disabled { opacity:.4; cursor:not-allowed; }
button:not(.sec, .warn, .copy, .iconbtn, .x, .preset, .helptip, .linkbtn, .linkish):disabled { background:var(--accent); }
button.warn:disabled { background:var(--bad); }
/* A form button that reads as a link: switching workspace is a POST, and a count in a table is a link. */
button.linkbtn, button.linkbtn:hover, button.linkbtn:active { background:none; border:0; padding:0; height:auto; color:var(--accent); font:inherit; text-align:left; white-space:normal; }
button.linkbtn:hover { text-decoration:underline; }
/* A maturity score against the scale's top of 5, its target a tick. */
.matbar { display:inline-block; position:relative; width:120px; height:8px; background:var(--panel-2); border-radius:4px; vertical-align:middle; }
.matbar .fillbar { position:absolute; inset:0 auto 0 0; background:var(--accent); border-radius:4px; }
.mattable td:first-child { white-space:nowrap; }
/* As wide as its longest option, so the column fits "Partly implemented". */
.mattable select { width:auto; min-width:11em; }
.mattable textarea { width:100%; min-width:12em; }
table.firstwide td:first-child { min-width:12em; }
.copy.draftcopy { opacity:1; border:1px solid var(--line-2); color:var(--ink); font-family:inherit; font-size:var(--fs-1); }
/* A light box, so its text is the ink of the page and not the pale grey of the dark code block. */
pre.draft { white-space:pre-wrap; word-break:break-word; background:var(--panel-2); color:var(--ink); border:1px solid var(--line); border-radius:7px; padding:var(--inset); font-size:var(--fs-1); }
/* The tabletop clock: an inject not yet reached is dimmed, the clock stays in view. */
.inject { scroll-margin-top:calc(var(--ctl-h) + var(--sp-3)); }
.inject.later { opacity:.5; }
.ttclock { position:sticky; top:0; z-index:2; background:var(--bg); padding:var(--gap-2) 0; }
.ttclock #tt-clock { font-family:var(--mono, monospace); font-size:var(--fs-3); }
.mattable td:nth-child(2) { min-width:16em; }
.matbar .tgt { position:absolute; top:-3px; width:2px; height:14px; margin-left:-1px; background:var(--ink); }
button.sec:disabled { background:transparent; }
.btnrow { display:flex; flex-wrap:wrap; gap:var(--sp-1); align-items:center; margin:var(--sp-2) 0 var(--sp-3); }
.btnrow.presets { gap:var(--gap-2); margin:var(--sp-1) 0 0; }
/* Anything placed in a row sits on the row's centre line. A label carries a
   block margin for the stacked form layout, which pushed it off the line of
   the buttons and selects beside it. */
.btnrow > label, .btnrow > .inlinelabel, .btnrow > span, .btnrow > a, .btnrow > select, .btnrow > input { margin:0; }
.btnrow > select { width:auto; }
/* A label holding a field in a row sits on the line of the row with its field
   beside it, at the width of the field, whatever the length of its text. */
.btnrow > label:not(.check):not(.inlinelabel):has(> input:not([type=checkbox]):not([type=radio]), > select) { display:inline-flex; align-items:center; gap:var(--gap-2); }
.btnrow > label > :is(input, select) { width:auto; }
.btnrow.presets .preset { padding:var(--gap-1) var(--sp-1); font-size:var(--fs-0); font-weight:600; }
/* Controls share the interface face. Every text input was monospace, so a
   filter row rendered its two inputs in one typeface and its five selects in
   another, side by side at the same size. A textarea keeps the monospace,
   because what goes in one here is a list of domains or CIDR ranges read
   column by column. */
input[type=text],input:not([type]),input[type=search],input[type=password],input[type=date],input[type=datetime-local],input[type=number],input[type=email],input[type=url],input[type=tel],textarea,select { width:100%; max-width:560px;
  border:1px solid var(--line-2); border-radius:7px; padding:var(--sp-1) var(--sp-1); background:var(--panel); color:var(--ink);
  font-family:inherit; font-size:var(--fs-2); line-height:1.5; }
input[type=text],input:not([type]),input[type=search],input[type=password],input[type=date],input[type=datetime-local],input[type=number],input[type=email],input[type=url],input[type=tel],select {
  height:var(--ctl-h); padding-top:0; padding-bottom:0; }
textarea { font-family:"Roboto Mono",ui-monospace,SFMono-Regular,Menlo,monospace; }
/* A field the browser filled keeps the page's colours: its own autofill colour clashes with both themes. */
input:-webkit-autofill, input:-webkit-autofill:hover, input:-webkit-autofill:focus, textarea:-webkit-autofill, select:-webkit-autofill {
  -webkit-text-fill-color:var(--ink); caret-color:var(--ink); -webkit-box-shadow:0 0 0 1000px var(--panel) inset; box-shadow:0 0 0 1000px var(--panel) inset; transition:background-color 9999s ease-out 0s; }
input:autofill { background:var(--panel); color:var(--ink); }
select { max-width:260px; cursor:pointer; }
/* A secret field is as wide as any other, so a form of mixed fields lines up. */
input[type=date],input[type=datetime-local] { max-width:240px; }
td input[type=datetime-local], td input[type=date] { max-width:210px; }
input:focus,textarea:focus,select:focus { border-color:var(--accent);
  box-shadow:0 0 0 3px color-mix(in srgb,var(--accent) 18%,transparent); outline:none; }
textarea { min-height:116px; }
/* A short, fixed set of options, where the choice has a cost worth reading
   before it is made. A select hides every option but one behind a click, which
   is the wrong control when the comparison is the decision. */
.choices { display:grid; gap:var(--gap-2); margin:0 0 var(--sp-2); max-width:560px; }
/* A range (minimum, most likely, maximum) is one row of three fields. */
.choices.range3 { grid-template-columns:repeat(3,minmax(0,1fr)); align-items:end; }
@media (max-width:560px) { .choices.range3 { grid-template-columns:1fr; } }
.pagemarks { list-style:none; margin:0 0 var(--sp-2); padding:var(--gap-2) var(--sp-2); border:1px solid var(--line); border-radius:var(--radius); background:var(--panel); display:grid; gap:var(--gap-2); }
.pagemarks li { display:flex; align-items:baseline; gap:var(--gap-2); }
/* The dot is sized here: the menu and the tabs size theirs and this list did not. */
.pagemarks .navdot { position:static; flex:0 0 8px; width:8px; height:8px; border-radius:50%; background:var(--warn); transform:translateY(-1px); }
.pagemarks .navdot.bad { background:var(--bad); }
.pagemarks li > span:not(.navdot) { min-width:0; }
/* One form layout: a label above its field, the field at the standard width.
   Forms that wrap a field in its label used to lay out inline, so the incident
   form, the owner rules and the test plan each had a shape of their own. The
   label is a block, so its words, a note and the ? flow on the first line as
   text does, and the field is a block of its own width on the next: in a flex
   column the ? dropped onto a line of its own, and in a flex row a field
   narrower than the row (a date, a short select) sat beside the words. A
   fieldset in such a form stacks the same way; a fieldset of choices lays out
   its own. A box or a radio inside a bare label is left to its own rule. */
main :is(form:not(.inline):not(.btnrow), form:not(.inline):not(.btnrow) > fieldset:not(.choices)) > label:not(.check):not(.inlinelabel):not(.choice):has(> input:not([type=checkbox]):not([type=radio]), > select, > textarea) {
  display:block; max-width:560px; margin:0 0 var(--sp-2); font-weight:600; }
main :is(form:not(.inline):not(.btnrow), form:not(.inline):not(.btnrow) > fieldset:not(.choices)) > label:not(.check):not(.inlinelabel):not(.choice) > :is(input:not([type=checkbox]):not([type=radio]):not([type=hidden]), select, textarea) { display:block; font-weight:400; margin:var(--gap-1) 0 0; }
/* A select keeps the 260px look and grows to its longest option up to the
   standard width, so a long option is no longer cut at 260px. */
main :is(form:not(.inline):not(.btnrow), form:not(.inline):not(.btnrow) > fieldset:not(.choices)) > label:not(.check):not(.inlinelabel):not(.choice) > select { width:max-content; min-width:min(260px, 100%); max-width:100%; }
main form:not(.inline):not(.btnrow) > label + button { margin-top:var(--gap-1); }
/* A button in a paragraph after a field gets the gap of a control row. These forms
   are block, so after a stacked label the two margins collapse and nothing doubles. */
main form:not(.inline) > * + p:has(> button:first-child) { margin-top:var(--sp-2); }
/* A help line in a stack form is held to the width of the fields it explains. */
form.stack > p { max-width:560px; }
select + details.fold { margin-top:var(--sp-2); }
label.inlinelabel:has(select, input:not([type=checkbox]):not([type=radio])) { white-space:nowrap; }
.usermenu { position:relative; }
.usermenu > summary { list-style:none; cursor:pointer; display:flex; align-items:center; }
.usermenu > summary::-webkit-details-marker { display:none; }
.usermenu .avatar { width:30px; height:30px; border-radius:50%; display:inline-flex; align-items:center; justify-content:center;
  background:var(--accent); color:var(--accent-ink); font-weight:600; font-size:var(--fs-1); }
.usermenu .avatar.anon { background:var(--panel-2); color:var(--muted); border:1px solid var(--line); }
.usermenu > summary:focus-visible .avatar, .usermenu > summary:focus-visible .wsavatar { outline:2px solid var(--accent); outline-offset:2px; }
.usermenu .useravatar { width:30px; height:30px; }
.umenu .umhead .wsavatar { margin-bottom:var(--gap-2); }
.umenu { position:absolute; right:0; top:calc(100% + 6px); z-index:40; min-width:220px; background:var(--panel); border:1px solid var(--line);
  border-radius:var(--radius); box-shadow:0 8px 24px rgba(0,0,0,.18); padding:var(--gap-1) 0; }
.umenu .umhead { display:flex; gap:var(--sp-1); align-items:center; padding:var(--sp-1) var(--sp-2); border-bottom:1px solid var(--line); margin-bottom:var(--gap-1); }
.namecell { display:inline-flex; align-items:center; gap:var(--gap-2); }
.tenantsec .btnrow { align-items:center; }
.profilehead { display:flex; gap:var(--sp-2); align-items:center; margin-bottom:var(--sp-2); }
.profilehead .profileid { display:flex; flex-direction:column; gap:2px; min-width:0; }
.avedit { position:relative; display:inline-flex; border-radius:50%; flex:0 0 auto; }
.avedit .avedit-cue { position:absolute; inset:0; display:flex; align-items:center; justify-content:center; border-radius:50%; background:rgba(0,0,0,.5); color:#fff; opacity:0; transition:opacity .15s ease; pointer-events:none; }
.avedit:hover .avedit-cue, .avedit:focus-visible .avedit-cue { opacity:1; }
.avedit:focus-visible { outline:2px solid var(--accent); outline-offset:2px; }
.umenu .umwho { display:flex; flex-direction:column; min-width:0; }
.umenu .umwho > * { overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
.umenu .umrole { font-size:var(--fs-0); color:var(--ink-2); margin-top:2px; }
.umenu { min-width:260px; }
/* Preferences: a row per setting, the label and its description on the left
   and the control on the right, as most settings pages lay them out. */
.prefrows { max-width:860px; }
.prefrow { display:flex; align-items:center; justify-content:space-between; gap:var(--sp-3); padding:var(--sp-2) 0; border-bottom:1px solid var(--line); }
.prefrow .what b { display:block; font-weight:600; }
.prefrow .what span { color:var(--muted); font-size:var(--fs-1); }
.seg { display:inline-flex; flex-wrap:wrap; max-width:100%; padding:3px; border-radius:9px; background:var(--panel-2); border:1px solid var(--line); flex:none; }
/* margin:0, or the margin of a form label spaces each option of the switch. */
.seg label { display:inline-flex; align-items:center; gap:6px; margin:0; padding:5px 12px; border-radius:7px; cursor:pointer; color:var(--ink-2); font-size:var(--fs-1); }
.seg input { position:absolute; opacity:0; pointer-events:none; }
.seg label:has(input:checked) { background:var(--panel); color:var(--ink); box-shadow:0 1px 2px rgba(0,0,0,.12); font-weight:600; }
.seg label:has(input:focus-visible) { outline:2px solid var(--accent); outline-offset:1px; }
.seglinks a { display:inline-flex; align-items:center; padding:5px 12px; border-radius:7px; color:var(--ink-2); font-size:var(--fs-1); text-decoration:none; }
.seglinks a[aria-current] { background:var(--panel); color:var(--ink); box-shadow:0 1px 2px rgba(0,0,0,.12); font-weight:600; }
.sumbar { display:flex; flex-wrap:wrap; gap:var(--gap-2); align-items:center; margin:var(--sp-2) 0; }
article.summary { max-width:880px; line-height:1.65; }
article.summary .sumtitle { font-size:var(--fs-5); margin:0 0 2px; }
article.summary h2 { font-size:var(--fs-3); margin:var(--sp-3) 0 var(--gap-1); }
article.summary p, article.summary li { margin:0 0 var(--gap-2); }
article.summary a.src { color:var(--ink-3); opacity:.55; vertical-align:middle; }
article.summary #sum-figures ul { columns:2; column-gap:var(--sp-3); list-style:none; padding-left:0; }
@media (max-width: 560px) { article.summary #sum-figures ul { columns:1; } }
article.summary a.src:hover, article.summary a.src:focus-visible { opacity:1; color:var(--accent); }
@media (max-width:640px) { .prefrow { flex-direction:column; align-items:flex-start; } }
:root[data-motion="reduced"] *, :root[data-motion="reduced"] *::before, :root[data-motion="reduced"] *::after { animation:none !important; transition:none !important; scroll-behavior:auto !important; }
.umenu a, .umenu button { display:flex; align-items:center; gap:var(--gap-2); width:100%; padding:7px var(--sp-2); background:none; border:0;
  color:var(--ink); text-decoration:none; font:inherit; text-align:left; cursor:pointer; height:auto; border-radius:0; }
.umenu a:hover, .umenu button:hover { background:var(--panel-2); }
.umenu hr { border:0; border-top:1px solid var(--line); margin:var(--gap-1) 0; }
.umenu form { margin:0; }
.appearance fieldset { border:0; padding:0; margin:0 0 var(--sp-2); }
.appearance legend { font-weight:600; margin-bottom:var(--gap-1); }
.appearance .choices { display:flex; gap:var(--sp-2); flex-wrap:wrap; }
td.hostcell { min-width:9.5rem; max-width:14rem; }
td.hostcell code { white-space:normal; overflow-wrap:anywhere; }
td.wsactions .btnrow { flex-wrap:nowrap; }
td.wsactions { position:relative; }
@media (min-width:900px) { .tenantsec table { overflow:visible; } }
.wschange[open] > div { position:absolute; right:0; top:100%; z-index:5; min-width:300px; display:flex; flex-wrap:wrap; gap:var(--gap-2); align-items:center; padding:var(--gap-2); background:var(--panel); border:1px solid var(--line); border-radius:4px; box-shadow:0 4px 12px rgba(0,0,0,.18); }
.wschange[open] > summary { display:inline-flex; }
.tenantsec { margin:var(--sp-3) 0; }
.tenantsec h2 { margin:0; }
.wsmenu .wsgroup { font-size:var(--fs-0); color:var(--muted); text-transform:uppercase; letter-spacing:.04em; padding:var(--gap-2) var(--gap-2) 0; }
.choice { display:flex; align-items:flex-start; gap:var(--sp-1); margin:0;
  border:1px solid var(--line); border-radius:var(--radius); padding:var(--sp-1) var(--sp-2);
  background:var(--panel); cursor:pointer; font-weight:400;
  transition:border-color .12s ease,background-color .12s ease; }
.choice:hover { border-color:var(--line-2); background:var(--panel-2); }
.choice:has(input:checked) { border-color:var(--accent); background:var(--accent-weak); }
.choice input { width:auto; margin:var(--gap-1) 0 0; flex:0 0 auto; accent-color:var(--accent); }
.choice b { display:block; font-weight:650; font-size:var(--fs-2); }
/* A title line that carries a badge keeps the badge beside the title. */
.choice .ct { display:flex; align-items:center; gap:var(--gap-2); }
.choice .ct b { display:inline; }
.choice .sub { display:block; color:var(--muted); font-size:var(--fs-1); margin-top:1px; }
.choice select { margin-top:var(--gap-2); width:auto; }
.choice small { display:block; color:var(--muted); font-size:var(--fs-1); margin-top:1px; }

/* The on-demand explanation. Hover and keyboard focus both show it, because a
   hover-only affordance is one half the operators cannot reach. */
/* A circle of a fixed size. It was listed among the small buttons whose height
   is auto, a more specific rule than this one, so it lost its height and drew
   as a flattened oval. */
.helptip { all:unset; display:inline-flex; align-items:center; justify-content:center; box-sizing:border-box;
  width:16px; height:16px; min-width:16px; border-radius:50%; border:1px solid var(--line-2);
  color:var(--muted); font-size:11px; font-weight:700; line-height:1; cursor:help;
  vertical-align:text-top; margin-left:var(--gap-2); position:relative; flex:0 0 auto; }
.helptip:hover, .helptip:focus-visible { border-color:var(--accent); color:var(--accent); }
/* all:unset above takes the shared focus ring away, so it is put back. */
.helptip:focus-visible { outline:2px solid var(--accent); outline-offset:2px; }
/* Off screen until focused: the first Tab on a page, so a keyboard reader does not walk the whole menu to reach it. */
.skiplink { position:absolute; left:-9999px; top:0; z-index:100; }
.skiplink:focus { left:var(--sp-2); top:var(--sp-2); padding:var(--gap-2) var(--sp-2); background:var(--panel); color:var(--ink); border:1px solid var(--accent); border-radius:var(--radius); }
main:focus { outline:none; }
/* Fixed to the window and placed by the script beside the icon, because a
   table or panel that scrolls sideways clips anything absolutely positioned
   inside it, which cut the top off every tip in a table. */
.helptip .tip { position:fixed; left:0; top:0; width:max-content; max-width:320px; z-index:60;
  background:var(--panel-3); color:var(--ink); border:1px solid var(--line-2);
  border-radius:var(--radius); box-shadow:var(--shadow-lg);
  padding:var(--gap-2) var(--sp-1); font-size:var(--fs-1); font-weight:400;
  line-height:1.5; text-align:left; white-space:normal;
  display:none; }
/* Out of layout until shown: a hidden tip still widens the page it sits on,
   which made eleven pages scroll sideways on a phone. */
.helptip:hover .tip, .helptip:focus-visible .tip, .helptip .tip.show { display:block; }
/* A tip inside an uppercase label or legend keeps sentence case. */
.helptip .tip { text-transform:none; letter-spacing:normal; }
@media (max-width:700px) {
  .helptip .tip { position:fixed; left:var(--sp-2); right:var(--sp-2); bottom:var(--sp-2); top:auto;
    transform:none; width:auto; max-width:none; }
}

/* Secondary detail under a value, and a label that sits inside a row rather
   than above a field. Both were inline styles repeated across the console,
   each carrying its own font size. */
.sm { font-size:var(--fs-1); }
.inlinelabel { display:inline-flex; align-items:center; gap:var(--gap-2);
  margin:0; font-weight:600; font-size:var(--fs-1); }

label { display:block; font-weight:650; margin:var(--sp-2) 0 var(--gap-2); font-size:var(--fs-2); }
label .sub { font-weight:400; color:var(--muted); font-size:var(--fs-1); }
/* A box or a radio and its words: the box hangs in the margin and a wrapped line
   runs under the words, not under the box. A hanging indent and not a flex row,
   because these labels carry bold, notes and code, and a flex row would set each
   of those in a column of its own. A run of boxes sits close; the last one is
   followed by the gap a field gets. The switch and the picture picker lay out
   their own radios. */
main label:is(.check, .inline, :not([class])):not(:is(.seg, .avpick) label):has(> input:is([type=checkbox],[type=radio]):first-child) { --box:16px; display:block;
  padding-left:calc(var(--box) + var(--gap-2)); text-indent:calc(-1 * (var(--box) + var(--gap-2))); }
main label:is(.check, .inline, :not([class])):not(:is(.seg, .avpick) label):has(> input:is([type=checkbox],[type=radio]):first-child) > * { text-indent:0; }
main label:is(.check, .inline, :not([class])):not(:is(.seg, .avpick) label) > input:is([type=checkbox],[type=radio]):first-child { margin:0 var(--gap-2) 0 0; vertical-align:-3px; }
main .choices label.check.indent:not(:is(.seg, .avpick) label):has(> input:is([type=checkbox],[type=radio]):first-child) { padding-left:calc(var(--sp-3) + var(--box) + var(--gap-2)); }
label.check { margin:var(--gap-2) 0; }
label.check:not(:has(+ label.check)) { margin-bottom:var(--sp-2); }
/* At the foot of a fieldset or a form, the padding of the box is the gap. */
:is(fieldset, form) > label.check:last-child { margin-bottom:0; }
.choices > label.check, .choices > label.check:not(:has(+ label.check)) { margin:0; }
.field { max-width:560px; }
fieldset { border:1px solid var(--line); border-radius:var(--radius); padding:var(--gap-1) var(--sp-2) var(--sp-3); margin:var(--sp-3) 0; }
legend { font-weight:700; font-size:var(--fs-1); text-transform:uppercase; letter-spacing:.5px; color:var(--muted);
  padding:0 var(--gap-2); }

/* Message boxes ---------------------------------------------------------- */
.danger,.ok,.warnbox,.note,.running { border-radius:var(--radius); padding:var(--sp-2) var(--sp-2); margin:0 0 var(--sp-2);
  border:1px solid; }
/* Neutral panel for information the operator did not cause. Amber is for a
   caution about their own configuration; a list of suggestions styled amber
   reads as three warnings on a page that has one. */
.note { background:var(--panel-2); border-color:var(--line); }
.note ul { margin:var(--sp-1) 0 0; padding-left:var(--sp-3); }
.note li { margin:var(--gap-1) 0; }
/* Numbered steps, where a page is configure-then-act and the order matters. */
.steps { counter-reset:step; margin:var(--sp-3) 0 0; }
.step { counter-increment:step; position:relative; padding-left:var(--sp-4); margin:0 0 var(--sp-4); }
.step > h2 { margin:0 0 var(--sp-1); display:flex; align-items:center; gap:var(--sp-1); }
.step::before { content:counter(step); position:absolute; left:0; top:1px; width:26px; height:26px;
  border-radius:50%; background:var(--accent-weak); color:var(--accent); font-weight:700;
  font-size:var(--fs-2); display:flex; align-items:center; justify-content:center; }
.danger { background:color-mix(in srgb,var(--bad) 7%,var(--panel)); border-color:color-mix(in srgb,var(--bad) 35%,var(--line)); }
.ok { background:color-mix(in srgb,var(--good) 9%,var(--panel)); border-color:color-mix(in srgb,var(--good) 35%,var(--line)); }
.warnbox { background:color-mix(in srgb,var(--warn) 12%,var(--panel)); border-color:color-mix(in srgb,var(--warn) 40%,var(--line)); }
.warnbox > form:last-child, .warnbox > form:last-child .btnrow { margin-bottom:0; }
/* A chart directly above the table it summarises is separated from it. */
.chart + table, .chart + .scrollx, .hero + table, .hero + .scrollx { margin-top:var(--sp-2); }
/* A link back to the list a detail page was opened from, set off from the
   last block above it. */
a.backlink { display:inline-block; margin-top:var(--sp-3); }
/* Names one per line inside a key-value table. */
.kv ul.namelist { display:block; margin:0; }
.kv ul.namelist li { background:none; border:0; padding:0; margin:0; box-shadow:none; overflow-wrap:anywhere;
  white-space:normal; overflow:visible; text-overflow:clip; }
/* The bulk actions above the findings table keep to one row where they fit. */
.bulkbar { margin:0 0 var(--sp-2); gap:var(--gap-2); }
/* Hidden until a row is ticked, where script can tell; with no script it is
   always there. Sticky while shown, against the top of the scrolling area. */
html.js .bulkbar:not(.armed) { display:none; }
.bulkbar.armed { position:sticky; top:0; z-index:5; background:var(--panel); border:1px solid var(--line-2);
  border-radius:var(--radius); padding:var(--gap-2) var(--sp-1); box-shadow:var(--shadow); }
.bulkbar.armed .k { font-weight:650; color:var(--ink); }
.bulkmore { position:relative; }
/* A folded control is drawn as the button it opens, from the one btnlike rule. */
summary.btnlike { list-style:none; }
summary.btnlike::-webkit-details-marker { display:none; }
.bulkmore > summary::-webkit-details-marker { display:none; }
.bulkpop { position:absolute; top:calc(100% + 4px); left:0; z-index:8; background:var(--panel); border:1px solid var(--line-2); border-radius:6px; padding:var(--sp-1); display:flex; gap:var(--gap-2); flex-wrap:wrap; width:max-content; max-width:min(560px, 90vw); box-shadow:0 6px 20px rgba(0,0,0,.15); }
.bulkbar button:not(.helptip) { padding-left:var(--sp-1); padding-right:var(--sp-1); }
form.retest .btnrow { margin-top:var(--sp-1); }
/* Assign in a row of unowned hosts: a gap between the field and the button. */
td form.inline { display:inline-flex; gap:var(--sp-1); align-items:center; }
.running { background:color-mix(in srgb,var(--accent) 8%,var(--panel)); border-color:color-mix(in srgb,var(--accent) 35%,var(--line));
  display:flex; align-items:center; gap:var(--sp-2); flex-wrap:wrap; }
/* The sentence wraps beside its icon instead of leaving the icon on a line of its own. */
.running > svg { flex:none; }
.running > .rtext { flex:1 1 16em; min-width:0; }
.empty { background:var(--panel-2); border:1px dashed var(--line-2); border-radius:var(--radius);
  padding:var(--sp-3); text-align:center; color:var(--muted); margin:0 0 var(--sp-3);
  display:flex; flex-direction:column; align-items:center; gap:var(--gap-2); }
.empty .emptyicon { display:flex; color:var(--muted); opacity:.7; }
/* A zero is not news: the severity colour is kept for counts that need action. */
.kpi.zero .v, .kpi.zero.critical .v, .kpi.zero.high .v, .kpi.zero.medium .v, .kpi.zero.low .v { color:var(--muted); font-weight:500; }
.feed .rank .rowact { margin-left:auto; font-size:var(--fs-1); font-weight:600; white-space:nowrap; }
.feed .rank { display:flex; align-items:baseline; gap:var(--gap-2); flex-wrap:wrap; }
.status { display:inline-flex; align-items:center; gap:5px; padding:1px var(--gap-2); border-radius:999px; font-size:var(--fs-0);
  font-weight:600; white-space:nowrap; background:var(--panel-2); border:1px solid var(--line); color:var(--ink-2); vertical-align:middle; }
.status::before { content:""; width:7px; height:7px; border-radius:50%; background:var(--muted); flex:0 0 auto; }
.status.s-ok::before { background:var(--good); } .status.s-warn::before { background:var(--warn); } .status.s-bad::before { background:var(--bad); }
.tag { display:inline-block; padding:1px var(--gap-2); border-radius:4px; font-size:var(--fs-0); font-weight:500; white-space:nowrap;
  border:1px solid var(--line-2); color:var(--ink-2); background:transparent; vertical-align:middle; }
.flag { display:inline-block; padding:1px var(--gap-2); border-radius:4px; font-size:var(--fs-0); font-weight:700; white-space:nowrap;
  border:1px solid color-mix(in srgb,var(--bad) 60%,var(--line)); color:var(--bad); background:color-mix(in srgb,var(--bad) 8%,transparent); vertical-align:middle; }
a.pill.grade { text-decoration:none; }
a.pill.grade:hover { filter:brightness(1.1); text-decoration:underline; }
.decidedmeter { margin:0 0 var(--sp-2); max-width:420px; }
details.groupdecide { display:inline-block; }
details.groupdecide .btnrow { margin-top:var(--gap-2); }
.keylist { display:grid; grid-template-columns:max-content 1fr; gap:var(--gap-2) var(--sp-2); margin:0; }
.keylist dd { margin:0; }
.checkgrid { display:grid; grid-template-columns:repeat(auto-fill,minmax(min(240px,100%),1fr)); gap:0 var(--sp-2); }
.moddot { display:inline-block; width:7px; height:7px; border-radius:50%; background:var(--accent); margin-left:var(--gap-2); vertical-align:middle; }
.settingsfind { width:100%; max-width:420px; margin:0 0 var(--sp-2); }
.stickysave { position:sticky; bottom:0; background:var(--bg); padding:var(--sp-1) 0; margin:0; border-top:1px solid var(--line); z-index:4; }
.planassign { margin-top:var(--sp-1); gap:var(--gap-2); }
.peekpanel { position:fixed; top:0; right:0; bottom:0; width:min(560px, 100vw); z-index:45; background:var(--panel);
  border-left:1px solid var(--line); box-shadow:var(--shadow-lg); overflow:auto; padding:var(--sp-2) var(--sp-3); box-sizing:border-box; }
.peekpanel[hidden] { display:none; }
.peekhead { display:flex; justify-content:space-between; align-items:center; gap:var(--sp-1); position:sticky; top:calc(-1 * var(--sp-2));
  background:var(--panel); padding:var(--gap-2) 0; margin-bottom:var(--sp-1); border-bottom:1px solid var(--line); }
.iconbtn.peek { margin-left:var(--gap-1); vertical-align:middle; padding:2px; height:auto; }
.findbar { position:sticky; top:0; z-index:6; display:flex; flex-wrap:wrap; align-items:center; gap:var(--gap-2);
  background:var(--bg); padding:var(--gap-2) 0; margin:0 0 var(--sp-2); border-bottom:1px solid var(--line); }
.findbar .spacer { flex:1 1 auto; }
.findbar form.inline { margin:0; }
/* Three tiers in the action bar. Wayfinding is quiet so it does not read as an
   action; the immediate actions keep the standard look; the decisions that take
   the finding off the list are set off by a divider and a caution hover, so a
   reader does not reach for one by muscle memory. */
.findbar .findnav { display:inline-flex; align-items:center; gap:var(--gap-1); }
.findbar .findnav .btnlink { background:transparent; border-color:transparent; color:var(--muted); box-shadow:none; }
.findbar .findnav .btnlink:hover { background:var(--panel-2); border-color:transparent; color:var(--ink); }
.findbar .btnlink.ico { width:var(--ctl-h); padding:0; justify-content:center; font-size:var(--fs-4); }
.findbar .findsep { align-self:stretch; width:1px; margin:var(--gap-1) var(--gap-1); background:var(--line); }
.findbar .btnlink.decide:hover { border-color:color-mix(in srgb,var(--bad) 45%,var(--line-2)); color:var(--bad); background:color-mix(in srgb,var(--bad) 6%,var(--panel)); }
.unreaddot { display:inline-block; width:8px; height:8px; border-radius:50%; background:var(--accent); vertical-align:middle; margin-left:var(--gap-1); }
/* A filter chip is text and a remove control, not a link, so it takes the
   chip's padding and type itself rather than from the link rule. The remove
   control is always shown: it is the chip's one action. */
.filterchips { display:flex; flex-wrap:wrap; gap:var(--gap-2); margin:0 0 var(--sp-2); }
.chip.filterchip { gap:2px; padding:0 0 0 var(--sp-1); font-size:var(--fs-1); font-weight:600; line-height:1.5; color:var(--accent); }
.chip.filterchip .x { opacity:1; color:var(--accent); text-decoration:none; font-weight:600; font-size:var(--fs-2); padding:var(--gap-1) var(--sp-1) var(--gap-1) var(--gap-1); background:transparent; }
.chip.filterchip .x:hover { color:var(--bad); background:transparent; }
.listtools { display:flex; align-items:center; gap:var(--sp-1); margin:0 0 var(--sp-1); flex-wrap:wrap; }
.listtools .btnlink.on { border-color:var(--accent); color:var(--accent); }
.menucheck { display:flex; align-items:center; gap:var(--gap-2); padding:var(--gap-1) var(--sp-1); white-space:nowrap; cursor:pointer; }
details.grouprow summary { cursor:pointer; }
details.grouprow ul.plain { list-style:none; margin:var(--gap-2) 0 0; padding:0; }
/* Evidence proposed for several controls: each control's id and title, its two decisions on the same line. */
ul.proprefs { list-style:none; margin:0; padding:0; min-width:18em; }
ul.proprefs li { display:flex; flex-wrap:wrap; align-items:center; justify-content:space-between; gap:var(--sp-1); padding:var(--sp-1) 0; border-top:1px solid var(--line); }
ul.proprefs li:first-child { border-top:0; padding-top:0; }
ul.proprefs .btnrow { flex-wrap:nowrap; margin:0; }
ul.proprefs .ref { flex:1 1 14em; display:-webkit-box; -webkit-line-clamp:2; -webkit-box-orient:vertical; overflow:hidden; }
details.herofold > summary { cursor:pointer; color:var(--muted); font-size:var(--fs-1); margin:0 0 var(--gap-2); }

.overdue { display:inline-block; margin-top:var(--gap-1); font-size:var(--fs-0); font-weight:700; letter-spacing:.2px; white-space:nowrap;
  color:var(--bad); background:color-mix(in srgb,var(--bad) 13%,transparent); border-radius:999px; padding:var(--gap-1) var(--sp-1); }
/* How well a finding is supported. See confidence.ts. Accent, never the
   good colour: confirmed says the finding is real, which is not good news. */
ul.confreasons { margin:var(--gap-2) 0 0; padding-left:var(--sp-3); }
ol.confladder { display:flex; flex-wrap:wrap; gap:var(--gap-2); list-style:none; margin:var(--gap-2) 0 0; padding:0; font-size:var(--fs-0); }
ol.confladder li { border:1px solid var(--line); border-radius:999px; padding:0 var(--sp-1); color:var(--muted); }
ol.confladder li.on { color:var(--ink); border-color:var(--accent); }
ol.confladder li.reserved { border-style:dashed; }
.sig { font-size:var(--fs-1); color:var(--high); line-height:1.5; max-width:42ch; }
.sig + .sig { margin-top:var(--gap-2); }
/* Approve / Reject in a table row: a flex pair with real spacing, so they read
   as two choices rather than one crammed block. */
.rowacts { display:flex; gap:var(--sp-1); flex-wrap:wrap; justify-content:flex-end; }
.rowacts form.inline { display:inline-flex; }
.rowacts button { padding:var(--gap-2) var(--sp-2); }
.searchbar { display:flex; gap:var(--sp-1); margin:0 0 var(--sp-2); }
/* Workspace switcher, at the top of the menu. */
.wsswitch { position:relative; margin:var(--gap-2) var(--sp-1) 0; }
.wsswitch summary { list-style:none; display:flex; align-items:center; gap:var(--sp-1); cursor:pointer;
  padding:var(--gap-2) var(--sp-1); border:1px solid var(--nav-line); border-radius:var(--radius); color:var(--ink); }
.wsswitch summary::-webkit-details-marker { display:none; }
.wsswitch summary:hover, .wsswitch[open] summary { background:var(--nav-hover); }
.wsname { display:flex; flex-direction:column; min-width:0; flex:1; font-weight:600; font-size:var(--fs-2); line-height:1.25;
  white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }
/* The ellipsis is on a box of its own: text straight inside a flex column is
   cut at the edge with no mark, so a long workspace name lost its end unseen. */
.wsname .wsnm { overflow:hidden; text-overflow:ellipsis; }
.wsname small { font-weight:500; font-size:var(--fs-0); color:var(--nav-muted); text-transform:uppercase; letter-spacing:.05em; }
.wschev { color:var(--nav-muted); display:inline-flex; margin-left:auto; }
.wschev svg { width:16px; height:16px; }
.wsavatar { flex:none; display:inline-flex; align-items:center; justify-content:center; width:26px; height:26px;
  border-radius:6px; background:var(--accent-weak); color:var(--accent); font-weight:700; font-size:var(--fs-1); }
.wshue1 { background:color-mix(in srgb,var(--accent-3) 22%,transparent); color:var(--accent-3); }
.wshue2 { background:color-mix(in srgb,var(--accent-2) 22%,transparent); color:var(--accent-2); }
.wshue3 { background:color-mix(in srgb,var(--med) 22%,transparent); color:var(--med); }
.wshue4 { background:color-mix(in srgb,var(--high) 22%,transparent); color:var(--high); }
.wshue5 { background:color-mix(in srgb,var(--good) 22%,transparent); color:var(--good); }
/* On the page a letter is mixed with the ink, as the tiles of the overview mix their
   figures, so each hue reads at 4.5:1 on its tint: yellow was 1.4:1 and the
   others about 3:1. The menu rail keeps the bright hues. */
main .wshue1 { color:color-mix(in srgb,var(--accent-3) 70%,var(--ink)); }
main .wshue2 { color:color-mix(in srgb,var(--accent-2) 60%,var(--ink)); }
main .wshue3 { color:color-mix(in srgb,var(--med) 40%,var(--ink)); }
main .wshue4 { color:color-mix(in srgb,var(--high) 55%,var(--ink)); }
main .wshue5 { color:color-mix(in srgb,var(--good) 70%,var(--ink)); }
.wsavatar.sm { width:20px; height:20px; font-size:var(--fs-0); border-radius:5px; }
.wsavatar.round { border-radius:50%; }
.wsavatar.lg { width:56px; height:56px; font-size:var(--fs-5); border-radius:12px; }
.wsavatar.lg.round { border-radius:50%; }
.wsavatar.pic { background:var(--panel-2); overflow:hidden; }
.wsavatar.pic img { width:100%; height:100%; object-fit:cover; display:block; }
.avpick { display:grid; grid-template-columns:repeat(auto-fill,minmax(44px,1fr)); gap:var(--gap-2); max-width:560px; margin:var(--gap-2) 0 var(--sp-2); }
.avpick label { display:flex; align-items:center; justify-content:center; height:44px; margin:0; border:1px solid var(--line); border-radius:8px; cursor:pointer; }
.avpick input { position:absolute; opacity:0; pointer-events:none; }
.avpick label[hidden] { display:none; }
.avpick label:has(input:checked) { border-color:var(--accent); box-shadow:0 0 0 2px var(--accent-weak); }
.avpick label svg { transition:transform .12s ease; }
.avpick label:has(input:checked) svg, .avpick label:has(input:checked) b { transform:scale(1.4); }
.avpick label b { transition:transform .12s ease; }
.avpick label:has(input:focus-visible) { outline:2px solid var(--accent); outline-offset:2px; }
.avpick.avkept { grid-template-columns:repeat(auto-fill,minmax(64px,64px)); align-items:start; }
.avkeptitem { display:flex; flex-direction:column; align-items:center; gap:var(--gap-1); }
.avkeptitem label { width:100%; }
.avkept img { border-radius:4px; }
.wsmenu { position:absolute; left:0; right:0; top:calc(100% + 4px); z-index:50; padding:var(--gap-1);
  background:var(--panel); border:1px solid var(--line); border-radius:var(--radius); box-shadow:0 8px 24px rgba(0,0,0,.25); }
.wsmenu form { margin:0; }
.wsmenu .wslist { max-height:min(60vh, 480px); overflow-y:auto; }
.wsmenu .wsfind { width:100%; margin:0 0 var(--gap-1); }
.wsmenu .wsnone { margin:var(--gap-2) var(--sp-1); font-size:var(--fs-1); }
.wsmenu button, .wsmenu a { display:flex; align-items:center; gap:var(--sp-1); width:100%; padding:var(--gap-2) var(--sp-1);
  background:none; border:0; border-radius:var(--radius); color:var(--ink); font:inherit; font-size:var(--fs-2);
  text-align:left; text-decoration:none; cursor:pointer; }
.wsmenu button:hover, .wsmenu a:hover, .wsmenu button:active { background:var(--nav-hover); }
.wsmenu button.on { font-weight:600; }
.wsmenu button.on::after { content:"✓"; margin-left:auto; color:var(--accent); }
.wsmenu hr { border:0; border-top:1px solid var(--line); margin:var(--gap-1) 0; }
.navfoot { margin-top:auto; border-top:1px solid var(--nav-line); padding-top:var(--gap-1); }
/* Page-level controls, at the right of the heading. */
.pageactions { display:flex; align-items:center; flex-wrap:wrap; justify-content:flex-end; gap:var(--sp-1); }
/* Narrow: the heading is one row and the controls a second row of the same
   fixed height, scrolling sideways rather than wrapping, so the tabs under the
   band sit at the same place on every view. A menu opened from that row is
   fixed to the viewport, or the row's scrolling would clip it. */
@media (max-width:560px) {
  .pagehead.tabbed { height:auto; display:grid; grid-template-columns:minmax(0,1fr); row-gap:var(--sp-1); }
  .pagehead.tabbed h1 { height:var(--ctl-h); }
  .pagehead.tabbed .pageactions { height:var(--ctl-h); justify-content:flex-start; overflow-x:auto; overflow-y:hidden;
    scrollbar-width:none; }
  .pagehead.tabbed .pageactions::-webkit-scrollbar { display:none; }
  .pageactions details.dropmenu .menu { position:fixed; top:auto; left:16px; right:16px; min-width:0; max-width:none; }
}
/* The range keeps its own width in a row that scrolls, and the select keeps the
   room its drawn chevron needs: at width 100% it shrank to 14px at 375. */
.pagerange { display:flex; flex:none; align-items:center; gap:var(--gap-1); color:var(--muted); }
.pagerange select { width:auto; max-width:170px; padding:0 32px 0 var(--gap-2); font-size:var(--fs-1); }
details.dropmenu { position:relative; }
details.dropmenu > summary { list-style:none; display:inline-flex; align-items:center; gap:var(--gap-2); cursor:pointer; }
details.dropmenu > summary::-webkit-details-marker { display:none; }
details.dropmenu .menu { position:absolute; right:0; top:calc(100% + 4px); z-index:30; min-width:260px; max-width:340px;
  background:var(--panel); border:1px solid var(--line); border-radius:var(--radius); box-shadow:var(--shadow-lg); padding:var(--gap-1); }
details.dropmenu .menu a { display:block; padding:var(--gap-2) var(--sp-1); border-radius:6px; color:var(--ink); text-decoration:none; }
details.dropmenu .menu a:hover, details.dropmenu .menu a:focus-visible { background:var(--panel-2); }
details.dropmenu .menu small { display:block; color:var(--muted); font-size:var(--fs-0); white-space:normal; margin-top:2px; }
.filters { display:flex; gap:var(--sp-1); margin:0 0 var(--sp-2); flex-wrap:wrap; align-items:center; }
.filters input[type=text] { max-width:300px; flex:1 1 220px; }
.filters.search input[type=search] { flex:1 1 420px; max-width:none; font-family:"Roboto Mono",ui-monospace,SFMono-Regular,Menlo,monospace; font-size:var(--fs-1); }
.warnline { color:var(--ink); background:color-mix(in srgb,var(--warn) 14%,var(--panel)); border:1px solid color-mix(in srgb,var(--warn) 45%,var(--line));
  border-radius:var(--radius); padding:var(--gap-1) var(--gap-2); margin:0 0 var(--sp-2); font-size:var(--fs-1); }
.withfields { display:grid; grid-template-columns:200px minmax(0,1fr); gap:var(--sp-2); align-items:start; }
/* clip and not auto: auto made the column a scroll container, so the sticky
   headings and the armed bulk bar stuck to it and never to the page. */
.fieldmain { min-width:0; overflow-x:clip; }
/* Eight columns beside the field list were 53px wider than their space at
   1440px, so the last one scrolled out of sight. A tighter side inset fits them. */
.fieldmain table.wide th, .fieldmain table.wide td { padding-left:var(--sp-1); padding-right:var(--sp-1); }
.fieldmain table.wide td:first-child, .fieldmain table.wide th:first-child { width:1%; }
.fields { background:var(--panel); border:1px solid var(--line); border-radius:var(--radius); padding:var(--gap-2) var(--sp-2); font-size:var(--fs-1); }
.fields summary { font-weight:600; cursor:pointer; padding:var(--gap-1) 0; }
.fields section { margin:var(--gap-2) 0 var(--sp-1); }
.fields h3 { font-size:var(--fs-0); text-transform:uppercase; letter-spacing:.5px; color:var(--muted); margin:0 0 var(--gap-1); font-weight:600; }
.fields .fv { display:flex; align-items:center; gap:var(--gap-1); padding:2px 0; min-width:0; }
.fields .fv > a:first-child, .fields .fv > span { flex:1; min-width:0; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
.fields .fv a:first-child { color:var(--ink); text-decoration:none; }
.fields .fv a:first-child:hover { color:var(--accent); text-decoration:underline; }
.fields .fv b { font-weight:500; color:var(--muted); font-variant-numeric:tabular-nums; }
.fields .fv .x { color:var(--muted); text-decoration:none; width:18px; text-align:center; border-radius:4px; }
.fields .fv .x:hover { background:var(--panel-3); color:var(--ink); }
.fields .fv.on { background:var(--panel-3); border-radius:4px; padding:2px var(--gap-1); }
/* The field list sits beside the findings only where the table still fits next
   to it. At 1100px the menu and the list left the table about 580px for
   columns that need about 730, and it scrolled sideways inside its column
   behind an overlay scrollbar, which reads as a table cut off at the right. */
@media (max-width:1259px) { .withfields { grid-template-columns:minmax(0,1fr); } }
.matrix { display:grid; grid-template-columns:repeat(auto-fit,minmax(150px,1fr)); gap:var(--gap-2); overflow-x:auto; margin:var(--sp-2) 0; }
.matrix .mcol h3 { font-size:var(--fs-1); margin:0 0 var(--gap-2); padding:var(--gap-1) var(--gap-2); background:var(--panel-3); border-radius:var(--radius); }
.matrix .mcell { display:grid; grid-template-columns:1fr auto; gap:2px var(--gap-1); padding:var(--gap-1) var(--gap-2); margin:0 0 var(--gap-1);
  border:1px solid var(--line); border-radius:var(--radius); font-size:var(--fs-0); color:var(--ink); text-decoration:none;
  background:color-mix(in srgb,var(--bad) calc(var(--share,0%) * .35),var(--panel)); }
.matrix .mcell code { grid-column:1 / -1; font-size:var(--fs-0); background:none; border:0; padding:0; font-weight:600; }
.matrix .mcell span { grid-column:1; }
.matrix .mcell b { grid-column:2; grid-row:2; font-size:var(--fs-3); align-self:center; }
.matrix .mcell .pill { grid-column:1 / -1; justify-self:start; }
/* The info pill is translucent, so on a heat-tinted cell it took the tint. */
.matrix .mcell .pill.info { background:var(--panel); }
.matrix a.mcell:hover { border-color:var(--accent); }
table.ctl { table-layout:fixed; width:100%; }
table.ctl th:nth-child(1) { width:32%; } table.ctl th:nth-child(3), table.ctl th:nth-child(4) { width:11%; }
/* A regulation's table carries what this tool covers of each measure, the
   widest text on the page, so it takes the room the issue column had. */
table.ctl.reg th:nth-child(1) { width:26%; } table.ctl.reg th:nth-child(2) { width:34%; }
table.ctl.reg th:nth-child(3) { width:20%; } table.ctl.reg th:nth-child(4) { width:10%; }
/* The name of a framework in the jump links is one unit: NIST 800-53 split at its hyphen. */
.fwjump a { white-space:nowrap; }
ul.uncovered { margin:0 0 var(--sp-3); padding-left:var(--sp-3); }
ul.uncovered li { margin:var(--gap-1) 0; }
a > code { color:inherit; }
.matrix .mcell.none { color:var(--muted); background:var(--panel); border-style:dashed; }
.matrix .mcell:target { outline:2px solid var(--accent); }
@media (max-width:900px) { .matrix { grid-auto-flow:column; grid-auto-columns:minmax(160px,1fr); grid-template-columns:none; } }
.filters select { max-width:170px; }
.searchbar input { max-width:380px; }
.surfacewrap { display:inline-flex; align-items:center; gap:var(--gap-2); }

/* Score and charts ------------------------------------------------------- */
/* align-items:start stops a short panel being stretched to match a tall one,
   which is what left the severity card with a large empty area below it. */
/* A finger, not a pointer. On a touch screen 173 pages had controls under
   24px tall: the More under an explanation, the ? beside a label, the radios
   and boxes of a setting and the values in the findings field list. Each keeps
   its look and gains the area a thumb needs. */
@media (pointer:coarse) {
  main button.more { padding:var(--sp-1) 0; margin-top:calc(-1 * var(--sp-1)); }
  .helptip::after { content:""; position:absolute; inset:-10px; }
  main input[type=radio], main input[type=checkbox] { width:20px; height:20px; }
  main label:is(.check, .inline, :not([class])):not(:is(.seg, .avpick) label):has(> input:is([type=checkbox],[type=radio]):first-child) { --box:20px; }
  .fields .fv { padding:var(--gap-2) 0; }
  .sevlegend a.it, .legend a.it, details > summary { min-height:32px; }
  .legend a.it, .sevlegend a.it { align-items:center; }
}

/* Phone width. A table wider than the screen scrolls inside itself, so the
   page never scrolls sideways: a page that slides under the thumb loses the
   heading and the navigation together. Measured at 375px over every view. */
@media (max-width:700px) {
  /* The box of a short table hugs its rows; a wide one is capped and scrolls. */
  main table { display:block; overflow-x:auto; width:max-content; max-width:100%; -webkit-overflow-scrolling:touch; }
  /* The overlay scrollbar a phone draws is nearly invisible, so a wide table
     that scrolls sideways reads as a table with its right columns missing. A
     scroll shadow is the cue: the panel-coloured covers ride with the content
     and hide the shadow at an edge that is fully reached, so a shadow shows only
     on the side that has more. Not on a key-value table, which stacks instead. */
  main table:not(.kv) {
    background:
      linear-gradient(90deg, var(--panel) 32%, transparent) 0 0 / 36px 100% no-repeat local,
      linear-gradient(90deg, transparent, var(--panel) 68%) 100% 0 / 36px 100% no-repeat local,
      radial-gradient(farthest-side at 0 50%, var(--scroll-shade), transparent) 0 0 / 15px 100% no-repeat scroll,
      radial-gradient(farthest-side at 100% 50%, var(--scroll-shade), transparent) 100% 0 / 15px 100% no-repeat scroll,
      var(--panel); }
  main pre, main .console { max-width:100%; overflow-x:auto; }
  main input, main select, main textarea { max-width:100%; }
  main code { overflow-wrap:anywhere; }
  /* Inside a table that scrolls, an address or an id stays whole. */
  main table code { overflow-wrap:normal; white-space:nowrap; }
  /* A key-value table does not scroll, so an id in it wraps instead. */
  main table.kv code { white-space:normal; overflow-wrap:anywhere; }
  /* A status pill in a key-value table wraps rather than pushing past the cell. */
  main table.kv .status { white-space:normal; max-width:100%; }
  main li code, main p code { white-space:normal; overflow-wrap:anywhere; }
  /* A chip or a linked address in one stays whole and wraps between items. */
  main table.kv a.chip code, main table.kv a.nowrap code { white-space:nowrap; overflow-wrap:normal; }
  /* A key-value table stacks its label over its value, so the value has the
     width of the panel: a label column of 152px left a TXT record name or a run
     id to break mid-token in what was left. */
  main table.kv, main table.kv tbody, main table.kv tr,
  main table.kv th, main table.kv.narrowkv th, main table.kv td { display:block; width:auto; }
  main table.kv th { border-right:0; border-bottom:0; padding-bottom:0; }
  /* The top bar keeps the menu, the search and the theme on a phone. Density
     is a desktop control: on a phone the content is already one column. */
  .topbar { gap:var(--sp-1); padding:0 var(--sp-2); }

  .tb-search { flex:1 1 auto; min-width:0; }
  .tb-search input[type="search"] { width:100%; }
  .topbar .tb-brand { display:none; }
  .mainwrap { padding:var(--sp-3) var(--sp-2); }
  .btnrow { flex-wrap:wrap; }
}

/* Dashboard ---------------------------------------------------------------- */
/* The row a security console opens on: one tile per severity, coloured by it,
   each a link to the list it counts. */
.kpis { display:grid; grid-template-columns:repeat(6,minmax(0,1fr)); gap:var(--sp-2); margin:0 0 var(--sp-3); }
.kpi { display:flex; flex-direction:column; gap:var(--gap-1); padding:var(--sp-2); background:var(--panel);
  border:1px solid var(--line); border-radius:var(--radius); box-shadow:var(--shadow); color:var(--ink);
  text-decoration:none; min-width:0; }
.kpi:hover { border-color:var(--line-2); background:var(--panel-2); }
.kpi .k { font-size:var(--fs-1); color:var(--muted); font-weight:500; }
.kpi .v { font-size:var(--fs-6); font-weight:600; line-height:1.1; letter-spacing:-.4px; }
.kpi .s { font-size:var(--fs-0); color:var(--muted); }
.kpi .v { display:flex; align-items:flex-end; justify-content:space-between; gap:var(--gap-2); }
/* The 30-day line of a tile runs along its foot at full width, so a tile
   stretched to the height of the score beside it is filled by its trend and not
   by empty space. */
.kpi.critical .v { color:var(--crit); }
.kpi.high .v { color:color-mix(in srgb,var(--high) 55%,var(--ink)); }
.kpi.medium .v { color:color-mix(in srgb,var(--med) 45%,var(--ink)); }
.kpi.low .v { color:var(--low); }
.kpi.riskkpi.rl-critical .v { color:var(--crit); } .kpi.riskkpi.rl-high .v { color:color-mix(in srgb,var(--high) 80%,var(--ink)); }
.kpi.riskkpi.rl-medium .v { color:color-mix(in srgb,var(--med) 55%,var(--ink)); } .kpi.riskkpi.rl-low .v { color:var(--low); }
.kpi.pending .v { color:var(--accent); }
@media (max-width:1100px) { .kpis { grid-template-columns:repeat(3,minmax(0,1fr)); } }
@media (max-width:560px) { .kpis { grid-template-columns:repeat(2,minmax(0,1fr)); } .kpis > .kpi:last-child:nth-child(odd) { grid-column:1 / -1; } }
.kpis.three { grid-template-columns:repeat(3,minmax(0,1fr)); }
@media (max-width:560px) { .kpis.three { grid-template-columns:repeat(2,minmax(0,1fr)); } }
.hostcard { position:fixed; z-index:50; background:var(--panel); border:1px solid var(--line-2); border-radius:6px;
  box-shadow:0 6px 20px rgba(0,0,0,.18); padding:var(--sp-1) var(--sp-2); max-width:320px; font-size:var(--fs-1); pointer-events:none; }
.hostcard .hc > * + * { margin-top:4px; }
.hostcard .hcsev { display:flex; flex-wrap:wrap; gap:6px; align-items:center; }
[data-hostcard] { cursor:help; text-decoration:underline dotted var(--line-2); text-underline-offset:3px; }
a.newtab { visibility:hidden; margin-left:4px; font-size:var(--fs-0); text-decoration:none; color:var(--muted); }
tr:hover a.newtab { visibility:visible; }
a.newtab:hover { color:var(--accent); }
.headrow { display:flex; align-items:center; gap:var(--sp-1); flex-wrap:wrap; }
.headrow h2 { margin-right:auto; }
img.thumb { width:24px; height:15px; object-fit:cover; object-position:top; border:1px solid var(--line); border-radius:2px; vertical-align:middle; margin-right:6px; }
.thread { margin:0 0 var(--sp-1); }
.thread li { padding:var(--gap-2) 0; border-bottom:1px solid var(--line); }
.cmtext { white-space:pre-wrap; overflow-wrap:anywhere; }
.similar li { padding:2px 0; }
.sincevisit { display:flex; align-items:center; gap:var(--gap-2); flex-wrap:wrap; margin:0 0 var(--sp-2); padding:var(--sp-1) var(--sp-2); background:var(--panel); border:1px solid var(--line); border-radius:6px; font-size:var(--fs-1); }
.whatsnew { display:flex; flex-wrap:wrap; align-items:flex-start; gap:var(--sp-2); background:var(--panel); border:1px solid var(--line);
  border-radius:var(--radius); padding:var(--gap-2) var(--sp-2); margin:0 0 var(--sp-2); }
.whatsnew[hidden] { display:none; }
.whatsnew details { flex:1 1 16em; min-width:0; } .whatsnew summary { cursor:pointer; font-weight:600; line-height:var(--ctl-h, 32px); }
.qrbox { display:inline-block; padding:var(--sp-1); background:#fff; border-radius:var(--radius); margin:var(--gap-2) 0; }
.qrbox svg { display:block; }
code.setupkey { letter-spacing:.08em; overflow-wrap:anywhere; }
pre.recovery { font-family:var(--mono, monospace); font-size:var(--fs-3); line-height:1.7; columns:2; max-width:360px; }
.whatsnew ul { margin:var(--gap-2) 0 var(--sp-1); padding-left:1.2em; }
.whatsnew li { margin:2px 0; }
.qgroup { margin:0 0 var(--sp-2); }
.qhead { display:flex; justify-content:space-between; align-items:flex-start; gap:var(--sp-2); flex-wrap:wrap; }
.qtags { display:flex; gap:var(--gap-2); flex-wrap:wrap; align-items:center; }
.qsignals { margin:var(--gap-2) 0 0; padding-left:1.2em; font-size:var(--fs-1); color:var(--muted); }
.qaddrs > summary { cursor:pointer; color:var(--muted); font-size:var(--fs-1); margin:var(--gap-2) 0; }
.qgroup table { margin:var(--gap-2) 0 0; }
.qgroup .btnrow { margin-top:var(--sp-1); }
.stackbar { display:flex; height:14px; border-radius:4px; overflow:hidden; background:var(--panel-2); margin:var(--sp-2) 0; min-width:80px; }
/* The parts of the bar are spans, never the .seg of the segmented control, whose grey fill covered every colour. */
.stackbar > span { display:block; height:100%; }
.dot[class*="seg-"] { display:inline-block; width:9px; height:9px; border-radius:3px; margin-right:4px; }
.seg-rawOutput { background:var(--high); } .seg-screenshots { background:var(--accent-3); }
.seg-backups { background:var(--med); } .seg-leftovers { background:var(--crit); }
.seg-reports { background:var(--accent-2); } .seg-snapshots { background:var(--low); }
.seg-records { background:var(--accent); } .seg-state { background:var(--info); } .seg-logs { background:var(--muted); }
.seg-evidence { background:var(--good); }
.purgeform { display:grid; grid-template-columns:max-content minmax(0,220px); gap:var(--gap-2) var(--sp-2); align-items:center; max-width:560px; }
.purgeform label.inline, .purgeform .btnrow { grid-column:1 / -1; }
@media (max-width:560px) { .purgeform { grid-template-columns:minmax(0,1fr); } }
/* A titled white panel, as OUI draws one. */
/* The resolved staging targets the operator confirms against, as a plain code block. */
pre.echo { background:var(--panel-2); color:var(--ink); border:1px solid var(--line); border-radius:var(--radius); padding:var(--sp-2);
  font-family:"Roboto Mono",ui-monospace,SFMono-Regular,Menlo,monospace; font-size:var(--fs-1); overflow-x:auto; white-space:pre; margin:var(--gap-2) 0; }
/* The staging readiness list: one row per precondition, a status dot and a
   sentence, so what a run needs reads top to bottom rather than from a
   disabled control. The dot's colour is the only severity signal. */
ul.readylist { list-style:none; margin:var(--gap-2) 0 var(--sp-2); padding:0; max-width:620px; }
ul.readylist .ready { display:flex; align-items:flex-start; gap:var(--sp-1); padding:var(--gap-2) 0; border-bottom:1px solid var(--line); }
ul.readylist .ready:last-child { border-bottom:0; }
ul.readylist .rdot { flex:0 0 auto; width:9px; height:9px; border-radius:50%; margin-top:5px; background:var(--muted); }
ul.readylist .ready.pass .rdot { background:var(--good); }
ul.readylist .ready.fail .rdot { background:var(--warn); }
ul.readylist .rtext { min-width:0; }
ul.readylist .rtext b { font-weight:650; }
section.panel { background:var(--panel); border:1px solid var(--line); border-radius:var(--radius);
  box-shadow:var(--shadow); padding:var(--sp-2) var(--sp-3) var(--sp-2); margin:0 0 var(--sp-3); min-width:0; }
section.panel > h2.ptitle, section.panel h2:first-child { margin:0 0 var(--sp-2); padding-bottom:var(--sp-1);
  border-bottom:1px solid var(--line); font-size:var(--fs-3); }
section.panel table { box-shadow:none; }
details.addpanel { background:var(--panel); border:1px solid var(--line); border-radius:var(--radius);
  box-shadow:var(--shadow); padding:var(--sp-1) var(--sp-3); margin:0 0 var(--sp-3); min-width:0; }
details.addpanel > summary { list-style:none; cursor:pointer; }
details.addpanel > summary::-webkit-details-marker { display:none; }
details.addpanel > summary > h2.ptitle { margin:0; padding:var(--gap-1) 0; font-size:var(--fs-3); border:0; }
details.addpanel > summary > h2.ptitle::before { content:"+"; display:inline-block; width:1em; color:var(--accent); font-weight:700; }
details.addpanel[open] > summary > h2.ptitle { margin-bottom:var(--sp-2); border-bottom:1px solid var(--line); padding-bottom:var(--sp-1); }
details.addpanel[open] > summary > h2.ptitle::before { content:"−"; }
details.addpanel[open] { padding-bottom:var(--sp-2); }
details.addpanel > summary:hover > h2.ptitle { color:var(--accent); }
/* A framework fold carries what it holds beside its name, so a closed one still says whether to open it. */
details.fwfold > summary { display:flex; align-items:center; flex-wrap:wrap; gap:var(--gap-2) var(--sp-1); }
details.fwfold > summary > h2.ptitle { flex:0 1 auto; }
details.fwfold[open] > summary { margin-bottom:var(--sp-2); border-bottom:1px solid var(--line); padding-bottom:var(--sp-1); }
details.fwfold[open] > summary > h2.ptitle { margin:0; border:0; padding:var(--gap-1) 0; }
/* The last block of a box, and the last block inside that (a table in its wrapper, a
   button row in its form), leaves no margin at its foot: it collapsed through
   its zero-margin parent into a deep empty band. */
:is(section.panel, details.addpanel, .chart) > :last-child,
:is(section.panel, details.addpanel) > :last-child > :last-child { margin-bottom:0; }
section.panel > h3:first-child { margin-top:0; }
.plainwords { padding:var(--sp-2); background:var(--panel); border:1px solid var(--line); border-radius:var(--radius); margin:0 0 var(--sp-2); }
.plainwords p { margin:0 0 var(--gap-2); } .plainwords p:last-child { margin-bottom:0; }
.runcards { display:grid; grid-template-columns:repeat(3,minmax(0,1fr)); gap:var(--sp-2); margin:0 0 var(--sp-3); align-items:stretch; }
.runcards .panel.runcard { display:flex; flex-direction:column; margin:0; }
.runcard .ptitle { margin:0 0 var(--gap-1); font-size:var(--fs-3); }
.runcard > p { margin:0 0 var(--sp-2); }
.runcard .btnrow { margin-top:auto; padding-top:var(--sp-2); }
.runcard form.inline { display:inline; margin:0; }
dl.cardfacts { display:grid; grid-template-columns:9.5em minmax(0,1fr); gap:var(--gap-1) var(--sp-2); margin:0; font-size:var(--fs-1); }
dl.cardfacts dt { color:var(--muted); } dl.cardfacts dd { margin:0; min-width:0; overflow-wrap:anywhere; }
/* A date and time, and a duration, wrap as units. */
dl.cardfacts dd a, dl.cardfacts dd .muted { white-space:nowrap; }
.glance { display:grid; grid-template-columns:repeat(auto-fill,minmax(min(220px,100%),1fr)); gap:var(--gap-2) var(--sp-3); }
.gstage { display:flex; flex-wrap:wrap; align-items:center; gap:var(--gap-1) var(--gap-2); }
.gstage .k { flex:0 0 100%; color:var(--muted); font-size:var(--fs-1); }
.tchip { font-family:var(--mono, monospace); font-size:var(--fs-0); padding:2px 8px; border-radius:999px; border:1px solid var(--line-2); }
.tchip.on { background:var(--accent-weak); border-color:transparent; color:var(--ink); }
.tchip.off { color:var(--muted); text-decoration:line-through; }
.tchip.missing { border-color:var(--bad); color:var(--bad); }
@media (max-width:1000px) { .runcards { grid-template-columns:repeat(2,minmax(0,1fr)); } }
@media (max-width:560px) { .runcards { grid-template-columns:minmax(0,1fr); } .gstage .k { flex-basis:100%; } }
.grid2 { display:grid; grid-template-columns:repeat(2,minmax(0,1fr)); gap:var(--sp-3); }
.grid2 > section.panel { margin-bottom:var(--sp-3); }
@media (max-width:900px) { .grid2 { grid-template-columns:1fr; gap:0; } }
/* One sentence and one action per line, worst first. */
ul.issues { list-style:none; margin:0; padding:0; }
/* A panel's window, at the right of its title. */
h2.ptitle, .chart .khead { display:flex; flex-wrap:wrap; align-items:center; gap:var(--gap-2); }
.whenbadge { margin-left:auto; flex:none; font-size:var(--fs-0); font-weight:600; letter-spacing:.02em; text-transform:none;
  color:var(--muted); background:var(--panel-2); border:1px solid var(--line); border-radius:999px; padding:1px var(--sp-1); }
h2.ptitle .pagerange { margin-left:auto; font-weight:400; }
/* A panel title with a control beside it: the control sits in the bar and not
   inside the heading, and the bar carries the title's rule. */
section.panel > .ptitlebar { display:flex; flex-wrap:wrap; align-items:center; gap:var(--gap-2); margin:0 0 var(--sp-2);
  padding-bottom:var(--sp-1); border-bottom:1px solid var(--line); }
/* The controls beside a title keep their size and wrap under it on a phone. */
section.panel > .ptitlebar > :not(h2) { flex:none; white-space:nowrap; }
/* A link or control beside a title sits at the panel's right edge, where the Now badge sits. */
section.panel > .ptitlebar > :not(h2):last-child { margin-left:auto; }
/* The overview's narrow column holds Monitoring and the insights, one under the other. */
.sidestack { display:flex; flex-direction:column; gap:var(--sp-3); min-width:0; margin-bottom:var(--sp-3); }
.sidestack > .panel { margin:0; }
/* Two ways to start a run side by side: the same height, the form and the last run at the foot of each, so they line up. */
.grid2:has(> .runpanel) { align-items:stretch; }
.runpanel { display:flex; flex-direction:column; }
.runpanel > form { margin-top:auto; }
/* In the narrow column a row's link goes under its text, so the text keeps the width. */
.sidestack ul.issues li { flex-wrap:wrap; }
.sidestack ul.issues li > a:last-child { flex-basis:100%; margin-left:calc(8px + var(--sp-1)); }
section.panel > .ptitlebar h2.ptitle { margin:0; padding:0; border:0; font-size:var(--fs-3); }
.ptitlebar .pagerange { margin-left:auto; }
/* A chart inside a panel is titled as every panel is, not as a small caps
   label: two heading styles side by side read as two kinds of thing. */
.chart > .k { font-size:var(--fs-3); font-weight:600; color:var(--ink); text-transform:none;
  letter-spacing:0; margin:0 0 var(--sp-2); padding-bottom:var(--sp-1); border-bottom:1px solid var(--line); }
/* A long table's pages, under it. */
.pager { display:flex; align-items:center; justify-content:flex-end; flex-wrap:wrap; gap:var(--sp-1);
  margin:calc(-1 * var(--sp-2)) 0 var(--sp-3); font-size:var(--fs-1); color:var(--muted); }
.pager .pgcount { margin-right:auto; }
.pager label { white-space:nowrap; display:inline-flex; align-items:center; gap:var(--gap-2); margin:0; font-size:var(--fs-1); font-weight:400; color:var(--muted); }
.pager select { width:auto; padding:0 28px 0 var(--gap-2); background-position:right 8px center; font-size:var(--fs-1); }
.pager button { padding:3px var(--sp-1); font-size:var(--fs-1); }
ul.issues li { display:flex; align-items:baseline; gap:var(--sp-1); padding:var(--sp-1) 0; border-top:1px solid var(--line); }
ul.issues li:first-child { border-top:0; }
ul.issues .dot { flex:0 0 8px; height:8px; border-radius:50%; background:var(--muted); transform:translateY(-1px); }
ul.issues li.is-bad .dot { background:var(--bad); } ul.issues li.is-warn .dot { background:var(--warn); }
ul.issues li.is-step .dot { background:var(--accent); }
ul.issues li.is-ok .dot { background:var(--good); }
.insightbasis { display:block; margin-top:2px; }
ul.evidencelist { list-style:none; margin:0; padding:0; min-width:min(18em,100%); }
ul.evidencelist li { white-space:normal; padding:2px 0; margin:0; background:none; border:0; border-radius:0; }
/* The overview's what-to-do panel beside the narrower monitoring panel. */
.grid21 { display:grid; grid-template-columns:minmax(0,2fr) minmax(0,1fr); gap:var(--sp-3); align-items:start; }
.grid21 > section.panel { margin-bottom:var(--sp-3); }
@media (max-width:1100px) { .grid21 { grid-template-columns:1fr; gap:0; } }
.nextpanel .setupflow { margin:0 0 var(--sp-2); padding:0; border:0; box-shadow:none; background:none; }
.nextpanel .feed > li { padding:var(--sp-1) var(--sp-2); }
.demooffer { display:flex; align-items:center; justify-content:space-between; flex-wrap:wrap; gap:var(--gap-2) var(--sp-2); border:1px dashed var(--line); border-radius:8px; padding:var(--gap-2) var(--inset); margin:0 0 var(--sp-2); }
.demooffer p { margin:0; flex:1 1 280px; }
h3.subhead { margin:var(--sp-3) 0 var(--sp-1); font-size:var(--fs-2); font-weight:600; color:var(--ink-2); }
.alsowaiting { margin:var(--sp-2) 0 0; padding-top:var(--sp-1); border-top:1px solid var(--line); font-size:var(--fs-1);
  display:flex; flex-wrap:wrap; align-items:baseline; gap:var(--gap-1) var(--gap-2); }
.alsowaiting .k { color:var(--muted); font-weight:600; margin-right:var(--gap-1); }
.alsowaiting .sep { color:var(--muted); }
.kpinote { margin:var(--sp-1) 0 var(--sp-3); color:var(--muted); font-size:var(--fs-1); }
.kpi.infokpi .v { color:var(--info); }
td .bad, p .bad { color:var(--bad); font-weight:600; }
ul.issues .t { flex:1 1 auto; min-width:0; }
ul.issues a { flex:0 0 auto; font-weight:600; white-space:nowrap; }
/* Narrow: the dot keeps its own column and the action wraps under the text. */
@media (max-width:560px) {
  ul.issues li { display:grid; grid-template-columns:8px 1fr; column-gap:var(--sp-1); row-gap:var(--gap-1); align-items:baseline; }
  ul.issues .t, ul.issues a { grid-column:2; }
  ul.issues a { margin-left:0; justify-self:start; }
}
.meter { height:8px; border-radius:999px; background:var(--panel-3); overflow:hidden; margin:var(--gap-2) 0 var(--sp-1); }
.meter i { display:block; height:100%; background:var(--accent); }
section.panel p.covlead { margin:0 0 var(--sp-2); }
/* The score on its scale. */
.scorepanel .breakdown { display:flex; flex-wrap:wrap; gap:var(--gap-2) var(--sp-3); color:var(--muted); font-size:var(--fs-1); margin-top:var(--sp-2); }
.scorepanel .breakdown b { color:var(--ink); font-weight:650; }
.rating .rv { display:flex; align-items:baseline; gap:var(--sp-1); margin-bottom:var(--sp-2); }
.rating .rv b { font-size:40px; line-height:1; font-weight:600; letter-spacing:-.5px; }
.rating .rw { font-size:var(--fs-4); font-weight:650; }
.rating .rl-low { color:var(--low); } .rating .rl-medium { color:color-mix(in srgb,var(--med) 55%,var(--ink)); }
.rating .rl-high { color:color-mix(in srgb,var(--high) 80%,var(--ink)); } .rating .rl-critical { color:var(--crit); }
.scale { position:relative; padding-bottom:var(--sp-3); }
.scale .bands { display:flex; height:8px; border-radius:4px; overflow:hidden; }
.scale .bands i { display:block; } .scale .bands .rl-low { background:var(--low); } .scale .bands .rl-medium { background:var(--med); }
.scale .bands .rl-high { background:var(--high); } .scale .bands .rl-critical { background:var(--crit); }
.scale .marker { position:absolute; top:-4px; width:3px; height:16px; background:var(--ink); transform:translateX(-1.5px); border-radius:1px; }
.scale .ticks span { position:absolute; top:12px; font-size:var(--fs-0); color:var(--muted); transform:translateX(-50%); }
.scale .ticks span:first-child { transform:none; } .scale .ticks span:last-child { transform:translateX(-100%); }
.scale .bandnames { display:flex; margin-top:var(--sp-3); font-size:var(--fs-0); color:var(--muted); }
.scale .bandnames span { text-align:center; }
.trendgrid figure { margin:0; } .trendgrid svg { width:100%; height:auto; display:block; }
.trendgrid figcaption { text-align:center; font-size:var(--fs-1); color:var(--muted); margin-top:var(--gap-1); }
/* The trend charts draw a 520-unit box with 9-unit labels, which a phone scales
   to about 5px. Larger units keep them at 9 to 11px: two steps, because one size
   over the whole band drew them at 15px at 560 pixels. The 10 tick is dropped, or
   it would run into the 9. The loss curve sizes itself and scrolls instead. */
@media (max-width:560px) { svg.trend:not(.lec) text { font-size:12px; } svg.trend .tmax { display:none; } }
@media (max-width:460px) { svg.trend:not(.lec) text { font-size:16px; } }
/* A chart that draws its own box is borderless inside a panel, or it is a box
   in a box. */
section.panel > .panel, section.panel > .chart, section.panel > .score {
  border:0; box-shadow:none; padding:0; margin:0; background:transparent; min-width:0; }
section.panel svg { max-width:100%; }
/* The loss curve keeps a readable size: at the width of the panel its labels were
   4px on a phone and 15px on a wide screen. On a phone it scrolls in its box. */
.scrollx > svg.lec { display:block; width:100%; min-width:560px; max-width:900px; }
.hero { display:grid; grid-template-columns:repeat(auto-fit,minmax(min(300px,100%),1fr)); gap:var(--sp-2);
  margin:0 0 var(--sp-3); align-items:start; }
.score { display:grid; grid-template-columns:auto minmax(0,1fr); gap:var(--sp-3) var(--sp-4); align-items:center;
  background:var(--panel); border:1px solid var(--line); border-radius:var(--radius-lg);
  padding:var(--sp-3) var(--sp-3); }
.score .gaugewrap { display:flex; flex-direction:column; align-items:center; gap:var(--gap-1); }
.score .k { color:var(--muted); font-size:var(--fs-0); font-weight:650; letter-spacing:.3px; text-align:center; }
.scoreright { display:flex; flex-direction:column; gap:var(--sp-3); min-width:0; }
.score .trend { display:flex; flex-direction:column; gap:var(--gap-2); min-width:0; }
/* Two tidy columns rather than one tall stack, so the figures line up. */
.score .breakdown { color:var(--muted); font-size:var(--fs-1); display:grid;
  grid-template-columns:repeat(auto-fit,minmax(108px,1fr)); gap:var(--sp-1) var(--sp-3); }
.score .breakdown span { display:flex; gap:var(--gap-2); align-items:baseline; }
.score .breakdown b { color:var(--ink); font-weight:700; font-variant-numeric:tabular-nums; }
@media (max-width:560px) { .score { grid-template-columns:1fr; justify-items:center; } }
.delta { font-weight:700; display:inline-flex; align-items:center; gap:var(--gap-2); font-size:var(--fs-2); }
.delta.down { color:var(--good); } .delta.up { color:var(--bad); } .delta.flat { color:var(--muted); }
svg.gauge { display:block; }
.chart { background:var(--panel); border:1px solid var(--line); border-radius:var(--radius-lg);
  padding:var(--sp-2) var(--sp-3); }
/* A chart on its own is held off what follows it, as a panel is. */
.mainwrap > .chart { margin:0 0 var(--sp-2); }
.sevbar { display:flex; height:16px; border-radius:999px; overflow:hidden; background:var(--panel-3); }
.sevbar span, .sevbar a { display:block; }
.sevbar a:hover { filter:brightness(1.15); }
.stackbar { display:flex; height:14px; border-radius:4px; overflow:hidden; gap:2px; margin:var(--gap-2) 0 var(--sp-1); }
.stackbar a { display:block; min-width:4px; }
.stackbar a:hover { filter:brightness(.9); }
.agegrid { width:100%; border-collapse:collapse; font-size:var(--fs-1); margin-top:var(--gap-2); }
.agegrid th { font-weight:600; white-space:normal; line-height:1.2; }
.triageboard { grid-template-columns:repeat(auto-fit,minmax(min(260px,100%),1fr)); }
.triageboard .chart { min-width:0; overflow-x:auto; }
.agegrid th, .agegrid td { padding:3px 4px; border-bottom:1px solid var(--line); text-align:left; }
.agegrid .num { text-align:right; font-variant-numeric:tabular-nums; }
.agegrid td a { font-weight:650; }
.sevlegend a.it { color:inherit; text-decoration:none; }
.sevlegend a.it:hover { color:var(--ink); text-decoration:underline; }
.sevlegend { display:grid; grid-template-columns:repeat(auto-fit,minmax(104px,1fr)); gap:var(--sp-1) var(--sp-2);
  margin-top:var(--sp-2); font-size:var(--fs-1); color:var(--muted); }
.sevlegend .it { display:flex; align-items:center; gap:var(--gap-2); }
.sevlegend b { color:var(--ink); font-weight:700; }
.sevlegend.rows { grid-template-columns:1fr; gap:var(--gap-2); margin-bottom:var(--sp-1); }
.sevlegend.rows b { margin-left:auto; }
/* A legend of a few items set beside each other under a chart, not spread over its width. */
.sevlegend.inline { display:flex; flex-wrap:wrap; gap:var(--gap-2) var(--sp-2); }
.sevlegend .dot,.legend .dot { width:9px; height:9px; border-radius:3px; flex:0 0 auto; }
.hbars { display:flex; flex-direction:column; gap:var(--sp-2); }
.hbar { display:grid; grid-template-columns:minmax(0,1fr) auto; gap:var(--gap-2) var(--sp-2); font-size:var(--fs-1);
  align-items:baseline; }
.hbar .lbl { color:var(--ink-2); overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
.hbar .lbl a { text-decoration:none; }
.hbar .lbl a:hover { text-decoration:underline; }
.hbar .val { font-weight:700; font-variant-numeric:tabular-nums; color:var(--ink); }
.hbar .track { grid-column:1/-1; height:8px; border-radius:999px; background:var(--panel-3); overflow:hidden; }
/* A span, so it is made a block: inline, it ignored its width and every bar was an empty track. */
.hbar .fill { display:block; height:100%; border-radius:999px; }
.donutwrap { display:flex; align-items:center; gap:var(--sp-3); flex-wrap:wrap; }
.scrollx { overflow-x:auto; padding-bottom:var(--gap-1); }
.legend { display:grid; gap:var(--gap-2); font-size:var(--fs-1); color:var(--muted); min-width:0; }
/* dot | label | count, so the counts form a column instead of trailing the text. */
.legend a.it { color:inherit; text-decoration:none; }
.legend a.it:hover { color:var(--ink); text-decoration:underline; }
.legend .it { display:grid; grid-template-columns:auto minmax(0,1fr) auto; align-items:center; gap:var(--sp-1); }
.legend b { color:var(--ink); font-weight:700; font-variant-numeric:tabular-nums; }

/* Feed: a leading status dot, never a left accent bar --------------------- */
ul.plain { list-style:none; padding:0; margin:0 0 var(--gap-2); display:grid;
  grid-template-columns:repeat(auto-fill,minmax(min(290px,100%),1fr)); gap:var(--sp-1); }
ul.plain li { background:var(--panel); border:1px solid var(--line); border-radius:var(--radius);
  padding:var(--gap-2) var(--sp-1); font-size:var(--fs-1); overflow-wrap:anywhere; }
/* In a table cell the list is lines, not boxed cards that read as text fields. */
td ul.plain { display:block; margin:0; }
td ul.plain li { border:0; background:none; border-radius:0; padding:0 0 var(--gap-1); }
/* A card list ending in its own small margin ran into the fold under it. */
ul.plain + details.fold { margin-top:var(--sp-2); }
/* An item wraps and is never cut with an ellipsis: these lists carry sentences
   (the meaning of a maturity level, the approval of a version, the findings of a function),
   and the end of a sentence was the part a reader lost. */
.feed { list-style:none; padding:0; margin:0; }
/* An entry is a card; a list of detail lines inside one is a plain list. */
.feed > li { background:var(--panel); border:1px solid var(--line); border-radius:var(--radius);
  padding:var(--sp-2) var(--sp-2); margin-bottom:var(--sp-1); }
.feed .when { color:var(--muted); font-size:var(--fs-1); margin-top:var(--gap-1); }
/* A title is text and flows as text: the dot is placed on its first line out of
   the flow, and the glyph and the words wrap beside it. As a flex row a long
   title was one item that moved to a line of its own, leaving the dot and the
   glyph above it. */
.feed .ttl { font-weight:650; position:relative; padding-left:calc(8px + var(--sp-1)); }
.feed .ttl > .icon { margin-right:var(--sp-1); }
.feed .ttl::before { content:""; width:8px; height:8px; border-radius:50%; background:var(--info);
  position:absolute; left:0; top:calc(.5lh - 4px); }
.feed li.bad .ttl::before { background:var(--bad); }
.feed li.good .ttl::before { background:var(--good); }
.feed ul { margin:var(--sp-1) 0 0 var(--sp-4); padding:0; color:var(--muted); font-size:var(--fs-1); }
.feed li.new-since { border-color:color-mix(in srgb,var(--accent) 50%,var(--line)); }
.feed li.new-since .ttl::after { content:"new"; display:inline-block; vertical-align:middle; margin-left:var(--sp-1); line-height:1.4;
  background:var(--accent); color:var(--accent-ink); font-size:var(--fs-0);
  padding:var(--gap-1) var(--gap-2); border-radius:999px; font-weight:700; letter-spacing:.3px; }
/* The rank row mixes a badge, a bold sentence and a pill, which have three
   different line heights, so centring them left the pill riding high against a
   two-line action. Baseline alignment on the text, with the badge pinned to
   the first line. */
.rank { display:flex; align-items:baseline; gap:var(--gap-2) var(--sp-1); flex-wrap:wrap;
  line-height:1.45; }
.rank > b { flex:1 1 320px; min-width:0; font-weight:650; }
.rank .pill { align-self:center; }
/* The rank number, in the accent. margin:0, because the word lead in the markup also
   names the lead panel, whose bottom margin it was taking. */
.rank .n { background:var(--accent); color:var(--accent-ink); border:1px solid transparent; border-radius:7px;
  min-width:24px; text-align:center; font-weight:700; padding:1px var(--gap-2); font-size:var(--fs-1); margin:0;
  font-variant-numeric:tabular-nums; align-self:flex-start; flex:0 0 auto; }
.why { color:var(--muted); font-size:var(--fs-1); margin-top:var(--gap-2); }
/* The triage reason sits under the risk reasons and has to read as a different
   kind of fact: one is why it ranks here, the other is that nobody has read it. */
.why.unread { color:var(--accent); font-weight:600; margin-top:var(--gap-1); }

.icon { vertical-align:-4px; flex:0 0 auto; }

/* Live run console ------------------------------------------------------- */
.runbox { margin:var(--sp-2) 0; }
/* The dot keeps its size and sits on the first line when the heading wraps. */
.runhead { display:flex; align-items:flex-start; gap:var(--sp-1); font-weight:650; margin-bottom:var(--sp-1); font-size:var(--fs-2); }
.runhead .dot { width:9px; height:9px; flex:0 0 9px; margin-top:calc((1lh - 9px) / 2); border-radius:50%; background:var(--accent);
  animation:pulse 1.2s ease-in-out infinite; }
/* A reader who asked the system for less motion gets none: the pulsing dots
   hold still and transitions and smooth scrolling are instant. */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { animation-duration:0.01ms !important; animation-iteration-count:1 !important;
    transition-duration:0.01ms !important; scroll-behavior:auto !important; }
}
/* A finished run keeps its console, so the dot stops pulsing and states the
   outcome instead of the window simply disappearing. */
.runbox.done .runhead .dot { background:var(--good); animation:none; }
.runbox.failed .runhead .dot { background:var(--bad); animation:none; }
.runbox.cancelled .runhead .dot { background:var(--muted); animation:none; }
pre.console { max-height:360px; overflow:auto; }
.runfoot:not(:empty) { display:flex; flex-wrap:wrap; gap:var(--sp-1); align-items:center; margin-top:var(--sp-1); }
.runfoot .muted { font-size:var(--fs-1); }


/* Tabs -------------------------------------------------------------------- */
.tabs { display:flex; gap:var(--gap-1); border-bottom:1px solid var(--line); margin:0 0 var(--sp-3); overflow-x:auto; overflow-y:hidden; }
.tabs a { padding:var(--sp-1) var(--sp-2); font-size:var(--fs-2); font-weight:600; color:var(--muted); text-decoration:none;
  border-bottom:2px solid transparent; white-space:nowrap; margin-bottom:-1px; }
.tabs a:hover { color:var(--ink); }
.tabs a.on { color:var(--accent); border-bottom-color:var(--accent); }
/* The second row of a grouped destination: the pages in the chosen section. */
/* In a page the switch is its own block; in a tab head the head sets its margin. */
.subtabs { display:flex; gap:var(--gap-1); margin:var(--sp-2) 0 var(--sp-3); overflow-x:auto; overflow-y:hidden; }
.subtabs a { padding:var(--gap-1) var(--sp-2); font-size:var(--fs-1); font-weight:600; color:var(--muted); text-decoration:none; border-radius:999px; white-space:nowrap; }
.subtabs a:hover { color:var(--ink); background:var(--panel-2); }
.subtabs a.on { color:var(--accent); background:var(--accent-weak); }

/* Pipeline ---------------------------------------------------------------- */
.setupflow { background:var(--panel); border:1px solid var(--line); border-radius:var(--radius-lg);
  padding:var(--sp-2) var(--sp-3); margin-bottom:var(--sp-2); display:flex; align-items:center;
  gap:var(--sp-3); flex-wrap:wrap; }
/* A fixed 5-column grid, so the connectors can be drawn between column centres
   and never end up pointing at nothing. Below the breakpoint it becomes a
   vertical list and the connectors are dropped entirely rather than wrapped. */
.setupflow ol { list-style:none; margin:0; padding:0; flex:1 1 560px; min-width:0;
  display:grid; grid-template-columns:repeat(5,minmax(0,1fr)); }
.setupflow li { position:relative; min-width:0; }
.setupflow li:not(:last-child)::after { content:""; position:absolute; top:17px; left:50%; width:100%;
  height:2px; background:var(--line); z-index:0; }
.setupflow li.done:not(:last-child)::after { background:color-mix(in srgb,var(--good) 55%,var(--line)); }
.setupflow a { display:flex; flex-direction:column; align-items:center; gap:var(--gap-2); text-decoration:none;
  color:inherit; position:relative; z-index:1; padding:var(--gap-1) var(--gap-2); border-radius:var(--radius); }
.setupflow a:hover .txt b { text-decoration:underline; }
.setupflow .node { width:30px; height:30px; border-radius:50%; display:inline-flex; align-items:center;
  justify-content:center; font-size:var(--fs-1); font-weight:700; border:2px solid var(--line);
  background:var(--panel); color:var(--muted); flex:0 0 auto; }
.setupflow .txt { display:flex; flex-direction:column; align-items:center; text-align:center; min-width:0; }
.setupflow .txt b { font-size:var(--fs-1); font-weight:650; }
.setupflow .txt .d { font-size:var(--fs-0); color:var(--muted); line-height:1.35; }
.setupflow .done .node { background:var(--good); border-color:var(--good); color:#fff; }
.setupflow .ready .node { border-color:var(--accent); color:var(--accent); }
.setupflow .blocked .node { background:var(--panel-3); color:var(--muted); }
.setupflow .blocked .txt b, .setupflow .idle .txt b { color:var(--muted); }
.setupflow .action .node { background:var(--accent); border-color:var(--accent); color:var(--accent-ink); }
.setupflow .action .txt b { color:var(--accent); }
.setupflow .cta { flex:0 0 auto; }
@media (max-width:760px) {
  .setupflow ol { grid-template-columns:1fr; gap:var(--gap-1); }
  .setupflow li::after { display:none; }
  .setupflow a { flex-direction:row; align-items:center; gap:var(--sp-1); padding:var(--gap-2) var(--gap-1); }
  .setupflow .txt { align-items:flex-start; text-align:left; }
}
/* A disabled action states why it is disabled, next to itself. */
/* The button keeps its own width above its reason, and the other controls in the row
   line up with the button and not with the button and its reason together. */
.blockedbtn { display:inline-flex; flex-direction:column; align-items:flex-start; gap:var(--gap-1); }
.btnrow:has(.blockedbtn) { align-items:flex-start; }
.blockedbtn .why { font-size:var(--fs-0); color:var(--muted); max-width:30ch; line-height:1.35; }
a.btnlink.primary { background:var(--accent); color:var(--accent-ink); border-color:transparent; }
a.btnlink.primary:hover { background:color-mix(in srgb,var(--accent) 86%,#000); border-color:transparent;
  color:var(--accent-ink); }

/* The browser's own controls (a date picker, a scrollbar) follow the theme
   chosen here and not only the system's. */
:root { color-scheme:light; }
@media (prefers-color-scheme: dark) { :root:not([data-theme="light"]) { 
  --bg:#111219; --panel:#1a1b24; --panel-2:#22232e; --panel-3:#2a2b38;
  --line:#343741; --line-2:#424650; --ink:#dfe5ef; --ink-2:#c4cad6; --muted:#98a2b3;
  --accent:#8b8ef8; --accent-2:#5fd4c4; --accent-3:#c49bf2;
  --accent-weak:#24254a; --accent-ink:#0d0e1f;
  --crit:#FF6666; --high:#FF9F43; --med:#FFD54A; --low:#79AAD9; --info:#98A2B3;
  --warn:#FFCE7A; --sev-ink:#1D1E24; --high-ink:#1D1E24;
  --good:#7de2d1; --bad:#f86b63; --bad-ink:#1D1E24;
  --scroll-shade:rgba(0,0,0,.65);
  --shadow:0 1px 2px rgba(0,0,0,.3);
  --shadow-lg:0 8px 24px rgba(0,0,0,.45);
  --nav:#0b0c14; --nav-ink:#e4e6f2; --nav-muted:#8f93ab; --nav-hover:#171828;
  --nav-on:#ffffff; --nav-line:#1d1f30;
 color-scheme:dark; } }
:root[data-theme="dark"] { 
  --bg:#111219; --panel:#1a1b24; --panel-2:#22232e; --panel-3:#2a2b38;
  --line:#343741; --line-2:#424650; --ink:#dfe5ef; --ink-2:#c4cad6; --muted:#98a2b3;
  --accent:#8b8ef8; --accent-2:#5fd4c4; --accent-3:#c49bf2;
  --accent-weak:#24254a; --accent-ink:#0d0e1f;
  --crit:#FF6666; --high:#FF9F43; --med:#FFD54A; --low:#79AAD9; --info:#98A2B3;
  --warn:#FFCE7A; --sev-ink:#1D1E24; --high-ink:#1D1E24;
  --good:#7de2d1; --bad:#f86b63; --bad-ink:#1D1E24;
  --scroll-shade:rgba(0,0,0,.65);
  --shadow:0 1px 2px rgba(0,0,0,.3);
  --shadow-lg:0 8px 24px rgba(0,0,0,.45);
  --nav:#0b0c14; --nav-ink:#e4e6f2; --nav-muted:#8f93ab; --nav-hover:#171828;
  --nav-on:#ffffff; --nav-line:#1d1f30;
 color-scheme:dark; }

@media (max-width:900px) {
  aside { position:fixed; top:0; left:0; height:100vh; height:100dvh; transform:translateX(-100%);
    transition:transform .22s ease; box-shadow:var(--shadow-lg); }
  body.nav-open aside { transform:translateX(0); }
  aside .brand .x { display:inline-flex; }
  #navcollapse { display:none; }
  .topbar { padding:0 var(--sp-2); }
  .tb-search input[type="search"] { width:120px; }
  .topbar .menubtn { display:inline-flex; }
  .topbar .tb-brand { display:flex; }
  .topbar .tb-title { display:none; }
  body.nav-open .backdrop { display:block; position:fixed; inset:0; background:rgba(4,8,14,.55); z-index:35; }
  .mainwrap { padding:var(--sp-3) var(--sp-2) var(--sp-4); }
  .score { gap:var(--sp-2); }
}
.backdrop { display:none; }

/* Design layer ------------------------------------------------------------ */
/* One kit, written last so it is the rule that wins: the brand rail, display
   type, one badge, one button scale, styled native controls, toasts and the
   overview hero. Components above keep their layout; this sets their look. */

/* The rail carries its own dark tokens, so every component inside it (the
   workspace switcher, chips, badges) renders for a dark surface without a
   parallel set of rules. */
aside { --panel:#171830; --panel-2:#1b1c32; --panel-3:#25274a; --line:#2a2c48; --line-2:#3a3d60;
  --ink:#eceef8; --ink-2:#c7cae0; --muted:#9094ad; --accent-weak:rgba(139,142,248,.16); --accent:#a9abff;
  border-right-color:var(--nav-line); }
aside nav a { color:var(--nav-ink); opacity:.86; }
aside nav a:hover { background:var(--nav-hover); opacity:1; }
aside nav a.on { background:rgba(139,142,248,.18); color:#fff; opacity:1; }
aside nav a .icon { opacity:.9; }
aside nav .navhead { color:#6f7392; }
/* The name in the brand gradient, the mark's own. Wiz, Datadog, Tenable and
   Vercel carry no tagline in the console, so the name stands alone, on the
   sign-in page too. */
aside .brand .name, .topbar .tb-brand .name, .barecard .brandline .name { font-family:var(--display); font-weight:650; letter-spacing:-.03em; font-size:22px;
  background:linear-gradient(120deg,#a5b4fc 0%,#818cf8 40%,#c084fc 100%); -webkit-background-clip:text; background-clip:text; color:transparent; }
.topbar .tb-brand .name, .barecard .brandline .name { background-image:linear-gradient(120deg,#6366f1 0%,#4f46e5 45%,#9333ea 100%); font-size:19px; }
aside .brand .name small { color:var(--nav-muted); letter-spacing:0; }
aside .buildid, aside .navcollapse { color:var(--nav-muted); }

/* The mark: a globe with one meridian, drawn here and never fetched. */
.logo { width:34px; height:34px; background:none; box-shadow:none; border-radius:0; }
.logo svg { display:block; }
.topbar .tb-brand .logo { width:30px; height:30px; }

/* Display type: Geist throughout, set heavier and tighter for headings and
   the large numbers. */
h1, .kpi .v, .card .v, .hero-score .v, .kstrip .v { font-family:var(--display); letter-spacing:-.022em; }
h1 { font-size:24px; font-weight:600; }
h1, h2, h3 { letter-spacing:-.025em; }
/* One heading scale: a section heading is the same size whether or not it
   titles a panel (it was 16px bare and 15px in a panel, and five pages had
   both), and a sub-heading is a step below it, not the same size. */
h2 { font-size:var(--fs-3); font-weight:600; border-bottom:0; padding-bottom:0; }
h2 .icon { color:var(--accent); }
:root[data-density="compact"] h1 { font-size:21px; }

/* Surfaces: three levels. The canvas, a panel lifted off it, and a raised
   layer (menus, toasts) above both. */
.panel, .card, .kpi, table, .fold, .chart { border-radius:var(--radius-lg); box-shadow:var(--shadow-sm); border-color:var(--line); }
.panel { padding:var(--sp-3); }
/* A chart keeps its panel-style title from the chart rule above. */
.panel > .k { color:var(--ink-2); letter-spacing:.04em; }
table:not(.kv) th { background:var(--panel-2); color:var(--muted); font-size:var(--fs-0); font-weight:650; text-transform:uppercase; letter-spacing:.05em; }
/* A heading followed by cells labels its row, so it reads as the label of a fact
   sheet does and wraps, giving the value columns their width back. The heat map
   keeps its own look. */
table:not(.kv):not(.riskgrid) tr:has(> td) > th { white-space:normal; text-transform:none; letter-spacing:normal; font-size:var(--fs-1); font-weight:600; color:var(--ink-2); }
th .pill, th .status { text-transform:none; letter-spacing:normal; }
.stagehead .muted { text-transform:none; letter-spacing:normal; font-weight:400; }
table.kv th { color:var(--ink-2); font-weight:600; font-size:var(--fs-1); }
table tr:hover td { background:color-mix(in srgb,var(--accent) 4%,var(--panel)); }
.umenu, .wsmenu, .bulkpop, .exportmenu, .popover { border-radius:var(--radius-xl); box-shadow:var(--shadow-lg); }

/* One badge. Severity, status, tag and flag were four shapes; they are one
   pill now and differ only in colour. */
.pill, .tag, .status, .flag { display:inline-flex; align-items:center; gap:5px; height:20px; padding:0 8px;
  border-radius:999px; font-size:var(--fs-0); font-weight:600; line-height:1; letter-spacing:.01em;
  white-space:nowrap; vertical-align:middle; border:1px solid transparent; }
.tag { border-color:var(--line-2); background:var(--panel-2); color:var(--ink-2); }
.status { border-color:var(--line); background:var(--panel-2); color:var(--ink-2); }
.flag { border-color:color-mix(in srgb,var(--bad) 45%,var(--line)); background:color-mix(in srgb,var(--bad) 9%,var(--panel)); color:var(--bad); }
.pill.info { border-color:color-mix(in srgb,var(--info) 30%,transparent); }

/* One button scale: small, standard and large, one radius, one weight. */
button, a.btnlink, summary.btnlike { border-radius:var(--radius-md); font-weight:600; gap:var(--gap-2);
  display:inline-flex; align-items:center; justify-content:center; padding-left:14px; padding-right:14px; }
/* :where keeps this at the specificity of a bare button, so every component
   rule that restyles a button also removes the lift. */
:where(button:not(.sec, .warn, .copy, .iconbtn, .x, .preset, .navcollapse, .menubtn, .helptip, .linkish, .linkbtn)) {
  box-shadow:0 1px 0 rgba(255,255,255,.18) inset, 0 1px 2px rgba(30,27,120,.25); }
button.sec, a.btnlink, summary.btnlike { background:var(--panel); border-color:var(--line-2); color:var(--ink); box-shadow:var(--shadow-sm); }
a.btnlink.primary { background:var(--accent); color:var(--accent-ink); border-color:transparent; }
a.btnlink.primary:hover { background:color-mix(in srgb,var(--accent) 86%,#000); color:var(--accent-ink); }
button.sm, a.btnlink.sm { height:28px; padding:0 10px; font-size:var(--fs-1); }
/* Every small button is the one small size: a copy button, a preset and a
   pager's Previous and Next were 25, 27 and 28 pixels on different pages. */
button.copy, button.preset, .btnrow.presets .preset, .pager button, .pager select { height:28px; padding-top:0; padding-bottom:0; font-size:var(--fs-1); }
/* A copy glyph in a cell is no taller than the text it copies, so a hidden one
   does not lower the value or add blank lines when it wraps. A touch screen has
   no hover to reveal it, so there it is always shown. */
td .copy { height:auto; padding-block:0; line-height:inherit; }
@media (hover:none) { .copy { opacity:1; } }
/* A copy button that is the visible action of a toolbar is the size of the
   buttons beside it, not the 28px glyph. */
button.copy.draftcopy { height:var(--ctl-h); padding:0 14px; font-size:var(--fs-2); }
/* A control in a table row is a small one: full-size Mark done, Edit and
   Remove side by side wrapped into a stack and made every row three lines deep. */
td button:not(.copy):not(.helptip):not(.iconbtn):not(.x):not(.linkbtn), td a.btnlink, td summary.btnlike, td select,
td input[type=text], td input:not([type]), td input[type=number], td input[type=date],
td input[type=email], td input[type=url], td input[type=search], td input[type=password], td input[type=tel] { height:28px; font-size:var(--fs-1); }
td button:not(.copy):not(.helptip):not(.iconbtn):not(.x):not(.linkbtn), td a.btnlink, td summary.btnlike { padding:0 10px; }
/* A 28px control on the first line of a top-aligned cell makes that line 28px
   deep, so its text sat about 4px below the text in the next cell. The padding
   of the cell gives back the difference, so the text of the control sits on the
   line of the row and a row of controls is as deep as a row of text. On the padding
   and not on the control: a negative margin on the control left a second row of
   controls, wrapped in a narrow cell, overlapping the first. */
td:has(> :is(button:not(.copy, .helptip, .iconbtn, .x, .linkbtn), a.btnlink, summary.btnlike):first-child,
  > form.inline:first-child > button:not(.copy, .helptip, .iconbtn, .x, .linkbtn),
  > details.inlineedit:first-child > summary.btnlike) { padding-block:calc(var(--sp-1) - (28px - 1lh) / 2); }
/* A disclosure in an assessment row sits on its own line under the title. */
.mattable td > details.inlineedit { display:block; margin-top:var(--gap-1); }
/* A long label wraps on a narrow phone instead of pushing the page sideways,
   keeping the standard height as its floor. A control in a table row, the pager
   and the small kit keep 28px on one line: a table scrolls inside itself at this
   width, so a row control cannot push the page. */
@media (max-width:420px) { main :is(button, summary.btnlike):not(td *, .pager *, .sm, .copy, .iconbtn, .x, .preset, .helptip, .linkbtn, .linkish, .more) { white-space:normal; height:auto; min-height:var(--ctl-h); max-width:100%; } }
button.lg, a.btnlink.lg { height:42px; padding:0 18px; font-size:var(--fs-3); }
/* A button drawn as a link stays a link wherever it is: the button scale above
   and the table rule boxed it, and a workspace name in Client work wrapped
   inside a 28-pixel box. */
button.linkbtn, td button.linkbtn { display:inline; height:auto; padding:0; border-radius:0; box-shadow:none; font-size:inherit; font-weight:inherit; white-space:normal; }
/* The portfolio's onboarding marks: one per step, done, open or regressed. */
.ckrow { display:inline-flex; gap:3px; vertical-align:middle; } .ckmark { display:inline-grid; place-items:center; width:18px; height:18px; border-radius:4px; font-size:11px; font-weight:700; background:var(--panel-2); color:var(--muted); border:1px solid var(--line); } .ckmark.ck-done { background:color-mix(in srgb,var(--good) 14%,var(--panel)); color:var(--good); border-color:color-mix(in srgb,var(--good) 35%,var(--line)); } .ckmark.ck-regressed { background:color-mix(in srgb,var(--warn) 14%,var(--panel)); color:var(--warn); border-color:color-mix(in srgb,var(--warn) 35%,var(--line)); }

/* Native controls, drawn. A select keeps the browser's list and loses its
   own chrome; a file input's button is a secondary button. */
select { appearance:none; -webkit-appearance:none; padding-right:32px; border-radius:var(--radius-md);
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 12 12'%3E%3Cpath d='M3 4.5l3 3 3-3' fill='none' stroke='%238a8fa6' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
  background-repeat:no-repeat; background-position:right 11px center; background-size:12px; }
select[multiple] { background-image:none; padding-right:var(--sp-1); }
input[type=text],input:not([type]),input[type=search],input[type=password],input[type=date],input[type=datetime-local],input[type=number],input[type=email],input[type=url],input[type=tel],textarea { border-radius:var(--radius-md); }
input[type=checkbox], input[type=radio] { accent-color:var(--accent); width:16px; height:16px; }
input[type=file] { font:inherit; font-size:var(--fs-1); color:var(--muted); max-width:560px; }
input[type=file]::file-selector-button { font:inherit; font-size:var(--fs-2); font-weight:600; height:var(--ctl-h);
  padding:0 14px; margin-right:var(--sp-1); border-radius:var(--radius-md); border:1px solid var(--line-2);
  background:var(--panel); color:var(--ink); cursor:pointer; }
input[type=file]::file-selector-button:hover { background:var(--panel-2); }

/* The segmented control is the one switch for a short set of choices: the
   surface switch and the sort row are drawn as it is. */
.surfacebar, .seg { border-radius:var(--radius-md); background:var(--panel-3); border-color:transparent; padding:3px; }
.surfacebar a, .seg label { border-radius:6px; }
.surfacebar a.on, .seg label:has(input:checked) { background:var(--panel); box-shadow:0 1px 2px rgba(16,18,40,.12), 0 0 0 1px var(--line); }

/* The key-number strip under a page's heading: list, detail and settings
   pages lead with the same row of three to five figures. */
.kstrip { display:flex; flex-wrap:wrap; gap:0; margin:0 0 var(--sp-3); background:var(--panel);
  border:1px solid var(--line); border-radius:var(--radius-lg); box-shadow:var(--shadow-sm); overflow:hidden; }
.kstrip > * { flex:1 1 140px; display:flex; flex-direction:column; gap:2px; padding:var(--sp-2) var(--sp-3);
  border-right:1px solid var(--line); color:inherit; text-decoration:none; min-width:0; }
.kstrip > *:last-child { border-right:0; }
.kstrip a:hover { background:var(--panel-2); }
.kstrip .k { font-size:var(--fs-0); color:var(--muted); font-weight:600; text-transform:uppercase; letter-spacing:.05em; }
.kstrip .v { font-size:var(--fs-6); font-weight:600; line-height:1.15; }
/* A key figure that opens its list is a figure first: the colour and weight of
   every other figure in a strip, underlined only under the pointer. */
.kstrip .v a, .cards .v a { color:inherit; text-decoration:none; }
.kstrip .v a:hover, .cards .v a:hover { text-decoration:underline; }
.kstrip .bad .v, .kstrip .v.bad { color:var(--bad); }
.kstrip .warn .v, .cards > .warn .v { color:color-mix(in srgb,var(--warn) 70%,var(--ink)); }
.kstrip .good .v { color:var(--good); }

/* A row of cards is the key-number strip: one surface divided by hairlines,
   so every page that leads with figures leads with the same object. */
.cards { display:flex; flex-wrap:wrap; gap:0; background:var(--panel); border:1px solid var(--line); border-radius:var(--radius-lg);
  overflow:hidden; box-shadow:var(--shadow-sm); }
/* Each card draws the hairline on its left and top, and the strip clips the
   ones on its outer edge, so a wrapped last row fills the width. */
.cards > .card { flex:1 1 140px; border:0; border-radius:0; box-shadow:-1px 0 0 var(--line), 0 -1px 0 var(--line); padding:var(--sp-2) var(--sp-3); }
.cards > .card .k { text-transform:uppercase; letter-spacing:.05em; font-weight:600; }
.cards > .card .v { font-family:var(--display); font-weight:600; letter-spacing:-.025em; }
/* The basis is that of the strip, so two cards share a phone row; one card alone is a
   card and not a band across the page. */
.cards:has(> .card:only-child) { max-width:360px; }
:root[data-density="compact"] .cards { gap:1px; }

/* The account menu. Its items are menu rows and not buttons: left-aligned,
   one height, no fill or shadow, whatever the button kit says. */
.umenu { min-width:280px; padding:0; overflow:hidden; }
.umenu .umhead { display:flex; gap:var(--sp-2); align-items:center; padding:var(--sp-2); border:0; margin:0; }
.umenu .umhead .wsavatar { width:44px; height:44px; font-size:18px; margin:0; }
.umenu .umwho b { font-size:var(--fs-3); font-weight:600; color:var(--ink); }
.umenu .umemail { font-size:var(--fs-1); color:var(--muted); }
.umenu .umfacts { display:grid; gap:var(--gap-1); margin:0; padding:0 var(--sp-2) var(--sp-2); border-bottom:1px solid var(--line); }
.umenu .umfacts > div { display:flex; justify-content:space-between; gap:var(--sp-2); align-items:baseline; min-width:0; }
.umenu .umfacts dt { font-size:var(--fs-0); color:var(--muted); font-weight:600; text-transform:uppercase; letter-spacing:.05em; }
.umenu .umfacts dd { margin:0; font-size:var(--fs-1); font-weight:600; color:var(--ink); text-align:right; overflow-wrap:anywhere; }
.umenu .umgroup { display:flex; flex-direction:column; padding:var(--gap-2); margin:0; }
.umenu .umout { border-top:1px solid var(--line); }
.umenu a, .umenu button { display:flex; align-items:center; justify-content:flex-start; gap:var(--sp-1); width:100%; height:auto;
  padding:var(--sp-1) var(--sp-1); border:0; border-radius:var(--radius-sm); background:none; box-shadow:none;
  color:var(--ink); font:inherit; font-size:var(--fs-2); font-weight:500; text-align:left; text-decoration:none; }
.umenu a .icon, .umenu button .icon { color:var(--muted); flex:none; }
.umenu a:hover, .umenu button:hover, .umenu a:focus-visible, .umenu button:focus-visible { background:var(--panel-2); color:var(--ink); }
.umenu .umout button:hover { color:var(--bad); }
.umenu .umout button:hover .icon { color:var(--bad); }
.wsmenu button, .wsmenu a { justify-content:flex-start; box-shadow:none; height:auto; }

/* Search is a button in the top bar; the field opens beside it on request.
   Without script the field stays open, since the button would do nothing. */
html.js .tb-search { display:none; }
html.js .tb-search.open { display:flex; animation:toastin .14s ease-out; }
.tb-search input[type="search"] { width:280px; height:var(--ctl-h); border-radius:var(--radius-md); }
html:not(.js) .searchbtn { display:none; }
.topbar .iconbtn.searchbtn { width:var(--ctl-h); height:var(--ctl-h); border-radius:var(--radius-md); display:inline-flex; align-items:center; justify-content:center;
  background:transparent; border:1px solid transparent; color:var(--ink-2); box-shadow:none; padding:0; }
.topbar .iconbtn.searchbtn:hover, .topbar .iconbtn.searchbtn[aria-expanded="true"] { background:var(--panel-2); border-color:var(--line); color:var(--ink); }
.topbar .tb-actions { gap:var(--gap-2); }
.topbar .menubtn { border-color:transparent; width:var(--ctl-h); height:var(--ctl-h); justify-content:center; padding:0; border-radius:var(--radius-md); }
.topbar .tb-actions:empty { display:none; }
@media (max-width:560px) { html.js .tb-search.open { position:absolute; left:var(--sp-2); right:96px; top:10px; z-index:5; }
  html.js .tb-search.open input[type="search"] { width:100%; } }

/* One inset. Panels, cards, tiles, folds, message boxes, empty states and
   table cells had 14, 16 and 22 pixels of side padding, so text in a stack of
   them started at three different distances from the edge. */
:root { --inset:16px; }
:root[data-density="compact"] { --inset:12px; }
.panel, .chart { padding:var(--inset); }
.card, .cards > .card, .kpi, .ovhero .kpi, .kstrip > * { padding:var(--sp-2) var(--inset); }
.danger, .ok, .warnbox, .note, .running, .empty { padding:var(--sp-2) var(--inset); }
.fold > summary { padding:var(--sp-1) var(--inset); }
.fold .foldbody { padding:var(--gap-1) var(--inset) var(--sp-2); }
th, td { padding-left:var(--inset); padding-right:var(--inset); }
.filterbar, form.filters { padding:var(--sp-1) var(--inset); }
/* Blocks inside a form sit on the spacing scale: a text area was an inline
   box, so the line box under it added 6 pixels to every gap below it. */
main form textarea { display:block; margin:0 0 var(--sp-2); }
h3 { margin:var(--sp-3) 0 var(--sp-1); font-size:var(--fs-2); font-weight:600; letter-spacing:-.01em; }
h3 + p, h3 + .muted { margin-top:0; }
h2 + ul, h2 + ol { margin-top:0; }
b + div.muted { margin-top:var(--gap-1); }
.prefrow .what b + span, .prefrow .what b + .muted { display:block; margin-top:var(--gap-1); }

/* Tabbed pages. The tab row is the page's heading: the controls sit at its
   end, the visually hidden h1 names the page for the title and screen readers. */
.vh { position:absolute !important; width:1px; height:1px; overflow:hidden; clip:rect(0 0 0 0); white-space:nowrap; margin:0; padding:0; }
/* The page's controls share the first row with the tabs and nothing else: the
   second row, the pages in the chosen section, runs the full width. In one flex
   row the controls took their width from both rows, so on Period report, with
   the surface switch, a time range and Export, the second row was cut short at
   1440 pixels and scrolled its first page out of view. */
.tabhead { display:grid; grid-template-columns:minmax(0,1fr) auto; column-gap:var(--sp-2); align-items:start;
  border-bottom:1px solid var(--line); margin:0 0 var(--sp-3); min-height:var(--ctl-h); }
.tabhead .tabstack { display:contents; }
.tabhead .tabstack > * { grid-column:1 / -1; grid-row:2; min-width:0; }
.tabhead .tabstack > .tabs { grid-column:1; grid-row:1; }
.tabhead > .pageactions { grid-column:2; grid-row:1; }
.tabhead .tabs { border-bottom:0; margin:0; scrollbar-width:none; }
.tabhead .tabs::-webkit-scrollbar, .tabhead .subtabs::-webkit-scrollbar { display:none; }
.tabhead .subtabs { scrollbar-width:none; }
.tabhead .subtabs { margin:var(--sp-2) 0 var(--sp-2); padding-bottom:var(--sp-1); }
/* A scrollable tab strip hides its scrollbar, so without a cue a reader cannot
   tell more tabs sit off the edge and the active one can be scrolled out of
   view entirely. A fade on each overflowing edge is that cue; the class is set
   by script from the scroll position, so it shows only on the side with more. */
.tabs.ovf-l, .subtabs.ovf-l, .tabhead .pageactions.ovf-l { -webkit-mask-image:linear-gradient(90deg,transparent,#000 26px); mask-image:linear-gradient(90deg,transparent,#000 26px); }
.tabs.ovf-r, .subtabs.ovf-r, .tabhead .pageactions.ovf-r { -webkit-mask-image:linear-gradient(90deg,#000 calc(100% - 26px),transparent); mask-image:linear-gradient(90deg,#000 calc(100% - 26px),transparent); }
.tabs.ovf-l.ovf-r, .subtabs.ovf-l.ovf-r, .tabhead .pageactions.ovf-l.ovf-r { -webkit-mask-image:linear-gradient(90deg,transparent,#000 26px,#000 calc(100% - 26px),transparent); mask-image:linear-gradient(90deg,transparent,#000 26px,#000 calc(100% - 26px),transparent); }
/* The tabs set the row's height: an action beside them (Export, a time range) is
   no taller than they are, so the line under the row, and the active tab's
   underline on it, sit at the same place on a page with actions as on one
   without. A padded action row made it 4px deeper and floated the underline. */
.tabhead .pageactions { flex:none; display:flex; gap:var(--gap-2); align-items:center; padding-bottom:0; }
.tabhead .pageactions:empty:not(.reserve) { display:none; }
.topbar .crumb.here { color:var(--ink); font-weight:600; }
.tabhead + .surfacenote { margin-top:calc(var(--sp-2) * -1); }
@media (max-width:760px) { .tabhead { grid-template-columns:minmax(0,1fr); }
  .tabhead > .pageactions { grid-column:1; grid-row:1; }
  .tabhead .tabstack > .tabs { grid-row:2; }
  .tabhead .tabstack > :not(.tabs) { grid-row:3; }
  .tabhead .pageactions { padding:0 0 var(--sp-1); overflow-x:auto; flex-wrap:nowrap; justify-content:flex-start; min-height:calc(var(--ctl-h) + var(--sp-1)); } }

/* Preferences and other settings rows: each group is one card with a small
   heading above it, rows at the standard inset, the control at the row's end. */
.prefrows { max-width:880px; background:var(--panel); border:1px solid var(--line); border-radius:var(--radius-lg); box-shadow:var(--shadow-sm); margin:0 0 var(--sp-3); }
.prefrow { padding:var(--sp-1) var(--inset); min-height:56px; gap:var(--sp-2); }
.prefrow:last-child { border-bottom:0; }
.prefrow .what b { font-size:var(--fs-2); }
.prefrow .what b + span { margin-top:0; }
h2 + .prefrows, h2:has(+ .prefrows) { margin-bottom:var(--sp-1); }
h2:has(+ .prefrows) { margin-top:var(--sp-3); color:var(--ink-2); }
.tabhead + p.hint + h2:has(+ .prefrows), .tabhead + h2:has(+ .prefrows) { margin-top:0; }
.seg label { padding:3px 10px; font-size:var(--fs-1); }

/* The filter bar: one row, one surface, above the list it filters. */
.filterbar, form.filters { background:var(--panel); border:1px solid var(--line); border-radius:var(--radius-lg);
  padding:var(--sp-1) var(--sp-2); box-shadow:var(--shadow-sm); }

/* Explanations stay on the page and take one line until asked for. */
p.hint.clamp, .surfacenote.clamp { display:-webkit-box; -webkit-box-orient:vertical; -webkit-line-clamp:1; overflow:hidden; }
p.hint.clamp.open, .surfacenote.clamp.open { display:block; -webkit-line-clamp:unset; }
/* The padding and border of a code chip reach above its own line, so one on the
   hidden second line drew a stray rule under the first. */
p.hint.clamp:not(.open) code { padding-block:0; border-top-color:transparent; border-bottom-color:transparent; }
p.hint.clamp, .surfacenote.clamp { margin-bottom:var(--gap-1); }
button.more { all:unset; cursor:pointer; color:var(--accent); font-size:var(--fs-1); font-weight:600; margin:0 0 var(--sp-3); display:block; width:max-content; }
button.more:focus-visible { outline:2px solid var(--accent); outline-offset:2px; border-radius:4px; }

/* Toasts. A confirmation is a message about the action just taken, so it is
   raised over the page for a few seconds rather than pushing the page down. */
.toasts { position:fixed; right:20px; bottom:20px; z-index:90; display:flex; flex-direction:column; gap:var(--sp-1);
  max-width:min(440px, calc(100vw - 32px)); pointer-events:none; }
/* Icon, message, close: three columns, so a long message wraps beside its icon
   rather than under it. The kind is carried by the icon's colour; the box is
   the panel's own, with no coloured edge. */
.toasts > .ok, .toasts > .danger { pointer-events:auto; margin:0; display:grid; grid-template-columns:auto 1fr auto;
  align-items:start; column-gap:var(--sp-1);
  background:var(--panel); border:1px solid var(--line); border-radius:var(--radius-md);
  box-shadow:var(--shadow-lg); padding:var(--sp-1) var(--sp-2); animation:toastin .22s ease-out; }
.toasts > .ok > .icon, .toasts > .danger > .icon { margin-top:3px; }
.toasts .toastmsg { min-width:0; }
.toasts .toastmsg:first-child { grid-column:1 / 3; }
.toasts .toastmsg form.inline { margin-left:var(--gap-1); }
.toasts > .ok .icon { color:var(--good); }
.toasts > .danger .icon { color:var(--bad); }
.toasts > .gone { opacity:0; transform:translateY(6px); transition:opacity .25s ease, transform .25s ease; }
.toasts .toastx { all:unset; cursor:pointer; grid-column:3; color:var(--muted); padding:2px 4px; font-size:18px; line-height:1; }
.toasts .toastx::before { content:"\00d7"; }
@keyframes toastin { from { opacity:0; transform:translateY(8px); } to { opacity:1; transform:none; } }
:root[data-motion="reduced"] .toasts > *, :root[data-motion="reduced"] .toasts > .gone { animation:none; transition:none; }
@media (prefers-reduced-motion: reduce) { .toasts > * { animation:none; } }
main.swapping .mainwrap { opacity:.6; transition:opacity .12s ease; }

/* Empty states: a quiet panel with the glyph in a soft disc. */
.empty { background:var(--panel); border:1px dashed var(--line-2); border-radius:var(--radius-lg); }
.empty .emptyicon { width:44px; height:44px; border-radius:50%; align-items:center; justify-content:center;
  background:var(--accent-weak); color:var(--accent); opacity:1; }

/* The overview's top row: three cards on one skeleton (overviewcards.ts), the
   exposure score first. Each is the same rows in the same places, label, figure,
   detail, bar and change, so a row reads straight across the three. */
.ovhero { display:grid; grid-template-columns:repeat(3,minmax(0,1fr)); gap:var(--sp-2); margin:0 0 var(--sp-1); }
.ovhero > a { display:grid; grid-template-rows:auto auto 24px 1fr auto; row-gap:var(--gap-2); align-items:start; min-height:196px;
  padding:var(--sp-2) var(--inset); border-radius:var(--radius-lg); position:relative; text-decoration:none; }
.ovhero > a > .meter { align-self:end; margin:0; height:6px; }
.ovhero > a > .meter i { border-radius:999px; }
.ovhero > a > .meter i + i { border-radius:0 999px 999px 0; }
.ovhero .k { font-size:var(--fs-1); font-weight:600; color:var(--muted); text-transform:uppercase; letter-spacing:.06em; }
.ovhero .v { font-size:56px; font-weight:600; line-height:1; display:block; }
.ovhero .v.nm { font-size:28px; }
.ovhero .s { display:flex; align-items:center; font-size:var(--fs-1); color:var(--muted); }
.ovhero .chg { margin:0; }
.ovhero .hero-score { color:#fff; overflow:hidden; border:1px solid transparent;
  background:radial-gradient(120% 140% at 100% 0%,color-mix(in srgb,var(--accent) 80%,#fff) 0%,color-mix(in srgb,var(--accent) 80%,#000) 45%,color-mix(in srgb,var(--accent) 30%,#000) 100%);
  box-shadow:0 10px 30px -12px rgba(49,46,129,.6); }
.ovhero .hero-score::after { content:""; position:absolute; right:-60px; top:-60px; width:220px; height:220px; border-radius:50%;
  border:1px solid rgba(255,255,255,.14); box-shadow:0 0 0 30px rgba(255,255,255,.03), 0 0 0 60px rgba(255,255,255,.02); }
.ovhero .hero-score .k { color:rgba(255,255,255,.78); }
.ovhero .hero-score .v { color:#fff; }
.ovhero .hero-score .v small { font-size:20px; font-weight:600; color:rgba(255,255,255,.6); margin-left:4px; letter-spacing:0; }
.ovhero .hero-score.rl-unmeasured { --dot:rgba(255,255,255,.5); }
.ovhero .hero-score .lvl { display:inline-flex; justify-self:start; align-items:center; gap:6px; height:24px; padding:0 10px;
  border-radius:999px; background:rgba(255,255,255,.14); font-size:var(--fs-1); font-weight:650; }
.ovhero .hero-score .lvl::before { content:""; width:8px; height:8px; border-radius:50%; background:var(--dot,#fff); }
.ovhero .hero-score .s { color:rgba(255,255,255,.78); }
.ovhero .hero-score .meter { background:rgba(255,255,255,.16); }
.ovhero .hero-score .meter i { background:var(--dot,#fff); }
.ovhero .hero-score.rl-critical { --dot:#ff7a7a; } .ovhero .hero-score.rl-high { --dot:#ffaa5c; }
.ovhero .hero-score.rl-medium { --dot:#ffd54a; } .ovhero .hero-score.rl-low { --dot:#8fbaf0; } .ovhero .hero-score.rl-none { --dot:#7de2d1; }
.ovhero .kpi.urgentkpi:not(.zero) .v { color:var(--crit); }
.ovhero .kpi.kevkpi:not(.zero) .v { color:color-mix(in srgb,var(--high) 70%,var(--ink)); }
.ovhero .kpi .v.nm { color:var(--muted); }
.ovhero .kpi .meter i.crit { background:var(--crit); } .ovhero .kpi .meter i.high { background:var(--high); }
.ovhero .kpi .meter i.kev { background:color-mix(in srgb,var(--high) 70%,var(--ink)); }
.chg { display:inline-flex; align-items:center; gap:var(--gap-1); margin-top:auto; font-size:var(--fs-1); font-weight:600; }
.chg.same { color:var(--muted); font-weight:500; }
.chg.bad { color:var(--crit); } .chg.good { color:var(--good); }
.ovhero .hero-score .chg.same { color:rgba(255,255,255,.7); }
.ovhero .hero-score .chg.bad { color:#ffb0b0; } .ovhero .hero-score .chg.good { color:#a7f3d0; }
/* What the cards count, as short captions under them rather than one long sentence. */
.kpinote { display:flex; flex-wrap:wrap; gap:var(--gap-1) var(--sp-2); }
.trendgrid .ctitle { margin:0 0 var(--gap-1); font-size:var(--fs-2); font-weight:600; }
.trendgrid .sevlegend { margin:0 0 var(--gap-2); }
.sevlegend .dot.unsplit { background:color-mix(in srgb,var(--muted) 35%,transparent); }
/* No measurement yet: the panel keeps its place and its height, and says when the trend starts. */
.trendempty { display:grid; place-items:center; height:180px; border:1px dashed var(--line-2); border-radius:var(--radius);
  color:var(--muted); font-size:var(--fs-1); text-align:center; padding:var(--sp-2); }
@media (max-width:900px) { .ovhero { grid-template-columns:1fr; } .ovhero > a { min-height:0; } }
@media (max-width:560px) { .ovhero .v { font-size:48px; } }
