/* Resilyo — redesigned UI. Deep red on warm neutrals, K2D. Light + dark. */

/* K2D — self-hosted (../fonts/), not fetched from Google Fonts. Keeps the CSP
   first-party (style-src/font-src 'self') and avoids sending every visitor's IP
   to Google (a GDPR concern for an EU compliance product). Only the six upright
   weights the UI uses (300–800); italics/thai/vietnamese are not shipped. Greek
   and Cyrillic (el/bg) have no K2D glyphs and fall back to the system stack, as
   they always did. font-display:swap keeps text visible while the font loads. */
@font-face{font-family:"K2D";font-style:normal;font-weight:300;font-display:swap;src:url("../fonts/k2d-300.ttf") format("truetype")}
@font-face{font-family:"K2D";font-style:normal;font-weight:400;font-display:swap;src:url("../fonts/k2d-400.ttf") format("truetype")}
@font-face{font-family:"K2D";font-style:normal;font-weight:500;font-display:swap;src:url("../fonts/k2d-500.ttf") format("truetype")}
@font-face{font-family:"K2D";font-style:normal;font-weight:600;font-display:swap;src:url("../fonts/k2d-600.ttf") format("truetype")}
@font-face{font-family:"K2D";font-style:normal;font-weight:700;font-display:swap;src:url("../fonts/k2d-700.ttf") format("truetype")}
@font-face{font-family:"K2D";font-style:normal;font-weight:800;font-display:swap;src:url("../fonts/k2d-800.ttf") format("truetype")}

/* color-scheme travels with the tokens in every one of the four blocks below.
   Without it the UA keeps painting its light chrome — the scrollbar gutters
   (page and every overflow:auto panel), the canvas past the content, and the
   native controls (select, search, date) — which frames a dark page in white.
   It has to be repeated per block, not set once: the manual toggle must flip it
   too, or a dark theme chosen on a light OS keeps the light scrollbars. */
:root{
  color-scheme:light;
  --bg:#f6f3f3; --surface:#ffffff; --surface-2:#faf7f7;
  --border:#ece5e5; --border-2:#e0d7d7; --border-strong:#1f1b1b;
  --ink:#1f1b1b; --muted:#6c6363; --faint:#6e6868;
  --brand:#980909; --brand-2:#7a0707; --brand-tint:#fbeded; --on-brand:#fff; --on-brand-2:#fff;
  --logo-product:url(../assets/resilyo-logo-light.png);
  --logo-attribution:url(../assets/resilyo-logo-light.png);
  --ready:#0b6e37; --ready-bg:#e7f6ee;
  --partial:#DAA520; --partial-bg:#fbf1dc;
  --notready:#b3212e; --notready-bg:#fce8ea;
  --critical:#7a0707; --critical-bg:#f6dede;
  --unknown:#6f6a68; --unknown-bg:#efecec;
  --track:#ece6e6;
  --gate-dim:brightness(1);
  --shadow:0 1px 2px rgba(31,27,27,.05),0 3px 10px rgba(31,27,27,.05);
  --shadow-lg:0 10px 40px rgba(31,27,27,.14);
  --radius:12px; --radius-sm:8px;
  --font:"K2D",-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Helvetica,Arial,sans-serif;
  --mono:"SFMono-Regular",ui-monospace,"Cascadia Mono","Roboto Mono",monospace;
}
@media (prefers-color-scheme:dark){
  :root{
    color-scheme:dark;
    --bg:#151212; --surface:#201c1c; --surface-2:#262121;
    --border:#332c2c; --border-2:#3d3535; --border-strong:#6e6262;
    --ink:#f3ecec; --muted:#ab9f9f; --faint:#a09595;
    --brand:#f07a7a; --brand-2:#e56464; --brand-tint:#3a1f1f; --on-brand:#fff; --on-brand-2:#fff;
    --logo-product:url(../assets/resilyo-logo-dark.png);
    --logo-attribution:url(../assets/resilyo-logo-dark.png);
    --ready:#3ac47f; --ready-bg:#16281f;
    --partial:#e3ab44; --partial-bg:#2c2413;
    --notready:#f0707a; --notready-bg:#301a1d;
    --critical:#ff4d5e; --critical-bg:#3a1418;
    --unknown:#8f8785; --unknown-bg:#2a2424;
    --track:#332c2c;
    --gate-dim:brightness(.55) contrast(1.05);
    --shadow:0 1px 2px rgba(0,0,0,.3),0 3px 12px rgba(0,0,0,.3);
    --shadow-lg:0 12px 44px rgba(0,0,0,.5);
  }
}
/* manual override (header toggle) — wins over the system media query in both directions */
:root[data-theme="light"]{
  color-scheme:light;
  --bg:#f6f3f3; --surface:#ffffff; --surface-2:#faf7f7;
  --border:#ece5e5; --border-2:#e0d7d7; --border-strong:#1f1b1b;
  --ink:#1f1b1b; --muted:#6c6363; --faint:#6e6868;
  --brand:#980909; --brand-2:#7a0707; --brand-tint:#fbeded; --on-brand:#fff; --on-brand-2:#fff;
  --logo-product:url(../assets/resilyo-logo-light.png);
  --logo-attribution:url(../assets/resilyo-logo-light.png);
  --ready:#0b6e37; --ready-bg:#e7f6ee; --partial:#DAA520; --partial-bg:#fbf1dc;
  --notready:#b3212e; --notready-bg:#fce8ea; --critical:#7a0707; --critical-bg:#f6dede;
  --unknown:#6f6a68; --unknown-bg:#efecec;
  --track:#ece6e6; --shadow:0 1px 2px rgba(31,27,27,.05),0 3px 10px rgba(31,27,27,.05); --shadow-lg:0 10px 40px rgba(31,27,27,.14);
  --gate-dim:brightness(1);
}
:root[data-theme="dark"]{
  color-scheme:dark;
  --bg:#151212; --surface:#201c1c; --surface-2:#262121;
  --border:#332c2c; --border-2:#3d3535; --border-strong:#6e6262;
  --ink:#f3ecec; --muted:#ab9f9f; --faint:#a09595;
  --brand:#f07a7a; --brand-2:#e56464; --brand-tint:#3a1f1f; --on-brand:#fff; --on-brand-2:#fff;
  --logo-product:url(../assets/resilyo-logo-dark.png);
  --logo-attribution:url(../assets/resilyo-logo-dark.png);
  --ready:#3ac47f; --ready-bg:#16281f; --partial:#e3ab44; --partial-bg:#2c2413;
  --notready:#f0707a; --notready-bg:#301a1d; --critical:#ff4d5e; --critical-bg:#3a1418;
  --unknown:#8f8785; --unknown-bg:#2a2424;
  --track:#332c2c; --shadow:0 1px 2px rgba(0,0,0,.3),0 3px 12px rgba(0,0,0,.3); --shadow-lg:0 12px 44px rgba(0,0,0,.5);
  --gate-dim:brightness(.55) contrast(1.05);
}

*{box-sizing:border-box}
[hidden]{display:none!important}
html,body{margin:0;padding:0;color:var(--ink);font-family:var(--font);font-size:15px;line-height:1.5;-webkit-font-smoothing:antialiased}
/* Footer stays pinned to the bottom of the viewport on short pages instead of
   riding up under sparse content: body is a flex column, the header/nav stay
   their natural size, whichever content section is visible absorbs the extra
   space, and the footer sits after it. */
body{min-height:100vh;display:flex;flex-direction:column}
a{color:var(--brand-2);text-decoration:none}
.tnum{font-variant-numeric:tabular-nums}
:focus-visible{outline:2px solid var(--brand);outline-offset:2px;border-radius:4px}
@media (prefers-reduced-motion:reduce){*{transition:none!important;animation:none!important}}

/* ---------- buttons ---------- */
button{font-family:inherit;font-size:13.5px;cursor:pointer;border:1px solid transparent;border-radius:var(--radius-sm);padding:8px 14px;background:var(--surface);color:var(--ink);transition:background .12s,border-color .12s,transform .05s}
button:active{transform:translateY(1px)}
/* Text colour comes from the background, not a hardcoded #fff — a light brand
   (a yellow, a lime) would otherwise ship an unreadable primary button. Both
   states need their own: :hover swaps the background to --brand-2, which can
   sit the other side of the ink/white threshold. js/brands.js computes them;
   the defaults above keep the house brand exactly as it was. */
.btn-primary{background:var(--brand);color:var(--on-brand);border-color:var(--brand);font-weight:650}
.btn-primary:hover{background:var(--brand-2);color:var(--on-brand-2)}
/* For "this step is done, successfully" rather than "this needs attention
   now" — e.g. Readiness assessment once an analysis has run and there is a
   report to download. A light tint + colored border/text, same family as
   the .r-ready / .pill.direct badges elsewhere, so a completed, clickable
   step reads as a confirmation chip rather than a loud CTA. */
.btn-success{background:var(--ready-bg);color:var(--ready);border-color:var(--ready);font-weight:650}
.btn-success:hover{background:color-mix(in srgb,var(--ready-bg) 60%,var(--ready) 12%)}
.btn-outline{border-color:var(--border-2);background:var(--surface);font-weight:600}
.btn-outline:hover{background:var(--surface-2)}
/* Disabled button: lighter, inert, and no hover lift — the affordance has to go
   with the ability, or the click just fails silently. Same weight as
   .fw-tile[disabled] below so the two read as one state across the app. The
   hover rules restate each variant's resting background because the base
   :hover above would otherwise still fire on a disabled button. */
.btn-outline[disabled],.btn-primary[disabled],.btn-success[disabled],.btn-danger[disabled]{opacity:.5;cursor:not-allowed}
.btn-outline[disabled]:hover{background:var(--surface)}
.btn-primary[disabled]:hover{background:var(--brand);color:var(--on-brand)}
.btn-success[disabled]:hover{background:var(--ready-bg);color:var(--ready)}
.btn-danger[disabled]:hover{background:var(--notready-bg);filter:none}
.btn-outline[disabled]:active,.btn-primary[disabled]:active,.btn-success[disabled]:active,.btn-danger[disabled]:active{transform:none}
/* Same lighter look as [disabled] above, but for a step that is merely not
   reached yet rather than actually blocked — the button stays clickable
   (e.g. Readiness assessment before an analysis has run). */
.btn-dim{opacity:.5}
.btn-danger{color:var(--notready);border-color:color-mix(in srgb,var(--notready) 40%,transparent);background:var(--notready-bg)}
.btn-danger:hover{filter:brightness(.97)}
.btn-lg{padding:11px 20px;font-size:15px}

/* ---------- header ---------- */
/* .app-header is a plain block; .header-content is the ordinary centered-block
   pattern used everywhere else (main, .fw-top) rather than a flex item relying
   on auto-margins to override a stretch parent — logo-left/menu-right/vertical
   centering all live on .header-brands, one unambiguous rule each. */
.header-content{max-width:1300px;margin:0 auto}
.app-header{background:var(--surface);color:var(--ink);padding:11px 24px;flex:0 0 auto;
  border-bottom:3px solid var(--brand);box-shadow:var(--shadow);position:sticky;top:0;z-index:50}
.header-brands{display:flex;align-items:center;justify-content:space-between;gap:12px;width:100%}
.header-right{display:flex;align-items:center;gap:28px;min-width:0}
.tenant-switch{display:flex;align-items:center;min-width:0}
.tenant-switch:empty{display:none}
.brand-lockup{display:flex;align-items:center}
/* Shared trigger style for the three header items (tenant, help, account) —
   the same visual language as the tier-1 nav tabs (.cat, below): muted at
   rest, ink on hover with a soft chip, brand red + underline bar when open. */
.hdr-link{display:inline-flex;align-items:center;gap:5px;font:inherit;font-size:14.5px;font-weight:700;
  color:var(--muted);background:transparent;border:0;padding:4px 1px;border-radius:6px;
  position:relative;cursor:pointer;text-decoration:none;line-height:1.2}
.hdr-link:hover{color:var(--ink)}
.hdr-link[aria-expanded="true"]{color:var(--brand);background:transparent}
.hdr-link[aria-expanded="true"]::after{content:"";position:absolute;left:1px;right:1px;bottom:-1px;
  height:3px;background:var(--brand);border-radius:3px 3px 0 0}
.hdr-caret{font-size:11px;color:inherit}
/* Dropdown panel shared by the tenant switcher and the account menu — same
   card, same list-item pattern, so both read as one component. */
.tenant-dd{position:relative}
.dd-panel{position:absolute;left:0;top:calc(100% + 6px);min-width:200px;background:var(--surface);
  border:1px solid var(--border);border-radius:12px;box-shadow:var(--shadow-lg);padding:8px;z-index:60;
  display:flex;flex-direction:column;gap:2px;max-height:60vh;overflow-y:auto}
.dd-panel[hidden]{display:none}
.dd-item{display:flex;align-items:center;justify-content:space-between;gap:10px;width:100%;text-align:left;
  border:0;background:transparent;padding:9px 10px;border-radius:8px;font-weight:600;font-size:13.5px;
  color:var(--ink);cursor:pointer;font-family:inherit}
.dd-item:hover{background:var(--surface-2)}
.dd-item.is-active{background:var(--brand-tint);color:var(--brand)}
.dd-check{font-size:13px}
/* user menu (header top-right) — content-specific rules only; shape/color/
   hover/open states come from .hdr-link on the button itself. */
.user-menu{position:relative}
.user-menu-btn{gap:6px;max-width:230px}
.user-menu-btn .um-id{display:flex;flex-direction:column;align-items:flex-end;line-height:1.15;overflow:hidden}
.user-menu-btn .uname{font:inherit;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;max-width:180px}
.user-menu-btn .utenant{font-size:11px;color:var(--muted);white-space:nowrap;overflow:hidden;text-overflow:ellipsis;max-width:180px}
.user-menu-btn .um-caret{color:inherit;font-size:11px;flex:none}
.user-menu-panel{position:absolute;right:0;top:calc(100% + 6px);min-width:236px;background:var(--surface);border:1px solid var(--border);border-radius:12px;box-shadow:var(--shadow-lg);padding:10px;z-index:60;display:flex;flex-direction:column;gap:10px}
.user-menu-panel[hidden]{display:none}
.umenu-auth .um-full{width:100%;justify-content:center}
.umenu-row{display:flex;align-items:center;justify-content:space-between;gap:12px}
.umenu-label{font-size:12.5px;color:var(--muted)}
.umenu-row .lang-select{min-width:118px}
.umenu-items{display:flex;flex-direction:column;gap:3px;border-top:1px solid var(--border);padding-top:8px;margin-top:2px}
.umenu-items[hidden]{display:none}
#umenu-dyn{display:flex;flex-direction:column;gap:3px}
#umenu-dyn:empty{display:none}
.umenu-item{width:100%;justify-content:flex-start;text-align:left;border:0;background:transparent;padding:8px;border-radius:8px;font-weight:600;font-size:13px}
.umenu-item:hover{background:var(--surface-2)}
.umenu-auth{border-top:1px solid var(--border);padding-top:8px;margin-top:2px}
/* No house (vendor) mark in the chrome: the product wordmark is the only logo.
   Partner packs may still carry a house logo; it is used in generated reports
   only (see ReportBrand in js/brands.js). */
