/*
 * ChaxIQ autotagger trial app — ported from the locked design "B / Bold civic"
 * (design/mockups/v3/b-civic.html). Brand: Lapis Blue #283584 + Chax Red #E7131A,
 * PT Sans. Accessible by construction (skip link, focus rings, reduced motion).
 * Font URLs resolved by Propshaft (files live in app/assets/fonts/).
 */
@font-face{font-family:'PT Sans';src:url("/assets/PTSans-Regular-29f3529d.ttf") format('truetype');font-weight:400;font-display:swap}
@font-face{font-family:'PT Sans';src:url("/assets/PTSans-Bold-f757dd12.ttf") format('truetype');font-weight:700;font-display:swap}

:root{
  /* Tells the browser which way its own controls should render: the date
     picker's calendar glyph and popup, select dropdowns, scrollbars. Without it
     they stay in light chrome on the dark theme, which renders the calendar
     icon dark-on-dark and makes the date field look like it has no picker. */
  color-scheme:light;
  --bg:#ffffff; --surface:#f4f6fc; --page:#dfe5f2; --card:#ffffff; --text:#231f20; --muted:#565b73; --border:#d3dae9;
  --lapis:#283584; --lapis-deep:#1d2862;
  --red:#e7131a; --red-deep:#c20f15; --blue:#2798ef; --yellow:#ffe471;
  /* Red as a FILL under white text: buttons, labels, the alert banner, failure
     markers. Separate from --red, which dark mode lightens so red TEXT reads on
     a dark ground; under white text that lighter red measured 3.05:1. White on
     these is 4.66:1 and 6.23:1. */
  --red-fill:#e7131a; --red-fill-hover:#c20f15;
  --hero-grad:linear-gradient(150deg,#2b3890,#1a2358);
  --ring:#ffe471; --shadow:0 22px 55px rgba(27,35,88,.22); --warn-line:#8a6100;
  /* Tag-type colours (validated categorical palette). Red is reserved for the
     failing state, so no tag type uses it. */
  --t-heading:#2a78d6; --t-text:#1baf7a; --t-th:#eda100; --t-td:#008300;
  --t-link:#4a3aa7; --t-form:#eb6834; --t-figure:#e87ba4;
}
[data-theme="dark"]{
  color-scheme:dark;
  --bg:#0c1230; --surface:#141c44; --page:#0c1230; --card:#141c44; --text:#eef1fb; --muted:#aab2d6; --border:#283163;
  --lapis:#8f9ce4; --lapis-deep:#aab4ec; --red:#ff5a5f; --red-deep:#ff7a7e;
  /* White on these is 6.23:1 and 8.00:1; see --red-fill above. */
  --red-fill:#c20f15; --red-fill-hover:#a30d12;
  --hero-grad:linear-gradient(150deg,#161f4d,#0e1638);
  --ring:#ffe471; --shadow:0 22px 55px rgba(0,0,0,.55); --warn-line:#ffd166;
  --t-heading:#3987e5; --t-text:#199e70; --t-th:#c98500; --t-td:#008300;
  --t-link:#9085e9; --t-form:#d95926; --t-figure:#d55181;
}
*{box-sizing:border-box}
/* The UA gives [hidden] display:none, but any rule that sets display beats it —
   .btn sets inline-flex, so a hidden button stayed on screen. Restore the
   attribute's meaning once, globally, rather than per component. */
[hidden]{display:none!important}
html{scroll-behavior:smooth}
body{margin:0;background:var(--page);color:var(--text);font-family:'PT Sans',-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Arial,sans-serif;line-height:1.55}
a{color:var(--lapis)}
.wrap{max-width:1120px;margin:0 auto;padding:0 24px}
.skip{position:absolute;left:-9999px;background:var(--yellow);color:#231f20;padding:10px 16px;border-radius:8px;z-index:10}
.skip:focus{left:16px;top:16px}
:focus-visible{outline:4px solid var(--ring);outline-offset:3px;border-radius:6px}

.hero-field{background:var(--hero-grad);color:#fff}
header{position:sticky;top:0;background:color-mix(in srgb,#1b2358 80%,transparent);backdrop-filter:blur(8px);z-index:5;border-bottom:1px solid rgba(255,255,255,.12)}
.bar{display:flex;align-items:center;gap:18px;height:72px}
.bar img.logo{height:36px;width:auto}
nav[aria-label="Primary"]{margin-left:auto}
nav ul{display:flex;gap:24px;list-style:none;margin:0;padding:0}
/* Scoped to the header: this is pale text for the dark bar. Unscoped it also
   claimed the pager's nav on a light card, where #cfd6f3 measured 1.14:1
   (axe, 2026-09-25). The pager's links fall back to the ordinary link colour. */
header nav a{color:#cfd6f3;text-decoration:none;font-weight:700;font-size:.92rem}
header nav a:hover{color:#fff}
.toggle{display:inline-flex;align-items:center;gap:8px;background:rgba(255,255,255,.12);color:#fff;border:1px solid rgba(255,255,255,.3);border-radius:999px;padding:8px 14px;font-weight:700;cursor:pointer;font-family:inherit}
.toggle:hover{background:rgba(255,255,255,.2)}

/* ---- Profile disclosure (account menu) ----
   A disclosure, not a role="menu": the contents are ordinary links, so Tab
   navigation is what users expect and what the browser already gets right. */
.profile{position:relative;display:flex;align-items:center}
.profile-btn{display:inline-flex;align-items:center;gap:6px;background:rgba(255,255,255,.12);border:1px solid rgba(255,255,255,.3);border-radius:999px;padding:4px 10px 4px 4px;color:#fff;font:inherit;font-weight:700;cursor:pointer}
.profile-btn:hover{background:rgba(255,255,255,.2)}
/* Brand red pinned, not var(--red): the dark theme lightens that token for
   text-on-dark, which drops white-on-red to ~3:1 in the avatar. */
.profile-initial{display:grid;place-items:center;width:28px;height:28px;border-radius:999px;background:#E7131A;color:#fff;font-size:.85rem;line-height:1}
.profile-caret{font-size:.7rem}
.profile-menu{position:absolute;right:0;top:calc(100% + 12px);min-width:15rem;background:var(--card);border:1px solid var(--border);border-radius:12px;box-shadow:var(--shadow);padding:10px;z-index:10}
.profile-menu[hidden]{display:none}
.profile-who{margin:0 0 8px;padding:2px 8px;color:var(--muted);font-size:.85rem;overflow-wrap:anywhere}
.profile-menu ul{display:block;list-style:none;margin:0;padding:0}
.profile-menu li + li{margin-top:2px}
.profile-menu form{margin:0}
/* `.bar .linkbtn` further down the file is the pale blue for the dark header and
   has equal specificity, so it would win on source order and leave "Sign out" at
   1.4:1 on the light panel. Hence `.bar` here — it outweighs rather than races. */
.profile-menu a,.bar .profile-menu .linkbtn{display:block;width:100%;text-align:left;padding:8px;border-radius:8px;color:var(--text);text-decoration:none;font-size:.95rem;font-weight:700}
.profile-menu a:hover,.bar .profile-menu .linkbtn:hover{background:var(--surface);color:var(--text)}

.btn{display:inline-flex;align-items:center;gap:10px;font-weight:700;border-radius:11px;padding:16px 26px;text-decoration:none;cursor:pointer;border:2px solid transparent;font-size:1.05rem;font-family:inherit}
/* White text on a red fill: --red-fill, not --red (see the token). */
.btn-red{background:var(--red-fill);color:#fff;border-color:var(--red-fill)}
.btn-red:hover{background:var(--red-fill-hover);border-color:var(--red-fill-hover)}
.btn-yellow{background:var(--yellow);color:#231f20;border-color:var(--yellow)}
.btn-yellow:hover{filter:brightness(.95)}
.btn-on-dark{background:transparent;color:#fff;border-color:rgba(255,255,255,.5)}
.btn-on-dark:hover{background:rgba(255,255,255,.12)}

.hero{padding:72px 0 80px;text-align:center}
.kicker{display:inline-flex;gap:8px;align-items:center;background:rgba(255,255,255,.12);border:1px solid rgba(255,255,255,.22);color:#fff;border-radius:999px;padding:7px 16px;font-weight:700;font-size:.85rem;margin-bottom:24px}
.kicker .yr{color:var(--yellow)}
.hero h1{font-size:clamp(2.6rem,7vw,5rem);line-height:.98;letter-spacing:-.03em;margin:0 auto 20px;max-width:15ch}
.hero h1 .hl{color:var(--yellow)}
.hero p.lead{font-size:1.25rem;color:#d3d9f4;max-width:50ch;margin:0 auto 30px}
.cta-row{display:flex;flex-wrap:wrap;gap:16px;justify-content:center}

.strip{max-width:1120px;margin:-46px auto 0;padding:0 24px;position:relative;z-index:2}
.strip-inner{display:grid;grid-template-columns:repeat(4,1fr);background:var(--bg);border:1px solid var(--border);border-radius:18px;box-shadow:var(--shadow);overflow:hidden}
.si{padding:24px;text-align:center;border-right:1px solid var(--border)}
.si:last-child{border-right:none}
.si b{display:block;font-size:1.9rem;font-weight:700;color:var(--lapis)}
[data-theme="dark"] .si b{color:var(--text)}
.si span{color:var(--muted);font-size:.84rem}

section{padding:44px 0}
.lbl{display:inline-block;font-weight:700;color:#fff;background:var(--red-fill);letter-spacing:.06em;text-transform:uppercase;font-size:.76rem;padding:5px 12px;border-radius:6px;margin:0 0 16px}
h2{font-size:clamp(1.8rem,4.5vw,2.7rem);letter-spacing:-.02em;margin:0 0 22px;color:var(--lapis)}
[data-theme="dark"] h2{color:var(--text)}

.steps{display:grid;grid-template-columns:repeat(3,1fr);gap:22px}
.step{background:var(--card);border:1px solid var(--border);border-radius:16px;padding:30px;border-top:5px solid var(--lapis)}
.step:nth-child(2){border-top-color:var(--red)}
.step:nth-child(3){border-top-color:var(--blue)}
.step img{width:58px;height:58px;margin-bottom:10px}
.step h3{margin:0 0 10px;font-size:1.25rem;color:var(--lapis)}
[data-theme="dark"] .step h3{color:var(--text)}
.step p{margin:0;color:var(--muted)}

.compliance{background:var(--surface)}
.badges{display:flex;flex-wrap:wrap;gap:12px}
.badge{border:2px solid var(--lapis);color:var(--lapis);background:transparent;border-radius:10px;padding:11px 18px;font-weight:700;font-size:.88rem}
[data-theme="dark"] .badge{border-color:var(--border);color:var(--text)}
.badge.on{background:var(--yellow);color:#231f20;border-color:var(--yellow)}

.ctaband{background:var(--hero-grad);color:#fff;border-radius:22px;padding:62px 40px;text-align:center}
.ctaband h2{color:#fff}
.ctaband p{color:#d3d9f4;max-width:46ch;margin:0 auto 28px}

footer{padding:38px 0;color:var(--muted);font-size:.88rem;border-top:1px solid var(--border)}
footer img{height:30px;width:auto;vertical-align:middle;margin-right:10px}
.logo-dark{display:none}
[data-theme="dark"] .logo-light{display:none}
[data-theme="dark"] .logo-dark{display:inline-block}
@media (max-width:760px){.strip-inner{grid-template-columns:1fr 1fr}.si:nth-child(2){border-right:none}.si{border-bottom:1px solid var(--border)}.steps{grid-template-columns:1fr}nav[aria-label="Primary"]{display:none}}
@media (prefers-reduced-motion:reduce){*{transition:none!important;scroll-behavior:auto!important}}

/* ---- Flow screens (signup / upload / status) reuse the card + button system ---- */
.panel{max-width:560px;margin:0 auto;background:var(--card);border:1px solid var(--border);border-radius:18px;box-shadow:var(--shadow);padding:40px}
.panel h1{font-size:clamp(1.8rem,4vw,2.4rem);color:var(--lapis);margin:0 0 10px;letter-spacing:-.02em}
[data-theme="dark"] .panel h1{color:var(--text)}
.panel p.sub{color:var(--muted);margin:0 0 24px}
.field{display:block;margin:0 0 18px}
.field label{display:block;font-weight:700;margin:0 0 6px}
.field input[type=email],.field input[type=text],.field input[type=password]{width:100%;font-family:inherit;font-size:1rem;padding:13px 14px;border:2px solid var(--border);border-radius:11px;background:var(--bg);color:var(--text)}

/* Branded, cross-browser file picker: native input visually replaced by a
   label-button (clicking the label opens the picker in every browser). */
.field-heading{display:block;font-weight:700;margin:0 0 6px}
.filepick{display:flex;align-items:center;gap:14px;flex-wrap:wrap}
.filepick input[type=file]{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap;border:0}
.filepick .filepick-btn{display:inline-flex;align-items:center;gap:8px;margin:0;font-weight:700;font-family:inherit;font-size:1rem;color:#fff;background:var(--lapis);border:2px solid var(--lapis);border-radius:11px;padding:13px 20px;cursor:pointer}
.filepick .filepick-btn:hover{background:var(--lapis-deep);border-color:var(--lapis-deep)}
[data-theme="dark"] .filepick .filepick-btn{color:#0c1230}
.filepick input[type=file]:focus-visible + .filepick-btn{outline:4px solid var(--ring);outline-offset:3px}
.filepick-name{color:var(--muted)}
/* The size refusal sits inside the picker's flex row (it must, to be a target of
   the picker's controller); full width puts it on its own line under the button. */
.filepick .upload-size-error{flex-basis:100%;margin:2px 0 0}
.field .hint{color:var(--muted);font-size:.85rem;margin:6px 0 0}
.form-notes{margin-top:26px;padding:16px 18px;background:var(--surface);border:1px solid var(--border);border-radius:12px}
.form-notes-heading{font-size:.95rem;margin:0 0 8px;color:var(--text)}
.form-notes ul{margin:0;padding-left:18px;color:var(--muted);font-size:.9rem}
.form-notes li{margin:4px 0}
.flash{border-radius:11px;padding:13px 16px;margin:0 0 20px;font-weight:700}
.flash-notice{background:var(--yellow);color:#231f20}
.flash-alert{background:var(--red-fill);color:#fff}
.errors{background:color-mix(in srgb,var(--red) 14%,transparent);border:1px solid var(--red);border-radius:11px;padding:13px 16px;margin:0 0 20px}
.errors ul{margin:6px 0 0;padding-left:20px}
.center-wrap{padding:60px 0}

/* ---- Submission status panel ---- */
.btn-outline{background:transparent;color:var(--lapis);border-color:var(--lapis)}
.btn-outline:hover{background:color-mix(in srgb,var(--lapis) 10%,transparent)}
.status-state{font-size:1.15rem;font-weight:700;margin:0 0 8px}
.state-working{color:var(--lapis)}
[data-theme="dark"] .state-working{color:var(--text)}
.state-done{color:#1a7f37}
[data-theme="dark"] .state-done{color:#5bd07a}
.state-failed{color:var(--red)}
.state-canceled{color:var(--muted)}
.cancel-audit{margin-top:14px}
.state-note{color:var(--lapis)}
[data-theme="dark"] .state-note{color:var(--text)}
.state-note .i-mark{display:inline-block;width:18px;height:18px;line-height:18px;text-align:center;border-radius:50%;background:var(--lapis);color:#fff;font-size:.8rem;font-style:normal;font-weight:700;margin-right:8px;vertical-align:middle}
.dot{display:inline-block;width:12px;height:12px;border-radius:50%;background:var(--lapis);margin-right:8px;animation:pulse 1.2s ease-in-out infinite;vertical-align:middle}
@keyframes pulse{0%,100%{opacity:.3}50%{opacity:1}}
@media (prefers-reduced-motion:reduce){.dot{animation:none}}
.result{margin:10px 0}
.findings{margin:18px 0 0;padding:0;list-style:none}
.findings li{padding:10px 0;border-top:1px solid var(--border);font-size:.92rem;color:var(--muted)}
.findings .clause{font-weight:700;color:var(--lapis);margin-right:6px}
[data-theme="dark"] .findings .clause{color:var(--text)}

/* Done state: primary download + deliverable cards */
.result-badges{margin:20px 0 0}
.btn-block{width:100%;justify-content:center}
.deliverables{display:grid;grid-template-columns:1fr 1fr;gap:14px;margin:16px 0 2px}
@media (max-width:520px){.deliverables{grid-template-columns:1fr}}
.deliverable{display:flex;flex-direction:column;gap:5px;text-decoration:none;background:var(--surface);border:1px solid var(--border);border-top:4px solid var(--lapis);border-radius:14px;padding:16px 16px 18px;color:var(--text);transition:box-shadow .15s ease,transform .15s ease}
.deliverable:hover{box-shadow:var(--shadow);transform:translateY(-2px)}
.deliverable--report{border-top-color:var(--lapis)}
.deliverable--overlay{border-top-color:var(--blue)}
/* Three cards in a two-column grid: the report runs the full width so the two
   overlays sit side by side as a before/after pair. */
.deliverable--wide{grid-column:1/-1}
.deliverable .d-icon{width:34px;height:34px;margin-bottom:2px}
.deliverable .d-title{font-weight:700;font-size:1.02rem;color:var(--lapis)}
[data-theme="dark"] .deliverable .d-title{color:var(--text)}
.deliverable .d-desc{color:var(--muted);font-size:.84rem;line-height:1.4}
.deliverable .d-cta{margin-top:6px;font-weight:700;font-size:.84rem;color:var(--red)}
.reports-pending{display:flex;align-items:center;gap:10px;margin:16px 0 2px;padding:14px 16px;background:var(--surface);border:1px solid var(--border);border-radius:12px;color:var(--muted);font-size:.92rem}
.reports-note{margin-top:14px}
/* Drop zone: a dashed target around the existing pick-a-file controls. Drag is
   mouse-only, so this is decoration over a control that already works from the
   keyboard — the button and the file input inside are unchanged. The hover state
   changes border AND background, so it does not depend on colour alone. */
.dropzone{display:block;border:2px dashed var(--border);border-radius:14px;padding:22px;background:var(--surface);transition:border-color .12s ease,background-color .12s ease}
.dropzone--over{border-color:var(--lapis);background:color-mix(in srgb,var(--lapis) 10%,var(--surface))}
.dropzone .dropzone-lead{margin:0 0 10px;color:var(--muted);font-weight:700}
.dropzone .filepick-name{display:inline-block;margin-left:14px}
.dropzone .hint{margin-top:12px}

/* Opt-in checkbox with a second line of explanation under the label text. */
.checkline{display:flex;align-items:flex-start;gap:10px;margin:0}
.checkline input[type=checkbox]{margin-top:3px;width:18px;height:18px;flex:0 0 auto}
.checkline label{font-weight:700}
.checkline-note{display:block;font-weight:400;color:var(--muted);font-size:.88rem}

/* Secondary route out of a form: a sibling path for a different starting point,
   set apart from the primary action without competing with it. */
.aside-route{margin:22px 0 0;padding-top:18px;border-top:1px solid var(--border);color:var(--muted);font-size:.92rem}
/* Result-panel warning: the run finished, but the audited document may not be the
   page that was asked for (entry status >= 400). Tinted fill plus a solid rule so
   it reads as a warning without relying on colour alone — the bolded first line
   carries the meaning. */
.audit-warning{background:color-mix(in srgb,var(--yellow) 26%,transparent);border:1px solid var(--warn-line);border-left-width:5px;border-radius:11px;padding:13px 16px;margin:0 0 18px;color:var(--text)}
.audit-warning b{display:block;margin-bottom:4px}
.findings-box{margin:20px 0 0;padding:2px 16px;background:var(--surface);border:1px solid var(--border);border-radius:12px}
.findings-box summary{cursor:pointer;font-weight:700;color:var(--text);padding:12px 0}
.findings-box .findings{margin:0 0 8px}
/* Ask-an-AI: a quiet block at the foot of the findings list (submissions/_ask_ai). */
.ask-ai{border-top:1px solid var(--border);margin:6px 0 10px;padding:12px 0 0}
.ask-ai-heading{margin:0 0 10px;font-weight:700}
.ask-ai-actions{display:flex;flex-wrap:wrap;gap:10px}
.ask-ai .copy-status{margin:8px 0 0}
.ask-ai-question summary{cursor:pointer;font-weight:700;color:var(--lapis);padding:4px 0}
[data-theme="dark"] .ask-ai-question summary{color:var(--text)}
.ask-ai-text{white-space:pre-line;margin:6px 0 0;padding:10px 12px;background:var(--card);border:1px solid var(--border);border-radius:8px;font-size:.88rem;overflow-wrap:anywhere}
.ask-ai-note{margin:8px 0 0}
.result-footer{display:flex;flex-wrap:wrap;gap:10px;align-items:center;margin-top:22px;color:var(--muted);font-size:.9rem}
.subtle-link{color:var(--muted);text-decoration:underline}
.subtle-link:hover{color:var(--lapis)}
[data-theme="dark"] .subtle-link:hover{color:var(--text)}

/* ---- Hub: two product choices (links styled as large cards) ---- */
.choices{display:grid;grid-template-columns:1fr 1fr;gap:22px}
@media (max-width:760px){.choices{grid-template-columns:1fr}}
.choice{display:flex;flex-direction:column;gap:8px;text-decoration:none;background:var(--card);border:1px solid var(--border);border-top:5px solid var(--lapis);border-radius:16px;padding:30px;color:var(--text);transition:box-shadow .15s ease,transform .15s ease}
.choice:hover{box-shadow:var(--shadow);transform:translateY(-2px)}
.choice--audit{border-top-color:var(--red)}
.choice .c-icon{width:58px;height:58px;margin-bottom:6px}
.choice .c-title{font-weight:700;font-size:1.35rem;color:var(--lapis)}
[data-theme="dark"] .choice .c-title{color:var(--text)}
.choice .c-desc{color:var(--muted)}
.choice .c-cta{margin-top:8px;font-weight:700;color:var(--red)}
/* The signed-in chooser POSTs (it carries the "remember" checkbox), so its cards
   are submit buttons, not links. Strip the button chrome only — everything else
   is the same .choice card, and :focus-visible is already global. */
button.choice{font:inherit;text-align:left;cursor:pointer;appearance:none}
/* Two options or three, without a second breakpoint to keep in sync. */
.choices--flex{grid-template-columns:repeat(auto-fit,minmax(15.5rem,1fr))}
.choice--runs{border-top-color:var(--muted)}

/* ---- Signed-in chooser ---- */
.start-page{padding:40px 0 70px}
/* The intro used to be spaced off the cards by the checkbox block that sat
   between them; with that moved below, the gap has to be explicit. */
.start-page .choices{margin-top:26px}
/* Under the options and right-aligned, which lands the box itself nearer the
   middle of the page. Order here matches DOM order on purpose — see the note in
   the view. */
.start-remember{display:flex;align-items:flex-start;justify-content:flex-end;gap:10px;margin:22px 0 0;color:var(--muted)}
@media (max-width:760px){.start-remember{justify-content:flex-start}}
.start-remember input{margin-top:.25rem;width:1.15rem;height:1.15rem;flex:none}
.start-remember label{max-width:60ch}

/* ---- Activity dashboard ---- */
.dash-head{padding:40px 0 70px}
.dash-sub{color:var(--muted);max-width:60ch;margin:6px 0 0}
.dash-bar{display:flex;align-items:baseline;gap:16px;flex-wrap:wrap;margin:0 0 18px}
.dash-bar h2{margin:0}
.live-now{display:inline-flex;align-items:center;gap:8px;color:var(--muted);font-weight:700;font-size:.9rem}
.table-card{background:var(--card);border:1px solid var(--border);border-radius:16px;box-shadow:var(--shadow);overflow:hidden}
table.activity{width:100%;border-collapse:collapse;font-size:.94rem}
table.activity th{text-align:left;font-size:.74rem;letter-spacing:.06em;text-transform:uppercase;color:var(--muted);padding:14px 18px;border-bottom:1px solid var(--border);background:var(--surface)}
table.activity td{padding:13px 18px;border-bottom:1px solid var(--border);vertical-align:middle}
table.activity tr:last-child td{border-bottom:none}
table.activity tbody tr:hover{background:var(--surface)}
.t-when{color:var(--muted);white-space:nowrap}
.t-kind{white-space:nowrap;font-weight:700;color:var(--lapis)}
[data-theme="dark"] .t-kind{color:var(--text)}
.t-kind .k-icon{width:20px;height:20px;vertical-align:-5px;margin-right:8px}
.t-who{color:var(--muted);white-space:nowrap}
.t-target{font-weight:700;word-break:break-all}
.t-result{color:var(--muted);white-space:nowrap}
.chip{display:inline-block;font-weight:700;font-size:.78rem;padding:4px 11px;border-radius:999px;text-transform:capitalize}
.chip--working{background:color-mix(in srgb,var(--lapis) 14%,transparent);color:var(--lapis)}
[data-theme="dark"] .chip--working{color:var(--text)}
/* #1a7f37 measured 4.09:1 against its own 16% tint (2026-09-25, axe) — under
   the 4.5:1 floor on both the activity table and the engine cards. #15692c is
   5.3:1 there. */
.chip--done{background:color-mix(in srgb,#15692c 16%,transparent);color:#15692c}
[data-theme="dark"] .chip--done{color:#5bd07a}
.chip--failed{background:color-mix(in srgb,var(--red) 16%,transparent);color:var(--red-deep)}
.retag-offer{margin:22px 0 0;padding:18px 0 0;border-top:1px solid var(--border)}
.retag-offer .retag-q{font-weight:700;color:var(--lapis);margin:0 0 4px}
[data-theme="dark"] .retag-offer .retag-q{color:var(--text)}
.retag-offer form{margin-top:12px}
.chip--note{background:color-mix(in srgb,var(--yellow) 30%,transparent);color:#6a4a00}
[data-theme="dark"] .chip--note{color:var(--yellow)}
/* Who goes below 760px. Addressed by class, not position: this was
   th:nth-child(3) back when Who was the third column, and the column reorder
   left it hiding Result's header while still showing Result's cells. */
@media (max-width:760px){table.activity .t-who{display:none}}

/* ---- Audit report-format chooser ---- */
.formats{border:1px solid var(--border);border-radius:11px;padding:10px 16px 6px;margin:0 0 20px}
.formats legend{padding:0 6px;font-weight:700}
.format{display:flex;gap:11px;align-items:flex-start;padding:9px 0;cursor:pointer}
.format + .format{border-top:1px solid var(--border)}
.format input[type=radio]{margin-top:5px;width:18px;height:18px;accent-color:var(--lapis);flex:none}
.format-text{display:flex;flex-direction:column;gap:2px}
.format-label{font-weight:700}
.format-hint{color:var(--muted);font-size:.85rem;line-height:1.4}

/* ---- Audit status: progress bar + result counts ---- */
.progress{height:12px;background:var(--surface);border:1px solid var(--border);border-radius:999px;overflow:hidden;margin:14px 0 10px}
.progress-fill{display:block;height:100%;background:var(--lapis);border-radius:999px;transition:width .3s ease}
[data-theme="dark"] .progress-fill{background:var(--lapis-deep)}
@media (prefers-reduced-motion:reduce){.progress-fill{transition:none}}
/* Pre-flight (no count yet): an indeterminate sweep so the bar reads as "working". */
.progress--indeterminate .progress-fill{width:35%;border-radius:999px;animation:indeterminate 1.6s ease-in-out infinite}
@keyframes indeterminate{0%{margin-left:-35%}100%{margin-left:100%}}
@media (prefers-reduced-motion:reduce){.progress--indeterminate .progress-fill{animation:none;width:100%;opacity:.45}}
.elapsed{font-variant-numeric:tabular-nums;font-weight:700}
.count-grid{display:grid;grid-template-columns:repeat(3,1fr);gap:14px;margin:8px 0 20px}
.count{text-align:center;background:var(--surface);border:1px solid var(--border);border-top:4px solid var(--lapis);border-radius:14px;padding:18px 12px}
.count b{display:block;font-size:1.9rem;font-weight:700;color:var(--lapis)}
[data-theme="dark"] .count b{color:var(--text)}
.count span{color:var(--muted);font-size:.84rem}
.count--fail{border-top-color:var(--red)}
.count--fail b{color:var(--red)}
.count--warn{border-top-color:var(--yellow)}
.count--pass{border-top-color:#1a7f37}
.count--pass b{color:#1a7f37}
[data-theme="dark"] .count--pass b{color:#5bd07a}

/* ---- Remediation editor: page-raster canvas + overlay boxes + findings ---- */
.rm-head{display:flex;flex-wrap:wrap;gap:14px 24px;align-items:flex-start;justify-content:space-between;margin:0 0 22px}
.rm-head-titles{min-width:0}
.rm-head-actions{flex:0 1 340px;min-width:260px;display:flex;flex-direction:column;gap:10px;align-items:stretch;margin-top:4px}
.rm-head-actions .result-badges,.rm-head-actions .hint,.rm-head-actions .rm-pending-bar{margin:0}
.rm-head h1{font-size:clamp(1.8rem,4vw,2.4rem);color:var(--lapis);margin:0 0 4px;letter-spacing:-.02em}
[data-theme="dark"] .rm-head h1{color:var(--text)}
.rm-head .sub{color:var(--muted);margin:0;word-break:break-all}
/* Working / failed states: a narrow card, same feel as the status panel. */
.rm-status-card{max-width:560px;margin:0 auto;background:var(--card);border:1px solid var(--border);border-radius:18px;box-shadow:var(--shadow);padding:32px}
.rm-working{display:flex;align-items:center;gap:10px;color:var(--muted);margin:14px 0 0}
/* Ready state: canvas of pages on the left, findings + actions on the right. */
.rm-layout{display:grid;grid-template-columns:minmax(0,1fr) 340px;gap:26px;align-items:start}
@media (max-width:900px){.rm-layout{grid-template-columns:1fr}}
.rm-canvas{display:flex;flex-direction:column;gap:22px;min-width:0}
.rm-page{position:relative;margin:0;background:#fff;border:1px solid var(--border);border-radius:10px;box-shadow:var(--shadow);overflow:hidden;line-height:0}
.rm-raster{display:block;width:100%;height:auto}
/* Overlay layer tracks the raster exactly (boxes are % of the page). */
.rm-boxes{position:absolute;inset:0;margin:0;padding:0;list-style:none}
.rm-box{position:absolute;min-width:16px;min-height:16px;display:block;padding:0;margin:0;background:transparent;border:2px solid var(--tc,var(--lapis));border-radius:3px;cursor:pointer;font-family:inherit}
.rm-box:hover{background:color-mix(in srgb,var(--tc,var(--lapis)) 14%,transparent)}
/* State no longer recolours the type border — it adds an outer ring plus the
   corner marker, so a failing H1 still reads as an H1 yet clearly flags itself. */
.rm-box--attention{box-shadow:0 0 0 2px #8a5a00}
.rm-box--failing{box-shadow:0 0 0 2px var(--red)}
[data-theme="dark"] .rm-box--attention{box-shadow:0 0 0 2px #e0a83c}
/* Type chip: kept out of the way until the box is hovered/focused. */
.rm-box-tag{position:absolute;left:0;top:-2px;transform:translateY(-100%);font-size:.68rem;font-weight:700;line-height:1;padding:2px 5px;border-radius:4px 4px 0 0;background:var(--tc,var(--lapis));color:#fff;white-space:nowrap;opacity:0;pointer-events:none;transition:opacity .12s ease}
.rm-box:hover .rm-box-tag,.rm-box:focus-visible .rm-box-tag{opacity:1}
@media (prefers-reduced-motion:reduce){.rm-box-tag{transition:none}}
/* State marker (text, not colour alone): "!" for failures, "alt" for missing alt. */
.rm-box-marker{position:absolute;right:-1px;top:-1px;min-width:15px;height:15px;padding:0 3px;display:inline-flex;align-items:center;justify-content:center;font-size:.62rem;font-weight:700;line-height:1;color:#fff;border-radius:0 3px 0 4px}
.rm-box--failing .rm-box-marker{background:var(--red-fill)}
.rm-box--attention .rm-box-marker{background:#8a5a00}
[data-theme="dark"] .rm-box--attention .rm-box-marker{background:#8a5a00;color:#fff}
/* Sidebar */
.rm-side{position:sticky;top:88px;background:var(--card);border:1px solid var(--border);border-radius:16px;box-shadow:var(--shadow);padding:22px}
.rm-summary{margin:0 0 6px}
.rm-summary .btn-block{margin-top:14px}
.rm-side-h{font-weight:700;color:var(--lapis);margin:18px 0 0}
[data-theme="dark"] .rm-side-h{color:var(--text)}
.rm-obj{display:inline-block;margin-left:6px;font-size:.74rem;font-weight:700;color:var(--muted);white-space:nowrap}
@media (max-width:900px){.rm-side{position:static}}
/* Pending-edit queue marker + bar */
.rm-box.is-pending{border-color:var(--lapis);border-style:dashed}
.rm-box-marker--pending{background:var(--lapis)}
.rm-pending-bar{margin-top:14px}
.rm-pending-count{font-weight:700;color:var(--lapis);margin:0 0 8px}
[data-theme="dark"] .rm-pending-count{color:var(--text)}
/* Edit dialog */
.rm-dialog{border:1px solid var(--border);border-radius:16px;box-shadow:var(--shadow);padding:26px;max-width:440px;width:90vw;background:var(--card);color:var(--text)}
.rm-dialog::backdrop{background:rgba(12,18,48,.55)}
.rm-dialog h2{font-size:1.3rem;color:var(--lapis);margin:0 0 16px}
[data-theme="dark"] .rm-dialog h2{color:var(--text)}
.rm-dialog textarea,.rm-dialog select{width:100%;font-family:inherit;font-size:1rem;padding:11px 12px;border:2px solid var(--border);border-radius:11px;background:var(--bg);color:var(--text)}
.rm-dialog-actions{display:flex;gap:12px;justify-content:flex-end;margin:20px 0 0;padding:0}
.rm-dialog-actions .btn{padding:12px 20px;font-size:1rem}
.rm-suggest{margin:14px 0 0}
.rm-suggest .btn-suggest{padding:9px 14px;font-size:.92rem}
.rm-suggest .btn-suggest:disabled{opacity:.5;cursor:not-allowed}
.rm-suggest .hint{display:block;color:var(--muted);font-size:.8rem;margin:6px 0 0}
/* Reading order: numbered boxes + synced sidebar list (ported from overlay.py).
   Badge backgrounds are fixed-dark so white numerals pass contrast in both themes. */
.rm-box-num{position:absolute;top:-9px;left:-9px;min-width:17px;height:17px;padding:0 4px;display:inline-flex;align-items:center;justify-content:center;font-size:.62rem;font-weight:700;line-height:1;color:#fff;background:#283584;border-radius:9px;box-shadow:0 0 0 1.5px #fff}
.rm-box--attention .rm-box-num{background:#8a5a00}
.rm-box--failing .rm-box-num{background:#c20f15}
.rm-box.is-linked{background:color-mix(in srgb,var(--lapis) 26%,transparent);border-width:3px;z-index:3}
.rm-reading{margin:0 0 18px}
.rm-ro-count{color:var(--muted);font-weight:400}
.rm-ro-list{list-style:none;margin:10px 0 0;padding:0;max-height:44vh;overflow-y:auto;border:1px solid var(--border);border-radius:12px}
.rm-ro-list li{margin:0}
.rm-ro-item{display:flex;gap:10px;align-items:flex-start;width:100%;text-align:left;background:transparent;border:0;border-bottom:1px solid var(--border);border-left:3px solid var(--tc,var(--lapis));padding:9px 10px;cursor:pointer;font-family:inherit;color:var(--text)}
.rm-ro-list li:last-child .rm-ro-item{border-bottom:0}
.rm-ro-item:hover,.rm-ro-item.is-linked{background:color-mix(in srgb,var(--tc,var(--lapis)) 12%,transparent)}
.rm-ro-num{flex:none;min-width:20px;height:20px;display:inline-flex;align-items:center;justify-content:center;font-size:.7rem;font-weight:700;color:#fff;background:var(--tc,var(--lapis));border-radius:10px}
/* State flag at the row's trailing edge (colour + text), since colour now = type. */
.rm-ro-flag{flex:none;align-self:center;min-width:18px;height:18px;padding:0 5px;display:inline-flex;align-items:center;justify-content:center;font-size:.66rem;font-weight:700;color:#fff;border-radius:9px}
.rm-ro-flag--failing{background:var(--red-fill)}
.rm-ro-flag--attention{background:#8a5a00}
[data-theme="dark"] .rm-ro-flag--attention{background:#e0a83c;color:#231f20}
.rm-ro-body{min-width:0;display:flex;flex-direction:column;gap:2px}
.rm-ro-type{font-weight:700;font-size:.72rem;letter-spacing:.03em;text-transform:uppercase;color:var(--muted)}
.rm-ro-text{font-size:.86rem;line-height:1.35;color:var(--text);overflow-wrap:anywhere}

/* --- Tag-type colour coding --------------------------------------------------
   One custom property (--tc) per type group; boxes, rows, badges and legend all
   read it, so each tag type reads distinctly on the canvas and in the list. */
.t-heading{--tc:var(--t-heading)} .t-text{--tc:var(--t-text)} .t-th{--tc:var(--t-th)}
.t-td{--tc:var(--t-td)} .t-link{--tc:var(--t-link)} .t-form{--tc:var(--t-form)}
.t-figure{--tc:var(--t-figure)}
.rm-legend{list-style:none;display:flex;flex-wrap:wrap;gap:6px 14px;margin:10px 0 0;padding:0;font-size:.76rem;color:var(--muted)}
.rm-legend li{display:inline-flex;align-items:center;gap:6px}
.rm-legend-sw{width:11px;height:11px;border-radius:3px;border:2px solid var(--tc);flex:none}
/* Visually-hidden live region for edit announcements */
.vh,.rm-sr{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap;border:0}

/* --- Auth (step 2): sign-out / resend buttons that read as links, the verify
   banner, and site-wide flash placement below the header bar. --- */
form.button_to{display:inline;margin:0}
.linkbtn{background:none;border:0;padding:0;font:inherit;font-weight:700;cursor:pointer;text-decoration:underline}
/* On the dark brand bar, match the nav links (weight + colour, no underline). */
.bar .linkbtn{color:#cfd6f3;font-size:.92rem;text-decoration:none}
.bar .linkbtn:hover{color:#fff}
/* Confirm-your-email strip: dark text on brand yellow — high contrast. */
.verify-banner{background:var(--yellow);color:#231f20}
/* Keep .wrap's 24px gutters: padding:12px 0 cancelled them, so under 1120px the
   banner text ran into the viewport edge. */
.verify-banner .wrap{display:flex;align-items:center;justify-content:space-between;gap:16px;padding:12px 24px;flex-wrap:wrap}
.verify-banner .linkbtn{color:#231f20}
/* Flash now renders under the header (not inside a panel), so give it a wrap. */
.flashes{margin:18px auto 0}
/* Compact button for table-row actions (admin users list). */
.btn-sm{padding:8px 14px;font-size:.9rem;border-radius:9px}
/* The audited URL on the results page: a real link (wraps long URLs). */
.audited-url{overflow-wrap:anywhere}

/* ---- Invite links (admin/users): dialog, copy affordances, invites table ---- */
.admin-actions{margin:0 0 22px}
.section-head{font-size:1.25rem;color:var(--lapis);margin:34px 0 12px}
[data-theme="dark"] .section-head{color:var(--text)}
/* Native <dialog>: the platform supplies modality, Escape, and focus return. */
.modal{width:min(520px,calc(100vw - 32px));border:1px solid var(--border);border-radius:18px;
  background:var(--card);color:var(--text);box-shadow:var(--shadow);padding:32px}
.modal::backdrop{background:rgba(12,18,48,.62)}
.modal h2{font-size:1.5rem;color:var(--lapis);margin:0 0 10px;letter-spacing:-.02em}
[data-theme="dark"] .modal h2{color:var(--text)}
.modal p.sub{color:var(--muted);margin:0 0 22px}
.modal-actions{display:flex;gap:12px;flex-wrap:wrap;align-items:center;margin-top:24px}
/* The generated link: readonly, full width, monospace so a token is checkable. */
.invite-link{width:100%;font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-size:.92rem;
  padding:13px 14px;border:2px solid var(--border);border-radius:11px;background:var(--surface);color:var(--text)}
/* Copy feedback. role="status" announces it; this makes it visible too. */
.copy-status{min-height:1.4em;margin:14px 0 0;font-weight:700;color:var(--lapis)}
[data-theme="dark"] .copy-status{color:var(--lapis-deep)}
.row-actions{display:flex;gap:8px;flex-wrap:wrap;align-items:center}

/* ---- Live dashboard: pause control and its announcement ---- */
/* The dash head sits on --page, a light band in both themes, so these use the
   ordinary text tokens. An earlier version assumed a dark brand band and set
   white ink, which failed contrast on the one control that exists for a11y. */
.live-controls{display:flex;align-items:center;gap:14px;flex-wrap:wrap;margin:18px 0 0}
.live-status{margin:0;color:var(--text);font-size:.9rem;min-height:1.3em}
/* Paused: the "Live" label should not keep claiming to be live. */
.is-paused .lbl::after{content:" — paused"}

/* ---- All runs: filter sidebar, free-text box, table, pager ---- */
/* Sidebar beside the results on wide screens, stacked above them when there is
   not room for both. minmax(0,1fr) so the table column can shrink rather than
   forcing the grid wider than the page. */
/* Wider than the site's prose measure: this page is a seven-column table with a
   sidebar beside it. No fixed cap — on a 2000px monitor a 1380px cap left the
   table using half the screen while the right third sat empty. The table grows
   into whatever room there is; 2200px is a stop so the rows do not become
   unreadably long on a very wide display. */
.wrap--wide{max-width:min(2200px,100%)}
/* Inside the page wrap the totals take its width; centring themselves at their
   own 1120px (which is what the full-bleed landing pages need) left the card
   floating off to one side of the filter layout below it. */
.wrap--wide .strip{max-width:none;margin:0 0 18px;padding:0}

/* ---- Activity page, compact ----
   Everything above the first row of the table is overhead. Stacked badge,
   title, description, pause control and full-size totals put that row 800px
   down the page; this is the same content in about half the height. */
/* 60px of top padding above a page whose first useful pixel is a table. */
.center-wrap--tight{padding:16px 0 40px}
.wrap--wide .dash-head{padding:10px 0 18px}
.head-row{display:flex;align-items:center;gap:16px;flex-wrap:wrap}
.wrap--wide .dash-head h1{font-size:clamp(1.45rem,2.2vw,1.8rem);margin:0}
.wrap--wide .dash-head .lbl{margin:0}
.wrap--wide .live-controls{margin:0 0 0 auto}
.wrap--wide .si{padding:13px 14px}
.wrap--wide .si b{font-size:1.45rem}
.wrap--wide .results-bar{margin:0 0 12px}
.wrap--wide .results-bar .hint{margin:4px 0 0;font-size:.82rem}
.wrap--wide .dash-bar{margin:0 0 10px}
.runs-layout{display:grid;grid-template-columns:260px minmax(0,1fr);gap:28px;align-items:start}
/* Collapsing the panel hands its column to the table. Without this the grid
   track stays 260px wide and closing the panel just leaves a hole, which makes
   the control look broken. :has() is the whole mechanism — no JS, and in a
   browser without it the layout simply stays two-column. */
.runs-layout:has(> .filter-panel:not([open])){grid-template-columns:minmax(0,1fr)}
/* Collapsed, the panel keeps the width of the track it had when open and its
   padding is untouched, so the chevron holds the same x and y and the header
   reads as one thing folding sideways rather than two different boxes. Only the
   body below it goes. Below 900px the open panel is full width anyway, so there
   is nothing to pin. */
@media (min-width:901px){
  .runs-layout:has(> .filter-panel:not([open])) .filter-panel{width:260px}
}
@media (min-width:901px) and (max-width:1300px){
  .runs-layout:has(> .filter-panel:not([open])) .filter-panel{width:230px}
}
/* minmax(0,1fr), not 1fr: a bare 1fr takes its minimum from the content, so the
   wide table pushed the column past the viewport and the whole page scrolled
   sideways instead of the table scrolling inside its own box. */
@media (max-width:900px){.runs-layout{grid-template-columns:minmax(0,1fr)}}

.filter-panel{background:var(--card);border:1px solid var(--border);border-radius:16px;
  box-shadow:var(--shadow);padding:20px 22px}
.filter-panel h2{display:inline;font-size:1.1rem;color:var(--lapis);margin:0}
[data-theme="dark"] .filter-panel h2{color:var(--text)}
/* The label on the left, the caret on the right, pointing the way the panel
   actually moves: right while open, back at the label once collapsed. A caret
   below the label read as a top-to-bottom collapse, which is not what happens —
   the panel folds sideways and the table takes the width. */
.filter-panel summary{display:flex;align-items:center;justify-content:space-between;
  gap:12px;cursor:pointer;padding:2px 0;list-style:none}
.filter-panel summary::-webkit-details-marker{display:none}
.filter-panel summary::marker{content:""}
.filter-panel summary:focus-visible{outline:4px solid var(--ring);outline-offset:3px}
.disclosure-caret{flex:none;width:20px;height:20px;color:var(--text);
  transform:rotate(180deg);transition:transform .15s ease}
.filter-panel[open] .disclosure-caret{transform:rotate(0deg)}
/* The panel is a disclosure at every width; collapsible_controller decides the
   starting state from the viewport. */
.filter-panel fieldset{border:0;border-top:1px solid var(--border);margin:18px 0 0;padding:16px 0 0}
.filter-panel legend{font-weight:700;font-size:.95rem;padding:0}
.filter-panel .field{margin:0 0 12px}
.filter-panel .field:last-child{margin-bottom:0}
.filter-panel label{font-weight:400;font-size:.9rem}
/* --muted, not --border, for a control outline: --border is 1.49:1 against the
   dark background and 1.2:1 against the light one, and a control's visual
   boundary needs 3:1 (WCAG 1.4.11). Measured after: 7.9:1 dark, 6.2:1 light. */
.filter-panel input[type=date],.filter-panel select,.results-bar input[type=search]{
  width:100%;font-family:inherit;font-size:.92rem;padding:8px 10px;
  border:2px solid var(--muted);border-radius:9px;background:var(--bg);color:var(--text)}
.filter-panel .checkline{display:flex;align-items:center;gap:9px;margin:0 0 8px}
.filter-panel .checkline input{width:18px;height:18px;flex:none;accent-color:var(--lapis)}
.filter-panel .checkline label{margin:0}
.filter-actions{display:flex;align-items:center;gap:14px;flex-wrap:wrap;margin:20px 0 0}
.filter-actions .linkbtn{color:var(--lapis)}
[data-theme="dark"] .filter-actions .linkbtn{color:var(--lapis-deep)}

/* The free-text box sits above the table with the result count, as in the
   WET-BOEW pattern this follows. */
.results-bar{margin:0 0 16px}
.results-bar .field-inline{margin:0;max-width:420px}
.results-bar .field-inline label{display:block;font-weight:700;margin:0 0 6px}
/* The count sits above the table rather than beside the search box: it lives
   inside the results frame, so that it is replaced together with the rows it
   describes. The 26px of top padding that used to align it with the field is
   gone with the alignment. */
.pager-count{margin:0 0 10px;color:var(--text);font-size:.92rem}
/* Tighter than the dashboard's table: seven columns in a column that is already
   sharing the page with the filter panel. Selector carries .activity as well —
   `table.activity th` is one class and two elements, so a bare `.runs-table th`
   loses to it and the padding silently stays at 18px. */
table.activity.runs-table th,table.activity.runs-table td{padding:12px 11px}
.runs-table .empty-row{padding:28px 18px;text-align:center;color:var(--muted)}
/* Sizing: each column hugs its content, floored by its own header text and
   capped so one long value cannot take the row. Beyond the cap the value wraps
   rather than being cut off — a filename is the thing being identified, so
   losing its end is worse than two lines.
   The caps are what let the table narrow gracefully instead of hitting a rigid
   minimum and clipping into the scroller a few pixels in. */
.runs-table .t-target{max-width:340px}
.runs-table .t-result{max-width:220px}
.runs-table .t-who{max-width:210px}
.runs-table .t-target,.runs-table .t-who,.runs-table .t-result{overflow-wrap:anywhere}
/* Every capped column has to be allowed to wrap. .t-who and .t-result are nowrap
   for the dashboard's wider table; capped here, that combination neither scrolls
   nor clips — the value paints straight over the cell beside it. Measured:
   cm•••••••@tammaninc.com spilled 35px over the Open link at 1269px, and
   "12 fail · 6 review · 34 pass" spilled 15px at 1100px, both while the scroller
   reported no overflow at all. Wrapping inside the cap is what makes the cap mean
   anything. */
.runs-table .t-who,.runs-table .t-result{white-space:normal}
/* When keeps its own line while there is room: "about 15 hours ago" split over
   two lines reads as two separate facts. Below 1300px the room is worth more
   than the tidiness, so it wraps and the context columns tighten — measured, it
   is the difference between the table fitting at 1280 and fitting at 1120. */
.runs-table .t-when{white-space:nowrap;color:var(--muted)}
table.activity .t-when{color:var(--muted)}
/* Bounded at both ends on purpose: this block sits after the stacking rule, so
   an unbounded max-width would re-apply the two-column grid below 900px and the
   sidebar would never stack. */
@media (min-width:901px) and (max-width:1300px){
  /* The sidebar gives up 30px before the table starts scrolling: its controls
     are full-width and lose nothing, the table loses a column to the scroller. */
  .runs-layout{grid-template-columns:230px minmax(0,1fr);gap:22px}
}

/* Table tweaks apply all the way down, stacked or not. */
@media (max-width:1300px){
  .runs-table .t-when{white-space:normal}
  .runs-table .t-who{max-width:130px}
  .runs-table .t-result{max-width:160px}
  /* The type icon is decorative (alt=""), so it is the cheapest thing to drop:
     the word beside it carries the whole meaning. */
  .runs-table .k-icon{display:none}
  /* Below the caps the browser falls back to each column's min-content width,
     so trimming the caps further buys nothing. Padding is the lever that still
     works: 4px off each side of seven columns is 56px. */
  table.activity.runs-table th,table.activity.runs-table td{padding:11px 7px}
}
/* The table can outgrow a narrow viewport. Scroll it rather than clip it; the
   scroller is made keyboard-reachable only while it actually scrolls
   (scrollable_controller.js) — WCAG 2.1.1 without a dead tab stop. */
.runs-scroll{overflow-x:auto}
.runs-scroll:focus-visible{outline:4px solid var(--ring);outline-offset:-4px}
.pager-links{display:flex;align-items:center;gap:16px;margin:16px 2px 0}
.pager-page{color:var(--muted);font-size:.92rem}
.dash-bar-link{margin-left:auto;font-weight:700;color:var(--lapis)}
[data-theme="dark"] .dash-bar-link{color:var(--lapis-deep)}

/* Admin → Engines: one card per engine, a definition list of facts inside each.
   The ready/not-ready state is a chip (shared with the activity table) so it is
   never colour alone. */
.engine-list{list-style:none;margin:0 0 30px;padding:0;display:grid;gap:16px}
.engine-card{background:var(--card);border:1px solid var(--border);border-radius:16px;box-shadow:var(--shadow);padding:20px 22px}
.engine-head{display:flex;align-items:center;justify-content:space-between;gap:14px;flex-wrap:wrap}
.engine-name{margin:0;font-size:1.15rem;color:var(--lapis)}
[data-theme="dark"] .engine-name{color:var(--text)}
.engine-role{margin:6px 0 0;color:var(--muted);font-size:.9rem}
.engine-health{margin:10px 0 0;font-size:.92rem}
.engine-facts{display:grid;grid-template-columns:1fr 1fr;gap:14px 22px;margin:18px 0 0}
.engine-facts--app{margin:0 0 30px}
@media (max-width:560px){.engine-facts{grid-template-columns:1fr}}
.engine-facts .fact--wide{grid-column:1/-1}
.engine-facts dt{font-weight:700;font-size:.78rem;text-transform:uppercase;letter-spacing:.04em;color:var(--muted)}
.engine-facts dd{margin:3px 0 0;font-size:.93rem}
.engine-facts code{font-size:.88rem}
.engine-path{word-break:break-all;color:var(--muted)}
.engine-section{margin:0 0 14px;font-size:1.05rem}
.engine-checked{margin:18px 0 0;color:var(--muted);font-size:.85rem}
.tool-source{color:var(--muted);font-size:.88rem}
/* A fact we could not read, and a checkout with uncommitted changes. Both are
   states to notice, not errors: they read as words, not as a red dot. */
.e-none{color:var(--muted);font-style:italic}
.e-dirty{color:var(--red-deep);font-weight:700}
[data-theme="dark"] .e-dirty{color:var(--red)}

/* Redraw consent (submissions/_redraw_required): opentag can tag the document
   only by redrawing part of it. Keeping the original is the primary action and
   sits first; consent is a separate, quieter form behind one checkbox. */
.redraw-heading{margin:18px 0 8px;font-size:1.15rem;line-height:1.3}
.redraw-body{margin:0 0 16px;line-height:1.55}
.redraw-reasons{background:var(--surface);border:1px solid var(--border);border-radius:12px;padding:14px 18px;margin:0 0 20px}
.redraw-reasons-heading{margin:0 0 8px;font-size:.95rem}
.redraw-reasons ul{margin:0;padding-left:20px}
.redraw-reasons li{margin:4px 0;line-height:1.45}
.redraw-pages{font-weight:700}
.redraw-keep{margin:0 0 22px}
.redraw-declined{margin:0 0 16px}
.redraw-consent fieldset{border:1px solid var(--border);border-radius:12px;padding:14px 18px 16px;margin:0 0 14px}
.redraw-consent legend{font-weight:700;padding:0 6px}
.consent-check{display:flex;align-items:flex-start;gap:10px}
.consent-check input[type=checkbox]{margin-top:3px;width:20px;height:20px;flex:0 0 auto}
.consent-check label{line-height:1.45}
/* An error only once someone has interacted (:user-invalid) or the server sent
   the form back unticked (aria-invalid) — never on arrival. The message carries
   a glyph and words, so the state does not rest on colour. */
.consent-check input:user-invalid,
.consent-check input[aria-invalid="true"]{outline:3px solid var(--red-deep);outline-offset:2px}
.field-error{margin:10px 0 0;color:var(--red-deep);font-weight:700}
.field-error-mark{margin-right:4px}
/* After a consented redraw: which parts were rebuilt, on the tagged result. */
.redraw-done{margin:14px 0 18px}
.redraw-done > p{margin:0 0 12px;line-height:1.5}