/* theme toggle button */
#btn-theme{font-size:15px;line-height:1;padding:7px 10px;min-width:38px;min-width: 118px;}
.brand-divider{width:1px;align-self:stretch;background:var(--border-2);margin:2px}
/* Product mark + the workspace's own logo, side by side. */
.product{display:flex;align-items:center;gap:14px;min-width:0}
.customer-brand{display:flex;align-items:center;gap:14px;min-width:0}
.customer-brand[hidden]{display:none}
.customer-logo{height:30px;width:auto;max-width:210px;object-fit:contain;display:block}
.wslogo-preview{display:flex;align-items:center;justify-content:center;min-height:74px;margin:4px 0 14px;
  border:1px dashed var(--border-2);border-radius:10px;background:var(--surface-2);color:var(--muted);font-size:12.5px}
.wslogo-preview img{max-height:56px;max-width:80%;object-fit:contain}
.product h1{font-size:19px;margin:0;font-weight:800;color:var(--ink);line-height:1.05;letter-spacing:-.01em}
.product h1 .resilio-logo{height:35px;width:auto;display:block}
.login-card h2 .resilio-logo{height:38px;width:auto;display:inline-block;vertical-align:middle}
/* Product logo — theme-swapped via --logo-product */
.resilio-logo{content:var(--logo-product)}
/* ---------- branding console (provider admin) ---------- */
/* .modal sets max-width:560px further down the file, so this needs the extra
   class to win on specificity rather than on source order. */
.modal.modal-wide{max-width:1020px}
.brand-admin{display:grid;grid-template-columns:264px 1fr;gap:18px;align-items:start}
.brand-list{display:flex;flex-direction:column;gap:6px;max-height:62vh;overflow:auto}
.brand-pick{display:grid;grid-template-columns:14px 1fr auto;gap:8px;align-items:center;text-align:left;padding:9px 10px}
.brand-pick.on{border-color:var(--brand);background:var(--brand-tint)}
.bp-swatch{width:14px;height:14px;border-radius:4px;border:1px solid var(--border-2)}
.bp-name{font-weight:700;font-size:13px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.bp-hosts{grid-column:2;font-size:10.5px;color:var(--muted);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.bp-off{font-size:10px;font-weight:700;color:var(--muted);text-transform:uppercase}
.bp-warn{color:var(--partial);font-size:14px}
.bf-grid{display:grid;grid-template-columns:1fr 1fr;gap:14px;max-height:62vh;overflow:auto;padding-right:4px}
.bf-grid fieldset{border:1px solid var(--border);border-radius:10px;padding:10px 12px 12px;margin:0}
.bf-grid legend{font-size:11px;font-weight:700;text-transform:uppercase;letter-spacing:.05em;color:var(--muted);padding:0 4px}
.bf-wide{grid-column:1/-1}
.bf-row{display:grid;grid-template-columns:112px 1fr;gap:8px;align-items:center;margin-top:7px;font-size:12.5px}
.bf-row>span{color:var(--muted)}
.bf-row input{padding:6px 8px;border:1px solid var(--border-2);border-radius:7px;background:var(--surface);color:var(--ink);font:inherit;font-size:12.5px;min-width:0}
.bf-row input:disabled{color:var(--muted);background:var(--surface-2)}
.bf-hex{grid-template-columns:112px 1fr 22px}
.bf-swatch{width:22px;height:22px;border-radius:6px;border:1px solid var(--border-2)}
.bf-check{display:grid;grid-template-columns:auto 1fr;gap:7px;align-items:center;margin-top:8px;font-size:12.5px}
.bf-check em{grid-column:2;font-style:normal;font-size:11px;color:var(--muted)}
.bf-logos{display:grid;grid-template-columns:1fr 1fr;gap:10px;margin-top:8px}
.bf-logo{display:grid;gap:3px;font-size:12px}
.bf-logo-label{font-weight:600}
.bf-logo-state{font-size:11px;color:var(--muted)}
.bf-logo input{font-size:11px}
.bf-note{font-size:11px;color:var(--muted);margin:10px 0 0}
.bf-warnings{border:1px solid color-mix(in srgb,var(--partial) 40%,transparent);background:var(--partial-bg);border-radius:10px;padding:10px 12px;font-size:12px}
.bf-warnings ul{margin:6px 0 0;padding-left:18px}
.bf-actions{display:flex;gap:8px;justify-content:flex-end}
@media (max-width:860px){.brand-admin{grid-template-columns:1fr}.bf-grid{grid-template-columns:1fr}}

/* Retained product attribution under a partner brand: the Resilyo wordmark with
   its ™. --logo-attribution is the vendor's own mark in every pack — brand packs
   override --logo-product, never this one, so attribution cannot be skinned away. */
.powered-by{display:flex;align-items:center;gap:9px;margin-top:12px;font-size:11px;color:var(--muted)}
.login-card .powered-by{justify-content:center;margin-top:22px}
.powered-by[hidden]{display:none}
.pb-mark{display:inline-flex;align-items:flex-start;gap:1px}
.powered-logo{content:var(--logo-attribution);height:15px;width:auto;display:block;opacity:.85}
/* Scaled off the wordmark rather than the 11px label so it reads as part of the
   mark, and raised to sit against the cap line instead of the baseline. */
.pb-tm{font-size:7.5px;line-height:1;margin-top:1px;opacity:.85}
.product .tagline{font-size:12px;color:var(--muted);margin-top:1px;max-width:520px}
.header-spacer{flex:1}
.lang-select{padding:7px 8px;border:1px solid var(--border-2);border-radius:8px;background:var(--surface);color:var(--ink);font-family:inherit;font-size:13px;cursor:pointer}
.user-chip{display:flex;flex-direction:column;align-items:flex-end;line-height:1.15}
.user-chip .uname{font-size:13px;font-weight:700}
.user-chip .utenant{font-size:11px;color:var(--muted)}

/* ---------- login / ws gate ---------- */
.login-gate{min-height:72vh;display:grid;place-items:center;padding:40px 20px;flex:1 0 auto;position:relative;overflow:hidden}
/* Ambient backdrop: blurred product screenshots and sales-deck slides
   crossfading behind the login card, slideshow-style. gate-init.js injects the
   markup only when it reveals the gate, so a signed-in session never downloads
   the images. Sources are 1280px-wide thumbnails (~75 KB each) so the softness
   comes purely from blur(3px), not upscaling: headlines shimmer through and UI
   shapes like the readiness donuts and framework cards read clearly.
   --gate-dim keeps the mostly-light shots from glowing in dark theme. */
.gate-bg{position:absolute;inset:0;overflow:hidden;pointer-events:none}
.gate-bg img{position:absolute;top:-4%;left:-4%;width:108%;height:108%;object-fit:cover;
  filter:blur(3px) saturate(1.1) var(--gate-dim);opacity:0;animation:gate-slide 42s linear infinite}
/* Base opacity above is 0 so slides only appear via the animation; the global
   prefers-reduced-motion rule kills all animations, which would blank the
   backdrop entirely — this keeps the first slide as a static backdrop there.
   While animations run, the keyframed opacity overrides it. */
.gate-bg img:first-child{opacity:.55}
.gate-bg img:nth-child(2){animation-delay:7s}
.gate-bg img:nth-child(3){animation-delay:14s}
.gate-bg img:nth-child(4){animation-delay:21s}
.gate-bg img:nth-child(5){animation-delay:28s}
.gate-bg img:nth-child(6){animation-delay:35s}
/* 6 slides × 7s: fade in, hold, drift-zoom out; each slide owns ~22% of the
   cycle so consecutive slides overlap during the crossfade. */
@keyframes gate-slide{
  0%{opacity:0;transform:scale(1)}
  4%{opacity:.55}
  17%{opacity:.55}
  22%{opacity:0;transform:scale(1.1)}
  100%{opacity:0;transform:scale(1.1)}
}
/* Vignette to the page background so the backdrop melts into header/footer
   instead of ending at a hard edge. */
.gate-bg::after{content:"";position:absolute;inset:0;background:radial-gradient(ellipse at center,transparent 30%,var(--bg) 92%)}
.login-card{position:relative;background:var(--surface);border:1px solid var(--border);border-top:4px solid var(--brand);border-radius:16px;box-shadow:var(--shadow-lg);padding:38px 34px;max-width:430px;text-align:center}
.login-card h2{margin:0 0 11px;font-size:23px;color:var(--ink);font-weight:800}
.login-card p{color:var(--muted);font-size:14px;margin:0 0 22px}
.login-card p.login-signup-hint{margin:22px 0 0;font-size:12px}
.login-signup-hint a{color:var(--brand);font-weight:600;text-decoration:none}
.login-signup-hint a:hover{text-decoration:underline}
.ms-logo{display:inline-block;width:16px;height:16px;vertical-align:-2px;margin-right:6px;
  background:linear-gradient(#f25022 0 0) 0 0/7px 7px no-repeat,linear-gradient(#7fba00 0 0) 9px 0/7px 7px no-repeat,linear-gradient(#00a4ef 0 0) 0 9px/7px 7px no-repeat,linear-gradient(#ffb900 0 0) 9px 9px/7px 7px no-repeat}

/* ---------- framework pane ---------- */
.fw-pane{background:var(--surface);position:sticky;top:65px;z-index:40;flex:0 0 auto}
/* Tier 1 (Compliance frameworks / Financial audit) shares this bar with the
   action buttons — the selected .cat pill sits on it as a raised white tab
   (see .cat[aria-selected="true"] below), same trick .fw[aria-current="true"]
   uses elsewhere. Tier 2 (.fw-groups: markets/domains) gets its own plain
   row underneath instead, since it isn't paired with any actions. */
.fw-top{display:flex;align-items:center;justify-content:space-between;gap:16px;max-width:1300px;margin:0 auto;padding:10px 24px 0;border-radius:8px;}
.fw-cats{display:flex;gap:2px;flex:1 1 auto;min-width:0}
.fw-groups{display:flex;gap:4px;flex-wrap:wrap;max-width:1300px;margin:0 auto;padding:14px 24px 0;background:var(--bg);}
.fw-actions{display:flex;gap:8px;flex:0 0 auto;padding-bottom: 10px;}
.cat{border:0;background:transparent;color:var(--muted);font-size:14.5px;font-weight:700;padding:11px 14px 10px;position:relative;border-radius:8px 8px 0 0;display:flex;align-items:center;gap:2px;background:var(--bg);margin-bottom: -15px;}
.cat:hover{color:var(--ink);background:var(--surface-2)}
.cat[aria-selected="true"]{color:var(--brand);padding:11px 20px;background:var(--bg);}
.cat[aria-selected="false"]{opacity: 0.5;}
/* Action + the state it depends on, stacked. The sub-label is the same element
   in both states, so the button does not change height as the count arrives. */
.btn-2l{display:flex;flex-direction:column;align-items:center;justify-content:center;gap:1px;line-height:1.2;padding:7px 14px;text-align:center}
.btn-2l-t{font-size:13px;font-weight:650}
.btn-2l-s{font-size:10.5px;font-weight:600;opacity:.72;min-height:13px}
.grp{border:0;background:transparent;color:var(--muted);font-size:13.5px;font-weight:650;padding:8px 13px 14px;position:relative;border-radius:8px 8px 0 0;display:flex;align-items:center;gap:8px}
.grp:hover{color:var(--ink);background:var(--surface-2)}
.grp .n{background:var(--track);color:var(--muted);font-size:11px;font-weight:700;padding:1px 7px;border-radius:999px}
.grp[aria-selected="true"]{color:var(--brand)}
.grp[aria-selected="true"] .n{background:var(--brand-tint);color:var(--brand)}
.grp[aria-selected="true"]::after{content:"";position:absolute;left:8px;right:8px;bottom:0;height:3px;background:var(--brand);border-radius:3px 3px 0 0}
.fw-strip{max-width:1300px;margin:0 auto;padding:12px 24px 13px;display:flex;gap:9px;overflow-x:auto;scrollbar-width:thin;background-color: var(--bg);}
.fw-strip::-webkit-scrollbar{height:6px}.fw-strip::-webkit-scrollbar-thumb{background:var(--border-2);border-radius:6px}
.fw-dom{flex:0 0 auto;align-self:center;color:var(--muted);font-size:10.5px;font-weight:750;text-transform:uppercase;letter-spacing:.07em;white-space:nowrap;padding:0 3px 0 14px;border-left:1px solid var(--border-2)}
.fw-dom:first-child{padding-left:2px;border-left:0}
.fw{flex:none;display:flex;align-items:center;gap:10px;padding:8px 14px 8px 9px;border:1px solid var(--border-2);border-radius:999px;background:var(--surface);transition:border-color .12s,background .12s}
.fw:hover{background:var(--surface-2)}
.fw[aria-current="true"]{border-color:var(--brand);background:var(--brand-tint)}
.fw.out{opacity:.6}
.fw-txt{display:flex;flex-direction:column;line-height:1.2;text-align:left}
.fw .fname{font-size:13.5px;font-weight:650;white-space:nowrap}
.fw .fmeta{font-size:10.5px;color:var(--faint);white-space:nowrap}
.beta-tag{display:inline-block;margin-left:6px;padding:1px 6px;border-radius:9px;font-size:9.5px;font-weight:700;
  letter-spacing:.4px;text-transform:uppercase;vertical-align:middle;color:var(--brand);
  background:var(--brand-tint);border:1px solid var(--brand)}
.ring{--p:0;--c:var(--ready);width:32px;height:32px;border-radius:50%;flex:none;position:relative;display:grid;place-items:center;
  background:conic-gradient(var(--c) calc(var(--p)*1%),var(--track) 0)}
.ring::after{content:"";position:absolute;inset:3px;border-radius:50%;background:var(--surface)}
.fw[aria-current="true"] .ring::after{background:var(--brand-tint)}
.ring b{position:relative;z-index:1;font-size:10px;font-weight:800;color:var(--ink)}

/* ---------- toolbar ---------- */
main{max-width:1300px;margin:0 auto;flex:1 0 auto;width:100%;display:flex;flex-direction:column}
.toolbar{display:flex;flex-wrap:wrap;gap:10px;align-items:center;margin-bottom:12px}
.searchbox{flex:1;min-width:230px;max-width:360px;position:relative;display:flex;align-items:center}
.searchbox svg{position:absolute;left:12px;color:var(--faint)}
.searchbox input{width:100%;padding:9px 12px 9px 34px;border:1px solid var(--border-2);border-radius:999px;background:var(--surface);color:var(--ink);font-family:inherit;font-size:13.5px}
.toolbar select{padding:9px 10px;border:1px solid var(--border-2);border-radius:8px;font-size:13.5px;background:var(--surface);color:var(--ink);font-family:inherit}
.tb-label{font-size:12px;color:var(--muted);margin-left:auto;font-weight:600}
.profile-note{font-size:12px;color:var(--muted);flex-basis:100%}
.profile-note:empty{display:none}
.appl-pills{display:flex;flex-wrap:wrap;gap:6px;margin-bottom:14px}
.appl-pills:empty{display:none}
.pill{font-size:11.5px;font-weight:600;padding:3px 10px;border-radius:999px;border:1px solid var(--border)}
.pill.direct{background:var(--ready-bg);color:var(--ready);border-color:transparent}
.pill.conditional{background:var(--partial-bg);color:var(--partial);border-color:transparent}
.pill.out{background:var(--unknown-bg);color:var(--muted);border-color:transparent}

/* ---------- work layout ---------- */
.work{display:grid;grid-template-columns:1fr 400px;gap:20px;align-items:start}
@media (max-width:1000px){.work{grid-template-columns:1fr}}
.work-main{min-width:0}
.card{background:var(--surface);border:1px solid var(--border);border-radius:var(--radius);box-shadow:var(--shadow)}

/* summary */
.summary{display:flex;gap:22px;align-items:center;padding:18px 20px;margin-bottom:16px}
.donut{--p:0;--c:var(--ready);width:76px;height:76px;border-radius:50%;flex:none;position:relative;background:conic-gradient(var(--c) calc(var(--p)*1%),var(--track) 0)}
.donut.big{width:104px;height:104px}
.donut::after{content:"";position:absolute;inset:9px;border-radius:50%;background:var(--surface)}
.donut.big::after{inset:11px}
.donut .d-lbl{position:absolute;inset:0;display:grid;place-content:center;text-align:center;z-index:1}
.donut .d-lbl b{font-size:18px;font-weight:800;letter-spacing:-.02em}
.donut.big .d-lbl b{font-size:25px}
.donut .d-lbl span{display:block;font-size:8.5px;font-weight:700;color:var(--faint);text-transform:uppercase;letter-spacing:.05em}
.donut.big .d-lbl span{font-size:9.5px}
.sum-body{flex:1;min-width:0}
.sum-head{display:flex;align-items:baseline;gap:9px;margin-bottom:4px;flex-wrap:wrap}
.sum-head h2{font-size:18px;font-weight:750;margin:0;letter-spacing:-.01em}
.sum-head .full{font-size:12px;color:var(--muted)}
.sum-sub{font-size:12.5px;color:var(--muted);margin-bottom:12px}
.sum-sub b{color:var(--ink);font-weight:700}
.segbar{height:9px;border-radius:6px;overflow:hidden;display:flex;margin-bottom:11px;background:var(--track)}
.segbar i{display:block;height:100%}
.legend{display:flex;flex-wrap:wrap;gap:7px}
.lg{display:inline-flex;align-items:center;gap:6px;font-size:12px;font-weight:600;padding:4px 9px;border-radius:999px;border:1px solid var(--border)}
.lg .ld{width:8px;height:8px;border-radius:50%}
.lg .c{color:var(--faint);font-weight:700}

/* listhead */
.listhead{display:flex;align-items:center;gap:10px;padding:2px 4px 12px}
.listhead:empty{display:none}
.listhead h3{font-size:12px;font-weight:750;text-transform:uppercase;letter-spacing:.06em;color:var(--muted);margin:0}
.lh-count{font-size:12px;color:var(--faint);font-weight:700}

/* control rows */
.controls{display:flex;flex-direction:column;gap:9px}
.ctrl{display:grid;grid-template-columns:auto 1fr auto auto;gap:13px;align-items:center;padding:13px 15px;background:var(--surface);border:1px solid var(--border);border-radius:var(--radius);box-shadow:var(--shadow);cursor:pointer;transition:border-color .12s,box-shadow .12s}
.ctrl:hover{border-color:var(--border-2);box-shadow:var(--shadow-lg)}
.ctrl.sel{border-color:var(--brand);box-shadow:0 0 0 1px var(--brand) inset,var(--shadow)}
.badge{display:inline-flex;align-items:center;gap:7px;padding:5px 11px;border-radius:999px;font-size:12px;font-weight:700;white-space:nowrap}
.badge .bd{width:8px;height:8px;border-radius:50%}
.r-ready{background:var(--ready-bg);color:var(--ready)}.r-ready .bd{background:var(--ready)}
.r-partial{background:var(--partial-bg);color:var(--partial)}.r-partial .bd{background:var(--partial)}
.r-notready{background:var(--notready-bg);color:var(--notready)}.r-notready .bd{background:var(--notready)}
.r-unknown{background:var(--unknown-bg);color:var(--muted)}.r-unknown .bd{background:var(--unknown)}
.r-na{background:var(--unknown-bg);color:var(--muted)}.r-na .bd{background:var(--unknown)}
.c-mid{min-width:0}
.c-top{display:flex;align-items:center;gap:9px;margin-bottom:3px}
.cref{font-family:var(--mono);font-size:11px;font-weight:700;color:var(--brand);background:var(--brand-tint);padding:1px 7px;border-radius:5px;white-space:nowrap}
.ctitle{font-size:14.5px;font-weight:650;letter-spacing:-.005em;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.c-meta{display:flex;align-items:center;gap:8px;font-size:12px;color:var(--muted);flex-wrap:wrap}
.dotsep{width:3px;height:3px;border-radius:50%;background:var(--faint);flex:none}
.xlink{color:var(--brand);font-weight:650;cursor:pointer}
.xlink:hover{text-decoration:underline}
.src{display:inline-flex;align-items:center;gap:4px;font-size:10.5px;font-weight:700;color:var(--faint);text-transform:uppercase;letter-spacing:.03em}
.src svg{width:12px;height:12px}
.c-right{display:flex;flex-direction:column;align-items:flex-end;gap:6px}
.rmeta{font-size:11px;color:var(--faint);font-weight:600}
.mtrack{width:64px;height:5px;border-radius:4px;background:var(--track);overflow:hidden}
.mtrack i{display:block;height:100%;background:var(--brand);border-radius:4px}
.chev{color:var(--faint);font-size:18px}
/* The 4-column row (badge/mid/right/chev) has nowhere to put that width on
   a phone screen — text was overflowing past the card edge rather than
   wrapping. Stacked instead, status on top: badge is already the first
   child, so a single column puts it there for free. */
@media (max-width:640px){
  .ctrl{grid-template-columns:1fr}
  .c-top{flex-wrap:wrap}
  .cref{white-space:normal}
  .ctitle{white-space:normal;overflow:visible;text-overflow:clip}
  .c-right{flex-direction:row;align-items:center;width:100%}
  .c-right .mtrack{flex:1;width:auto}
  .chev{justify-self:end}
}
.empty{padding:40px;text-align:center;color:var(--muted);background:var(--surface);border:1px dashed var(--border-2);border-radius:var(--radius)}

/* overview tiles */
.fw-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(240px,1fr));gap:12px}
.fw-tile{display:flex;gap:14px;align-items:center;text-align:left;padding:15px 16px;background:var(--surface);border:1px solid var(--border);border-radius:var(--radius);box-shadow:var(--shadow)}
.fw-tile:hover:not([disabled]){border-color:var(--brand);box-shadow:var(--shadow-lg)}
.fw-tile[disabled]{opacity:.5;cursor:default}
.ft-body{min-width:0;flex:1}
.ft-name{font-size:14.5px;font-weight:700}
.ft-meta{font-size:11.5px;color:var(--muted);margin:2px 0 8px}

/* ---------- detail panel ---------- */
.detail{position:sticky;top:150px;min-height:200px}
@media (max-width:1000px){
  .detail{position:static}
  /* No control picked yet: on desktop this is a side panel with room to
     spare, but stacked full-width below the list on mobile it's just a
     tall empty card the operator has to scroll past. */
  .detail:not(.has){display:none}
}
.dt-empty{display:grid;place-content:center;text-align:center;padding:56px 26px;color:var(--muted)}
.dt-empty-ic{width:40px;height:40px;margin:0 auto 12px;color:var(--faint)}
.dt-empty p{font-size:13.5px;margin:0}
.dt-head{padding:17px 20px 15px;border-bottom:1px solid var(--border)}
.crumb{display:flex;align-items:center;gap:5px;font-size:11.5px;color:var(--muted);margin-bottom:10px;flex-wrap:wrap}
.crumb a{color:var(--brand);font-weight:650;cursor:pointer}.crumb a:hover{text-decoration:underline}
.crumb svg{width:13px;height:13px;color:var(--faint)}
.dt-title{font-size:16.5px;font-weight:750;letter-spacing:-.01em;margin:0 0 11px;text-wrap:balance}
.dt-badges{display:flex;align-items:center;gap:9px;flex-wrap:wrap}
.conf{font-size:11.5px;color:var(--muted);font-weight:600}
.dt-x{margin-left:auto;width:28px;height:28px;padding:0;display:grid;place-items:center;border:1px solid var(--border-2);color:var(--muted);border-radius:8px;font-size:13px}
/* On mobile the list and detail are stacked, not side-by-side, and closing
   now hides the detail card outright (see .detail:not(.has) above) — the
   operator scrolls back to the list instead, so this button has nothing
   left to usefully do there. */
@media (max-width:640px){.dt-x{display:none}}
.dt-body{padding:16px 20px 22px}
.field{margin-bottom:15px}
.field h4{font-size:10.5px;font-weight:750;text-transform:uppercase;letter-spacing:.07em;color:var(--faint);margin:0 0 5px}
.field p{margin:0;font-size:13.5px;line-height:1.55}
.mono-sm{font-family:var(--mono);font-size:12px;color:var(--muted)}
.muted-sm{color:var(--faint);font-size:12.5px}
.kv{display:flex;gap:18px}.kv .field{flex:1;margin-bottom:0}
.relief{background:var(--partial-bg);border-radius:var(--radius-sm);padding:10px 12px;font-size:12.5px;margin-bottom:15px}
.steps{list-style:none;margin:0;padding:0;display:flex;flex-direction:column;gap:8px}
.steps li{font-size:13px;line-height:1.45}
.ck-lb{display:flex;gap:10px;align-items:flex-start;cursor:pointer;position:relative}
.ck-lb input{position:absolute;opacity:0;width:0;height:0}
.ck{width:18px;height:18px;border-radius:5px;flex:none;margin-top:1px;border:1.5px solid var(--border-2);background:var(--surface);display:grid;place-items:center;transition:background .12s}
.ck::after{content:"";width:9px;height:5px;border-left:2px solid #fff;border-bottom:2px solid #fff;transform:rotate(-45deg) translate(0,-1px);opacity:0}
.ck-lb input:checked+.ck{background:var(--ready);border-color:var(--ready)}
.ck-lb input:checked+.ck::after{opacity:1}
.ck-lb input:disabled+.ck{opacity:.5}
.steps li.done .ck-t{color:var(--muted)}
.evlist{margin:0;padding-left:18px;font-size:13px;color:var(--ink)}.evlist li{margin-bottom:3px}
.divider{height:1px;background:var(--border);margin:17px 0}
.rec{background:var(--partial-bg);border:1px solid color-mix(in srgb,var(--partial) 26%,transparent);border-radius:var(--radius-sm);padding:13px 14px}
.rec p{margin:0 0 9px;font-size:13px;line-height:1.5}
.gaps{list-style:none;margin:0 0 9px;padding:0;display:flex;flex-direction:column;gap:6px}
.gaps li{position:relative;padding-left:15px;font-size:12.5px}
.gaps li::before{content:"";position:absolute;left:2px;top:7px;width:5px;height:5px;border-radius:50%;background:var(--partial)}
.rec-docs{display:flex;flex-wrap:wrap;gap:6px}
.doc-chip{display:inline-flex;align-items:center;gap:5px;font-size:11px;font-weight:600;padding:3px 8px;border-radius:6px;background:var(--surface);border:1px solid var(--border);color:var(--muted)}
.doc-chip svg{width:11px;height:11px}
.doc-chip-open{font-family:inherit;cursor:pointer}
.doc-chip-open:hover{color:var(--brand);border-color:var(--brand)}
.rec-hint{display:flex;align-items:center;gap:8px;font-size:12.5px;color:var(--muted);background:var(--surface-2);border-radius:var(--radius-sm);padding:11px 13px}
.rec-hint svg{width:15px;height:15px;color:var(--faint);flex:none}
.audit{margin-top:2px}
.audit-h{font-size:12px;font-weight:750;text-transform:uppercase;letter-spacing:.06em;color:var(--muted);margin-bottom:11px;display:flex;align-items:center;gap:9px}
.flash{color:var(--ready);font-size:11px;font-weight:700;opacity:0;transition:opacity .2s;text-transform:none;letter-spacing:0}
.flash.show{opacity:1}
.audit-grid{display:grid;grid-template-columns:1fr 1fr;gap:11px}
@media (max-width:640px){.audit-grid{grid-template-columns:1fr}}
.af{display:flex;flex-direction:column;gap:4px}
.af.full{grid-column:1/-1}
.af span{font-size:11px;font-weight:600;color:var(--muted)}
.af input,.af select,.af textarea{width:100%;padding:8px 10px;border:1px solid var(--border-2);border-radius:var(--radius-sm);background:var(--surface);color:var(--ink);font-family:inherit;font-size:13px}
.af textarea{min-height:64px;resize:vertical}
.af :disabled{opacity:.6;cursor:not-allowed}

/* ---------- modals ---------- */
.modal-overlay{position:fixed;inset:0;background:rgba(20,16,16,.5);display:grid;place-items:center;z-index:100;padding:20px}
.modal{background:var(--surface);border:1px solid var(--border);border-radius:16px;box-shadow:var(--shadow-lg);width:100%;max-width:560px;max-height:86vh;overflow:auto;padding:22px 24px}
.modal-wide{max-width:820px}
.modal-head{display:flex;align-items:center;justify-content:space-between;margin-bottom:6px}
.modal-head h3{margin:0;font-size:18px;font-weight:750}
.modal-close{border:0;background:transparent;font-size:16px;color:var(--muted);padding:6px}
.modal-sub{color:var(--muted);font-size:13px;margin:0 0 16px}
.roles-add{display:flex;gap:8px;flex-wrap:wrap;margin-bottom:16px}
.roles-add input,.roles-add select{padding:8px 11px;border:1px solid var(--border-2);border-radius:8px;background:var(--surface);color:var(--ink);font-family:inherit;font-size:13.5px;flex:1;min-width:130px}
.roles-list{display:flex;flex-direction:column;gap:7px}
.role-row{display:flex;align-items:center;gap:10px;padding:9px 12px;border:1px solid var(--border);border-radius:var(--radius-sm);background:var(--surface-2);flex-wrap:wrap}
.role-row .re{font-weight:650;font-size:13.5px;flex:1;min-width:140px}
.role-row .rf{font-size:12.5px;color:var(--muted)}
.role-row .rr{font-size:12.5px;font-weight:600}
.ws-rr{display:flex;gap:6px;flex-wrap:wrap}
.roles-legend{margin-top:16px;padding-top:14px;border-top:1px solid var(--border)}
.roles-legend h4{margin:0 0 8px;font-size:12px;text-transform:uppercase;letter-spacing:.05em;color:var(--muted)}
.lg-row{font-size:12.5px;color:var(--muted);margin-bottom:5px}.lg-row b{color:var(--ink)}
.muted{color:var(--muted);font-size:13px;padding:8px 2px}
.ws-ai.on{color:var(--ready);border-color:color-mix(in srgb,var(--ready) 40%,transparent)}
.fw-pick-actions{display:flex;gap:8px;margin-bottom:12px}
.fw-pick{display:grid;grid-template-columns:repeat(auto-fill,minmax(200px,1fr));gap:14px}
.fw-grp h5{margin:0 0 6px;font-size:11px;text-transform:uppercase;letter-spacing:.05em;color:var(--muted)}
.fw-opt{display:flex;align-items:center;gap:7px;font-size:13px;padding:3px 0}

/* ---------- AI modal (ai.js) ---------- */
.ai-drop{border:2px dashed var(--border-2);border-radius:var(--radius);padding:26px;text-align:center;color:var(--muted);font-size:13.5px;cursor:pointer;background:var(--surface-2)}
.ai-drop.drag{border-color:var(--brand);background:var(--brand-tint)}
/* Per-file upload progress — sits between the drop zone and the doc list,
   one row per file in flight, using the same track/fill idiom as .mtrack. */
.ai-up-queue{display:flex;flex-direction:column;gap:8px;margin-top:10px}
.ai-up-row{padding:9px 11px;border:1px solid var(--border-2);border-radius:var(--radius-sm);background:var(--surface-2)}
.ai-up-top{display:flex;align-items:center;gap:8px;margin-bottom:6px}
.ai-up-name{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-size:12.5px;font-weight:650;color:var(--ink)}
.ai-up-pct{flex:none;font-size:12px;font-weight:700;color:var(--muted);font-variant-numeric:tabular-nums}
.ai-up-x{flex:none;border:0;background:transparent;color:var(--faint);padding:0 0 0 2px;cursor:pointer;font-size:12px;line-height:1}
.ai-up-x:hover{color:var(--brand)}
.ai-up-track{height:6px;border-radius:4px;background:var(--track);overflow:hidden}
.ai-up-fill{display:block;height:100%;width:0;border-radius:4px;background:var(--ready);transition:width .2s ease}
.ai-up-row.done .ai-up-pct{color:var(--ready)}
.ai-up-row.err .ai-up-fill{background:var(--notready)}
.ai-up-row.err .ai-up-pct{color:var(--notready)}
.ai-up-note{display:none;margin-top:5px;font-size:11.5px;color:var(--notready)}
.ai-up-row.err .ai-up-note{display:block}
@media (prefers-reduced-motion:reduce){.ai-up-fill{transition:none}}
/* A hairline divider (same idiom as .roles-legend) reads as "this row is its
   own control", separating it from the drop zone/upload queue above rather
   than leaving it floating. The button itself stays quiet at rest — matching
   the modal's own register of muted borders and dashed drop zone — and only
   commits to the danger palette on hover/focus, the same reveal-on-interaction
   idiom .ai-del already uses for the per-row delete icon. The confirm()
   dialog carries the "this is destructive" weight, not a permanently loud
   red button sitting above a list that's visible almost all the time. */
.ai-doc-actions{display:flex;justify-content:flex-end;gap:8px;margin-top:10px;padding:10px 0;border-top:1px solid var(--border)}
/* Sized here, not on .btn-outline itself — .btn-outline is used at the default
   13.5px size all over the app, and only this action row (Download all +
   Delete all, side by side) needs the two to visibly match. */
.ai-doc-actions button{padding:6px 12px;font-size:12.5px}
.ai-delete-all{background:transparent;border-color:var(--border-2);color:var(--muted);font-weight:600}
.ai-delete-all:hover{background:var(--notready-bg);color:var(--notready);border-color:color-mix(in srgb,var(--notready) 40%,transparent)}
.ai-doc-list{display:flex;flex-direction:column;gap:6px;margin:12px 0}
.ai-doc{display:flex;align-items:center;gap:10px;padding:8px 12px;border:1px solid var(--border);border-radius:var(--radius-sm);background:var(--surface-2);font-size:13px}
.ai-doc-name{font-weight:600;flex:1}.ai-doc-meta{color:var(--muted);font-size:12px}
button.ai-doc-open{font:inherit;font-weight:600;text-align:left;border:0;background:transparent;color:var(--ink);padding:0;cursor:pointer}
button.ai-doc-open:hover{color:var(--brand);text-decoration:underline}
.ai-dl,.ai-del{border:0;background:transparent;color:var(--muted);padding:2px 6px;cursor:pointer;font-size:14px;line-height:1}
.ai-dl:hover,.ai-del:hover{color:var(--brand)}
.ai-muted{color:var(--muted);font-size:13px;padding:6px 2px}
/* Meta drops out and the name truncates so it stays on one row with delete;
   the separate download icon is redundant on mobile since tapping the name
   already opens/downloads the same file (see ai.js's canDownload comment). */
@media (max-width:640px){
  .ai-doc-meta,.ai-dl{display:none}
  .ai-doc-name{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;min-width:0}
}
.ai-run{display:flex;gap:8px;flex-wrap:wrap;margin:14px 0}
.ai-run select{padding:8px 11px;border:1px solid var(--border-2);border-radius:8px;background:var(--surface);color:var(--ink);font-family:inherit;font-size:13.5px}
.ai-progress{font-size:13px;color:var(--muted);padding:8px 0;display:flex;align-items:center;gap:8px}
.ai-spin{display:inline-block;vertical-align:middle;width:13px;height:13px;border:2px solid var(--border-2);border-top-color:var(--brand);border-radius:50%;animation:fa-spin .8s linear infinite}
.ai-results{display:flex;flex-direction:column;gap:8px;margin-top:8px}
.risk-badge{display:inline-flex;align-items:center;gap:5px;padding:3px 9px;border-radius:999px;font-size:11.5px;font-weight:700}
.risk-ready{background:var(--ready-bg);color:var(--ready)}
.risk-partial{background:var(--partial-bg);color:var(--partial)}
.risk-not{background:var(--notready-bg);color:var(--notready)}
.risk-unknown{background:var(--unknown-bg);color:var(--muted)}

/* ---------- footer ---------- */
.app-footer{max-width:1300px;margin:0 auto;padding:22px 24px 40px;border-top:1px solid var(--border);color:var(--muted);font-size:12.5px;line-height:1.6;flex:0 0 auto;width:100%}
.app-footer p{margin:0 0 10px}
.app-footer strong{color:var(--ink)}
.brand-mark{width:30px;height:30px;border-radius:8px;background:var(--brand);color:#fff;display:grid;place-items:center;font-weight:800;font-size:12px;flex:none}

/* ---------- toast ---------- */
.toast{position:fixed;bottom:24px;left:50%;transform:translateX(-50%) translateY(20px);background:var(--ink);color:var(--bg);padding:11px 20px;border-radius:999px;font-size:13.5px;font-weight:600;box-shadow:var(--shadow-lg);opacity:0;pointer-events:none;transition:opacity .2s,transform .2s;z-index:200}
.toast.show{opacity:1;transform:translateX(-50%) translateY(0)}

/* ---------- app loading overlay (post sign-in, until gated content is ready) ---------- */
/* Full-viewport and fixed (out of document flow) so it never competes with
   <main> for flex space — app.js reveals <main> and THEN awaits Store.init(),
   so the two are briefly in the DOM at the same time; an in-flow overlay
   would fight main for the body's flex:1 slot and split the page. Sits BELOW
   the header in stacking (z-index 45 vs. the header's 50 — see the z-index
   scale note above .app-header) so the sticky, opaque header renders on top
   of the blur/dim automatically, staying crisp and clickable with no extra
   rule needed. The footer needs the mirror treatment below, since it comes
   after this element in the DOM and has no z-index of its own otherwise. */
.app-loading-overlay{position:fixed;inset:0;z-index:45;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:14px;
  background:var(--surface);backdrop-filter:blur(4px) saturate(1.1);-webkit-backdrop-filter:blur(4px) saturate(1.1)}
.app-loading-overlay .ai-spin{width:36px;height:36px;border-width:4px}
/* var(--ink), not a fixed light color — the overlay's own background is now
   theme-aware (var(--surface): white in light, dark in dark), and a color
   picked for the old always-dark background was nearly invisible on white. */
.app-loading-overlay-text{color:var(--ink);font-size:13.5px;font-weight:600;letter-spacing:.2px}
/* main is flex:1 0 auto and normally pushes the footer to the bottom of a
   short page; while the overlay is up, main may still be hidden (or empty,
   mid-fetch) and stops doing that, so the footer would collapse up under the
   header instead. Pin it to the bottom and raise it above the overlay (same
   z-index as the header) so it stays visible and clickable too. max-height
   is set by gate-init.js's syncOverlayBounds (--footer-max-h) so a tall
   footer (long text wrapping at a narrow width) scrolls internally instead
   of creeping up past the header — falls back to unconstrained if that
   hasn't run yet. Guarded by the same :not([hidden]) selector that pins the
   footer, so both stop applying on their own once the overlay hides again. */
#app-loading-overlay:not([hidden]) ~ .app-footer{position:fixed;left:0;right:0;bottom:0;z-index:50;margin:0 auto;max-height:var(--footer-max-h, none);overflow-y:auto}
.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}

/* ---------- responsive: framework-nav (product switch + actions) ---------- */
/* Own breakpoint, wider than the general 720px one below: .fw-cats and
   .fw-actions share one row (.fw-top) and, measured with the longest current
   label (Bulgarian "Финансов одит" + the beta tag, against all three action
   buttons' two-line labels), need ~980px to sit side by side without
   truncating or overlapping — happens well before the header/gate layout
   below needs to change at all. 1000px gives that a little headroom.
   Below it, actions stack full-width, one per row, above the product switch
   (.fw-cats) rather than beside it — order flips them below their source
   order in the markup. The negative margin-bottom on .cat is a wide-layout-
   only trick (tucking the selected pill into the row beneath it); with
   .fw-cats now sitting under the buttons instead of overlapping anything,
   that overlap has to be switched off or the pill floats wrong. */
@media (max-width:1000px){
  .fw-top{flex-wrap:wrap;padding-left:14px;padding-right:14px}
  .fw-groups{padding-left:14px;padding-right:14px}
  .fw-cats{order:2;margin-bottom:0}
  .cat{font-size:13.5px;padding-left:10px;padding-right:10px;margin-bottom:0}
  .fw-actions{order:1;flex:1 1 100%;display:flex;flex-direction:column;gap:6px;padding:0}
  .fw-actions>*{width:100%;font-size:12.5px;padding:7px 8px;white-space:nowrap}
  /* The sub-label is the first thing to go: two lines of 10px in a half-width
     grid cell truncates the label that actually names the action. */
  .fw-pane{position:static}
  .fw-strip{padding-left:14px;padding-right:14px}
}
/* ---------- responsive: header + spacing ---------- */
@media (max-width:720px){
  html,body{overflow-x:hidden;max-width:100%}
  .app-header{padding:10px 14px;max-width:100vw}
  .product h1{font-size:17px}
  .product .tagline{display:none}
  .brand-divider{display:none}
  .header-spacer{display:none}
  .brand-lockup{margin-left:auto}  /* keep Roussinov pinned right when the header wraps */
  /* login / ws gate: cap the card so it never inflates the page width */
  .login-gate{display:block;padding:34px 14px}
  .login-card{width:auto;max-width:340px;margin:0 auto;padding:28px 22px}
  /* header stacks, everything left-aligned: logo row, then tenant, help and
     account each on their own full-width row, in that order. */
  .header-brands{flex-wrap:wrap;gap:8px 12px;justify-content:flex-start}
  .header-right{display:contents}
  .product{order:1}
  .reg-bell{order:2}
  .tenant-switch{order:4;flex:1 1 100%;min-width:0}
  .tenant-dd,#tenant-trigger{width:100%}
  #tenant-trigger{justify-content:left;}
  #help-link{order:3}
  .header-brands .user-menu{order:5;flex:1 1 100%;margin-left:0}
  .header-brands .user-menu-btn{width:100%;justify-content:left;}
  .header-brands .user-menu-btn .uname,.header-brands .user-menu-btn .utenant{max-width:70vw}
  /* Both dropdown panels span the same width as the tenant/account row
     instead of a narrow box hugging the trigger. */
  .user-menu-panel,.dd-panel{left:50%;right:auto;width:calc(100vw - 28px);max-width:calc(100vw - 28px);min-width:0;transform:translateX(-50%)}
  .app-footer{padding-left:14px;padding-right:14px}
  .summary{flex-direction:column;align-items:flex-start;gap:16px}
  /* Same rule as .cx-mark/.cx-tile below: the donut is a graphic, so it
     centers on its own row — the title/description/segbar/legend beside
     it are text, and stay left-aligned like any other paragraph. Applies
     to every .summary use (Overall readiness, a market's Overview, and
     each individual framework — DORA, NIS2, and the rest), since they all
     share this one markup. */
  .summary>.donut{align-self:center}
  .toolbar select{width: 100%;}
  .tb-label{display: none;}
}
/* ─────────────────────────── crosswalk ─────────────────────────── */
.grp-cx{margin-left:4px}
.grp-cx svg{width:14px;height:14px}

/* related-controls block in the detail panel */
.field.related h4{display:flex;align-items:center;gap:6px;flex-wrap:wrap}
.field.related h4 svg{width:13px;height:13px;color:var(--brand)}
.field.related .rel-fam{color:var(--brand);text-transform:none;letter-spacing:0;font-size:11px;font-weight:750;background:var(--brand-tint);padding:2px 8px;border-radius:999px}
.field.related .rel-n{color:var(--faint);font-weight:700}
.field.related>.muted-sm{margin:0 0 9px}
.rel-list{display:flex;flex-direction:column;gap:7px}
.rel-row{display:grid;grid-template-columns:auto 1fr auto auto;gap:10px;align-items:center;padding:9px 11px;background:var(--surface-2);border:1px solid var(--border);border-radius:var(--radius-sm);cursor:pointer;transition:border-color .12s,background .12s}
.rel-row:hover{border-color:var(--brand-2);background:var(--surface)}
.rel-row:focus-visible{border-color:var(--brand-2);background:var(--surface);outline:2px solid var(--brand);outline-offset:2px}
.rel-row .badge{padding:3px 8px;font-size:10.5px;gap:5px}
.rel-mid{min-width:0;display:flex;flex-direction:column;gap:1px}
.rel-ref{font-size:11px;color:var(--muted);font-weight:650}
.rel-title{font-size:13px;color:var(--ink);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.rel-copy{display:inline-flex;align-items:center;justify-content:center;width:28px;height:28px;padding:0;border:1px solid var(--border-2);border-radius:7px;background:var(--surface);color:var(--muted);cursor:pointer}
.rel-copy:hover{color:var(--brand);border-color:var(--brand-2)}
.rel-copy svg{width:14px;height:14px}
.rel-row .chev{font-size:16px}
.rel-more{margin-top:9px;border:1px dashed var(--border-2);background:transparent;color:var(--brand);font-family:inherit;font-size:12.5px;font-weight:650;padding:8px 12px;border-radius:var(--radius-sm);cursor:pointer;width:100%}
.rel-more:hover{background:var(--brand-tint)}

/* crosswalk families overview */
.cx-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(270px,1fr));gap:12px}
.cx-tile{display:flex;gap:14px;align-items:flex-start;text-align:left;padding:15px 16px;background:var(--surface);border:1px solid var(--border);border-radius:var(--radius);box-shadow:var(--shadow);cursor:pointer;transition:border-color .12s,box-shadow .12s}
.cx-tile:hover{border-color:var(--brand-2);box-shadow:var(--shadow-lg)}
.cx-tile .donut{flex:0 0 auto;margin-top:2px}
.cx-desc{font-size:12px;color:var(--muted);margin:3px 0 8px;line-height:1.35}
.cx-mark{width:54px;height:54px;flex:0 0 auto;display:inline-flex;align-items:center;justify-content:center;border-radius:14px;background:var(--brand-tint);color:var(--brand)}
.cx-mark svg{width:26px;height:26px}
/* Placed after the base rules above, not inside the general layout media
   query near the top of this file — same selectors, equal specificity, so
   whichever comes LAST in the file wins the tie regardless of the media
   query, and that has to be this one. (Same mistake, same fix, as the
   Legislation dropdown's admin.css rules earlier — worth remembering.) */
@media (max-width:720px){
  /* .summary's own text (a real paragraph, e.g. the crosswalk intro) stays
     left-aligned — only the icon/donut is a graphic, so only it gets
     centered on its own row. Shared by the crosswalk and OSS-licence
     summary cards, both of which reuse .cx-mark for their icon. */
  .cx-mark{align-self:center}
  /* Crosswalk family tiles: side-by-side (donut left, text right) is what
     was cramping both into half-width columns. Stacked instead, donut on
     its own row — same rule as .cx-mark above, only the graphic centers,
     the title/description/meta stay left-aligned like any other text. */
  .cx-tile{flex-direction:column;align-items:flex-start}
  .cx-tile .donut{align-self:center}
  .cx-tile .ft-body{width:100%}
}
.cx-back{display:inline-flex;align-items:center;gap:2px;font-size:12px;font-weight:650;color:var(--brand);cursor:pointer;margin-bottom:3px}
.cx-back svg{width:14px;height:14px;transform:rotate(180deg)}

/* ─────────────────────────── audit trail ─────────────────────────── */
.field.history h4{display:flex;align-items:center;gap:6px}
.field.history h4 svg{width:13px;height:13px;color:var(--muted)}
.hist-list{display:flex;flex-direction:column;gap:2px}
.hist-row{display:grid;grid-template-columns:auto 1fr;gap:10px;align-items:start;padding:7px 2px;border-bottom:1px solid var(--border)}
.hist-row:last-child{border-bottom:0}
.hist-dot{width:8px;height:8px;border-radius:50%;margin-top:5px;background:var(--muted)}
.hist-dot.d-control{background:var(--brand-2)}
.hist-dot.d-step{background:var(--partial)}
.hist-dot.d-assess{background:#3b82c4}
.hist-dot.d-role{background:var(--notready)}
.hist-dot.d-doc{background:var(--ready)}
.hist-dot.d-state{background:var(--unknown)}
.hist-mid{min-width:0}
.hist-act{font-size:13px;color:var(--ink)}
.hist-tg{color:var(--brand);font-weight:600}
.hist-det{color:var(--muted);margin-left:6px;font-size:12.5px}
.hist-meta{font-size:11.5px;color:var(--faint);margin-top:1px}
#activity-list{max-height:60vh;overflow-y:auto}
#activity-list .hist-act{font-size:13.5px}

/* ─────────────────────── preliminary financial audit ─────────────────────── */
/* this section owns the whole work area: drop the framework toolbar + detail pane */
main[data-view="finaudit"] .toolbar,
main[data-view="finaudit"] .appl-pills,
main[data-view="finaudit"] .summary,
main[data-view="finaudit"] .detail{display:none}
main[data-view="finaudit"] .work{grid-template-columns:1fr}
/* flex:1 so its background (var(--bg)) always reaches the footer, matching
   main's own flex:1 0 auto — otherwise this shrink-wraps to its content and,
   whenever that content is short (e.g. the financial-audit loading state),
   leaves a gap of bare page background between it and the footer. */
.main-content{background-color: var(--bg);padding: 20px 24px 70px;flex:1 0 auto;width:100%}
.fa-wrap{display:flex;flex-direction:column;gap:14px}
/* Was space-between, pairing the profile toggle on the left with the save state
   and print button on the right. The toggle is a nav tab now, so the remaining
   block has to be told to stay right rather than sliding into the gap. */
.fa-top{display:flex;align-items:center;justify-content:flex-end;gap:12px;flex-wrap:wrap}
.fa-top-right{display:flex;align-items:center;gap:10px}
.fa-saved{font-size:12px;color:var(--faint);min-width:64px;text-align:right}
.fa-saved.ok{color:var(--ready)}
.fa-saved.err{color:var(--notready)}
.fa-ro{flex-basis:100%;font-size:12px;color:var(--partial);background:var(--partial-bg);border-radius:var(--radius-sm);padding:6px 11px}
.fa-note{font-size:12.5px;color:var(--muted);margin:0;line-height:1.45}
.fa-meta{display:flex;gap:12px;flex-wrap:wrap}
.fa-meta label{display:flex;flex-direction:column;gap:3px;flex:1 1 180px;min-width:0}
.fa-meta label span{font-size:11px;text-transform:uppercase;letter-spacing:.04em;color:var(--faint)}
.fa-meta input{padding:8px 10px;border:1px solid var(--border-2);border-radius:var(--radius-sm);background:var(--surface);color:var(--ink);font-family:inherit;font-size:13px}

.fa-cols{display:grid;grid-template-columns:1fr 1fr;gap:16px;align-items:start}
@media (max-width:1000px){.fa-cols{grid-template-columns:1fr}}
.fa-cols>.fa-panel{min-width:0}
.fa-panel{padding:16px 17px}
.fa-panel-h{display:flex;align-items:center;justify-content:space-between;gap:10px;margin-bottom:12px}
.fa-panel-h h3{margin:0;font-size:15px}
@media (max-width:640px){.fa-panel-h{flex-wrap:wrap}.fa-panel-h>button{flex:1 1 100%}}
.fa-prog{display:flex;align-items:center;gap:9px}
.fa-prog .donut{width:52px;height:52px}
.fa-prog .d-lbl b{font-size:13px}
.fa-prog-n{font-size:12px;color:var(--muted)}

.fa-secblock{margin-bottom:14px}
.fa-secblock h4{display:flex;align-items:center;justify-content:space-between;gap:8px;margin:0 0 7px;font-size:12.5px;color:var(--brand-2)}
.fa-isa{display:inline-block;font-size:10px;font-weight:700;letter-spacing:.2px;color:var(--brand);background:var(--brand-tint);border:1px solid var(--brand);border-radius:7px;padding:0 6px;line-height:1.6;white-space:nowrap}
.fa-secblock h4 .fa-isa{margin-right:auto}
.fa-info{border-top:3px solid var(--brand)}
.fa-disclaimer{font-size:13px;color:var(--ink);background:var(--partial-bg);border:1px solid color-mix(in srgb,var(--partial) 45%,transparent);border-radius:10px;padding:10px 12px;line-height:1.45}
.fa-standards{margin-top:10px}
.fa-standards summary{cursor:pointer;font-weight:700;font-size:13px;color:var(--brand-2);padding:2px 0}
.fa-standards>p{font-size:12.5px;color:var(--muted);margin:8px 2px}
.fa-isa-map{width:100%;border-collapse:collapse;font-size:12.5px;margin:6px 0}
.fa-isa-map th,.fa-isa-map td{text-align:left;padding:5px 8px;border-bottom:1px solid var(--border)}
.fa-isa-map th{color:var(--muted);font-weight:700}
.fa-isa-map td:last-child{white-space:nowrap;font-weight:700;color:var(--brand-2)}
.fa-secn{color:var(--faint);font-weight:600}

.fa-figgrp{margin-bottom:12px}
.fa-figgrp h5{margin:0 0 7px;font-size:11px;text-transform:uppercase;letter-spacing:.04em;color:var(--faint)}
.fa-figgrid{display:grid;grid-template-columns:1fr 1fr;gap:8px}
@media (max-width:520px){.fa-figgrid{grid-template-columns:1fr}}
.fa-fld{display:flex;flex-direction:column;gap:3px;min-width:0}
.fa-fld span{font-size:12px;color:var(--muted)}
.fa-fld input{padding:7px 9px;border:1px solid var(--border-2);border-radius:var(--radius-sm);background:var(--surface);color:var(--ink);font-family:inherit;font-size:13px;text-align:right;font-variant-numeric:tabular-nums}
.fa-fld input:focus{border-color:var(--brand-2);outline:none}

.fa-ratios-wrap{margin-top:6px}
.fa-ratios-wrap h3{font-size:14px;margin:10px 0 8px}
.fa-ratios{display:flex;flex-direction:column;gap:1px;border:1px solid var(--border);border-radius:var(--radius-sm);overflow:hidden}
.fa-ratio{display:grid;grid-template-columns:1fr auto 62px;gap:10px;align-items:center;padding:8px 11px;background:var(--surface);font-size:13px}
.fa-ratio:nth-child(even){background:var(--surface-2)}
.fa-rlab{color:var(--ink);display:flex;align-items:center;gap:5px}
.fa-rhint{display:inline-flex;align-items:center;justify-content:center;width:14px;height:14px;border-radius:50%;background:var(--border-2);color:var(--muted);font-size:9px;font-weight:700;cursor:help}
/* Its only content is the native title= tooltip, which needs a mouse to
   hover with — on a touch device (phone or tablet, same cutoff .fa-cols
   uses) it's a dot that does nothing when tapped, not a smaller affordance. */
@media (max-width:1000px){.fa-rhint{display:none}}
.fa-rval{text-align:right;font-variant-numeric:tabular-nums;font-weight:600}
.fa-rflag{text-align:center;font-size:11px;font-weight:700;text-transform:uppercase;letter-spacing:.03em;border-radius:999px;padding:2px 0}
.fa-ratio.fa-good .fa-rflag{color:var(--ready);background:var(--ready-bg)}
.fa-ratio.fa-watch .fa-rflag{color:var(--partial);background:var(--partial-bg)}
.fa-ratio.fa-alert .fa-rflag{color:var(--notready);background:var(--notready-bg)}
.fa-ratio.fa-na .fa-rflag,.fa-ratio.fa-info .fa-rflag{color:var(--unknown);background:var(--unknown-bg)}
.fa-ratio.fa-good .fa-rval{color:var(--ready)}
.fa-ratio.fa-alert .fa-rval{color:var(--notready)}
/* Prior-period reading: its own column, present only when the workspace has a
   comparative to show, so the value cell stays exactly the number. */
.fa-ratios-prior .fa-ratio{grid-template-columns:1fr auto 74px 62px}
.fa-rprior{text-align:right;font-size:11.5px;color:var(--muted);font-variant-numeric:tabular-nums;white-space:nowrap}

/* ─────────────────── multi-year trend ─────────────────── */
.fa-series-wrap{margin-top:16px}
.fa-series-wrap h3{font-size:14px;margin:0 0 6px}
.fa-series-note{font-size:11.5px;color:var(--muted);margin:0 0 9px;max-width:80ch}
.fa-series-scroll{overflow-x:auto}
.fa-series{width:100%;border-collapse:collapse;font-size:12.5px}
.fa-series th,.fa-series td{padding:6px 9px;border-bottom:1px solid var(--border);text-align:right;white-space:nowrap}
.fa-series th:first-child,.fa-series td:first-child{text-align:left;white-space:normal}
.fa-series thead th{font-size:11.5px;color:var(--muted);font-weight:700;border-bottom:1px solid var(--border-2)}
.fa-ser-cur{font-size:10px;text-transform:uppercase;letter-spacing:.03em;color:var(--brand)}
.fa-series-sep td{background:var(--surface-2);font-size:11px;text-transform:uppercase;letter-spacing:.03em;color:var(--muted);text-align:left}
.fa-series td.fa-good{color:var(--ready)}
.fa-series td.fa-watch{color:var(--partial)}
.fa-series td.fa-alert{color:var(--notready)}

/* Sector calibration: a marker on any ratio whose band came from the sector
   rather than from the general rules of thumb, and one note under the table
   saying which sector and how many bands it moved. */
.fa-rcal{font-size:9px;font-weight:700;text-transform:uppercase;letter-spacing:.04em;color:var(--brand);background:var(--brand-tint);border-radius:999px;padding:1px 6px;cursor:help}
.fa-rcal-note{font-size:11.5px;color:var(--muted);margin:7px 2px 0;line-height:1.45;max-width:80ch}
.fa-meta label select{padding:8px 10px;border:1px solid var(--border-2);border-radius:var(--radius-sm);background:var(--surface);color:var(--ink);font-family:inherit;font-size:13px;cursor:pointer}

/* Downside sensitivity. Below the red flags because it answers the question
   they raise: they say what is wrong today, this says what is one bad year
   away. The assumptions are editable because they ARE the analysis. */
.fa-str-wrap{margin-top:16px;padding:12px 13px;border:1px solid var(--border);border-radius:var(--radius-sm);background:var(--surface-2)}
.fa-str-wrap h3{margin:0 0 6px;font-size:14px;display:flex;align-items:center;gap:8px;flex-wrap:wrap}
.fa-str-note{font-size:11.5px;color:var(--muted);margin:0 0 10px;line-height:1.45;max-width:80ch}
.fa-str-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(110px,1fr));gap:8px;margin-bottom:10px}
.fa-str-f{display:flex;flex-direction:column;gap:3px;min-width:0}
.fa-str-f span{font-size:11px;color:var(--muted);cursor:help}
.fa-str-f input{padding:7px 9px;border:1px solid var(--border-2);border-radius:var(--radius-sm);background:var(--surface);color:var(--ink);font-family:inherit;font-size:13px;text-align:right;font-variant-numeric:tabular-nums}
.fa-str-f input:focus{border-color:var(--brand-2);outline:none}
.fa-str-list{list-style:none;margin:0;padding:0;display:flex;flex-direction:column;gap:5px}
.fa-str-list li{font-size:12.5px;line-height:1.4;padding:7px 11px;border-radius:var(--radius-sm);border-left:3px solid var(--partial);background:var(--partial-bg)}
.fa-str-list li b{color:var(--partial)}
/* A condition that comes into play — negative equity, cover under 1x — is a
   different order of answer from a ratio changing band, and reads as one. */
.fa-str-list li.fa-str-cond{border-left-color:var(--notready);background:var(--notready-bg)}
.fa-str-list li.fa-str-cond b{color:var(--notready)}
.fa-str-list li.fa-alert{border-left-color:var(--notready)}
.fa-str-held{font-size:12.5px;color:var(--muted);margin:0;padding:9px 12px;background:var(--ready-bg);border:1px solid color-mix(in srgb,var(--ready) 24%,transparent);border-radius:var(--radius-sm);line-height:1.45}
.fa-str-empty{font-size:12.5px;color:var(--muted);margin:0;line-height:1.45;max-width:80ch}
.fa-str-runway{font-size:12.5px;color:var(--ink);margin:8px 0 0;line-height:1.45}
/* The findings register — findings the engagement owns, rather than the last
   run's output. Cards are collapsed to a scannable summary because the list is
   read far more often than it is edited. */
.fa-fnds{margin-top:14px}
.fa-fnd-count{background:var(--brand);color:#fff;border-radius:999px;font-size:11px;padding:1px 8px}
.fa-fnd-tallies{display:flex;flex-wrap:wrap;gap:6px;margin-bottom:10px}
.fa-fnd-tally{font-size:11px;font-weight:700;border-radius:999px;padding:2px 9px}
.fa-fnd-list{display:flex;flex-direction:column;gap:7px}
.fa-fnd{border:1px solid var(--border);border-left-width:3px;border-radius:var(--radius-sm);background:var(--surface)}
.fa-fnd.fa-crit{border-left-color:var(--brand-2)}
.fa-fnd.fa-alert{border-left-color:var(--notready)}
.fa-fnd.fa-watch{border-left-color:var(--partial)}
.fa-fnd.fa-good{border-left-color:var(--ready)}
.fa-fnd.fa-na{border-left-color:var(--unknown)}
/* A decided finding recedes without disappearing: it stays in the list because
   the register has to show that it was raised and what was concluded. */
.fa-fnd-closed{opacity:.72}
.fa-fnd-h{display:flex;align-items:center;gap:9px;flex-wrap:wrap;padding:9px 11px;cursor:pointer;font-size:13px;list-style:none}
.fa-fnd-h::-webkit-details-marker{display:none}
.fa-fnd-h::after{content:"⌄";margin-left:auto;color:var(--faint);font-size:14px;line-height:1}
.fa-fnd[open] .fa-fnd-h::after{content:"⌃"}
.fa-fnd-sev{font-size:10px;font-weight:700;letter-spacing:.03em;text-transform:uppercase;border-radius:999px;padding:2px 8px;white-space:nowrap}
.fa-fnd-sev.fa-crit{color:#fff;background:var(--brand-2)}
.fa-fnd-sev.fa-alert{color:var(--notready);background:var(--notready-bg)}
.fa-fnd-sev.fa-watch{color:var(--partial);background:var(--partial-bg)}
.fa-fnd-sev.fa-good{color:var(--ready);background:var(--ready-bg)}
.fa-fnd-sev.fa-na{color:var(--unknown);background:var(--unknown-bg)}
.fa-fnd-area{font-weight:600;color:var(--ink)}
.fa-fnd-status{font-size:10px;font-weight:700;text-transform:uppercase;letter-spacing:.03em;border-radius:999px;padding:2px 8px;white-space:nowrap}
.fa-fst-open{color:var(--notready);background:var(--notready-bg)}
.fa-fst-planned{color:var(--brand);background:var(--brand-tint)}
.fa-fst-dismissed{color:var(--unknown);background:var(--unknown-bg)}
.fa-fst-resolved{color:var(--ready);background:var(--ready-bg)}
.fa-fnd-badges{display:flex;gap:5px;flex-wrap:wrap}
.fa-fnd-badge{font-size:10px;color:var(--faint);border:1px solid var(--border-2);border-radius:999px;padding:1px 7px;white-space:nowrap}
.fa-fnd-stale{border-color:var(--border-2);color:var(--muted)}
/* A dismissal with no reason recorded. Not blocked, but not quiet either: the
   file has to be able to show what the judgement was. */
.fa-fnd-nore{color:var(--partial);border-color:var(--partial)}
.fa-fnd-b{padding:2px 11px 11px;display:flex;flex-direction:column;gap:8px;border-top:1px solid var(--border)}
.fa-fnd-row{display:grid;grid-template-columns:repeat(auto-fit,minmax(130px,1fr));gap:8px}
.fa-fnd-wide{grid-column:span 2}
@media (max-width:640px){.fa-fnd-row{grid-template-columns:1fr}.fa-fnd-wide{grid-column:auto}}
.fa-fnd-f{display:flex;flex-direction:column;gap:3px;min-width:0}
.fa-fnd-f>span{font-size:11px;color:var(--muted)}
.fa-fnd-f input,.fa-fnd-f select,.fa-fnd-f textarea{padding:7px 9px;border:1px solid var(--border-2);border-radius:var(--radius-sm);background:var(--surface);color:var(--ink);font-family:inherit;font-size:12.5px;min-width:0}
.fa-fnd-f textarea{resize:vertical;line-height:1.45}
.fa-fnd-f input:focus,.fa-fnd-f select:focus,.fa-fnd-f textarea:focus{border-color:var(--brand-2);outline:none}
.fa-fnd-actions{display:flex;justify-content:flex-end}
.fa-fnd-del{font-size:12px}
.fa-ai-handoff{font-size:12.5px;color:var(--muted);margin:0;line-height:1.45;max-width:80ch}
/* Materiality (ISA 320). Sits between the figures it is computed from and the
   checks that are measured against it. */
/* The unit caption. Sits above the figures and above materiality, because
   every amount under both of them is denominated by it. */
.fa-unit-note{font-size:11.5px;color:var(--muted);margin:0 0 10px;font-style:italic}
.fa-mat-wrap{margin-top:16px;padding:12px 13px;border:1px solid var(--border);border-radius:var(--radius-sm);background:var(--surface-2)}
.fa-mat-wrap h3{margin:0 0 10px;font-size:14px;display:flex;align-items:center;gap:8px;flex-wrap:wrap}
.fa-mat-range{font-size:11px;font-weight:400;color:var(--faint);text-transform:none;letter-spacing:0}
.fa-mat-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(120px,1fr));gap:8px;margin-bottom:10px}
.fa-mat-basis{grid-column:span 2}
@media (max-width:640px){.fa-mat-grid{grid-template-columns:1fr}.fa-mat-basis{grid-column:1/-1}}
.fa-mat-f{display:flex;flex-direction:column;gap:3px;min-width:0}
.fa-mat-f span{font-size:11px;color:var(--muted)}
.fa-mat-f input,.fa-mat-f select{padding:7px 9px;border:1px solid var(--border-2);border-radius:var(--radius-sm);background:var(--surface);color:var(--ink);font-family:inherit;font-size:13px}
.fa-mat-f input{text-align:right;font-variant-numeric:tabular-nums}
.fa-mat-f input:focus,.fa-mat-f select:focus{border-color:var(--brand-2);outline:none}
.fa-mat-out{display:grid;grid-template-columns:repeat(auto-fit,minmax(150px,1fr));gap:8px}
.fa-mat-n{display:flex;flex-direction:column;gap:2px;padding:8px 11px;background:var(--surface);border:1px solid var(--border);border-radius:var(--radius-sm)}
.fa-mat-n span{font-size:11px;color:var(--muted)}
.fa-mat-n b{font-size:15px;color:var(--ink)}
/* The overall figure is the one the file is judged against; the two derived
   from it are subordinate, and the colour says so. */
.fa-mat-n:first-child{border-color:var(--brand)}
.fa-mat-n:first-child b{color:var(--brand)}
.fa-mat-basis-line{font-size:11.5px;color:var(--muted);margin:8px 0 0;line-height:1.45}
.fa-mat-empty{font-size:12.5px;color:var(--muted);margin:0;line-height:1.45;max-width:80ch}
.fa-mat-notes{list-style:none;margin:8px 0 0;padding:0;display:flex;flex-direction:column;gap:5px}
.fa-mat-notes li{font-size:11.5px;line-height:1.4;color:var(--ink);background:var(--partial-bg);border-left:3px solid var(--partial);border-radius:var(--radius-sm);padding:6px 10px}
.fa-mat-note-f{display:flex;flex-direction:column;gap:3px;margin-top:10px}
.fa-mat-note-f span{font-size:11px;color:var(--muted)}
.fa-mat-note-f textarea{padding:7px 9px;border:1px solid var(--border-2);border-radius:var(--radius-sm);background:var(--surface);color:var(--ink);font-family:inherit;font-size:12.5px;resize:vertical;min-height:110px}
.fa-mat-note-f textarea:focus{border-color:var(--brand-2);outline:none}
/* Integrity checks — the worksheet cross-footing against itself. Sits between
   the figure inputs and the ratios, because it is a verdict on the first and a
   caveat on the second. */
.fa-integ{margin-top:14px;padding:9px 12px;border-radius:var(--radius-sm);font-size:12.5px;line-height:1.45}
.fa-integ.ok{color:var(--muted);background:var(--ready-bg);border:1px solid color-mix(in srgb,var(--ready) 24%,transparent)}
.fa-integ.ok b{color:var(--ready)}
.fa-integ.warn{background:var(--partial-bg);border:1px solid color-mix(in srgb,var(--partial) 30%,transparent)}
.fa-integ.warn>b{color:var(--partial)}
.fa-integ.bad{background:var(--notready-bg);border:1px solid color-mix(in srgb,var(--notready) 30%,transparent)}
.fa-integ.bad>b{color:var(--notready)}
.fa-integ-note{margin:5px 0 8px;font-size:11.5px;color:var(--muted);max-width:80ch}
.fa-integ-list{list-style:none;margin:0;padding:0;display:flex;flex-direction:column;gap:5px}
.fa-integ-list li{padding-left:11px;border-left:3px solid var(--unknown);font-variant-numeric:tabular-nums}
.fa-integ-list li.fa-integ-alert{border-left-color:var(--notready)}
.fa-integ-list li.fa-integ-alert b{color:var(--notready)}
.fa-integ-list li.fa-integ-watch{border-left-color:var(--partial)}
.fa-integ-list li.fa-integ-watch b{color:var(--partial)}
.fa-flags-wrap{margin-top:14px}
.fa-flags-wrap h3{font-size:14px;margin:0 0 8px;display:flex;align-items:center;gap:7px}
.fa-flags-wrap h3 .tnum{background:var(--notready);color:#fff;border-radius:999px;font-size:11px;padding:1px 8px}
.fa-flags{list-style:none;margin:0;padding:0;display:flex;flex-direction:column;gap:6px}
.fa-flags li{font-size:12.5px;line-height:1.4;background:var(--notready-bg);border:1px solid color-mix(in srgb,var(--notready) 24%,transparent);border-radius:var(--radius-sm);padding:8px 11px}
.fa-flags li b{color:var(--notready)}
/* A trend flag is a statement about several periods, not this balance sheet —
   amber rather than red, so it does not read as a fresh alert. */
.fa-flags li.fa-flag-trend{background:var(--partial-bg);border-color:color-mix(in srgb,var(--partial) 24%,transparent)}
.fa-flags li.fa-flag-trend b{color:var(--partial)}
.fa-flags-empty{font-size:12.5px;color:var(--muted);background:var(--ready-bg);border:1px solid color-mix(in srgb,var(--ready) 24%,transparent);border-radius:var(--radius-sm);padding:9px 12px}
.fa-loading{padding:40px;text-align:center;color:var(--muted);display:flex;align-items:center;justify-content:center;gap:10px}

/* ─────────────────── financial-audit documents ─────────────────── */
.fa-docs{margin-top:14px}
.fa-docs-sub{font-size:12.5px;color:var(--muted);margin:0 0 12px;max-width:80ch}
.fa-doc-up{display:flex;flex-wrap:wrap;gap:8px;align-items:center;margin-bottom:12px}
.fa-doc-up select{padding:7px 9px;border:1px solid var(--border-2);border-radius:var(--radius-sm);background:var(--surface);color:var(--ink);font-family:inherit;font-size:13px;cursor:pointer}
@media (max-width:640px){.fa-doc-up>button{flex:1 1 100%}}
@media (max-width:640px){main[data-view="finaudit"] .ai-doc-actions{justify-content:center}}
.fa-doc-list{display:flex;flex-direction:column;gap:7px}
.fa-doc{display:grid;grid-template-columns:1fr auto auto;gap:10px;align-items:center;padding:9px 11px;background:var(--surface-2);border:1px solid var(--border);border-radius:var(--radius-sm)}
.fa-doc-name{min-width:0;text-align:left;border:0;background:transparent;color:var(--ink);font-family:inherit;font-size:13px;cursor:pointer;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;padding:0}
.fa-doc-name:hover{color:var(--brand);text-decoration:underline}
.fa-doc-meta{font-size:11.5px;color:var(--faint);white-space:nowrap}
.fa-doc-del{border:0;background:transparent;color:var(--faint);font-size:14px;cursor:pointer;padding:2px 4px;line-height:1}
.fa-doc-del:hover{color:var(--notready)}
.fa-doc-empty{font-size:12.5px;color:var(--faint);padding:6px 2px}
.fa-clear{margin-top:10px;padding:10px 12px;border:1px dashed var(--border-2);border-radius:var(--radius-sm);background:var(--surface-2)}
.fa-clear-note{margin:0 0 8px;font-size:12.5px;color:var(--muted)}
/* Meta (size/uploader/date) drops out on mobile so the name — truncated
   with an ellipsis rather than wrapped — stays on the same row as delete. */
@media (max-width:640px){.fa-doc{grid-template-columns:1fr auto}.fa-doc-meta{display:none}}

/* --- AI analysis of the financial statements --- */
.fa-ai{margin-top:14px}
.fa-ai-busy{font-size:13px;color:var(--muted);padding:10px 2px;display:flex;align-items:center;gap:8px}
.fa-ai-busy::before{content:"";width:14px;height:14px;border:2px solid var(--border-2);border-top-color:var(--brand);border-radius:50%;animation:fa-spin .8s linear infinite}
@keyframes fa-spin{to{transform:rotate(360deg)}}
.fa-ai-meta{font-size:11.5px;color:var(--faint);margin-bottom:8px}
.fa-ai-trunc{color:var(--partial)}
.fa-ai-summary{font-size:13.5px;line-height:1.55;margin:0 0 14px}
.fa-ai-figs h4,.fa-ai-finds h4{margin:0 0 9px;font-size:13px}
/* Analysis history: version picker plus a plain warning when the analysis on
   screen is not the current one. */
.fa-ai-hist{display:flex;align-items:center;gap:8px;margin-bottom:10px;font-size:12px;color:var(--muted)}
.fa-ai-hist select{font-size:12px;padding:3px 6px;background:var(--surface-2);color:var(--ink);border:1px solid var(--border);border-radius:var(--radius-sm)}
@media (max-width:640px){.fa-ai-hist{flex-wrap:wrap}.fa-ai-hist select{flex:1 1 100%;min-width:0;max-width:100%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}}
.fa-ai-older{margin:0 0 12px;padding:8px 11px;font-size:12px;background:var(--surface-2);border:1px solid var(--partial);border-left-width:3px;border-radius:var(--radius-sm)}
.fa-ai-figgrid{display:grid;grid-template-columns:repeat(auto-fill,minmax(180px,1fr));gap:8px;margin-bottom:16px}
.fa-ai-fig{display:flex;flex-direction:column;gap:2px;padding:8px 11px;background:var(--surface-2);border:1px solid var(--border);border-radius:var(--radius-sm)}
.fa-ai-flab{font-size:11.5px;color:var(--muted)}
.fa-ai-fval{font-size:14px;font-weight:600;color:var(--ink)}
.fa-ai-finds{display:flex;flex-direction:column;gap:9px}
.fa-ai-find{padding:10px 12px;background:var(--surface);border:1px solid var(--border);border-left:3px solid var(--unknown);border-radius:var(--radius-sm)}
.fa-ai-find.fa-crit{border-left-color:var(--critical)}
.fa-ai-find.fa-alert{border-left-color:var(--notready)}
.fa-ai-find.fa-watch{border-left-color:var(--partial)}
.fa-ai-find.fa-good{border-left-color:var(--ready)}
.fa-ai-find.fa-na{border-left-color:var(--unknown)}
.fa-ai-find-h{display:flex;align-items:center;gap:9px;margin-bottom:5px}
.fa-ai-sev{font-size:10px;font-weight:700;letter-spacing:.03em;text-transform:uppercase;padding:2px 8px;border-radius:999px;color:var(--unknown);background:var(--unknown-bg)}
.fa-ai-find.fa-crit .fa-ai-sev{color:var(--critical);background:var(--critical-bg)}
.fa-ai-find.fa-alert .fa-ai-sev{color:var(--notready);background:var(--notready-bg)}
.fa-ai-find.fa-watch .fa-ai-sev{color:var(--partial);background:var(--partial-bg)}
.fa-ai-find.fa-good .fa-ai-sev{color:var(--ready);background:var(--ready-bg)}
.fa-ai-area{font-size:12.5px;font-weight:600;color:var(--ink)}
.fa-ai-obs{font-size:13px;line-height:1.5}
.fa-ai-rec{font-size:12.5px;color:var(--muted);margin-top:5px;line-height:1.5}
.fa-ai-disclaimer{font-size:11px;color:var(--faint);font-style:italic;margin:14px 0 0}

/* ---------------- regulatory watch (bell + feed) ---------------- */
.reg-bell{position:relative;padding:6px 10px;line-height:1}
.reg-count{position:absolute;top:-6px;right:-6px;min-width:17px;height:17px;padding:0 4px;
  border-radius:999px;background:var(--brand);color:var(--on-brand);
  font-size:10.5px;font-weight:800;line-height:17px;text-align:center}
.reg-list{display:flex;flex-direction:column;gap:10px;max-height:60vh;overflow:auto}
.reg-item{border:1px solid var(--border);border-radius:var(--radius-sm);padding:12px 14px;background:var(--surface-2)}
/* Unacknowledged items carry the brand edge; acknowledged ones recede so the
   list reads as a work queue rather than an archive. */
.reg-item.reg-new{border-left:3px solid var(--brand);background:var(--surface)}
.reg-item.reg-done{opacity:.72}
.reg-head{display:flex;align-items:baseline;gap:8px;flex-wrap:wrap;margin-bottom:5px}
.reg-title{font-weight:700;font-size:14.5px}
.reg-date{font-size:11.5px;color:var(--faint);margin-left:auto}
.reg-sev{font-size:9.5px;font-weight:800;letter-spacing:.08em;text-transform:uppercase;
  border-radius:9px;padding:1px 7px;border:1px solid currentColor}
.reg-sev-action{color:var(--partial);background:var(--partial-bg)}
.reg-sev-info{color:var(--muted);background:var(--unknown-bg)}
.reg-summary{font-size:13px;line-height:1.55;white-space:pre-wrap}
.reg-action{font-size:12.5px;line-height:1.55;margin-top:6px;padding:7px 10px;
  border-radius:var(--radius-sm);background:var(--brand-tint);color:var(--ink)}
.reg-fws{display:flex;flex-wrap:wrap;gap:5px;margin-top:8px}
.reg-fw{font-size:10.5px;font-weight:700;border:1px solid var(--border-2);border-radius:9px;
  padding:1px 7px;color:var(--muted);background:var(--surface)}
.reg-foot{display:flex;align-items:center;gap:10px;flex-wrap:wrap;margin-top:10px}
.reg-ack-note{flex:1;min-width:160px;font:inherit;font-size:12.5px;color:var(--ink);
  background:var(--surface);border:1px solid var(--border-2);border-radius:var(--radius-sm);padding:6px 9px}
.reg-acked{font-size:11.5px;color:var(--ready)}
.reg-src{font-size:12px}

/* readiness trend on the overview summary */
.trend{font-weight:700;white-space:nowrap}
.trend-up{color:var(--ready)}
.trend-down{color:var(--notready)}
.trend-flat{color:var(--muted);font-weight:600}

/* evidence document links on a control */
.evd-block{display:flex;flex-direction:column;gap:5px}
.evd-label{font-size:11.5px;font-weight:600;color:var(--muted)}
.evd-row{display:flex;flex-wrap:wrap;gap:6px;align-items:center}
.evd{display:inline-flex;align-items:center;gap:5px;font-size:12px;padding:3px 4px 3px 9px;
  border:1px solid var(--border-2);border-radius:999px;background:var(--surface-2);max-width:100%}
.evd-stale{border-color:var(--partial);color:var(--partial);background:var(--partial-bg)}
.evd-missing{border-color:var(--notready);color:var(--notready);background:var(--notready-bg)}
.evd-x{border:0;background:transparent;color:inherit;cursor:pointer;font-size:11px;opacity:.6;padding:0 3px}
.evd-x:hover{opacity:1}
.evd-add{font-size:12px;padding:4px 8px;border-radius:999px;border:1px dashed var(--border-2);
  background:transparent;color:var(--muted);max-width:220px}

/* ---------------------------------------------------------------------------
   Open-source licence review (js/osslic.js).

   Severity reuses the readiness palette rather than defining a second one:
   an auditor should not have to learn that amber means "partial" on one screen
   and "medium" on another. none/low -> ready, medium -> partial,
   high -> notready, critical -> critical.
--------------------------------------------------------------------------- */
main[data-view="osslic"] .toolbar,
main[data-view="osslic"] .appl-pills,
main[data-view="osslic"] .detail{display:none}
main[data-view="osslic"] .work{grid-template-columns:1fr}

.ol-wrap{display:flex;flex-direction:column;gap:14px}

/* Stands in for the whole screen (not just one block) while the workspace's
   docs/runs are being fetched — same look as the app-wide sign-in spinner
   (.app-loading-overlay), but in-flow rather than position:fixed, since this
   is scoped to one view, not the whole page. */
.ol-loading{display:flex;flex-direction:column;align-items:center;justify-content:center;gap:14px;
  padding:56px 16px;background:var(--surface);border:1px solid var(--border);border-radius:var(--radius)}
.ol-loading .ai-spin{width:28px;height:28px;border-width:3px}
.ol-loading-text{color:var(--muted);font-size:13px;font-weight:600}

.ol-caveat{font-size:12px;font-style:italic}

.ol-input{background:var(--surface);border:1px solid var(--border);border-radius:var(--radius);padding:14px 16px;
  display:flex;flex-direction:column;gap:12px}
.ol-ctxrow{display:grid;grid-template-columns:repeat(auto-fit,minmax(200px,1fr));gap:8px}
.ol-ctx{text-align:left;padding:9px 11px;border:1px solid var(--border-2);border-radius:var(--radius-sm);
  background:var(--surface-2);color:var(--ink);cursor:pointer;display:flex;flex-direction:column;gap:3px}
.ol-ctx b{font-size:13px}
.ol-ctx span{font-size:11.5px;color:var(--muted);line-height:1.4}
.ol-ctx:hover{border-color:var(--border-strong)}
.ol-ctx.on{border-color:var(--brand);background:var(--brand-tint)}
.ol-ctx.on b{color:var(--brand)}

.ol-opts{display:flex;flex-wrap:wrap;gap:14px;align-items:center}
.ol-opt{display:inline-flex;align-items:center;gap:7px;font-size:12.5px;color:var(--muted)}
.ol-opt select{font:inherit;font-size:12.5px;padding:4px 7px;border:1px solid var(--border-2);
  border-radius:var(--radius-sm);background:var(--surface);color:var(--ink)}
.ol-chk{cursor:pointer}

.ol-ta{display:flex;flex-direction:column;gap:5px}
.ol-talabel{font-size:11.5px;font-weight:600;color:var(--muted)}
.ol-ta textarea{font:inherit;font-family:var(--mono);font-size:12px;line-height:1.5;padding:9px 11px;
  border:1px solid var(--border-2);border-radius:var(--radius-sm);background:var(--surface-2);
  color:var(--ink);resize:vertical;width:100%;box-sizing:border-box}

/* Extra breathing room above the buttons, beyond .ol-input's own 12px flex
   gap — Default linkage and the buttons read as two different steps. */
.ol-actions{display:flex;flex-wrap:wrap;gap:8px;align-items:center;margin-top:10px}
/* Pushed to the end of the row — Documents is a lookup into what's been
   uploaded, not a step in the upload/analyse flow the other buttons form. */
.ol-record-btn{margin-left:auto}
/* .ol-accept lives inside .ol-actions now (see osslic.js), specifically so
   mobile below can reorder it next to Upload & Analyse via `order` — a
   paragraph outside the flex row can't be interleaved between two of its
   buttons with CSS alone. flex:0 0 100% keeps it on its own full-width
   line within the wrapping desktop row too, so moving it in here doesn't
   change the desktop layout — flex-basis:100% alone isn't enough for that:
   with the default flex-shrink:1, a wide desktop row has room to spare
   after the buttons, and the browser shrinks it back down to fit inline
   there instead of wrapping; flex-shrink:0 stops that shrink, but .ol-sub's
   own max-width:78ch (a readability cap meant for running prose) still
   caps it below the row's full width even then, which is just as fatal —
   the item never actually claims enough space to need to wrap, so it never
   does. max-width:none here removes that ceiling for this one use.
   Explicit `order` on every sibling (rather than leaving the buttons at
   the default 0, same as this text) is what keeps their desktop order
   exactly as it was. */
.ol-actions .ol-upload{order:1}
.ol-actions [data-ol-clear],.ol-actions .ol-record-btn{order:2}
.ol-actions .ol-accept{order:3;flex:0 0 100%;max-width:none}
@media (max-width:720px){
  /* Same three groups, stacked one per row and stretched to the primary
     button's width — Clear findings/OSS Inventory used to keep their own
     content width, cramped next to the wide Upload & Analyse button. The
     accepted-file types move up to sit right under Upload & Analyse,
     ahead of the other two buttons: that's the message someone needs
     before they've picked a file, not after. */
  .ol-actions{flex-direction:column;align-items:stretch}
  .ol-record-btn{margin-left:0}
  .ol-actions .ol-accept{order:2}
  .ol-actions [data-ol-clear],.ol-actions .ol-record-btn{order:3}
}

.ol-warn{font-size:12.5px;color:var(--partial);background:var(--partial-bg);
  border:1px solid var(--partial);border-radius:var(--radius-sm);padding:8px 11px}
.ol-none{font-size:13px;color:var(--muted);background:var(--surface);border:1px solid var(--border);
  border-radius:var(--radius);padding:14px 16px}

/* The stale-AI-review banner: sits between the verdict headline and the AI
   review section once a saved analysis has been knocked out of date by a
   context/linking/modified change. Same amber "needs attention" treatment
   as .fa-ai-older (finaudit.js) — the one other place in the app flags an
   analysis pass that hasn't kept up with its document — plus a flex layout
   for the trailing button, which .fa-ai-older's purely-informational banner
   doesn't need. */
.ol-stale{display:flex;flex-wrap:wrap;align-items:center;gap:12px;padding:10px 14px;
  font-size:12.5px;background:var(--surface-2);border:1px solid var(--partial);
  border-left-width:3px;border-radius:var(--radius-sm)}
.ol-stale p{margin:0;flex:1 1 260px;color:var(--ink)}

.ol-head{display:flex;gap:16px;align-items:center;flex-wrap:wrap;
  background:var(--surface);border:1px solid var(--border);border-radius:var(--radius);padding:14px 16px}
.ol-verdict{display:flex;flex-direction:column;gap:2px;padding:9px 14px;border-radius:var(--radius-sm);min-width:170px}
.ol-verdict b{font-size:15px;line-height:1.2}
.ol-verdict span{font-size:11.5px;opacity:.85}
.ol-headbody{flex:1;min-width:240px;display:flex;flex-direction:column;gap:7px}
.ol-counts{font-size:12.5px;color:var(--muted)}
.ol-counts b{color:var(--ink)}
.ol-bar{display:flex;height:9px;border-radius:999px;overflow:hidden;background:var(--track)}
.ol-seg{display:block;height:100%}
.ol-legend{display:flex;flex-wrap:wrap;gap:12px;font-size:11.5px;color:var(--muted)}
.ol-lg{display:inline-flex;align-items:center;gap:5px}
.ol-lg b{color:var(--ink)}
.ol-dot{width:9px;height:9px;border-radius:50%;display:inline-block}

.ol-block{background:var(--surface);border:1px solid var(--border);border-radius:var(--radius);padding:14px 16px}
.ol-block h4,.ol-input h4{margin:0 0 10px;font-size:13.5px;display:flex;align-items:center;gap:8px}
/* .ol-input is a flex column with its own gap between children — the h4's
   own bottom margin above would stack on top of that and over-space it. */
.ol-input h4{margin:0}
/* Findings/Components/AI review fold to this heading — the whole row is the
   click target (nothing else in it is interactive), so it gets the same
   cursor/focus treatment as an actual button without being one. */
.ol-sechead{cursor:pointer;user-select:none}
.ol-sechead:focus-visible{outline:2px solid var(--brand);outline-offset:2px;border-radius:2px}
.ol-secarrow{font-size:10px;color:var(--muted);flex:0 0 auto}
.ol-n{font-size:11.5px;font-weight:600;color:var(--muted);border:1px solid var(--border-2);
  border-radius:999px;padding:0 7px}
.ol-hint{font-size:11.5px;font-weight:400;color:var(--faint);margin-left:auto}
.ol-sub{margin:-4px 0 10px;font-size:12.5px;color:var(--muted);max-width:78ch}

.ol-findings{list-style:none;margin:0;padding:0;display:flex;flex-direction:column;gap:10px}
.ol-finding{border:1px solid var(--border);border-radius:var(--radius-sm);padding:10px 12px;background:var(--surface-2)}
.ol-fhead{display:flex;align-items:center;gap:9px;margin-bottom:5px}
.ol-fhead h5{margin:0;font-size:13px}
.ol-fdetail{margin:0;font-size:12.5px;color:var(--muted);line-height:1.55;max-width:88ch}
.ol-fcomps{margin:7px 0 0;display:flex;flex-wrap:wrap;gap:5px}
.ol-fcomps code{font-family:var(--mono);font-size:11px;padding:1px 6px;border-radius:999px;
  border:1px solid var(--border-2);background:var(--surface);color:var(--muted)}

.ol-pill{font-size:11px;font-weight:700;padding:2px 8px;border-radius:999px;white-space:nowrap}
.ol-ready{color:var(--ready);background:var(--ready-bg)}
.ol-partial{color:var(--partial);background:var(--partial-bg)}
.ol-notready{color:var(--notready);background:var(--notready-bg)}
.ol-critical{color:var(--critical);background:var(--critical-bg)}
.ol-unknown{color:var(--unknown);background:var(--unknown-bg)}
.ol-bg-ready{background:var(--ready)}
.ol-bg-partial{background:var(--partial)}
.ol-bg-notready{background:var(--notready)}
.ol-bg-critical{background:var(--critical)}
.ol-bg-unknown{background:var(--unknown)}

.ol-table{width:100%;border-collapse:collapse;font-size:12.5px}
.ol-table th{text-align:left;font-size:11px;text-transform:uppercase;letter-spacing:.04em;
  color:var(--faint);font-weight:700;padding:0 8px 6px;border-bottom:1px solid var(--border)}
.ol-table td{padding:7px 8px;border-bottom:1px solid var(--border);vertical-align:top}
.ol-row{cursor:pointer}
.ol-row:hover{background:var(--surface-2)}
.ol-row.open{background:var(--surface-2)}
.ol-row:focus-visible{outline:2px solid var(--brand);outline-offset:-2px}
.ol-name b{font-weight:600}
.ol-ver{color:var(--muted);font-size:11.5px}
.ol-lic code{font-family:var(--mono);font-size:11.5px;word-break:break-word}
.ol-vd{color:var(--muted)}
.ol-tag{font-size:10.5px;padding:1px 6px;border-radius:999px;border:1px solid var(--border-2);
  color:var(--muted);white-space:nowrap}
.ol-tag.warn{border-color:var(--partial);color:var(--partial)}
.ol-why td{background:var(--surface-2);padding-top:0}
.ol-reasons{margin:0;padding:0 0 0 18px;font-size:12.5px;color:var(--muted);line-height:1.55;max-width:92ch}
.ol-reasons li{margin:3px 0}
.ol-obl{margin-top:8px;font-size:12.5px}
.ol-obl b{font-size:11.5px;color:var(--muted)}
.ol-obl ul{margin:4px 0 0;padding:0 0 0 18px;color:var(--muted);line-height:1.55}
.ol-obligations{margin:0;padding:0 0 0 18px;font-size:12.5px;color:var(--muted);line-height:1.6;max-width:92ch}

@media (max-width:760px){
  .ol-table thead{display:none}
  .ol-table tr{display:block;border-bottom:1px solid var(--border);padding:6px 0}
  .ol-table td{display:block;border:0;padding:2px 4px}
  .ol-head{flex-direction:column;align-items:stretch}
}

/* OSS licence review — file intake (picker, drop target, read errors).
   .ol-upload is a <label>, not a <button>, so it does not pick up the base
   button{} element rule the way .btn-primary/.btn-outline normally do —
   those two only ever set colour, so the shape has to be supplied here. */
/* No border-color here, deliberately: .ol-upload always pairs with
   .btn-primary or .btn-outline, and those set border-color themselves. A
   shorthand `border:1px solid transparent` here — even though it's the
   same specificity — would win on source order (this rule comes after
   them in the file) and silently reset it, which is exactly what made the
   .btn-outline variant invisible (.btn-primary only hid the bug because its
   solid fill doesn't depend on the border being visible). */
.ol-upload{display:inline-flex;align-items:center;gap:7px;font-family:inherit;font-size:13.5px;
  font-weight:650;cursor:pointer;border-width:1px;border-style:solid;border-radius:var(--radius-sm);
  padding:8px 14px;transition:background .12s,border-color .12s,transform .05s}
.ol-upload:focus-visible{outline:2px solid var(--brand);outline-offset:2px}
/* Disabled until a deployment context and a default linkage are both picked,
   or while an upload/analysis is already in flight — the label can't rely on
   the hidden input's :disabled styling alone. */
.ol-upload.disabled{opacity:.5;cursor:not-allowed}
/* Set smaller than .ol-sub's default 12.5px — this is fine print, not a
   sentence of its own. No pull-up margin any more: it's an .ol-actions flex
   item now (see there), spaced by that row's own 8px gap, not .ol-input's
   wider one it used to sit against as a plain sibling. */
.ol-accept{margin:0;font-size:11px}
/* The drop target is the whole inventory box, so a file aimed anywhere near
   the textarea lands rather than navigating the tab away to the file. */
.ol-ta.drag textarea{border-color:var(--brand);background:var(--brand-tint)}
.ol-ta.drag .ol-talabel{color:var(--brand)}

/* OSS licence review — the AI second pass. Same card background as
   Findings/Components/Obligations (all .ol-block) now that it sits among
   them as an equal, collapsible section rather than a visually subordinate
   panel; the .ol-aitag "second pass" badge is what marks it as generated,
   not a different background tint. */
.ol-aitag{font-size:9.5px;font-weight:700;letter-spacing:.04em;text-transform:uppercase;
  padding:1px 6px;border-radius:9px;color:var(--muted);border:1px solid var(--border-2);background:var(--surface)}
/* The AI review section's "analyzing" progress badge — a centred circle
   with a spinner in place of an icon (see .is-busy below) and a caption
   naming what's being analysed underneath. The one clickable "Re-run AI
   analysis" control lives in the stale banner above the report now
   (.ol-stale, further down) — this badge is progress feedback only. */
.ol-rerun-cta{display:flex;flex-direction:column;align-items:center;gap:10px;padding:18px 0;text-align:center}
.ol-rerun-btn{display:inline-flex;align-items:center;justify-content:center;width:52px;height:52px;
  border-radius:50%;border:1px solid var(--border-2);background:var(--surface-2);color:var(--brand);
  cursor:pointer;transition:background .12s,border-color .12s,transform .05s}
.ol-rerun-btn:hover{background:var(--brand-tint);border-color:var(--brand)}
.ol-rerun-btn:active{transform:scale(.94)}
.ol-rerun-btn:focus-visible{outline:2px solid var(--brand);outline-offset:2px}
/* The in-flight variant of the same badge — a <span>, not a <button>, since
   there's nothing to click mid-analysis; .is-busy drops the pointer cursor
   and hover/active affordances that would otherwise imply it still is one. */
.ol-rerun-btn.is-busy{cursor:default}
.ol-rerun-btn.is-busy:hover{background:var(--surface-2);border-color:var(--border-2)}
.ol-rerun-btn .ai-spin{width:24px;height:24px;border-width:3px}
.ol-rerun-label{margin:0;font-size:13px;font-weight:600;color:var(--ink);max-width:44ch}
.ol-aisum{margin:0 0 12px;font-size:13px;line-height:1.6;color:var(--ink);max-width:88ch}
.ol-aih{margin:14px 0 8px;font-size:12px;text-transform:uppercase;letter-spacing:.04em;color:var(--faint)}
.ol-act{border:1px solid var(--border);border-radius:var(--radius-sm);padding:10px 12px;background:var(--surface)}
.ol-unres{list-style:none;margin:0;padding:0;display:flex;flex-direction:column;gap:10px}
.ol-unres li{border:1px solid var(--border);border-radius:var(--radius-sm);padding:10px 12px;background:var(--surface);font-size:12.5px}
.ol-unres code{font-family:var(--mono);font-size:11.5px;padding:1px 6px;border-radius:999px;
  border:1px solid var(--border-2);background:var(--surface-2);color:var(--muted)}
.ol-unres p{margin:6px 0 0}

/* OSS licence review — the workspace record (stored inventories) */
.ol-docs{list-style:none;margin:0;padding:0;display:flex;flex-direction:column;gap:6px}
.ol-doc{display:flex;align-items:center;gap:9px;font-size:12.5px;padding:7px 10px;
  border:1px solid var(--border);border-radius:var(--radius-sm);background:var(--surface)}
.ol-docname{font-weight:600;color:var(--brand);text-decoration:none}
.ol-docname:hover{text-decoration:underline}
.ol-docmeta{color:var(--muted);font-size:11.5px}
.ol-docx{margin-left:auto;border:0;background:transparent;color:var(--muted);cursor:pointer;font-size:15px;line-height:1;padding:0 4px}
.ol-docx:hover{color:var(--notready)}
/* Meta drops out so the name — truncated with an ellipsis rather than
   wrapped — stays on the same row as the Current tag and delete button. */
@media (max-width:640px){
  .ol-docmeta{display:none}
  .ol-docname{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
}
.ol-inlinewarn{padding:4px 9px;font-size:12px;margin-top:8px}
/* "What am I looking at" — the filename is set off from the surrounding
   muted meta (status, date, version) by colour and weight, not a separate
   badge, so it reads as the one thing on this line that matters most. */
.ol-docid{font-size:12.5px;color:var(--muted)}
.ol-docid b{color:var(--ink);font-weight:650}
/* Holds the version picker, shown once there is more than one run. Sits
   inside .ol-input's own flex column now (see docIdentityHtml()), so its
   spacing to neighbours comes from that column's gap, not its own margin. */
.ol-viewing{display:flex;align-items:center;gap:10px;flex-wrap:wrap}
.ol-histpick{display:inline-flex;align-items:center;gap:7px;font-size:12.5px;color:var(--muted)}
.ol-histpick select{font:inherit;font-size:12.5px;padding:4px 7px;border:1px solid var(--border-2);
  border-radius:var(--radius-sm);background:var(--surface);color:var(--ink)}
@media (max-width:640px){.ol-histpick{flex-wrap:wrap;width:100%}.ol-histpick select{flex:1 1 100%;min-width:0;max-width:100%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}}
.ol-linkbtn{border:0;background:transparent;color:inherit;text-decoration:underline;cursor:pointer;font:inherit;padding:0}
