/* CommissionIQ by Delmatic — dashboard styles.
   Same token system as the approved design mockup. The first visit follows
   the operating-system theme; the toolbar can then save an explicit choice. */

/* Brand palette lifted from delmatic.com's theme stylesheet:
   lime #96d045 (accent), charcoal #2f2f2f (ink), olive #637525 (deep green),
   white/#f6f6f6/#ececec greys. Light mode mirrors the website; dark mode is
   the same brand translated (their site is light-only). Chart marks use
   validated darker lime steps (#7fb232 light / #74a52e dark) — pure #96d045
   is too pale for colour-blind-safe marks and stays on chrome only. */
:root {
  --page:#f6f6f6; --card:#ffffff; --card2:#f2f2f2;
  --ink:#2f2f2f; --ink2:#555555; --muted:#6d6d6d;
  --line:#ececec; --line2:#d7d6d5;
  --accent:#96d045; --accent-ink:#637525; --focus:#006b56;
  --btn-ink:#263311;
  /* The bar and the track it sits in were 2.22 to 1 apart, so a floor bar was
     hard to tell from its own groove. */
  --data:#6c972a; --data-track:#edf3df;
  --fail:#d03b3b;
  /* Darkened from #e3ad3d, which reached only 2.04 to 1 on white and coloured
     the Attention figure on the Action Center. Amber on white is the classic
     way to lose a number. Measured, not judged: tests/test_theme_contrast.py. */
  --progress-mid:#b88c31;
  --info:#3b82f6;
  --chip-pass-bg:#eef6dd; --chip-pass-ink:#56701f;
  --chip-info-bg:#e8f1fd; --chip-info-ink:#2c66a8;
  --chip-fail-bg:#f9e7e5; --chip-fail-ink:#a92f2f;
  --chip-na-bg:#efefef; --chip-na-ink:#6b6b6b;
  /* Amber. Selected Pending sat on --card2 in near-identical grey, so a
     chosen Pending was indistinguishable from an unchosen one. */
  --chip-warn-bg:#fdf0d2; --chip-warn-ink:#8a5a12;
  /* New work (teal). Solid, so it reads over a busy drawing preview. */
  --chip-new-bg:#d6f1ef; --chip-new-ink:#00655f; --chip-new-line:#57bdb6;
  --drawing-selected-inner:#ffffff; --drawing-selected-outer:#242424;
  --graphic-selected-fill:#e0218a; --graphic-selected-ink:#ffffff;
  --shadow:0 1px 3px rgba(0,0,0,.06);
  --workspace-gutter:clamp(16px,2vw,36px);
  --workspace-gap:clamp(16px,1.5vw,24px);
  --workspace-section:clamp(20px,2vw,30px);
  /* The rail. It used to be charcoal whatever the theme said, which left a
     dark column beside a light application. These tokens are the whole of
     its colour, so each theme answers for its own rail.

     Light: a genuinely light rail that belongs to the light application. It
     is white against the grey page, so the boundary is the page, not a
     shadow. Text is the ordinary ink, measured in tests/test_theme_contrast.py. */
  --rail-bg:#ffffff; --rail-ink:#2f2f2f; --rail-ink2:#5d5d5d;
  --rail-line:#e2e2e2; --rail-edge:#d7d6d5;
  --rail-hover-bg:#f0f0f0; --rail-hover-ink:#1c1c1c;
  --rail-sel-bg:#eef6dd; --rail-sel-ink:#243206; --rail-mark:#637525;
  --rail-count-bg:#ececec; --rail-count-ink:#454545;
  --rail-brand-ink:#232323; --rail-brand-sub:#6d6d6d; --rail-brand-iq:#637525;
}

/* Engineer-only drawing and databasing workbench. */
.engineering-coverage {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(190px, 1fr));
  gap: 12px;
  margin: 0 0 18px;
}
.engineering-check-card { position:relative; min-height:150px; }
.engineering-check-card .chip { float: right; }
.engineering-check-card h3 { margin: 0 0 12px; max-width: 75%; font-size: 1rem; }
.engineering-check-count { display: block; color: var(--accent); font-size: 2rem; line-height: 1; }
.engineering-check-card small { display:block; color: var(--muted); }
.engineering-coverage-summary { margin-top:10px; font-variant-numeric:tabular-nums; }
.engineering-status-help { display:grid; grid-template-columns:repeat(auto-fit,minmax(210px,1fr)); gap:8px 16px; margin-top:9px; }
.engineering-status-help p { margin:0; color:var(--ink2); font-size:12px; }
.engineering-filters { align-items: center; }
.engineering-filters .filter-search { min-width: min(280px, 100%); flex: 1; }
.engineering-report-tools { display:flex; flex-wrap:wrap; align-items:center; gap:8px; margin:0 0 16px; }
.engineering-report-tools label, .engineering-report-tools small { color:var(--ink2); font-size:12px; }
.engineering-report-tools small { flex-basis:100%; }
#engineering-report-print {
  background:var(--accent); color:var(--btn-ink); border:none; border-radius:8px;
  padding:7px 13px; font:inherit; font-weight:650; cursor:pointer;
}
.engineering-report-check { break-inside:avoid; margin-bottom:15px; }
#engineering-report-doc[hidden] { display:none; }
.engineering-report-check h3 { margin:0 0 4px; font-size:14px; }
.engineering-report-finding { break-inside:avoid; border-top:1px solid var(--line); padding:9px 0; }
.engineering-report-finding h3, .engineering-report-finding p { margin:0 0 4px; }
.engineering-report-finding h3 { font-size:13px; }
.engineering-report-finding p { font-size:11px; color:var(--ink2); }
.engineering-findings { display: grid; gap: 12px; }
.engineering-finding {
  border: 1px solid var(--line);
  border-radius: 10px;
  padding: 16px;
  background: var(--card2);
}
.engineering-finding-head {
  display: flex;
  justify-content: space-between;
  align-items: flex-start;
  gap: 16px;
}
.engineering-finding-head h3,
.engineering-finding-head p { margin: 0 0 6px; }
.engineering-finding-state { display: flex; flex-wrap: wrap; justify-content: flex-end; gap: 6px; }
.engineering-placements { list-style: none; margin: 12px 0 0; padding: 0; }
.engineering-placements li {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 12px;
  padding: 9px 0;
  border-top: 1px solid var(--line);
}
.engineering-actions { display: flex; justify-content: flex-end; margin-top: 12px; }

@media (max-width: 620px) {
  .engineering-coverage { grid-template-columns: 1fr 1fr; gap: 8px; }
  .engineering-check-card { min-height: 150px; padding: 12px; }
  .engineering-finding-head,
  .engineering-placements li { align-items: stretch; flex-direction: column; }
  .engineering-finding-state { justify-content: flex-start; }
  .engineering-placements button { width: 100%; }
}
:root[data-theme="dark"] {
    --page:#171717; --card:#202020; --card2:#282828;
    --ink:#ededed; --ink2:#b5b5b5; --muted:#969696;
    --line:#2f2f2f; --line2:#3d3d3d;
    --accent:#96d045; --accent-ink:#a8db60; --focus:#6ee7b7;
    --btn-ink:#1c2408;
    --data:#74a52e; --data-track:#2b2f24;
    --fail:#e66767;
    --progress-mid:#e8c274;
    --info:#6aa9ff;
    --chip-pass-bg:#2c3618; --chip-pass-ink:#b9dd7d;
    --chip-fail-bg:#3a1f1d; --chip-fail-ink:#eb9a9a;
    --chip-na-bg:#2a2a2a; --chip-na-ink:#a0a0a0;
    --chip-warn-bg:#3d3016; --chip-warn-ink:#e8c274;
    --chip-info-bg:#192d46; --chip-info-ink:#8fc1ff;
    --chip-new-bg:#1b3634; --chip-new-ink:#7ddcd3; --chip-new-line:#2e8c85;
    --drawing-selected-inner:#ffffff; --drawing-selected-outer:#111111;
    --graphic-selected-fill:#e0218a; --graphic-selected-ink:#ffffff;
    --shadow:0 1px 3px rgba(0,0,0,.4);
    /* Dark: a neutral rail, one step darker than the workspace so the two
       read as separate surfaces without a border doing the work. */
    --rail-bg:#111111; --rail-ink:#ededed; --rail-ink2:#9e9e9e;
    --rail-line:#2a2a2a; --rail-edge:#000000;
    --rail-hover-bg:#1e1e1e; --rail-hover-ink:#ffffff;
    --rail-sel-bg:rgba(150,208,69,.15); --rail-sel-ink:#ffffff; --rail-mark:#96d045;
    --rail-count-bg:#2a2a2a; --rail-count-ink:#dcdcdc;
    --rail-brand-ink:#ededed; --rail-brand-sub:#9e9e9e; --rail-brand-iq:#96d045;
}

/* ── The Delmatic theme ──────────────────────────────────────────────────────
   Light and dark are neutral. They are the tool getting out of the way, and
   they follow whatever the machine is set to.

   This one is the brand. The ground is not neutral grey: it is charcoal with
   green in it, mixed from the brand olive #637525, so the lime sits ON
   something rather than being dropped onto a grey card. The lime itself is
   unchanged — it is the one colour that must not drift — and it is asked to do
   structural work here, not decoration.

   Everything that carries MEANING keeps its meaning. Red is still failure,
   amber is still attention, blue is still information. A theme may change how a
   page feels; it may never change what a colour says. The grounds behind those
   colours are re-mixed for this darker, greener page, and every pair below was
   measured rather than judged by eye — see tests/test_theme_contrast.py.

   The printed report is untouched. @media print re-declares the light tokens
   for EVERY theme selector, at equal specificity, so a report looks the same
   whichever theme made it. */
:root[data-theme="delmatic"] {
  --page:#10140c; --card:#181e12; --card2:#212a19;
  --ink:#eef3e6; --ink2:#bcc7af; --muted:#8e9982;
  --line:#28321d; --line2:#3a4728;
  --accent:#96d045; --accent-ink:#b6e276; --focus:#b6e276;
  --btn-ink:#131d09;
  --data:#8cc63f; --data-track:#242d1a;
  --fail:#f08282;
  --progress-mid:#ecc673;
  --info:#82b8ff;
  --chip-pass-bg:#26331a; --chip-pass-ink:#bfe487;
  --chip-fail-bg:#3a201f; --chip-fail-ink:#f0a6a6;
  --chip-na-bg:#232a1c; --chip-na-ink:#96a189;
  --chip-warn-bg:#3a3018; --chip-warn-ink:#ecc673;
  --chip-info-bg:#1b2b41; --chip-info-ink:#9cc8ff;
  --drawing-selected-inner:#ffffff; --drawing-selected-outer:#10140c;
  --graphic-selected-fill:#e0218a; --graphic-selected-ink:#ffffff;
  --chip-new-bg:#143429; --chip-new-ink:#86e0d6; --chip-new-line:#2f8a7f;
  --shadow:0 1px 3px rgba(0,0,0,.55);
  /* Delmatic: the branded charcoal and green the rail always had. */
  --rail-bg:#0d0f0b; --rail-ink:#e5e8dc; --rail-ink2:#95a086;
  --rail-line:rgba(255,255,255,.08); --rail-edge:#000000;
  --rail-hover-bg:rgba(255,255,255,.06); --rail-hover-ink:#ffffff;
  --rail-sel-bg:rgba(150,208,69,.15); --rail-sel-ink:#ffffff; --rail-mark:#96d045;
  --rail-count-bg:rgba(255,255,255,.1); --rail-count-ink:#e5e8dc;
  --rail-brand-ink:#e9ece1; --rail-brand-sub:#95a086; --rail-brand-iq:#96d045;
}

/* ── Typefaces ────────────────────────────────────────────────────────────
   Held in the application, not fetched from the internet. An engineer works
   on site with no signal, so a font asked for at page load would silently
   fall back and the layout would shift with it. These files are in the
   service worker's shell list, so they are on the phone with everything
   else.

   Archivo carries headings and figures - a measure band is read at a
   glance, and its numbers need weight and tight spacing to read as numbers.
   Public Sans carries reading text. IBM Plex Mono carries device names,
   short addresses and codes, so an address looks like an address and
   columns of them line up.

   Every stack keeps a real fallback, so the application is still legible if
   a file ever fails to load. Licences: see fonts/LICENCES.md. */
@font-face {
  font-family:'Archivo'; font-style:normal; font-weight:400 700;
  font-display:swap; src:url('fonts/archivo-latin-ext.woff2') format('woff2');
  unicode-range:U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family:'Archivo'; font-style:normal; font-weight:400 700;
  font-display:swap; src:url('fonts/archivo-latin.woff2') format('woff2');
  unicode-range:U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family:'Public Sans'; font-style:normal; font-weight:400 700;
  font-display:swap; src:url('fonts/public-sans-latin-ext.woff2') format('woff2');
  unicode-range:U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family:'Public Sans'; font-style:normal; font-weight:400 700;
  font-display:swap; src:url('fonts/public-sans-latin.woff2') format('woff2');
  unicode-range:U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family:'IBM Plex Mono'; font-style:normal; font-weight:400;
  font-display:swap; src:url('fonts/plex-mono-latin.woff2') format('woff2');
  unicode-range:U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

* { box-sizing:border-box; }
html, body { margin:0; }
.environment-banner {
  position:sticky;
  inset-block-start:0;
  z-index:120;
  padding:5px 12px;
  border-block-end:1px solid color-mix(in srgb, var(--accent) 55%, var(--line));
  background:color-mix(in srgb, var(--accent) 15%, var(--bg));
  color:var(--ink);
  font-size:12px;
  font-weight:750;
  letter-spacing:.02em;
  text-align:center;
}
body {
  background:var(--page); color:var(--ink);
  font:15px/1.5 "Public Sans", "Segoe UI", system-ui, -apple-system, sans-serif;
}
a { color:var(--accent-ink); }

/* ── Buttons ──────────────────────────────────────────────────────────────
   The default button, from the reference mockup: a quiet bordered control
   that does not shout, so the one lime button on a page is obviously the
   one that acts.

   This is a bare element selector on purpose. It is the lowest specificity
   there is, so every existing class rule in this file still wins - the
   segmented controls, the device result buttons, the rail, the bottom
   navigation, the drawing viewer's own actions. It only reaches the 58
   buttons that had no styling at all and were falling back to the
   operating system's grey.

   It sits high in the file for the same reason: where specificity ties,
   the later rule wins, and everything specialised comes after this. */
button {
  display:inline-flex; align-items:center; justify-content:center; gap:7px;
  padding:7px 13px; border-radius:7px;
  border:1px solid var(--line2); background:var(--card); color:var(--ink);
  font:inherit; font-size:13.5px; font-weight:500;
  cursor:pointer; white-space:nowrap;
}
button:hover { background:var(--card2); border-color:var(--muted); }
/* A switched-off control shows the no-entry pointer, everywhere. It says the
   button is dead before the click rather than after it. Faded alone is not
   enough: fading reads as "quiet" at least as easily as it reads as "off". */
button:disabled { opacity:.55; cursor:not-allowed; }
button:disabled:hover { background:var(--card); border-color:var(--line2); }
[hidden] { display:none !important; }
/* Hidden for want of data, as opposed to [hidden] which a feature flag owns.
   Keeping them separate means neither can re-reveal what the other hid. */
.empty-hide { display:none !important; }

/* ── Login ─────────────────────────────────────────────────────────────── */
.login-wrap { min-height:100vh; display:grid; place-items:center; padding:20px; }
.login-card {
  background:var(--card); border:1px solid var(--line); border-radius:14px;
  box-shadow:var(--shadow); padding:34px 36px 30px; width:min(380px, 100%);
  display:flex; flex-direction:column;
}
.login-sub { margin:2px 0 22px; color:var(--muted); font-size:13px; }
.login-sub strong { color:var(--accent-ink); font-weight:650; }
.login-card label {
  font-size:11px; font-weight:600; letter-spacing:.08em; text-transform:uppercase;
  color:var(--muted); margin:12px 0 4px;
}
.login-card input {
  background:var(--card2); color:var(--ink); border:1px solid var(--line2);
  border-radius:8px; padding:9px 12px; font:inherit;
}
.login-card input:focus { outline:2px solid var(--accent); outline-offset:-1px; }
.login-card button {
  margin-top:22px; background:var(--accent); color:var(--btn-ink); border:none;
  border-radius:8px; padding:10px; font:inherit; font-weight:650; cursor:pointer;
}
.login-card button:disabled { opacity:.6; cursor:not-allowed; }
.login-card button:focus-visible { outline:2px solid var(--ink); outline-offset:2px; }
.login-error { color:var(--fail); font-size:13px; margin:12px 0 0; }
.login-message { color:var(--accent-ink); font-size:13px; margin:12px 0 0; }
.login-card .text-btn {
  margin-top:10px; padding:2px; background:none; color:var(--ink2);
  font-size:12.5px; font-weight:500; text-decoration:underline;
}

/* ── Chrome ────────────────────────────────────────────────────────────── */
/* CommissionIQ is the product. The company attribution stays smaller. The
   rounded tonal tile identifies digital product surfaces. */
.logo {
  display:flex; align-items:center; gap:10px; color:var(--ink); font-size:19px;
  font-family:'Archivo', "Segoe UI", system-ui, sans-serif;
}
.logo-mark { display:block; flex:0 0 auto; width:1.7em; height:1.7em; }
.logo-mark-digital { object-fit:contain; }
.brand-copy { display:flex; min-width:0; flex-direction:column; gap:1px; }
.brand-name {
  display:inline-flex; align-items:baseline; color:var(--ink);
  font-weight:700; line-height:1; letter-spacing:-.035em; white-space:nowrap;
}
.brand-iq { color:#96d045; font-style:normal; }
.rail-brand-text em { color:var(--rail-brand-iq); font-style:normal; }
.brand-attribution {
  color:var(--muted); font-family:'Public Sans', "Segoe UI", system-ui, sans-serif;
  font-size:.46em; font-weight:500; line-height:1.2; letter-spacing:0;
}
.logo.big { font-size:27px; gap:12px; }
.print-brand-lockup { display:inline-flex; align-items:baseline; gap:.55em; color:#1b2119; font-family:'Archivo',"Segoe UI",system-ui,sans-serif; }
.delmatic-wordmark { display:block; width:100%; height:auto; overflow:visible; }
.print-brand-product { width:114px; }
.print-brand-attribution { color:#596154; font:500 10px/1.1 'Public Sans',"Segoe UI",system-ui,sans-serif; white-space:nowrap; }
.print-brand-attribution b { color:#96d045; font:700 1.15em/1 'Archivo',"Segoe UI",system-ui,sans-serif; letter-spacing:-.025em; }
.print-brand-lockup.is-compact { gap:.35em; }
.print-brand-lockup.is-compact .print-brand-product { width:48px; }
.print-brand-lockup.is-compact .print-brand-attribution { font-size:6.5px; }
/* The toolbar follows the workspace reference. The brand now belongs to the
   rail, while the toolbar holds project context and workspace actions. */
header.top {
  min-height:56px; display:flex; align-items:center; gap:10px; flex-wrap:nowrap;
  padding:0 18px; position:sticky; top:0; z-index:6;
  background:color-mix(in srgb, var(--card) 92%, transparent);
  -webkit-backdrop-filter:blur(18px) saturate(145%);
  backdrop-filter:blur(18px) saturate(145%);
  border-bottom:1px solid var(--line);
}
.mobile-brand { display:none; }
.rail-toggle {
  flex:0 0 auto; width:34px; height:34px; padding:7px; border-color:transparent;
  background:none; color:var(--ink2);
}
.rail-toggle svg { width:19px; height:19px; }
.rail-toggle:hover { background:var(--card2); color:var(--ink); border-color:transparent; }
.project-context {
  min-width:0; max-width:290px; display:flex; align-items:center; gap:9px;
  padding:5px 11px 5px 9px; border:1px solid var(--line);
  border-radius:8px; background:var(--card2);
}
.project-context-dot {
  flex:0 0 auto; width:7px; height:7px; border-radius:50%;
  background:var(--accent); box-shadow:0 0 0 3px color-mix(in srgb, var(--accent) 16%, transparent);
}
.project-context-copy { min-width:0; display:flex; align-items:center; gap:7px; }
.project-context-status {
  flex:0 0 auto; color:var(--muted); font-size:10.5px; line-height:1.2;
  text-transform:capitalize; white-space:nowrap;
}
/* ── Workspace search ──────────────────────────────────────────────────────
   The field keeps the approved toolbar appearance: magnifier, the same
   placeholder sentence, the Ctrl K hint, and the quiet card ground. Every
   colour below is a token, so the control follows light, dark and Delmatic
   without a second set of rules. */
.workspace-search { position:relative; flex:1 1 320px; max-width:460px; min-width:190px; margin-inline:6px; }
.workspace-search-open { display:none; }
.workspace-search-field {
  display:flex; align-items:center; gap:8px; min-height:36px; padding:0 11px;
  border:1px solid var(--line); border-radius:8px; background:var(--card2);
}
.workspace-search-field:focus-within { border-color:var(--line2); background:var(--card); }
.workspace-search-icon { flex:0 0 auto; width:15px; height:15px; color:var(--muted); }
.workspace-search input[type="search"] {
  flex:1 1 auto; min-width:0; height:34px; padding:0; border:0; outline:0;
  background:none; color:var(--ink); font:400 13px/1.4 inherit;
}
.workspace-search input[type="search"]::placeholder { color:var(--muted); opacity:1; }
.workspace-search input[type="search"]::-webkit-search-cancel-button { display:none; }
.workspace-search kbd {
  flex:0 0 auto; padding:3px 5px; border:1px solid var(--line2); border-radius:4px;
  color:var(--muted); font:10.5px/1 'IBM Plex Mono', monospace;
}
.workspace-search-close {
  display:none; place-items:center; flex:0 0 auto; width:26px; height:26px;
  padding:0; border:1px solid transparent; border-radius:6px;
  background:none; color:var(--muted); cursor:pointer;
}
.workspace-search-close svg { width:15px; height:15px; }
.workspace-search-close:hover { border-color:var(--line2); background:var(--card2); color:var(--ink); }
.workspace-search[data-open="true"] .workspace-search-close { display:grid; }
.workspace-search[data-open="true"] kbd { display:none; }

.workspace-search-panel {
  position:absolute; z-index:120; top:calc(100% + 6px); right:0; left:auto;
  width:max(340px, 100%); max-width:min(460px, calc(100vw - 24px));
  max-height:min(70vh, 560px); overflow:auto; padding:6px;
  border:1px solid var(--line2); border-radius:10px;
  background:var(--card); box-shadow:var(--shadow);
}
.workspace-search-panel[hidden] { display:none; }
.workspace-search-status {
  margin:0; padding:6px 8px 4px; color:var(--muted); font-size:11.5px;
}
.workspace-search-foot {
  margin:0; padding:4px 8px 6px; color:var(--muted); font-size:11px;
  border-top:1px solid var(--line);
}
.workspace-search-foot[hidden] { display:none; }
.workspace-search-suggest[hidden] { display:none; }
.workspace-search-group-head {
  display:flex; align-items:baseline; justify-content:space-between; gap:8px;
  margin:6px 0 2px; padding:0 8px;
  color:var(--ink2); font-size:11px; font-weight:700; letter-spacing:.06em;
  text-transform:uppercase;
}
.workspace-search-recent-label {
  margin:0; padding:0 8px 4px; color:var(--ink2); font-size:11px; font-weight:700;
  letter-spacing:.06em; text-transform:uppercase;
}
.workspace-search-group-head small { color:var(--muted); font-size:10.5px; font-weight:600; letter-spacing:0; }
.workspace-search-option {
  display:grid; grid-template-columns:auto minmax(0,1fr) auto; align-items:center;
  gap:4px 10px; width:100%; padding:7px 8px; border:1px solid transparent;
  border-radius:8px; background:none; color:inherit; text-align:left; cursor:pointer;
}
/* The type of a result is a word and a shape, never colour alone: a reader who
   cannot separate the hues still reads "Device" beside a distinct outline. */
.workspace-search-badge {
  grid-row:1 / span 2; display:grid; place-items:center;
  width:26px; height:26px; border:1px solid var(--line2); border-radius:7px;
  color:var(--ink2); font-size:11px; font-weight:700;
}
.workspace-search-badge svg { width:14px; height:14px; }
.workspace-search-option b {
  min-width:0; overflow:hidden; text-overflow:ellipsis; white-space:nowrap;
  color:var(--ink); font-size:13px; font-weight:650;
}
.workspace-search-option .workspace-search-type {
  justify-self:end; color:var(--muted); font-size:10.5px; font-weight:700;
  letter-spacing:.04em; text-transform:uppercase;
}
.workspace-search-option .workspace-search-context {
  grid-column:2 / span 2; min-width:0; overflow:hidden; text-overflow:ellipsis;
  white-space:nowrap; color:var(--muted); font-size:11.5px;
}
.workspace-search-option mark { background:none; color:inherit; font-weight:800; text-decoration:underline; }
.workspace-search-option:hover { background:var(--card2); }
/* Selection is a ground, a border AND a left bar, so it survives without
   colour. The bar is the part a monochrome screen still shows. */
.workspace-search-option[aria-selected="true"] {
  border-color:var(--line2); background:var(--card2);
  box-shadow:inset 3px 0 0 0 var(--accent-ink);
}
.workspace-search-option[aria-selected="true"] .workspace-search-badge { border-color:var(--accent-ink); }
/* The row at the foot of a cut group. Same shape as a result, so the arrow
   keys reach it without looking like a different kind of thing, but it reads
   as an action rather than a record. */
.workspace-search-more .workspace-search-badge { grid-row:auto; font-size:14px; }
.workspace-search-more b { grid-column:2 / span 2; color:var(--accent-ink); }
.workspace-search-empty { margin:0; padding:12px 8px; color:var(--ink2); font-size:12.5px; }
.workspace-search-scope { display:flex; flex-wrap:wrap; gap:6px; padding:2px 8px 8px; }
.workspace-search-scope span {
  padding:3px 8px; border:1px solid var(--line); border-radius:999px;
  color:var(--ink2); font-size:11px;
}
.workspace-search-recent { display:flex; flex-wrap:wrap; gap:6px; padding:0 8px 8px; }
.workspace-search-recent button {
  padding:4px 9px; border:1px solid var(--line); border-radius:999px;
  background:var(--card2); color:var(--ink2); font:inherit; font-size:11.5px; cursor:pointer;
}
.workspace-search-recent button:hover { border-color:var(--line2); color:var(--ink); }

/* The row a search sent you to. A steady outline plus the moved keyboard
   focus, so the destination is found without hunting and without relying on
   a colour that fades. */
.search-landed {
  outline:2px solid var(--accent-ink); outline-offset:2px; border-radius:6px;
  scroll-margin:120px;
}
/* ── One filter control, everywhere ──────────────────────────────────────
   Five of the six list filters used to be bare inputs while the module one
   had a magnifier, and the two magnifiers on the page were drawn at
   different radii and stroke widths. Filtering a list is one idea, so it is
   one control: same magnifier from the sprite, same border, same focus ring,
   same 40px height as every other field beside it. */
.icon-sprite { position:absolute; width:0; height:0; overflow:hidden; }
.filter-search {
  display:flex; align-items:center; gap:7px; min-height:40px;
  padding:0 10px; border:1px solid var(--line2); border-radius:8px;
  background:var(--card2); color:var(--muted);
}
.filter-search:focus-within { outline:2px solid var(--accent); outline-offset:-1px; }
.filter-search-icon { width:14px; height:14px; flex:none; }
.filter-search input[type="search"], .toolbar .filter-search input[type="search"] {
  min-width:0; width:100%; min-height:40px; padding:0; border:0; border-radius:0;
  background:transparent; outline:0; color:var(--ink); font:inherit;
  font-size:var(--field-font); font-weight:400; text-transform:none; letter-spacing:0;
}
.filter-search input[type="search"]::-webkit-search-cancel-button { display:none; }
#page-admin .toolbar .filter-search { flex:1 1 240px; max-width:340px; }

.top-right { margin-left:auto; display:flex; align-items:center; gap:8px; flex:none; }
.theme-toggle {
  display:grid; place-items:center; flex:0 0 auto; width:36px; min-width:36px;
  height:36px; min-height:36px; padding:7px; border:1px solid transparent;
  border-radius:8px; background:transparent; color:var(--ink2); cursor:pointer;
}
.theme-toggle:hover { border-color:var(--line2); background:var(--card2); color:var(--ink); }
.theme-toggle:active { transform:translateY(1px); }
.theme-icon { width:19px; height:19px; }
:root[data-theme="dark"] .theme-icon-sun,
:root[data-theme="dark"] .theme-icon-brand,
:root[data-theme="light"] .theme-icon-moon,
:root[data-theme="light"] .theme-icon-brand,
:root[data-theme="delmatic"] .theme-icon-sun,
:root[data-theme="delmatic"] .theme-icon-moon { display:none; }
/* Freshness of the data, beside the project it belongs to. Quieter than the
   project pill: it is context, not identity. */
/* Freshness reads as a state, not as a sentence: a quiet pill with a dot,
   the same shape the rest of the application uses for a state. */
.synced-chip {
  display:inline-flex; align-items:center; gap:7px;
  font-size:12px; font-weight:500; white-space:nowrap;
  padding:4px 11px; border-radius:999px; align-self:center;
  background:var(--chip-pass-bg); color:var(--chip-pass-ink);
}
.synced-chip::before {
  content:""; width:6px; height:6px; border-radius:50%;
  background:currentColor; flex:none;
}
@media (max-width:640px) { .synced-chip { display:none; } }

.project-context span.proj-pill {
  display:block; min-width:0; max-width:250px; padding:0; border:0; border-radius:0;
  color:var(--ink); background:transparent; font:600 13.5px/1.25 'Public Sans', sans-serif;
  letter-spacing:0; overflow:hidden; text-overflow:ellipsis; white-space:nowrap;
}
/* The project picker is the browser's own list, drawn like every other list
   in the app: the base field look (card ground, line border, 8px corners) is
   left to the shared rule above. Only its size is set here. With the list
   showing, the list is the visible box, so the strip around it drops its own
   border and fill rather than draw a box inside a box. */
.project-context select.proj-pill {
  min-width:0; max-width:250px; text-overflow:ellipsis; cursor:pointer;
}
.project-context select.proj-pill:disabled { cursor:not-allowed; opacity:.6; }
.project-context:has(select.proj-pill:not([hidden])) {
  padding:0; border-color:transparent; background:transparent;
}
@media (max-width:700px) {
  .project-context select.proj-pill { min-height:44px; max-width:100%; }
}
.project-context .proj-pill[hidden] {
  display:none;
}
.ghost-btn {
  background:none; border:1px solid var(--line2); border-radius:7px;
  color:var(--ink2); font:inherit; font-size:13.5px; padding:7px 13px; cursor:pointer;
}
.ghost-btn:hover { color:var(--ink); background:var(--card2); border-color:var(--muted); }

/* ── The primary action ──────────────────────────────────────────────────────
   There was no class for this. Green was applied either by hardcoded id
   (#ra-submit, #part-submit, #engineering-report-print) or, worse, by POSITION
   — `.snag-primary-actions button:first-child` — so the colour followed
   whichever verb happened to be first in an array. Change what a snag may do
   next and the emphasis silently moved to a different word.

   Only creating or confirming wears this. A status verb never does: green
   means passed and red means fault everywhere else in this application, and a
   button that says "Mark cleared" in the colour of Completed is telling the
   reader something untrue. Colour belongs to the badge, not to the verb.

   The colour is a token so the whole system can be changed in one line. Lime
   is the Delmatic accent and carries no pass or fail meaning on a create
   action; if it ever needs to move further from the status palette, charcoal
   (--ink) is the intended alternative and only these two values change. */
:root, [data-theme] { --btn-primary-bg:var(--accent); --btn-primary-ink:var(--btn-ink); }
.primary-btn {
  background:var(--btn-primary-bg); color:var(--btn-primary-ink);
  border:1px solid var(--btn-primary-bg); border-radius:8px;
  font:inherit; font-weight:650; padding:8px 16px; cursor:pointer;
}
/* Keep the lime surface and its dark text together. The element hover rule
   has higher specificity than the resting primary class. */
.primary-btn:is(:hover, :focus-visible):not(:disabled) {
  background:var(--btn-primary-bg); color:var(--btn-primary-ink);
  border-color:var(--btn-primary-bg);
  box-shadow:0 0 0 2px var(--card), 0 0 0 4px var(--focus);
}
.primary-btn:focus-visible { outline:2px solid var(--focus); outline-offset:3px; }
.primary-btn:disabled:hover {
  background:var(--btn-primary-bg); color:var(--btn-primary-ink);
  border-color:var(--btn-primary-bg); box-shadow:none;
}
.primary-btn:disabled { opacity:.55; cursor:not-allowed; filter:none; }

main {
  width:100%; max-width:none; margin:0;
  padding:28px var(--workspace-gutter) 64px;
}
.eyebrow {
  font-size:11px; font-weight:600; letter-spacing:.09em; text-transform:uppercase;
  color:var(--muted); margin:0 0 2px;
}
h1, h2, h3, h4 {
  font-family:'Archivo', "Segoe UI", system-ui, sans-serif;
  letter-spacing:-.015em;
}
h2 { font-size:16.5px; margin:0 0 14px; letter-spacing:-.01em; text-wrap:balance; }
/* A measure is read at a glance rather than word by word, so its figure
   needs the weight and the tight fit of the display face. */
.dashboard-measure .v, .report-measure .v,
svg.trend .endlab { font-family:'Archivo', "Segoe UI", system-ui, sans-serif; }
.card {
  background:var(--card); border:1px solid var(--line); border-radius:12px;
  padding:20px 22px; box-shadow:var(--shadow);
}
.note { font-size:12px; color:var(--muted); margin:12px 0 0; }
section.block { margin-bottom:18px; }

/* ── Workspace shell ──────────────────────────────────────────────────────
   The rail and toolbar use the reference mockup's two-column structure.
   The document remains the scrolling element, so existing focus and drawing
   viewer behavior stays unchanged. */
:root { --rail-w:234px; --top-band:56px; }

/* ── Selection ───────────────────────────────────────────────────────────────
   One idiom for "this is the one you picked", used everywhere. A row in a
   list gets a tinted ground and a 3 px accent bar down its leading edge; a
   free-standing card gets the same tint with a one-pixel accent ring, because
   a card has no list edge to put a bar against. Nothing draws a second box
   inside its own border, which is what made the old selected project look
   like a badly fitted outline. */
:root {
  --sel-bg:color-mix(in srgb,var(--accent) 10%,var(--card2));
  --sel-bar:3px;
}
.is-picked {
  position:relative; background:var(--sel-bg); color:var(--ink); font-weight:650;
}
.is-picked::before {
  content:""; position:absolute; inset-block:0; inset-inline-start:0;
  width:var(--sel-bar); background:var(--accent); border-radius:0;
}
.is-picked-card {
  background:var(--sel-bg); border-color:var(--accent);
  box-shadow:0 0 0 1px var(--accent);
}



.app-shell {
  display:grid;
  grid-template-columns:var(--rail-w) minmax(0,1fr);
  align-items:start; min-height:100vh;
  transition:grid-template-columns 160ms ease;
}
.app-shell.rail-collapsed { --rail-w:64px; }
/* minmax(0,1fr) above and this below: without them a wide table inside a
   grid track refuses to shrink and pushes the whole page sideways. */
.app-stage { min-width:0; }
/* A drawing closed because the page reloaded (050). A fact, not a button:
   the soft information line of design rule 1. */
.viewer-closed-notice { margin:12px 16px 0; padding:10px 12px; border:1px solid var(--line2);
  border-top:3px solid var(--chip-info-ink); border-radius:8px; background:var(--card); color:var(--ink); }

.app-rail {
  position:sticky; top:0; height:100vh; overflow:hidden;
  display:flex; flex-direction:column;
  padding:0; background:var(--rail-bg); color:var(--rail-ink);
  border-right:1px solid var(--rail-edge);
}

.rail-brand {
  flex:0 0 56px; display:flex; align-items:center; gap:9px;
  padding:0 16px; border-bottom:1px solid var(--rail-line);
}
.rail-brand .logo-mark { width:28px; height:28px; }
.rail-brand-text { min-width:0; }
.rail-brand-text b {
  display:block; color:var(--rail-brand-ink); font:700 15px/1.1 'Archivo', sans-serif;
  letter-spacing:-.035em; white-space:nowrap;
}
.rail-brand-text small {
  display:block; color:var(--rail-brand-sub); font-size:9.5px; letter-spacing:.01em;
}

/* The rail follows the active theme through the tokens above, so its
   buttons are written once and read correctly in all three. */
.app-rail nav.tabs {
  flex:1 1 auto; min-height:0; overflow-x:hidden; overflow-y:auto; flex-direction:column; gap:2px;
  padding:14px 10px 8px; scrollbar-width:thin;
}
.rail-group { display:flex; flex-direction:column; gap:2px; margin-top:15px; }
.rail-group-label {
  margin:0 0 4px 10px; font-size:10px; font-weight:600;
  letter-spacing:.12em; text-transform:uppercase; color:var(--rail-ink2);
}
/* A heading with nothing under it is worse than no heading. app.js hides
   the buttons a project or an account may not reach, so a whole group can
   empty itself - Setup does, for a Client. Where :has is unsupported the
   heading simply stays, which is untidy rather than broken. */
.rail-group:not(:has(button:not([hidden]))) { display:none; }
.app-rail nav.tabs button {
  position:relative; display:flex; align-items:center; justify-content:flex-start; gap:11px;
  width:100%; min-height:36px; text-align:left; padding:8px 10px; border:0; border-radius:7px;
  background:none; color:var(--rail-ink); font-size:14px; line-height:1.2;
}
/* The icon is a landmark, not decoration: it is what the eye returns to
   when picking a destination it has used before. It carries no meaning of
   its own, so it stays quiet until its row is the current one. */
.app-rail .rail-ico { flex:0 0 auto; width:18px; height:18px; opacity:.72; }
.app-rail nav.tabs button:hover .rail-ico { opacity:1; }
.app-rail nav.tabs button.on .rail-ico { opacity:1; color:var(--rail-mark); }
.app-rail nav.tabs button:hover { color:var(--rail-hover-ink); background:var(--rail-hover-bg); }
/* Selection is a bar, a fill AND a weight. Colour alone would not say it to
   somebody who cannot tell these two greens apart. */
.app-rail nav.tabs button.on {
  background:var(--rail-sel-bg); color:var(--rail-sel-ink); font-weight:600;
  box-shadow:none;
}
.app-rail nav.tabs button.on::before {
  content:""; position:absolute; left:-10px; top:6px; bottom:6px; width:3px;
  border-radius:0 3px 3px 0; background:var(--rail-mark);
}
.app-rail nav.tabs button[hidden] { display:none; }
.rail-count {
  margin-left:auto; padding:1px 6px; border-radius:999px;
  background:var(--rail-count-bg); color:var(--rail-count-ink);
  font-size:11px; font-weight:600; font-variant-numeric:tabular-nums;
}

/* Who is signed in, at the foot of the rail. On a shared site laptop the
   account decides what is on the screen, so it should not take a menu to
   find out which one is in use. */
.rail-foot {
  flex:0 0 auto; margin-top:auto; display:flex; align-items:center; gap:10px;
  padding:16px 18px; border-top:1px solid var(--rail-line);
}
.rail-avatar {
  flex:0 0 auto; width:28px; height:28px; border-radius:50%;
  /* Dark ink on the accent circle. --btn-ink is exactly that, per theme. */
  display:grid; place-items:center; background:var(--accent); color:var(--btn-ink);
  font-family:'Archivo', "Segoe UI", system-ui, sans-serif;
  font-weight:700; font-size:12px;
}
.rail-who { min-width:0; }
.rail-who b {
  display:block; font-size:13px; font-weight:600; color:var(--rail-brand-ink);
  white-space:nowrap; overflow:hidden; text-overflow:ellipsis;
}
.rail-who small { display:block; font-size:11px; color:var(--rail-ink2); }
.rail-collapsed .rail-brand { justify-content:center; padding-inline:0; }
.rail-collapsed .rail-brand-text,
.rail-collapsed .app-rail nav.tabs button > span,
.rail-collapsed .rail-who { display:none; }
.rail-collapsed .rail-group-label { height:8px; margin:0; opacity:0; }
.rail-collapsed .app-rail nav.tabs button { justify-content:center; padding-inline:0; }
.rail-collapsed .rail-foot { justify-content:center; padding-inline:0; }
@media (prefers-reduced-motion:reduce) {
  .app-shell { transition:none; }
}
/* The Ctrl K hint is a desktop promise. A narrower window still has a real
   keyboard, but not the room, so the hint goes and the field stays. */
@media (max-width:1180px) {
  .workspace-search { flex:1 1 200px; min-width:150px; }
  .workspace-search kbd { display:none; }
}

/* ── Application workspace ────────────────────────────────────────────────
   Operational pages use the screen. Individual reading and form regions keep
   local width limits where they need them. The report has its own document
   rules and does not inherit the dashboard presentation below. */
.workspace-page { width:100%; max-width:none; }
.workspace-page h1 { margin:0 0 12px; font-size:26px; letter-spacing:-.025em; }
.workspace-heading {
  display:flex; align-items:flex-end; justify-content:space-between; gap:24px;
  min-height:62px; padding:0 0 20px; border-bottom:1px solid var(--line2);
  margin-bottom:0;
}
.workspace-heading h1 { margin:2px 0 0; font-size:26px; letter-spacing:-.025em; }
.admin-heading + .admin-tabs { margin-top:20px; }
.workspace-heading .ghost-btn { min-height:38px; padding-inline:16px; }
.workspace-heading-rich { flex-wrap:wrap; align-items:flex-start; }
.workspace-heading-rich > :first-child { min-width:0; flex:1 1 460px; }
.workspace-page-intro {
  max-width:76ch; margin:7px 0 0; color:var(--ink2); font-size:13.5px;
  line-height:1.55;
}
.workspace-heading-actions {
  display:flex; align-items:center; justify-content:flex-end; gap:8px; flex-wrap:wrap;
}
.workspace-heading-actions > button { min-height:38px; }
.workspace-heading-actions > button:not(.ghost-btn) {
  background:var(--accent); border-color:var(--accent); color:var(--btn-ink);
  font-weight:650;
}
.workspace-view-tabs {
  order:3; display:flex; align-items:center; gap:28px; width:100%; margin:4px 0 -20px;
  overflow-x:auto; border-top:1px solid var(--line); scrollbar-width:thin;
}
.workspace-view-tabs button {
  min-height:46px; padding:10px 1px 8px; border:0; border-bottom:2px solid transparent;
  border-radius:0; background:transparent; color:var(--ink2); font-weight:500;
}
.workspace-view-tabs button:hover { background:transparent; color:var(--ink); border-color:transparent; }
.workspace-view-tabs button.on {
  background:transparent; color:var(--ink); border-color:var(--accent); font-weight:650;
}
.workspace-scope {
  padding:14px 0; border-bottom:1px solid var(--line); margin:0;
}
.workspace-page > .card.block,
.workspace-page > section.card.block,
.workspace-page > #intelligence-content > .card.block {
  background:var(--card); border:1px solid var(--line); border-radius:10px;
  box-shadow:none; padding:14px 16px 16px; margin:0;
}
.workspace-page > .card.block > h1,
.workspace-page > .card.block > h2,
.workspace-page > #intelligence-content > .card.block > h2 {
  margin:0 -16px 14px; padding:0 16px 12px;
  border-bottom:1px solid var(--line);
}
.workspace-page > .card.block:first-child,
.workspace-page > section.card.block:first-child { padding-top:0; }
.workspace-page > .engineering-coverage { margin-top:var(--workspace-gap); }
.workspace-page .tbl-wrap,
.workspace-page .table-wrap { scrollbar-gutter:stable; }

/* The Overview measure band divides the available space between the measures
   that exist. Feature switches remove a measure and its grid track together. */
.dashboard-measures {
  display:grid; grid-template-columns:repeat(auto-fit,minmax(220px,1fr));
  gap:0; margin:0; overflow:hidden;
  background:var(--card); border:1px solid var(--line); border-radius:10px;
}
/* A band with no measures in it must not draw its own empty box. This only
   became visible once the band had a border: before, an empty band was
   invisible, so nothing said it was there. */
.dashboard-measures:empty { display:none; }
.dashboard-measure {
  min-width:0; padding:20px clamp(16px,1.6vw,26px);
  border-inline-start:1px solid var(--line);
}
.dashboard-measure:first-child { border-inline-start:0; }
.dashboard-measure.loading { grid-column:1 / -1; color:var(--muted); }
.dashboard-measure .v {
  font-size:32px; font-weight:680; letter-spacing:-.03em; line-height:1.1;
  font-variant-numeric:tabular-nums;
}
.dashboard-measure .v small { font-size:16px; color:var(--ink2); font-weight:500; }
.dashboard-measure .v small.unit { margin-left:3px; }
.dashboard-measure .v .ext { font-size:14px; vertical-align:super; }
.dashboard-measure .s { margin-top:4px; color:var(--ink2); font-size:12.5px; }
.dashboard-measure.link a { display:block; color:inherit; text-decoration:none; }
.dashboard-measure.link a:focus-visible { outline:2px solid var(--accent); outline-offset:5px; }

/* Scope and freshness under the project name. Two lines of quiet text: they
   say what the figures cover and how old they are, and neither is a measure. */
.overview-context {
  display:flex; flex-direction:column; gap:2px; margin:8px 0 0;
  color:var(--ink2); font-size:12.5px; line-height:1.5;
}
.overview-context:empty { display:none; }
.overview-evidence-line { font-variant-numeric:tabular-nums; }
/* The health sentence appears only when something is wrong, so it is allowed
   to be loud. A permanent green tick trains the eye to ignore the line. */
.overview-health {
  margin:8px 0 0; padding:7px 11px; border-radius:8px;
  border:1px solid var(--chip-warn-bg); background:var(--chip-warn-bg);
  color:var(--chip-warn-ink); font-size:12.5px; line-height:1.45;
  max-width:76ch;
}
.overview-health[data-state="unavailable"],
.overview-health[data-state="failed_latest"] {
  border-color:var(--chip-fail-bg); background:var(--chip-fail-bg);
  color:var(--chip-fail-ink);
}
/* The window the change figures cover, written out rather than implied. */
.overview-change-window {
  margin:0 0 6px; color:var(--ink); font-size:13px; font-weight:600;
  font-variant-numeric:tabular-nums;
}
.overview-change-measures {
  display:flex; flex-wrap:wrap; gap:8px; margin:10px 0 0;
}
.overview-change-measures:empty { display:none; }
.overview-change-measure {
  padding:5px 11px; border-radius:999px; background:var(--chip-pass-bg);
  color:var(--chip-pass-ink); font-size:12.5px; font-weight:600;
  font-variant-numeric:tabular-nums;
}
.overview-change-measure.regression {
  background:var(--chip-fail-bg); color:var(--chip-fail-ink);
}
/* Five work types, one project. Same row shape as the module hold-up bars, so
   a reader who has learned one has learned both. */
.worktype-bars { margin-top:12px; }

.overview-primary {
  display:grid; grid-template-columns:minmax(0,2fr) minmax(300px,.95fr);
  column-gap:var(--workspace-gap); align-items:start;
}
/* A grid item defaults to min-width:auto, so it refuses to shrink below its
   own content. The progress chart is an SVG with min-width:560px and its own
   scrolling wrapper — but the wrapper could never do its job, because the
   TRACK grew to 560px instead and pushed the whole page sideways. On a phone
   the document scrolled horizontally and the chart still did not fit.
   Invisible until a project had a progress history to draw. */
.overview-primary > *, .overview-summaries > * { min-width:0; }
.overview-primary:has(> #needs-attention[hidden]) { grid-template-columns:1fr; }

/* The summary band: Modules, Emergency and Snags side by side, each one a
   doorway to its own destination. Feature 013.

   auto-fit rather than a fixed column count, for the same reason the measure
   band uses it: a project can switch any of the three off, and a band that
   counted its columns would leave a gap where the missing one was. Three
   become two become one as the window narrows, with no breakpoint to keep in
   step with the rail. */
.overview-summaries {
  display:grid; grid-template-columns:repeat(auto-fit,minmax(300px,1fr));
  gap:var(--workspace-gap);
}
/* The tracks STRETCH — no align-items:start here, unlike .overview-primary
   above. Three panels of three different heights read as an accident, and the
   way through ends up on a different line in each one. Stretched, every
   doorway sits on the same line and the eye finds it in the same place. */
.overview-summary { display:flex; flex-direction:column; }
/* The way through sits at the foot of every panel, on the same line whatever
   the panel above it holds, so the eye finds it in the same place in all
   three. */
.overview-summary > .ghost-btn { margin-top:auto; align-self:flex-start; }
.overview-summary-lead { margin:12px 0 4px; color:var(--ink2); font-size:13px; }
.overview-summary-lead b { color:var(--ink); font-variant-numeric:tabular-nums; }
.overview-summary-notes {
  margin:10px 0 0; color:var(--ink2); font-size:12.5px;
}
.overview-summary-notes b { color:var(--ink); font-variant-numeric:tabular-nums; }
.overview-bars-head { margin:16px 0 6px; }
/* Three figures under the emergency bar, and two queues under the snag
   heading. Same shape: a number a person reads first, and a word saying what
   it counts. */
.overview-tallies, .snag-queues {
  display:flex; flex-wrap:wrap; gap:22px; margin:13px 0 4px;
}
.overview-tallies span, .snag-queues span { display:flex; flex-direction:column; gap:2px; }
.overview-tallies b, .snag-queues b {
  color:var(--ink); font-size:20px; font-weight:650; line-height:1.1;
  font-variant-numeric:tabular-nums;
}
.overview-tallies small, .snag-queues small {
  color:var(--muted); font-size:10.5px; font-weight:600;
  letter-spacing:.05em; text-transform:uppercase;
}
/* A figure that is a fault wears the fault colour. Nothing else in these
   panels is coloured, so the one that is carries real weight. */
.overview-tallies b.tone-fail, .overview-summary-notes b.tone-fail { color:var(--fail); }
/* Schedules get a line, not a panel, and only when something is missing. */
.overview-reference-line {
  display:flex; flex-wrap:wrap; align-items:center; gap:12px;
  margin:0; padding:12px 2px; color:var(--ink2); font-size:13px;
  border-top:1px solid var(--line);
}
.overview-reference-line b { color:var(--ink); font-variant-numeric:tabular-nums; }
/* Panels, from webapp-design/mockups/workspace-reference.html.
   These are NOT the heavy cards 008 removed: no shadow, a hairline border,
   a small radius, and a ruled head. The old card announced itself as a box;
   this one only holds its contents together, so the eye can find where a
   region ends on a wide screen. */
/* One rule for every workspace page. Six identical page-scoped copies of a
   flat treatment used to sit further down this file - one per page, each
   with an id selector that quietly beat this one. That is the duplication
   CLAUDE.md warns about when a shared style is lifted to a parent: the
   copies survive, and they win. */
.workspace-page .workspace-section {
  min-width:0; margin:0; padding:14px 16px 16px;
  background:var(--card); border:1px solid var(--line); border-radius:10px;
  box-shadow:none;
}
/* The head is the eyebrow and the title, ruled off from the body. The rule
   spans the whole panel, so the padding is pulled back for it. */
.workspace-page .workspace-section > h2,
.workspace-page .workspace-section > .section-heading {
  margin:0 -16px 14px; padding:0 16px 12px;
  border-bottom:1px solid var(--line);
}
.workspace-page .workspace-section > h2 { font-size:15px; }
.workspace-page .workspace-section > .eyebrow,
.workspace-page .workspace-section .section-heading .eyebrow { margin:0 0 3px; }
/* Panels stack with a gap between them instead of running together with
   rules, which is what makes each one read as its own region. */
.workspace-page {
  display:flex; flex-direction:column; gap:var(--workspace-gap);
}
/* NO inner scroll pane. It had max-height:480px and overflow-y:auto, which
   is the same fault the snag drawings tab had: a scrolling box inside a
   scrolling page hides how much there is, so a job with thirty floors looked
   like a job with twelve until somebody found the groove. A progress chart's
   LENGTH is information — it says how big the building is — and the page
   scrolls perfectly well on its own.

   The rows are sorted worst first, so the floors that need somebody are the
   ones at the top whatever the height. Feature 013, phase 4. */
.dashboard-floor-list { padding-inline-end:2px; }
.dashboard-floor-list .floor-row {
  grid-template-columns:minmax(140px,210px) minmax(120px,1fr) 52px;
  min-height:34px; border-bottom:1px solid var(--line);
}
.dashboard-floor-list .floor-row:last-child { border-bottom:0; }
.dashboard-floor-list .floor-row .nm { text-align:left; }
.needs-attention .section-heading { margin-bottom:12px; }
#page-dash #needs-attention-list { gap:0; }
/* A row carries its urgency in a stripe down its left edge, so the eye
   finds the line that needs somebody before reading any of the words. The
   colours are the same ones the rest of the application uses for a state. */
/* Rows, not buttons. They all opened the same unfiltered Action Center, so
   the chevron and the hover were promising a destination each that did not
   exist. The stripe stays: it is the part that was doing real work. */
#page-dash #needs-attention-list .attention-row {
  min-height:56px; padding:9px 12px 9px 9px; border:0;
  border-top:1px solid var(--line); border-left:3px solid transparent;
  border-radius:0; background:transparent; color:var(--ink);
  display:flex; align-items:center; gap:12px; width:100%; text-align:left;
}
#page-dash #needs-attention-list .attention-row:first-child { border-top:0; }
#page-dash #needs-attention-list .attention-row.urgent { border-left-color:var(--fail); }
#page-dash #needs-attention-list .attention-row.attention { border-left-color:var(--chip-warn-ink); }
#page-dash #needs-attention-list .attention-row.routine { border-left-color:var(--line2); }
#page-dash #needs-attention-list .txt { min-width:0; flex:1; }
#page-dash #needs-attention-list .txt b {
  display:block; font-size:13.5px; font-weight:600; line-height:1.3;
}
#page-dash #needs-attention-list .txt small { color:var(--muted); font-size:12px; }
#page-dash #needs-attention-list .cnt {
  font-family:'Archivo', "Segoe UI", system-ui, sans-serif;
  font-size:18px; font-weight:600; font-variant-numeric:tabular-nums;
}
#page-dash #needs-attention-list .attention-row b { font-size:18px; font-variant-numeric:tabular-nums; }
#page-dash #needs-attention-list .attention-row small {
  grid-column:1 / -1; color:var(--muted); font-size:11.5px;
}
#page-dash #needs-attention-note { margin:12px 0 0; }
.overview-trend .trend-wrap { margin-top:12px; }
.overview-trend .trend { min-height:230px; }

/* Phase 5 starts with Overview. Its sections already share the flat workspace
   panel treatment; keep the remaining furniture just as deliberate. Table
   regions get one bounded surface, and every page-level control settles at the
   same desktop height. These selectors stay under #page-dash so the frozen
   report and the pages still waiting for their own treatment cannot inherit. */
#page-dash :is(.tbl-wrap, .table-wrap) {
  overflow-x:auto; border:1px solid var(--line); border-radius:10px;
  background:var(--card);
}
#page-dash :is(.tbl-wrap, .table-wrap) th { background:var(--card2); }
#page-dash :is(.tbl-wrap, .table-wrap) tbody tr:last-child td { border-bottom:0; }
#page-dash .workspace-heading .ghost-btn,
#page-dash .section-heading .ghost-btn,
#page-dash .toolbar :is(input, select, button) {
  box-sizing:border-box; min-height:40px;
}
#page-dash .toolbar .seg { min-height:40px; align-items:stretch; }
#page-dash .toolbar .seg button { display:inline-flex; align-items:center; }

@media (max-width:1050px) {
  .overview-primary { grid-template-columns:1fr; }
  #page-dash .overview-primary > .overview-trend { padding-inline-end:0; }
  /* Needs attention goes FIRST once the two stop sitting side by side. It is
     the only thing on Overview that says do something, and stacked in source
     order it landed under a 230px chart — so on a laptop or a phone the one
     actionable panel was the one you had to scroll for. The markup order is
     unchanged, because the element contract records it and because on a wide
     screen the reading order is already correct. Feature 013, phase 4. */
  #page-dash .overview-primary > .needs-attention {
    order:-1;
    border-inline-start:0; border-bottom:1px solid var(--line); border-top:0;
    padding-inline-start:0;
  }
}

@media (max-width:700px) {
  main { padding:20px var(--workspace-gutter) 54px; }
  .workspace-heading { align-items:stretch; flex-direction:column; gap:12px; }
  .workspace-heading-rich > :first-child { flex:0 1 auto; }
  .workspace-heading .ghost-btn { width:100%; min-height:44px; }
  .workspace-heading-actions { width:100%; justify-content:stretch; }
  .workspace-heading-actions > * { flex:1 1 100%; min-height:44px; }
  .workspace-view-tabs { gap:20px; margin-top:0; }
  .workspace-view-tabs button { flex:0 0 auto; min-height:44px; }
  .dashboard-measures { grid-template-columns:repeat(auto-fit,minmax(150px,1fr)); }
  .dashboard-measure { padding:16px 12px; }
  .dashboard-measure:nth-child(odd) { border-inline-start:0; }
  .dashboard-measure .v { font-size:28px; }
  .dashboard-floor-list { padding-inline-end:0; }
  .dashboard-floor-list .floor-row {
    grid-template-columns:minmax(92px,130px) minmax(80px,1fr) 46px;
    gap:8px;
  }
  .overview-trend .trend { min-height:180px; }
}


/* When one side of the row is switched off, the remaining card takes the full
   width instead of leaving the other track standing empty. */

/* ── Floor bars ────────────────────────────────────────────────────────── */
.floor-row {
  display:grid; grid-template-columns:190px 1fr 52px; gap:12px;
  align-items:center; padding:4.5px 0; cursor:default;
}
.floor-row .nm {
  font-size:13px; color:var(--ink2); white-space:nowrap;
  overflow:hidden; text-overflow:ellipsis; text-align:right;
}
.floor-row .track { height:14px; background:var(--data-track); border-radius:4px; overflow:hidden; }
.floor-row .fill { height:100%; background:var(--data); border-radius:0 4px 4px 0; }
/* One red-amber-green scale, shared by every progress bar on screen and on
   paper. The band classes come from scoreBand() in app.js, so the screen and
   the report cannot drift apart. A bar with no score carries no band. */
.fill.band-low { background:var(--fail); }
.fill.band-mid { background:var(--progress-mid); }
.fill.band-high { background:var(--data); }
.floor-row .pc { font-size:12.5px; font-variant-numeric:tabular-nums; font-weight:600; }
.floor-row:hover .track { outline:1px solid var(--line2); }
.floor-row .pc.na, .na-txt { color:var(--muted); font-weight:400; }
@media (prefers-reduced-motion: no-preference) { .floor-row .fill { transition:width .5s ease; } }

/* ── Emergencies panel ─────────────────────────────────────────────────── */
.em-stat { margin-bottom:16px; }
.em-line { display:flex; align-items:baseline; gap:10px; }
.em-line .big { font-size:26px; font-weight:650; letter-spacing:-.02em; }
.em-line .lbl { font-size:13px; color:var(--ink2); }
.em-bar { display:flex; height:14px; border-radius:4px; overflow:hidden; margin-top:7px; gap:2px; }
.em-bar .pass { background:var(--data); border-radius:4px 0 0 4px; }
.em-bar .fail { background:var(--fail); }
.em-bar .no-result { background:var(--line2); border-radius:0 4px 4px 0; }
.em-legend { display:flex; gap:16px; font-size:12.5px; color:var(--ink2); margin-top:7px; }
.em-legend i {
  display:inline-block; width:9px; height:9px; border-radius:2.5px;
  margin-right:6px;
}
.fail-types { margin-top:14px; border-top:1px solid var(--line); padding-top:12px; }
.fail-types .rw {
  display:flex; justify-content:space-between; gap:10px;
  font-size:12.5px; padding:3px 0; color:var(--ink2);
}
.fail-types .rw b { color:var(--ink); font-variant-numeric:tabular-nums; font-weight:600; }

/* ── Tables ────────────────────────────────────────────────────────────── */
.tbl-wrap { overflow-x:auto; }
table { border-collapse:collapse; width:100%; font-size:13px; }
th {
  text-align:left; font-size:11px; letter-spacing:.07em; text-transform:uppercase;
  color:var(--muted); font-weight:600; padding:8px 10px;
  border-bottom:1px solid var(--line2); white-space:nowrap;
  position:sticky; top:0; background:var(--card);
}
td { padding:8px 12px; border-bottom:1px solid var(--line);
     font-variant-numeric:tabular-nums; white-space:nowrap; }
tbody tr:last-child td { border-bottom:0; }
tr:hover td { background:var(--card2); }
td.num, th.num { text-align:right; }
.scroll-y { max-height:430px; overflow-y:auto; }

.chip {
  display:inline-flex; align-items:center; gap:5px; font-size:11.5px;
  font-weight:600; border-radius:999px; padding:2px 9px;
  letter-spacing:.02em; line-height:1.6; white-space:nowrap;
}
/* An optional dot, for the chips that carry a live state rather than a
   result. Chips without one are unaffected. */
.chip .dot { width:6px; height:6px; border-radius:50%; background:currentColor; flex:none; }
.chip.pass { background:var(--chip-pass-bg); color:var(--chip-pass-ink); }
.chip.fail { background:var(--chip-fail-bg); color:var(--chip-fail-ink); }
.chip.warn { background:var(--chip-warn-bg); color:var(--chip-warn-ink); }
.chip.info { background:var(--chip-info-bg); color:var(--chip-info-ink); }
.chip.na   { background:var(--chip-na-bg);   color:var(--chip-na-ink); font-weight:500; }

/* ── Toolbar ───────────────────────────────────────────────────────────── */
.toolbar { display:flex; gap:10px; flex-wrap:wrap; align-items:center; margin-bottom:14px; }
.toolbar input[type=search] {
  background:var(--card2); color:var(--ink); border:1px solid var(--line2);
  border-radius:8px; padding:7px 12px; font:inherit; font-size:13.5px; width:230px;
}
.toolbar input[type=search]:focus { outline:2px solid var(--accent); outline-offset:-1px; }
#dashboard-scope {
  background:var(--card2); color:var(--ink); border:1px solid var(--line2);
  border-radius:8px; padding:7px 10px; font:inherit; min-width:220px;
}
.seg { display:flex; border:1px solid var(--line2); border-radius:8px; overflow:hidden; }
.seg button {
  background:none; border:none; color:var(--ink2); font:inherit; font-size:13px;
  padding:7px 14px; cursor:pointer;
}
.seg button.on { background:var(--card2); color:var(--ink); font-weight:600; }
.seg button:focus-visible { outline:2px solid var(--accent); outline-offset:-2px; }
.count-note { font-size:12.5px; color:var(--muted); margin-left:auto; }

/* The module tracker follows the approved reference: search field with a
   visible search icon, counted filters, a short complete bar and coloured
   percentages. The exact percentage remains visible inside every colour. */
#modules .module-toolbar { gap:8px; }
#modules .filter-search { width:260px; }
#modules .seg { gap:2px; padding:2px; border:0; background:var(--card2); }
#modules .seg button {
  min-height:40px; gap:6px; padding:5px 11px; border-radius:6px;
}
#modules .seg button.on { background:var(--card); box-shadow:var(--shadow); }
#modules .seg button b {
  color:var(--muted); font-size:12px; font-weight:600;
  font-variant-numeric:tabular-nums;
}
#modules .seg button.on b { color:var(--ink2); }
/* The Module tracker scrolls with the page, not inside itself. A second
   vertical scrollbar inside a page that already has one means the wheel does
   different things depending on where the pointer is, and every row below the
   360px cut was reachable only by finding the inner bar.

   Removing the inner scroller costs the sticky column header: th is sticky to
   its nearest scrolling ancestor, so against the document it would stick under
   header.top and sit behind it. An offset would have to be a magic number -
   the toolbar is 56px, 58px on a phone, and the environment banner adds an
   unknown band above it on preview builds. So the header scrolls away with the
   table, which is what every other page-flow table here already does.
   Horizontal scrolling stays: #mod-table has an 860px minimum width and narrow
   screens still need to reach the last columns. */
#mod-table th { position:static; }
#mod-table { min-width:860px; }
#mod-table .module-complete-head { width:20%; min-width:180px; }
#mod-table .module-name {
  font-family:'IBM Plex Mono', ui-monospace, "Cascadia Mono", Consolas, monospace;
  font-weight:600; letter-spacing:-.01em;
}
#mod-table .module-floor {
  display:block; max-width:170px; overflow:hidden; text-overflow:ellipsis;
  color:var(--muted); font-size:12px;
}
:is(#mod-table, .rep-modules) .module-progress { display:flex; align-items:center; gap:9px; min-width:150px; }
:is(#mod-table, .rep-modules) .module-progress .track {
  flex:1; min-width:60px; height:6px; overflow:hidden;
  border-radius:4px; background:var(--data-track);
}
:is(#mod-table, .rep-modules) .module-progress .fill { height:100%; border-radius:4px; }
:is(#mod-table, .rep-modules) .module-complete-value {
  min-width:38px; font-size:12.5px; font-variant-numeric:tabular-nums;
  text-align:right;
}
:is(#mod-table, .rep-modules) .module-complete-value.band-low { color:var(--chip-fail-ink); }
:is(#mod-table, .rep-modules) .module-complete-value.band-mid { color:var(--chip-warn-ink); }
:is(#mod-table, .rep-modules) .module-complete-value.band-high { color:var(--chip-pass-ink); }
:is(#mod-table, .rep-modules) .module-score {
  display:inline-flex; min-width:48px; justify-content:center;
  padding:2px 8px; border-radius:999px; font-size:11.5px; font-weight:600;
  font-variant-numeric:tabular-nums; line-height:1.6;
}
:is(#mod-table, .rep-modules) .module-score.band-low { background:var(--chip-fail-bg); color:var(--chip-fail-ink); }
:is(#mod-table, .rep-modules) .module-score.band-mid { background:var(--chip-warn-bg); color:var(--chip-warn-ink); }
:is(#mod-table, .rep-modules) .module-score.band-high { background:var(--chip-pass-bg); color:var(--chip-pass-ink); }
:is(#mod-table, .rep-modules) .module-score.na { background:var(--chip-na-bg); color:var(--chip-na-ink); }

@media (max-width:700px) {
  #modules .filter-search { flex:1 1 100%; width:100%; }
  #modules .count-note { flex:1 1 100%; margin-left:0; }
}

/* The Floors table. Seven fixed columns, so it is read across floors as well
   as along one: a column that came and went with the project would change
   what the column beside it means.

   It scrolls sideways inside its own box on a narrow screen, exactly as the
   module tracker does, and never sideways on the page. No inner vertical
   scroller: the length of the list says how big the building is. */
#floors-table { min-width:820px; }
#floors-table th { position:static; }
#floors-table .floor-overall-head { width:20%; min-width:170px; }
#floors-table tbody th {
  font-weight:600; text-align:left; color:var(--ink); font-size:13px;
}
#floors-table .floor-name {
  display:block; max-width:280px; overflow:hidden; text-overflow:ellipsis;
  white-space:nowrap;
}
#floors-table .module-progress { display:flex; align-items:center; gap:9px; min-width:150px; }
#floors-table .module-progress .track {
  flex:1; min-width:60px; height:6px; overflow:hidden;
  border-radius:4px; background:var(--data-track);
}
#floors-table .module-progress .fill { height:100%; border-radius:4px; }
#floors-table .module-complete-value {
  min-width:38px; font-size:13px; font-weight:650;
  font-variant-numeric:tabular-nums; text-align:right;
}
#floors-table .module-complete-value.band-low { color:var(--chip-fail-ink); }
#floors-table .module-complete-value.band-mid { color:var(--chip-warn-ink); }
#floors-table .module-complete-value.band-high { color:var(--chip-pass-ink); }
/* position:relative is load-bearing. The dash carries its explanation in a
   .sr-only span, which is position:absolute !important - and an absolutely
   positioned box is clipped by an ancestor's overflow ONLY if that ancestor
   is in its containing-block chain. With nothing positioned between the two,
   the span's containing block was outside the scrolling wrapper, so it
   escaped the clip and pushed the whole document sideways on a narrow
   window. The chip becomes the containing block and the clip holds. */
#floors-table .module-score {
  position:relative;
  display:inline-flex; min-width:48px; justify-content:center;
  padding:2px 8px; border-radius:999px; font-size:11.5px; font-weight:600;
  font-variant-numeric:tabular-nums; line-height:1.6;
}
#floors-table .module-score.band-low { background:var(--chip-fail-bg); color:var(--chip-fail-ink); }
#floors-table .module-score.band-mid { background:var(--chip-warn-bg); color:var(--chip-warn-ink); }
#floors-table .module-score.band-high { background:var(--chip-pass-bg); color:var(--chip-pass-ink); }
#floors-table .module-score.na { background:var(--chip-na-bg); color:var(--chip-na-ink); }
#floors-table tbody tr.search-landed th { border-radius:6px 0 0 6px; }
#page-floors .tbl-wrap {
  overflow-x:auto; border:1px solid var(--line); border-radius:10px;
  background:var(--card);
}
#page-floors .tbl-wrap th { background:var(--card2); }
#page-floors .tbl-wrap tbody tr:last-child td { border-bottom:0; }

/* Report sections panel. Every available section stays visible. */
.sections { position:relative; }
.sections > summary {
  cursor:pointer; list-style:none; user-select:none;
  border:1px solid var(--line2); border-radius:8px; background:var(--card2);
  color:var(--ink2); font-size:13px; padding:8px 14px; min-height:44px;
  display:inline-flex; align-items:center; gap:7px; white-space:nowrap;
}
.sections > summary::-webkit-details-marker { display:none; }
.sections > summary::after { content:"\25BE"; font-size:11px; }
.sections[open] > summary { color:var(--ink); }
.sections[open] > summary::after { content:"\25B4"; }
.sections-list {
  position:absolute; z-index:30; margin-top:6px; min-width:230px;
  background:var(--card); border:1px solid var(--line2); border-radius:10px;
  box-shadow:var(--shadow); padding:10px 14px;
  display:flex; flex-direction:column; gap:2px;
}
.sections-list .check-label { padding:5px 0; }
.sections-list .count-note { margin-left:6px; }
.sections-list .seg { margin:2px 0 6px 24px; align-self:flex-start; }
.section-heading { display:flex; align-items:center; justify-content:space-between; gap:12px; }
.section-heading h2 { margin-bottom:0; }

/* Administration */
.admin-intro { margin-bottom:18px; }

/* One status line, outside every pane, so a confirmation is readable from
   whichever tab the reader is on. It was written inside the Projects tab,
   which meant saving a person announced itself where nobody was looking. */
.admin-status {
  margin:14px 0 0; padding:9px 13px; border-radius:8px;
  background:var(--chip-pass-bg); color:var(--chip-pass-ink);
  border:1px solid var(--chip-pass-bg); font-size:13px; font-weight:600;
}
.admin-status[data-state="failed"] {
  background:var(--chip-fail-bg); color:var(--chip-fail-ink);
  border-color:var(--chip-fail-bg);
}
.admin-filter {
  display:flex; align-items:center; gap:7px; font-size:12px; color:var(--ink2);
}
.admin-filter select {
  background:var(--card2); color:var(--ink); border:1px solid var(--line2);
  border-radius:8px; padding:7px 9px; font:inherit; min-height:38px;
}

/* A settings group is a seam. The form used to be one column of twenty
   controls, so the only way to find the Inspectly field was to read all of
   them. */
.admin-group { grid-column:1 / -1; }
.admin-group > legend {
  padding:0 6px; font-size:12px; font-weight:650; letter-spacing:.04em;
  text-transform:uppercase; color:var(--muted);
}
.admin-group-note {
  grid-column:1 / -1; margin:0 0 4px; color:var(--ink2); font-size:12.5px;
  line-height:1.5;
}
.admin-feature-head {
  grid-column:1 / -1; margin:10px 0 0; color:var(--muted);
}
.admin-feature-head:first-of-type { margin-top:0; }
/* A subordinate switch is indented under the one it depends on, and dimmed
   when that parent is off. Disabled rather than hidden: a control that
   vanishes reads as a setting that does not exist. */
.admin-feature-child { padding-inline-start:22px; position:relative; }
.admin-feature-child::before {
  content:""; position:absolute; inset-inline-start:7px; inset-block:6px auto;
  height:calc(100% - 12px); width:1px; background:var(--line2);
}
.admin-feature-child.is-unavailable { opacity:.5; }
.admin-feature-child.is-unavailable input { cursor:not-allowed; }
/* A switch, the reason it may be unavailable, and the setting that depends
   on it are one block across the whole fieldset. Left as separate grid
   items, the reason took the next free column and read as a note about
   whatever happened to be beside it. The text is inset by the width of a
   switch and its gap, so it starts under the words it explains, and the
   block stacks the same way at every width. */
.admin-feature-block { grid-column:1 / -1; display:grid; gap:5px; }
.admin-feature-block > .admin-emergency-evidence,
.admin-feature-block > .admin-feature-dependency {
  margin:0; padding-inline-start:24px;
}

.admin-form-actions {
  grid-column:1 / -1; display:flex; align-items:center; gap:12px;
}
.admin-form-actions .count-note { color:var(--chip-pass-ink); font-weight:600; }

/* The dialogs follow the person editor, which is the pattern this
   application already had: a real <dialog>, so focus is trapped and Escape
   is answered by the browser rather than by hand. */
.admin-dialog .person-fields { grid-template-columns:repeat(2, minmax(0, 1fr)); }
.admin-dialog .person-fields .invite-field-wide { grid-column:1 / -1; }
.admin-dialog .invite-no-project #invite-level-row { grid-column:1 / -1; }
.admin-dialog .person-dialog-body { min-width:min(520px, 86vw); }
.admin-dialog .person-fields input, .admin-dialog .person-fields select {
  width:100%; background:var(--card2); color:var(--ink);
  border:1px solid var(--line2); border-radius:8px; padding:8px 10px; font:inherit;
  font-size:var(--field-font);
}
@media (max-width:640px) {
  .admin-dialog .person-fields { grid-template-columns:1fr; }
  .admin-dialog .person-dialog-body { min-width:min(320px, 90vw); }
}
.admin-project-detail { margin-top:10px; }
.admin-project-detail-head { display:flex; align-items:center; gap:16px; margin-bottom:8px; }
.admin-project-detail-head .eyebrow { margin:0; }
.admin-project-detail-head h3 { margin:2px 0 0; font-size:19px; }
.admin-project-tabs { display:flex; gap:22px; border-bottom:1px solid var(--line2); margin-bottom:18px; }
.admin-project-tabs button {
  padding:9px 1px; border:0; border-bottom:2px solid transparent;
  background:transparent; color:var(--ink2); font:inherit; cursor:pointer;
}
.admin-project-tabs button.on { border-bottom-color:var(--accent); color:var(--ink); font-weight:700; }
.admin-project-tabs button:focus-visible { outline:2px solid var(--accent); outline-offset:2px; }
/* A grid item defaults to min-width:auto, so it refuses to shrink below its
   own content: on a phone the settings column stayed 411px wide inside a
   375px window and took the whole document sideways with it. The same rule
   the Overview panels already carry. */
.admin-project-detail > *, .admin-form > *, .admin-group > * { min-width:0; }
.admin-project-row { min-width:0; }
.admin-project-row > span:first-child { min-width:0; }
.admin-project-row b, .admin-project-row small {
  display:block; overflow:hidden; text-overflow:ellipsis; white-space:nowrap;
}
.admin-project-list { display:grid; gap:7px; }
.admin-project-row {
  width:100%; display:flex; align-items:center; justify-content:space-between;
  gap:12px; text-align:left; background:var(--card2); color:var(--ink);
  border:1px solid var(--line); border-radius:8px; padding:10px 12px;
  font:inherit; cursor:pointer;
}
.admin-project-row.on {
  position:relative; background:var(--sel-bg); border-color:var(--line);
  color:var(--ink); font-weight:650;
}
.admin-project-row.on::before {
  content:""; position:absolute; inset-block:0; inset-inline-start:0;
  width:var(--sel-bar); background:var(--accent);
}
.admin-project-row small { display:block; color:var(--muted); }
.admin-form { display:grid; grid-template-columns:1fr 1fr; gap:12px; }
.admin-project-detail .admin-form { width:100%; }
.admin-form > label { display:flex; flex-direction:column; gap:4px; font-size:12px; color:var(--ink2); }
.admin-inspectly-picker {
  display:grid; grid-template-columns:minmax(120px, 1fr) auto; gap:6px 8px;
  align-items:end;
}
.admin-inspectly-picker label {
  display:flex; flex-direction:column; gap:4px; font-size:12px; color:var(--ink2);
}
.admin-inspectly-picker button { min-height:36px; }
.admin-inspectly-actions { display:flex; gap:6px; }
.admin-inspectly-picker select, .admin-inspectly-status { grid-column:1 / -1; }
.admin-inspectly-status { color:var(--muted); min-height:16px; font-size:12px; }
.admin-inspectly-status strong { display:block; color:var(--ink2); margin-bottom:5px; }
.admin-inspectly-summary {
  display:grid; gap:2px; margin:5px 0; padding:6px 8px;
  background:var(--card2); border:1px solid var(--line); border-radius:7px;
}
.admin-inspectly-summary > div { display:flex; justify-content:space-between; gap:12px; }
.admin-inspectly-summary b { color:var(--ink); font-variant-numeric:tabular-nums; }
.admin-form input:not([type=checkbox]), .admin-form select {
  width:100%; background:var(--card2); color:var(--ink); border:1px solid var(--line2);
  border-radius:8px; padding:8px 10px; font:inherit; font-size:var(--field-font);
}
.admin-form fieldset {
  grid-column:1 / -1; display:grid; grid-template-columns:repeat(2, minmax(0, 1fr));
  gap:7px 14px; border:1px solid var(--line); border-radius:8px; padding:12px;
}
.admin-driver-rules { grid-column:1 / -1; }
.admin-driver-rules > .note { grid-column:1 / -1; margin:0; }
.admin-driver-list { grid-column:1 / -1; display:grid; gap:6px; }
.admin-driver-list h3 { font-size:13px; margin:8px 0 2px; }
.admin-driver-list label { display:flex; align-items:flex-start; gap:8px; }
.admin-driver-list small { color:var(--ink2); }
.admin-form fieldset label {
  display:flex; align-items:center; gap:8px; min-height:20px;
  font-size:13px; color:var(--ink);
}
.admin-form fieldset input[type=checkbox] {
  width:16px; height:16px; flex:0 0 16px; margin:0;
}
.admin-form > button, .admin-form-actions > button {
  justify-self:start; background:var(--accent); color:var(--btn-ink); border:0;
  border-radius:8px; padding:8px 14px; font:inherit; font-weight:650; cursor:pointer;
}
#admin-access-table select { background:var(--card2); color:var(--ink); border:1px solid var(--line2); }
#admin-access-table button { padding:4px 9px; }
.admin-team-actions { display:flex; align-items:center; gap:8px; }
.admin-team-filters { display:grid; grid-template-columns:minmax(220px,1fr) minmax(160px,.5fr); gap:10px; }
.admin-team-filters > label:not(.filter-search) { display:flex; flex-direction:column; gap:4px; color:var(--ink2); font-size:12px; }
.admin-team-filters select { width:100%; }
.project-team-picker { border:1px solid var(--line); border-radius:8px; padding:6px; margin:12px 0; max-height:42vh; overflow:auto; }
.project-team-option { display:flex; align-items:flex-start; gap:10px; padding:9px; border-bottom:1px solid var(--line); }
.project-team-option:last-child { border-bottom:0; }
.project-team-option input { margin-top:3px; }
.project-team-option b,.project-team-option small { display:block; }
.project-team-option small { color:var(--muted); margin-top:2px; }
#project-member-handover { display:grid; gap:6px; }
#project-member-handover[hidden] { display:none; }
.admin-invite-form {
  display:grid; grid-template-columns:repeat(4, minmax(135px, 1fr));
  gap:10px; align-items:end; margin:18px 0; padding:14px;
  background:var(--card2); border:1px solid var(--line); border-radius:10px;
}
.admin-invite-form label { display:flex; flex-direction:column; gap:4px; font-size:12px; color:var(--ink2); }
.admin-invite-form input, .admin-invite-form select {
  min-width:0; background:var(--card); color:var(--ink); border:1px solid var(--line2);
  border-radius:8px; padding:7px 9px; font:inherit;
}
.admin-invite-form .check-label { flex-direction:row; align-items:center; padding-bottom:8px; }
.admin-invite-form button, #password-submit {
  background:var(--accent); color:var(--btn-ink); border:0; border-radius:8px;
  padding:8px 12px; font:inherit; font-weight:650; cursor:pointer;
}
#password-form { display:grid; gap:8px; min-width:min(340px, 80vw); }
#password-form input {
  background:var(--card2); color:var(--ink); border:1px solid var(--line2);
  border-radius:8px; padding:9px 11px; font:inherit; font-size:var(--field-font);
}
@media (max-width:800px) {
  .admin-form { grid-template-columns:1fr; }
  .admin-form fieldset { grid-template-columns:1fr; }
  .admin-filter { width:100%; }
  .admin-filter select { flex:1; }
  /* The Inspectly picker is a two-column grid with an auto track holding two
     buttons side by side. On a phone that track set the width of the whole
     settings column, and the document scrolled sideways behind it. */
  .admin-inspectly-picker { grid-template-columns:1fr; }
  .admin-inspectly-actions { flex-wrap:wrap; }
  .admin-inspectly-actions button { flex:1 1 auto; }
  .admin-inspectly-status { min-width:0; overflow-wrap:anywhere; }
  /* The project team table is wider than a phone and scrolls in its own box,
     which only works while the box itself is bounded. */
  #admin-access-card .tbl-wrap { max-width:100%; min-width:0; }
  #admin-access-table { min-width:640px; }
  .admin-invite-form { grid-template-columns:1fr 1fr; }
  .admin-team-filters { grid-template-columns:1fr; }
}
@media (max-width:520px) { .admin-invite-form { grid-template-columns:1fr; } }

/* ── Trend ─────────────────────────────────────────────────────────────── */
.deltas { display:flex; gap:10px; flex-wrap:wrap; margin-bottom:14px; }
.delta {
  border:1px solid var(--line); border-radius:8px; padding:7px 14px;
  background:var(--card2); font-size:12px; color:var(--ink2);
}
.delta b {
  display:block; font-size:17px; color:var(--ink);
  font-variant-numeric:tabular-nums; letter-spacing:-.01em;
}
.trend-wrap { overflow-x:auto; }
svg.trend { width:100%; height:auto; display:block; min-width:560px; }
svg.trend text { font:11px "Public Sans", "Segoe UI", system-ui, sans-serif; fill:var(--muted); }
svg.trend .endlab { font-size:12px; font-weight:600; fill:var(--ink); }
svg.trend .grid { stroke:var(--line); stroke-width:1; }
svg.trend { color:var(--data); }
svg.trend .area { stroke:none; }
svg.trend .lin { stroke:var(--data); stroke-width:2; fill:none; }
svg.trend .dot { fill:var(--card); stroke:var(--data); stroke-width:2; }
svg.trend .dot.hot { fill:var(--data); }
svg.trend .xh { stroke:var(--line2); stroke-width:1; stroke-dasharray:3 3; }

/* ── Parts ─────────────────────────────────────────────────────────────── */
.parts { display:grid; grid-template-columns:repeat(auto-fill,minmax(230px,1fr)); gap:14px; }
.part { border:1px solid var(--line); border-radius:10px; padding:14px 16px; background:var(--card2); }
.part img, .part .ph {
  width:100%; height:88px; object-fit:contain; border-radius:8px;
  background:var(--data-track); margin-bottom:10px;
}
.part .ph { display:grid; place-items:center; color:var(--muted); font-size:12px; }

/* Inspectly snag summary */
#snags-body > p { margin:0 0 8px; }
.snag-total { display:flex; align-items:baseline; gap:9px; color:var(--ink2); }
.snag-total b { color:var(--ink); font-size:30px; line-height:1; }
.snag-lifetime { margin:4px 0 0; color:var(--muted); font-size:12px; }
.snag-statuses { display:flex; flex-wrap:wrap; gap:8px; margin:13px 0 10px; }
.snag-statuses span { display:flex; gap:5px; align-items:baseline; color:var(--ink2); }
.snag-statuses small { color:var(--muted); font-size:10.5px; text-transform:uppercase; letter-spacing:.05em; }
.snag-statuses b { color:var(--ink); font-variant-numeric:tabular-nums; }
.snag-warning { color:var(--fail); }
.snag-breakdown {
  max-width:620px; margin:14px 0 10px; border-top:1px solid var(--line);
}
.snag-row {
  display:flex; align-items:center; justify-content:space-between; gap:16px;
  padding:7px 2px; border-bottom:1px solid var(--line); color:var(--ink2);
}
.snag-row span { display:flex; align-items:baseline; gap:9px; }
.snag-row small {
  min-width:68px; color:var(--muted); font-size:10.5px; font-weight:600;
  letter-spacing:.06em; text-transform:uppercase;
}
.snag-row b { color:var(--ink); font-variant-numeric:tabular-nums; }
.snag-scope, .snag-updated { margin:9px 0 0 !important; }
.snag-updated.stale { color:var(--fail); }
/* Snag records. The status tones come from the tokens already used elsewhere,
   so a colour means one thing across the product: amber is attention, blue is
   information (waiting to be looked at), green is passed, red is an issue.
   The chip pairs are the contrast-measured ones — see tests/test_theme_contrast.py. */
.snags-summary { margin:6px 0 12px; }
.snags-summary .snag-breakdown { margin-top:10px; }
#page-snags .snag-list { max-height:none; }

.snag-list-heading {
  display:flex; align-items:center; justify-content:space-between; gap:20px;
  margin:0 0 14px;
}
.snag-list-heading h2 { margin:0; }
.snag-page-actions { display:flex; align-items:center; justify-content:flex-end; gap:8px; flex:none; }
.snag-page-actions > button { min-height:40px; white-space:nowrap; }
.snag-filter-grid { display:grid; gap:12px; margin:0 0 10px; min-width:0; }
.snag-filter-row { display:grid; gap:10px 12px; align-items:end; min-width:0; }
.snag-filter-row-primary {
  grid-template-columns:minmax(110px,.7fr) minmax(130px,.9fr) minmax(320px,2fr) minmax(150px,1fr);
}
.snag-filter-row-secondary {
  grid-template-columns:minmax(440px,2.2fr) minmax(150px,1fr) minmax(150px,.9fr) auto;
}
.snag-filter-field { display:grid; gap:4px; min-width:0; color:var(--muted); font-size:11.5px; }
.snag-filter-field > label,
.snag-filter-group > legend { font-weight:650; color:var(--ink2); }
.snag-filter-field input,
.snag-filter-field select { width:100%; min-width:0; max-width:100%; min-height:40px; padding:4px 8px; }
.snag-filter-group { min-width:0; margin:0; padding:0; border:0; }
.snag-filter-group > legend { margin:0 0 4px; padding:0; font-size:11.5px; }
.snag-filter-group-fields { display:grid; grid-template-columns:repeat(2,minmax(0,1fr)); gap:10px; min-width:0; }
.snag-raised-group .snag-filter-group-fields { grid-template-columns:minmax(150px,1.3fr) repeat(2,minmax(130px,1fr)); }
.snag-filter-search-field .filter-search { width:100%; box-sizing:border-box; }
.snag-clear-filters { min-height:40px; white-space:nowrap; }
.snag-clear-filters[hidden] { display:none; }
@container (max-width:900px) {
  .snag-filter-row-primary { grid-template-columns:repeat(2,minmax(0,1fr)); }
  .snag-responsibility-group { grid-column:1 / -1; }
  .snag-filter-row-secondary { grid-template-columns:repeat(2,minmax(0,1fr)); }
  .snag-raised-group { grid-column:1 / -1; }
  .snag-clear-filters { justify-self:start; }
}
@container (max-width:680px) {
  .snag-list-heading { align-items:stretch; flex-direction:column; gap:10px; }
  .snag-page-actions { display:grid; grid-template-columns:repeat(2,minmax(0,1fr)); }
  .snag-page-actions > button { width:100%; }
  .snag-page-actions > :last-child { grid-column:1 / -1; }
  .snag-filter-row-primary, .snag-filter-row-secondary { grid-template-columns:minmax(0,1fr); }
  .snag-responsibility-group, .snag-raised-group { grid-column:auto; }
  .snag-raised-group .snag-filter-group-fields { grid-template-columns:repeat(2,minmax(0,1fr)); }
  .snag-raised-by { grid-column:1 / -1; }
}
@container (max-width:420px) {
  .snag-page-actions, .snag-filter-group-fields,
  .snag-raised-group .snag-filter-group-fields { grid-template-columns:minmax(0,1fr); }
  .snag-page-actions > :last-child, .snag-raised-by { grid-column:auto; }
}
.snag-caption { margin:0 0 8px; color:var(--muted); font-size:12px; }
.snag-list {
  list-style:none; margin:0; padding:0; overflow:hidden;
  border:1px solid var(--line2); border-radius:10px; background:var(--card2);
}
.snag-item + .snag-item { border-top:1px solid var(--line2); }
.snag-item .snag-open {
  display:flex; align-items:center; gap:10px; width:100%; padding:12px 12px 12px 14px;
  background:transparent; border:0; border-radius:0;
  color:inherit; text-align:start; font:inherit; cursor:pointer;
}
.snag-item .snag-open:hover { background:color-mix(in srgb,var(--accent) 5%,transparent); }
.snag-item.withdrawn .snag-open { opacity:.62; }
.snag-item-main { display:flex; flex-direction:column; gap:2px; flex:1 1 auto; min-width:0; }
.snag-item-main b { color:var(--ink); }
.snag-item-main small { color:var(--ink2); font-size:11.5px; }
.snag-badge {
  flex:0 0 auto; min-width:38px; padding:3px 7px; border-radius:999px;
  font-variant-numeric:tabular-nums; font-weight:600; font-size:12px; text-align:center;
}
.snag-state { flex:0 0 auto; font-size:11.5px; font-weight:600; }
.snag-badge.tone-attention   { background:var(--chip-warn-bg); color:var(--chip-warn-ink); }
.snag-badge.tone-information { background:color-mix(in srgb,var(--info) 12%,var(--card)); color:var(--info); }
.snag-badge.tone-passed      { background:var(--chip-pass-bg); color:var(--chip-pass-ink); }
.snag-badge.tone-issue       { background:var(--chip-fail-bg); color:var(--chip-fail-ink); }
.snag-state.tone-attention   { color:var(--chip-warn-ink); }
.snag-state.tone-information { color:var(--info); }
.snag-state.tone-passed      { color:var(--chip-pass-ink); }
.snag-state.tone-issue       { color:var(--chip-fail-ink); }
@container (max-width:420px) {
  .snag-item .snag-open { display:grid; grid-template-columns:auto minmax(0,1fr); align-items:start; }
  .snag-state { grid-column:2; justify-self:start; }
}
/* A button keeps its text on one line, so a long snag title ran past the edge
   of the list and was cut off. On a phone it wraps. */
@media (max-width:700px) {
  .snag-item .snag-open { white-space:normal; }
  .snag-item-main b, .snag-item-main small { overflow-wrap:anywhere; }
}
.snag-legacy-note { margin:14px 0 0; color:var(--muted); font-size:12px; }
.snag-detail-meta { display:flex; flex-wrap:wrap; gap:10px; align-items:baseline; color:var(--muted); font-size:12px; }
.snag-field { margin:6px 0 0; color:var(--ink); }
.snag-field small {
  display:block; color:var(--muted); font-size:10.5px;
  text-transform:uppercase; letter-spacing:.05em;
}
.snag-history { margin:6px 0 14px; padding-inline-start:0; list-style:none; display:flex; flex-direction:column; gap:8px; }
.snag-history li { border-inline-start:3px solid var(--line2); padding-inline-start:9px; }
.snag-history b { color:var(--ink); }
.snag-history small { display:block; color:var(--muted); font-size:11px; }
.snag-history p { margin:3px 0 0; color:var(--ink2); }
.snag-form-error { color:var(--fail); margin:8px 0 0; }
/* One record panel is shared by the list and drawing. It uses the existing
   surface and colour tokens in every theme. */
.snag-workspace { display:grid; grid-template-columns:minmax(0,1fr); gap:20px; align-items:start; }
/* The list and the open record, side by side, split at the top of the section
   rather than below the filters. The panel column runs the full height, so the
   record starts level with the heading and uses the band that used to be
   empty. The page's own title row is above this section and is untouched. */
#snags-work {
  container-type:inline-size;
  display:grid; grid-template-columns:minmax(0,1fr); gap:20px; align-items:start;
}
#page-snags.has-snag-selection #snags-work {
  grid-template-columns:minmax(260px,1fr) minmax(320px,400px);
}
.snag-column { min-width:0; }
#snag-page-outbox { grid-column:1 / -1; min-width:0; }
#snag-page-outbox:empty { display:none; }
/* The split moved up to #snags-work, so this must NOT make a second column any
   more: the panel is no longer a child here. Left in place it reserved a
   320-400px empty track and squeezed the list into a third of its own column,
   which the measurements missed and the screenshot showed at once. */
#snag-panel-home:empty { display:none; }
.snag-detail-panel { min-width:0; background:var(--card); border:1px solid var(--line2); border-radius:14px; overflow:auto; }
.snag-detail-panel[hidden] { display:none; }
#snag-panel-home { position:sticky; top:16px; min-width:0; }
#snag-panel-home .snag-detail-panel { max-height:calc(100dvh - 110px); }
#snag-detail-body { padding:18px; }
.snag-panel-nav { display:flex; align-items:center; gap:6px; margin-bottom:16px; }
.snag-panel-nav #snag-position { flex:1; text-align:center; font-variant-numeric:tabular-nums; }
.snag-detail-panel button { min-height:44px; }
.snag-panel-nav button { padding:7px 10px; }
#snag-detail-title { margin:0; font-size:20px; line-height:1.35; overflow-wrap:anywhere; }
/* The button rows of the snag details share one grid: the status actions, the
   drawing and print actions, and the mark actions (Edit marks, Remove drawing
   mark). One gap token, so the rows cannot drift apart (049). */
.snag-detail-panel { --snag-action-gap:8px; }
.snag-primary-actions, .snag-context-actions, .snag-mark-actions {
  display:flex; flex-wrap:wrap; gap:var(--snag-action-gap); margin:12px 0; }
.snag-primary-actions:empty { display:none; }
.snag-mark-actions:not(:has(> button:not([hidden]))) { display:none; }
/* Each action wears the colour of the status it LEADS TO — Cleared blue,
   Completed green, Re-open red — so the colour is information rather than
   decoration. The earlier version coloured by POSITION, which put the
   Completed green on "Mark cleared", the one state that button does not
   reach.

   A soft tint, not a filled button: three saturated actions side by side shout
   at each other, and these are peers. Same tones the badge and the drawing
   mark use, so a status looks the same wherever it is seen. */
.snag-primary-actions button { flex:1; }
.snag-detail-panel .snag-primary-actions button { font-weight:650; }
.snag-primary-actions button.tone-issue {
  background:var(--chip-fail-bg); color:var(--chip-fail-ink);
  border-color:color-mix(in srgb, var(--chip-fail-ink) 38%, transparent);
}
.snag-primary-actions button.tone-passed {
  background:var(--chip-pass-bg); color:var(--chip-pass-ink);
  border-color:color-mix(in srgb, var(--chip-pass-ink) 38%, transparent);
}
.snag-primary-actions button.tone-information {
  background:color-mix(in srgb, var(--action-ink) 12%, var(--card)); color:var(--action-ink);
  border-color:color-mix(in srgb, var(--action-ink) 38%, transparent);
}
/* A clear coloured edge shows hover without changing the status. */
.snag-primary-actions button.tone-issue { --action-ink:var(--chip-fail-ink); }
.snag-primary-actions button.tone-passed { --action-ink:var(--chip-pass-ink); }
.snag-primary-actions button.tone-information { --action-ink:var(--chip-info-ink, color-mix(in srgb, var(--info) 60%, var(--ink))); }
.snag-primary-actions button:is(:hover, :focus-visible):not(:disabled) {
  background:color-mix(in srgb, var(--action-ink) 12%, var(--card));
  color:var(--action-ink); border-color:var(--action-ink);
  box-shadow:inset 0 0 0 1px var(--action-ink);
}
.snag-primary-actions button:focus-visible { outline:2px solid var(--focus); outline-offset:3px; }

/* The edge of an Activity row says which state it reached, so the history can
   be read down the margin without reading a word of it. An entry that is not a
   status change keeps the neutral line it always had. */
.snag-history li.tone-issue { border-inline-start-color:var(--chip-fail-ink); }
.snag-history li.tone-passed { border-inline-start-color:var(--chip-pass-ink); }
.snag-history li.tone-information { border-inline-start-color:var(--info); }
.snag-context-actions button, .snag-mark-actions button { flex:1; font-size:12px; }
.snag-location-action:not([hidden]) {
  display:inline-flex; align-items:center; justify-content:center; gap:6px;
}
.snag-location-action > svg { width:16px; height:16px; flex:none; }
.snag-panel-tabs { display:flex; gap:18px; border-bottom:1px solid var(--line2); margin:18px 0 14px; }
.snag-panel-tabs [role=tab] { padding:8px 0; border:0; border-bottom:2px solid transparent; border-radius:0; background:transparent; color:var(--muted); }
.snag-panel-tabs [aria-selected=true] { border-bottom-color:var(--accent); color:var(--ink); font-weight:700; }
.snag-detail-panel [role=tabpanel] { min-height:100px; }
.snag-detail-panel label { display:block; margin:14px 0 6px; color:var(--muted); font-size:12px; font-weight:600; text-transform:none; letter-spacing:normal; }
.snag-detail-panel textarea, .snag-detail-panel select { box-sizing:border-box; width:100%; }
.snag-detail-panel .snag-field { white-space:pre-wrap; overflow-wrap:anywhere; margin-bottom:12px; }
.snag-detail-panel .snag-history p { white-space:pre-wrap; overflow-wrap:anywhere; }
.snag-detail-panel .dlg-actions { flex-wrap:wrap; justify-content:flex-start; gap:8px; }
.snag-detail-panel .hint { line-height:1.5; }
/* ── Choosing files ──────────────────────────────────────────────────────────
   The browser's own file control reports what is IN the input. This
   application takes the files out of the input immediately, keeps them in its
   own draft list, and clears the input so the same file can be chosen twice.
   The native text then reads "No file chosen" directly above the files you
   just chose, which is the one thing it must never say.

   The input keeps the label, the keyboard and the focus ring — it is moved
   out of sight, never `display:none`, which would take it off the tab order.
   The button beside it is a visual proxy and is hidden from screen readers,
   because the input itself is already announced. */
.file-picker { display:flex; align-items:center; gap:10px; flex-wrap:wrap; margin-bottom:4px; }
/* Two class names on purpose, and they must both stay.
   `dialog input:not([type="checkbox"])` sets width:100% and a padding, and at
   (0,1,2) it beats a single class. Measured, not guessed: with one class the
   input still drew 428x20 of invisible layout inside the picker, pushing the
   button along and leaving a dead click target beside it. Two classes reach
   (0,2,0), which wins on class count without reaching for !important. */
.file-picker .file-picker-input {
  position:absolute; width:1px; height:1px; padding:0; margin:0; border:0;
  opacity:0; overflow:hidden; white-space:nowrap;
}
.file-picker-btn {
  background:none; border:1px solid var(--line2); border-radius:7px;
  color:var(--ink2); font:inherit; font-size:13.5px; padding:7px 13px; cursor:pointer;
}
.file-picker-btn:hover { color:var(--ink); background:var(--card2); border-color:var(--muted); }
.file-picker-input:focus-visible + .file-picker-btn { outline:2px solid var(--focus); outline-offset:2px; }
.file-picker-state { color:var(--muted); font-size:12.5px; }

/* A refused operation is not a failed one. It is quiet, not alarming: the
   person did nothing wrong, and the only move left is to discard it. */
.outbox-rejected { border-inline-start:3px solid var(--progress-mid); padding-inline-start:10px; }

/* The attachment mark sits on the text baseline it belongs to and takes the
   colour of the line it is in, which is what the emoji could not do. */
.attachment-count { display:inline-flex; align-items:center; gap:3px; color:var(--muted); }
.attachment-icon { width:14px; height:14px; flex:none; }

.snag-item .snag-open[aria-pressed=true] { background:color-mix(in srgb,var(--accent) 10%,var(--card)); box-shadow:inset 3px 0 var(--accent-ink); }
.snag-item .snag-open:focus-visible { outline:2px solid var(--accent-ink); outline-offset:-3px; }
.snag-selection-bar {
  display:flex; align-items:center; flex-wrap:wrap; gap:8px; margin:0 0 10px;
  padding:9px 10px; border:1px solid var(--line2); border-radius:9px; background:var(--card2);
}
.snag-selection-bar > .hint { flex:1 1 260px; margin:0; }
.snag-selection-steps { display:flex; flex:1 1 680px; flex-wrap:wrap; gap:8px 18px; margin:0; padding:0; list-style:none; }
.snag-selection-steps li { display:flex; flex-wrap:wrap; align-items:center; gap:8px; }
.snag-selection-step { display:grid; width:24px; height:24px; place-items:center; border-radius:50%; background:var(--accent); color:#13200a; font-weight:750; }
.snag-list.is-selecting .snag-item { display:grid; grid-template-columns:48px minmax(0,1fr); align-items:stretch; }
.snag-report-select { display:grid; place-items:center; margin:0; border-inline-end:1px solid var(--line); cursor:pointer; }
.snag-report-select input { width:20px; height:20px; accent-color:var(--accent-ink); }
/* ── The snag drawing ────────────────────────────────────────────────────────
   One dialog serves two viewers. A snag drawing is not a progress drawing with
   some pieces switched off — the Snapshot comparison, the change markers and
   the marked export are about what altered between syncs, which is a different
   question from where the faults are. Measured before this was written: the
   toolbar came to 1583px inside a 1440px window, so it did not merely look
   busy, it did not fit.

   Hiding is done here rather than in JavaScript on purpose. showDrawingMode()
   shows several of these unconditionally on every call, so a second writer
   toggling the same `hidden` property would be a race between two owners. CSS
   only ever ADDS hiding: with the class on, these are gone whatever `hidden`
   says; with it off, the existing logic is the only voice. Nothing here tries
   to reveal an element the browser has hidden, which cannot work anyway —
   `[hidden]` is display:none !important in the user-agent sheet. */
.drawing-viewer-dlg.snag-viewer #drawing-mode-toolbar,
.drawing-viewer-dlg.snag-viewer #drawing-newwork-control,
.drawing-viewer-dlg.snag-viewer #drawing-newwork-status,
.drawing-viewer-dlg.snag-viewer #drawing-markers-status,
.drawing-viewer-dlg.snag-viewer #drawing-current-control,
.drawing-viewer-dlg.snag-viewer #drawing-overlay-control,
.drawing-viewer-dlg.snag-viewer #drawing-overlay-strength-control,
.drawing-viewer-dlg.snag-viewer #drawing-overlay-status,
.drawing-viewer-dlg.snag-viewer #drawing-change-panel,
.drawing-viewer-dlg.snag-viewer #drawing-panel-collapse,
/* "Download PDF with markers" means the CHANGE markers. Plain Download PDF
   already composes the snag marks, so nothing is lost by removing it here. */
.drawing-viewer-dlg.snag-viewer #drawing-viewer-download-markers { display:none; }
/* ── The issue drawing ───────────────────────────────────────────────────────
   Opened from Issues. An engineering issue is a database mismatch, not a
   failure and not progress, so the comparison, new work, snags, the previous
   drawing and the Emergency work sheets are not part of it. Hidden here for
   the reason given above the snag drawing: CSS only adds hiding. */
.drawing-viewer-dlg:not(.issue-viewer) #drawing-mode-floor-issues,
.drawing-viewer-dlg.issue-viewer #drawing-mode-failures,
.drawing-viewer-dlg.issue-viewer #drawing-mode-changes,
.drawing-viewer-dlg.issue-viewer #drawing-comparison-label,
.drawing-viewer-dlg.issue-viewer #drawing-comparison,
.drawing-viewer-dlg.issue-viewer #drawing-marker-types,
.drawing-viewer-dlg.issue-viewer #drawing-newwork-control,
.drawing-viewer-dlg.issue-viewer #drawing-newwork-status,
.drawing-viewer-dlg.issue-viewer #drawing-snags-control,
.drawing-viewer-dlg.issue-viewer #drawing-snag-focus-control,
.drawing-viewer-dlg.issue-viewer #drawing-snag-scope-control,
.drawing-viewer-dlg.issue-viewer #drawing-snag-mark-edit,
.drawing-viewer-dlg.issue-viewer #drawing-snags-status,
.drawing-viewer-dlg.issue-viewer #drawing-offline-control,
.drawing-viewer-dlg.issue-viewer #drawing-offline-status,
.drawing-viewer-dlg.issue-viewer #drawing-current-control,
.drawing-viewer-dlg.issue-viewer #drawing-overlay-control,
.drawing-viewer-dlg.issue-viewer #drawing-overlay-strength-control,
.drawing-viewer-dlg.issue-viewer #drawing-overlay-status,
.drawing-viewer-dlg.issue-viewer #drawing-emergency-work-list { display:none; }
/* ── Controls of a layer this drawing does not show ──────────────────────────
   applyDrawingLayerControls() in app.js puts one class on the dialog for each
   layer that drawingLayerPolicy() does not allow here. A layer's controls go
   with its layer, so an emergency drawing cannot keep a snag drawing's "Show
   snags" or a progress drawing's "Previous drawing". The blocks above say what
   each viewer is; this one says what each layer owns. CSS only adds hiding,
   for the reason given above the snag drawing. */
.drawing-viewer-dlg.layer-off-snags #drawing-snags-control,
.drawing-viewer-dlg.layer-off-snags #drawing-snag-focus-control,
.drawing-viewer-dlg.layer-off-snags #drawing-snag-scope-control,
.drawing-viewer-dlg.layer-off-snags #drawing-snag-mark-edit,
.drawing-viewer-dlg.layer-off-snags #drawing-snags-status,
.drawing-viewer-dlg.layer-off-new-work #drawing-newwork-control,
.drawing-viewer-dlg.layer-off-new-work #drawing-newwork-status,
.drawing-viewer-dlg.layer-off-previous #drawing-overlay-control,
.drawing-viewer-dlg.layer-off-previous #drawing-overlay-strength-control,
.drawing-viewer-dlg.layer-off-previous #drawing-current-control,
.drawing-viewer-dlg.layer-off-previous #drawing-overlay-status,
.drawing-viewer-dlg.layer-off-comparison #drawing-mode-changes,
.drawing-viewer-dlg.layer-off-comparison #drawing-comparison-label,
.drawing-viewer-dlg.layer-off-comparison #drawing-comparison,
.drawing-viewer-dlg.layer-off-areas #drawing-areas-control,
.drawing-viewer-dlg.layer-off-areas #drawing-area-new,
.drawing-viewer-dlg.layer-off-areas #drawing-area-fill,
.drawing-viewer-dlg.layer-off-areas #drawing-not-ours,
.drawing-viewer-dlg.layer-off-areas #drawing-names-control,
.drawing-viewer-dlg.layer-off-areas #drawing-names-hint,
.drawing-viewer-dlg.layer-off-areas #drawing-walls-hint,
.drawing-viewer-dlg.layer-off-changes #drawing-markers-control,
.drawing-viewer-dlg.layer-off-changes #drawing-markers-status,
.drawing-viewer-dlg.layer-off-changes #drawing-marker-types,
.drawing-viewer-dlg.layer-off-changes #drawing-viewer-download-markers { display:none; }
.drawing-issue-list { list-style:none; margin:0 0 12px; padding:0; display:grid; gap:4px; }
.drawing-issue-row {
  display:grid; grid-template-columns:minmax(0,1fr); justify-content:stretch; justify-items:start; gap:2px; width:100%; text-align:left; padding:8px 10px; border-radius:8px;
  border:1px solid var(--line2); background:transparent; color:var(--ink); font:inherit; cursor:pointer;
}
.drawing-issue-row b { font-size:13.5px; }
.drawing-issue-row span { font-size:12.5px; color:var(--muted); }
.drawing-issue-row:hover { border-color:var(--accent-ink); }
.drawing-issue-row.is-selected { border-color:var(--accent); background:var(--chip-pass-bg); }
.drawing-issue-row.is-selected span { color:var(--ink2); }

/* A tool in the toolbar: icon and words on one line, sitting on the same
   centre as the switches beside it. Move mark drew 5px higher than every
   neighbour and 91px wide among 139-183px controls, which is what "it did not
   look like it belonged" was. */
.drawing-target-toolbar .drawing-tool-btn {
  display:inline-flex; align-items:center; gap:6px; align-self:center;
  font-size:12px; white-space:nowrap;
}
.drawing-target-toolbar .drawing-tool-btn svg { width:16px; height:16px; flex:none; }
.drawing-viewer-dlg .drawing-target-toolbar > * { align-self:center; }
/* A label's ordinary block margin has no meaning in a row of controls, and it
   was doing real damage: measured on the real elements, each switch reported
   `margin:14px 0 4px` while the buttons reported 0. That made the switches an
   18px-taller box, stretched the toolbar to 62px, and centred every BUTTON
   five pixels above every SWITCH. It reads as one control not belonging with
   the others, which is exactly how it was reported. */
.drawing-target-toolbar .marker-visibility-control,
.drawing-mode-toolbar .marker-visibility-control { margin-block:0; }

/* The legend dialog carries both keys and shows one. */
.drawing-legend-dlg .drawing-snag-legend { display:none; }
.drawing-legend-dlg.snag-legend .drawing-marker-legend { display:none; }
.drawing-legend-dlg.snag-legend .drawing-snag-legend { display:block; }
.drawing-snag-legend dl { display:grid; gap:10px; margin:0; }
.drawing-snag-legend dt { display:flex; align-items:center; gap:9px; font-weight:650; }
.drawing-snag-legend dd { margin:3px 0 0 73px; color:var(--ink2); font-size:12.5px; }
.legend-snag {
  display:grid; place-items:center; width:64px; height:44px; flex:none;
  overflow:visible;
}
.legend-snag svg { display:block; overflow:visible; }
.legend-snag.tone-issue { color:var(--snag-ink-issue); }
.legend-snag.tone-information { color:var(--snag-ink-information); }
.legend-snag.tone-passed { color:var(--snag-ink-passed); }
.legend-snag-area {
  display:inline-block; width:42px; height:30px; margin-inline:11px; flex:none;
  border:2px solid var(--snag-ink-issue); background:transparent;
}

.drawing-viewer-dlg.has-snag-selection { grid-template-columns:minmax(0,1fr) minmax(320px,380px); }
.drawing-viewer-dlg.has-snag-selection > .drawing-viewer-head,
.drawing-viewer-dlg.has-snag-selection > .drawing-toolbars { grid-column:1 / -1; }
.drawing-viewer-dlg > .snag-detail-panel { grid-column:2; grid-row:3; height:100%; box-sizing:border-box; z-index:4; }
.drawing-viewer-dlg.has-snag-selection > .drawing-change-panel { display:none; }
.snag-detail-panel.is-marking .snag-panel-nav button:not(#snag-detail-close),
.snag-detail-panel.is-marking .snag-primary-actions,
.snag-detail-panel.is-marking .snag-context-actions,
.snag-detail-panel.is-marking .dlg-actions { visibility:hidden; }
#snag-report-dlg { box-sizing:border-box; width:min(1000px,96vw); height:92dvh; max-width:none; }
.snag-report-head { display:flex; align-items:center; flex-wrap:wrap; gap:8px; }
.snag-report-head h2 { flex:1; margin:0; }
#snag-report-frame { width:100%; height:calc(100% - 110px); border:1px solid var(--line2); background:white; }
@media (max-width:1000px) {
  .snag-workspace.has-selection { grid-template-columns:minmax(220px,1fr) minmax(300px,360px); }
  .has-selection .snag-open { flex-wrap:wrap; }
}
@container (max-width:680px) {
  .snag-workspace.has-selection { grid-template-columns:minmax(0,1fr); }
  /* Narrow: the record takes the whole width and the list steps aside, so the
     split above has to collapse with it. */
  #page-snags.has-snag-selection #snags-work { grid-template-columns:minmax(0,1fr); }
  .has-selection #snags-body { display:none; }
  .has-snag-selection .snag-list-heading,
  .has-snag-selection .snag-filter-grid,
  .has-snag-selection .snag-filter-chips,
  .has-snag-selection .snag-types,
  .has-snag-selection #snags-caption { display:none; }
  #snag-panel-home { position:static; }
  #snag-panel-home .snag-detail-panel { max-height:none; }
}
@media (max-width:760px) {
  .snag-workspace.has-selection { grid-template-columns:minmax(0,1fr); }
  #page-snags.has-snag-selection #snags-work { grid-template-columns:minmax(0,1fr); }
  #page-snags.has-snag-selection .workspace-heading,
  #page-snags.has-snag-selection #snags-heading,
  #page-snags.has-snag-selection .snag-list-heading,
  #page-snags.has-snag-selection .snag-filter-grid,
  #page-snags.has-snag-selection .snag-filter-chips,
  #page-snags.has-snag-selection .snag-types,
  #page-snags.has-snag-selection #snags-caption,
  #page-snags.has-snag-selection #snags-body { display:none; }
  #snag-panel-home { position:static; }
  #snag-panel-home .snag-detail-panel { max-height:none; }
  .drawing-viewer-dlg.has-snag-selection { grid-template-columns:minmax(0,1fr); grid-template-rows:auto auto minmax(180px,1fr) minmax(220px,42dvh) auto; overflow:auto; }
  .drawing-viewer-dlg > .snag-detail-panel { grid-column:1; grid-row:4; width:100%; }
}
/* Mark colours are NOT theme colours.
   A drawing is white in every theme, and the chip inks are chosen to read as
   text against the app's own background — in dark mode --chip-fail-ink is
   #eb9a9a, a pale pink. Inheriting it painted the marks pink on white paper.
   These are fixed, and they are the same values the PDF composer uses, so a
   mark is the same colour on screen as it is on the sheet. */
:root, [data-theme] {
  --snag-ink-issue:#b42323;
  --snag-ink-information:#3b82f6;
  --snag-ink-passed:#567020;
}

/* Saved snags on the drawing. The badge keeps a fixed size on screen so its
   number stays readable at any zoom — the same deliberate choice the other
   markers make. In a PDF it is sized in page units instead. */
#drawing-snag-layer { position:absolute; inset:0; pointer-events:none; }
#drawing-graphic-layer { position:absolute; inset:0; pointer-events:none; }
#graphic-select-toolbar, #graphic-select-panel { flex:1 1 100%; min-width:0; }
.drawing-target-page.graphic-selecting :is(#drawing-snag-layer,#drawing-area-layer,#drawing-name-layer,#drawing-availability-layer) { pointer-events:none; }
.drawing-target-page.graphic-selecting :is(.drawing-snag-badge,.drawing-area-label,[data-drawing-name],[data-drawing-availability]) { pointer-events:none; }
.drawing-target-page.graphic-selecting.rectangle-selecting,
.drawing-target-page.graphic-selecting.rectangle-selecting .drawing-graphic-target { cursor:default; }
.drawing-viewer-dlg:has(.rectangle-selecting) .drawing-target-stage:not(.is-panning) { cursor:default; }
.drawing-viewer-dlg .drawing-graphic-target {
  position:absolute; transform:translate(-50%, -50%); display:grid; place-items:center;
  width:44px; height:44px; min-width:44px; min-height:44px; padding:0;
  border:2px solid var(--accent); border-radius:50%; background:var(--card);
  color:var(--accent); font-size:20px; font-weight:700; pointer-events:auto;
  box-shadow:0 0 0 2px var(--card); cursor:pointer;
}
.drawing-viewer-dlg .drawing-graphic-target[aria-pressed="true"] {
  border-color:var(--graphic-selected-ink); background:var(--graphic-selected-fill);
  color:var(--graphic-selected-ink); box-shadow:0 0 0 2px var(--graphic-selected-fill); z-index:2;
}
.drawing-viewer-dlg .drawing-graphic-target[aria-pressed="true"]:hover {
  border-color:var(--graphic-selected-ink); background:var(--graphic-selected-fill);
}
.drawing-viewer-dlg .drawing-graphic-target:focus-visible { outline:3px solid var(--ink); outline-offset:3px; z-index:3; }
#drawing-graphic-border {
  position:absolute; border:2px solid var(--accent); background:color-mix(in srgb,var(--accent) 16%,transparent);
  pointer-events:none; box-sizing:border-box; z-index:5;
}
.graphic-select-panel { padding:10px 12px; border:1px solid var(--line2); border-radius:10px; background:var(--card2); margin-bottom:8px; }
.graphic-select-panel p { margin:0 0 6px; }
.graphic-select-panel ul { list-style:none; display:flex; flex-wrap:wrap; gap:6px; padding:0; margin:0; max-height:140px; overflow:auto; }
.graphic-select-panel li { display:flex; align-items:center; gap:8px; padding:4px 6px; border:1px solid var(--line2); border-radius:8px; }
.graphic-select-panel button { min-height:44px; }
#graphic-select-choices:not([hidden]) { display:flex; flex-wrap:wrap; gap:6px; margin:8px 0; }
#graphic-select-choices p { flex-basis:100%; }
.snag-graphic-context { padding:10px; border:1px solid var(--line2); border-radius:8px; background:var(--card2); }
.drawing-snag-badge {
  position:absolute; transform:translate(-50%, -50%); line-height:0;
  color:var(--snag-ink-issue);
}
/* The open ring is the stored point. The opaque number sits above it, so the
   fault location stays visible. This is screen geometry only; PDF geometry
   remains in marker-shapes.js. */
/* A finger-sized target around a smaller badge.
   The badge is 34px and the target is 44px, so the badge MUST be centred in
   it: the whole element is positioned by translate(-50%,-50%) onto the stored
   point, and an off-centre child would move every mark about five pixels up
   and left of the fault it names. */
.drawing-viewer-dlg button.drawing-snag-badge {
  /* The size itself is set in app.js, so the balloon layout and the button
     cannot disagree about how much room a mark needs. */
  min-width:0; min-height:0; padding:0;
  display:grid; place-items:center;
  border:0; border-radius:0; background:transparent; pointer-events:auto;
  cursor:pointer; box-shadow:none; overflow:visible; z-index:1;
}
.drawing-snag-badge[aria-pressed=true] { z-index:2 !important; }
.drawing-snag-badge.is-subdued, .drawing-snag-area.is-subdued { opacity:.4; }
.drawing-snag-badge:hover, .drawing-snag-badge:focus-visible { opacity:1; z-index:3 !important; }
.drawing-target-page.marking .drawing-snag-badge { pointer-events:none; opacity:.3; }
.drawing-snag-badge.tone-attention   { color:var(--snag-ink-issue); }
.drawing-snag-badge.tone-information { color:var(--snag-ink-information); }
.drawing-snag-badge.tone-passed      { color:var(--snag-ink-passed); }
.drawing-snag-badge.tone-issue       { color:var(--snag-ink-issue); }
/* Placed from its recorded position after the drawing was re-issued. It is
   drawn, because the position is honest, but it says it is not the sheet the
   mark was made on. */
.drawing-snag-badge.reissued { opacity:.85; }
/* An outline and a tail cover only their own box: app.js places the holder
   (markSvgOpen). Never inset:0, which made each one the size of the sheet
   under the zoom (050). */
.drawing-snag-area { position:absolute; }
.drawing-snag-area svg { position:absolute; left:0; top:0; overflow:visible; }
.drawing-snag-area polygon {
  fill:color-mix(in srgb, var(--snag-ink-issue) 22%, transparent);
  stroke:var(--snag-ink-issue); stroke-linejoin:round;
}
/* The tail from the fault to its label, and the open ring on the fault.
   The ring is OPEN so the fitting shows through it — that is the whole reason
   the label was moved aside. The casing is drawn first and heavier, in paper
   colour, so both survive crossing drawing linework; the same pair the PDF
   draws. pointer-events:none, or the tail would swallow clicks meant for the
   drawing underneath it. */
.drawing-snag-lead { position:absolute; pointer-events:none; }
.drawing-snag-lead svg { position:absolute; left:0; top:0; overflow:visible; }
.drawing-snag-lead line, .drawing-snag-lead circle {
  fill:none; stroke:currentColor; stroke-linecap:round;
}
/* White, not a theme token: this is drawn ON the sheet, and the sheet is
   white paper in every theme. A token that followed the interface would turn
   the casing dark on a dark theme and the tail would vanish into the drawing. */
.drawing-snag-lead .casing { stroke:#fff; }
.drawing-snag-lead.tone-attention   { color:var(--snag-ink-issue); }
.drawing-snag-lead.tone-information { color:var(--snag-ink-information); }
.drawing-snag-lead.tone-passed      { color:var(--snag-ink-passed); }
.drawing-snag-lead.tone-issue       { color:var(--snag-ink-issue); }
.drawing-snag-lead.is-subdued { opacity:.4; }
.drawing-snags-status { color:var(--muted); font-size:12px; }

.admin-roles-head { margin-top:26px; }
.admin-roles-list { display:flex; flex-wrap:wrap; gap:12px; margin:10px 0 0; }
.admin-role {
  border:1px solid var(--line2); border-radius:10px; padding:10px 14px 12px;
  min-width:200px; flex:1 1 220px;
}
.admin-role legend { color:var(--muted); font-size:11.5px; font-weight:600; padding:0 4px; }
.admin-role-person { display:flex; align-items:center; gap:7px; margin:4px 0; }

.snag-assign { margin:12px 0 4px; }
.snag-assign select { width:100%; }
.snag-assign .hint { display:block; margin:5px 0 0; color:var(--muted); font-size:11.5px; }
.snag-evidence-list { margin-top:12px; }

.snag-preview { margin:14px 0 4px; }
.snag-preview h3 { margin:0 0 7px; color:var(--ink); font-size:12px; font-weight:600; }
.snag-preview-open {
  position:relative; display:block; width:100%; min-height:0 !important; padding:0;
  overflow:hidden; border:1px solid var(--line2); border-radius:9px;
  background:var(--card2); color:var(--ink); text-align:start;
}
.snag-preview-open:disabled { opacity:1; cursor:not-allowed; }
.snag-preview-stage { position:relative; display:block; width:100%; height:190px; background:#fff; }
.snag-preview-stage.is-empty {
  height:76px;
  background:repeating-linear-gradient(135deg,var(--card2),var(--card2) 12px,
    color-mix(in srgb,var(--line2) 35%,var(--card2)) 12px,
    color-mix(in srgb,var(--line2) 35%,var(--card2)) 24px);
}
#snag-preview-canvas { display:block; width:100%; height:100%; object-fit:cover; }
.snag-preview-action {
  position:absolute; right:8px; bottom:8px; padding:5px 8px; border-radius:6px;
  background:rgba(255,255,255,.94); color:#1c2421; font-size:11px; font-weight:700;
  box-shadow:0 1px 5px rgba(0,0,0,.18);
}
.snag-preview-open:disabled .snag-preview-action { display:none; }
.snag-preview-status { margin:6px 0 0; color:var(--muted); font-size:11.5px; line-height:1.45; }

/* Marking a snag on a drawing. The toolbar follows the drawing toolbars above
   it so the viewer keeps one look, and the crosshair says the next click will
   place something rather than pan. */
/* One row, every control the same height and centred on the same line. The
   height is the phone-sized touch target (44px), so a gloved finger can hit
   any of them. The status text takes the spare width; Cancel and Save stay
   together at the right. On a narrow screen the row wraps, and each wrapped
   row is still centred and the same height. Snag marking and the area outline
   share this, so they look the same. */
.snag-mark-toolbar {
  display:flex; flex-wrap:wrap; align-items:center; gap:8px 10px;
  padding:8px 12px; border:1px solid var(--line2); border-radius:10px;
  background:var(--card2); margin:0 0 8px;
}
/* Dialogs give every label a top margin; here it would push the field off the line. */
.snag-mark-toolbar label { margin:0; }
.snag-mark-toolbar button, .snag-mark-toolbar input {
  box-sizing:border-box; min-height:44px; margin:0; padding-block:0;
}
.snag-mark-toolbar button { padding-inline:14px; }
/* The shape choice has a 1px border all round, so its buttons are 2px shorter
   and the whole control is the same 44px as the rest. */
.snag-mark-toolbar .shape-choice button { min-height:42px; padding-block:0; }
.snag-mark-what { font-weight:600; color:var(--ink); white-space:nowrap; }
.snag-mark-status { color:var(--muted); font-size:12px; flex:1 1 140px; min-width:0; }
.snag-mark-kinds { display:flex; gap:6px; }
.snag-mark-end { display:flex; align-items:center; gap:8px; margin-left:auto; flex:none; }
.drawing-target-page.marking { cursor:default; }
#snag-mark-layer {
  position:absolute; inset:0; pointer-events:none; overflow:visible;
}
/* A mark being placed has to be seen against dense drawing linework, at a zoom
   where a whole A0 is a few hundred pixels wide. A thin dark ring disappears
   into it, which is exactly what happened. So every stroke is drawn twice: a
   wide pale casing, then the coloured line on top of it — the same white-face
   idea the markers already use on paper.

   These sizes are SCREEN sizes and stay constant at any zoom, deliberately, so
   the mark you are placing is always the same size under your cursor. What
   reaches the PDF is sized separately, in page units, by the composer. */
.snag-mark-casing {
  fill:none; stroke:#ffffff;
  stroke-linejoin:round; stroke-linecap:round; opacity:.9;
}
.snag-mark-join {
  fill:none; stroke:var(--snag-ink-issue);
  stroke-linejoin:round; stroke-linecap:round;
}
.snag-mark-halo { fill:#ffffff; stroke:none; opacity:.9; }
.snag-mark-dot { fill:#ffffff; stroke:var(--snag-ink-issue); }
/* The one you just put down, so you can see where you are in a run of them. */
.snag-mark-dot.last { fill:var(--snag-ink-issue); stroke:#ffffff; }
/* The shape choice, one control for all three corner tools: snag marking, the
   area outline and the zone redline. A joined row of buttons with the chosen
   one filled, so it reads as "pick one" and not as three actions. */
.shape-choice {
  display:inline-flex; align-items:stretch; flex:none;
  border:1px solid var(--line2); border-radius:8px; overflow:hidden;
}
.shape-choice button {
  min-height:36px; padding:6px 14px; border:0; border-radius:0;
  background:var(--card); color:var(--ink2);
}
.shape-choice button + button { border-left:1px solid var(--line2); }
.shape-choice button:hover { background:var(--card2); color:var(--ink); }
.shape-choice button[aria-pressed="true"] { background:var(--accent); color:var(--btn-ink); font-weight:600; }
.zone-panel .shape-choice { justify-self:start; }
.zone-panel .shape-choice button { min-height:44px; }
.snag-link, .snag-link-missing { display:inline-block; margin-top:12px; }
.snag-link { color:var(--accent-ink); font-weight:600; }
.snag-link-missing { color:var(--muted); }
.part .nm { font-weight:600; font-size:13.5px; }
.part .code { font-size:12.5px; color:var(--ink2); font-variant-numeric:tabular-nums; }
.part-notes { color:var(--ink2); font-size:12px; margin-top:7px; white-space:pre-wrap; }
.part-actions { display:flex; flex-wrap:wrap; gap:6px; margin-top:12px; }
.part-actions .ghost-btn { font-size:12px; padding:4px 8px; }
.part-actions .ghost-btn:disabled { opacity:.45; cursor:not-allowed; }
.danger-btn { color:var(--fail); }
/* Delete-type buttons (design rule 9): Delete is red text, Remove and Discard
   are plain; all are compact, never stretched to their row's height, with a
   finger-size target on touch. The two panel buttons below are matched by
   their data attributes so the drawing panels need no markup change. */
:is(.danger-btn, .guided-note-delete, .guided-note-discard, [data-failed-remove], [data-snag-action="delete"],
  [data-check-delete], [data-check-discard], [data-discard-evidence], [data-area-op-discard], [data-guided-item-remove]) {
  align-self:center; min-height:32px; height:auto; padding:4px 12px; font-size:13px; line-height:1.2; }
:is([data-snag-action="delete"], [data-check-delete]) { color:var(--fail); }
@media (pointer:coarse) {
  :is(.danger-btn, .guided-note-delete, .guided-note-discard, [data-failed-remove], [data-snag-action="delete"],
    [data-check-delete], [data-check-discard], [data-discard-evidence], [data-area-op-discard], [data-guided-item-remove]) { min-height:44px; }
}

/* Portable snapshot workflow */
.snapshot-upload-form, .snapshot-inline-form {
  display:flex; align-items:end; gap:10px; flex-wrap:wrap; margin-top:16px;
}
.snapshot-installation-form {
  display:grid; grid-template-columns:minmax(180px,1fr) minmax(180px,1fr) auto auto;
  gap:10px; align-items:end; margin:14px 0;
}
.snapshot-installation-form input, .snapshot-installation-form select,
.snapshot-installation-row select {
  min-height:38px; border:1px solid var(--line); border-radius:7px;
  background:var(--card2); color:var(--ink); padding:7px 9px;
}
.snapshot-installation-form button { min-height:38px; }
/* Four in a row needs a wide screen. Narrower, the two names share the first
   row and the mode and Trust workstation the second, so the button is never
   squeezed below its words (051). */
@media (max-width:1100px) {
  .snapshot-installation-form { grid-template-columns:minmax(0,1fr) minmax(0,1fr); }
}
.snapshot-installations { display:grid; gap:10px; margin-top:14px; }
.snapshot-installation-row {
  display:grid; grid-template-columns:minmax(180px,2fr) minmax(145px,1fr) minmax(160px,1fr) auto;
  gap:12px; align-items:center; padding:11px 12px;
  border:1px solid var(--line); border-radius:8px; background:var(--card2);
}
.snapshot-installation-row small { color:var(--muted); }
.snapshot-installation-secret {
  margin:12px 0; padding:12px; border:1px solid var(--accent);
  border-radius:8px; background:var(--data-track);
}
.snapshot-token-row { display:flex; gap:10px; align-items:center; margin-top:9px; }
.snapshot-token-row code { overflow-wrap:anywhere; flex:1; user-select:all; }
.snapshot-upload-form label {
  display:flex; flex:1 1 330px; flex-direction:column; gap:5px;
  color:var(--ink2); font-size:12px;
}
.snapshot-upload-form input, .snapshot-inline-form input,
.snapshot-map select, .snapshot-map input, .snapshot-source-row select,
.snapshot-package-row input {
  background:var(--card2); color:var(--ink); border:1px solid var(--line2);
  border-radius:8px; padding:8px 10px; font:inherit;
}
.snapshot-upload-form button, .snapshot-inline-form button,
.snapshot-actions button {
  background:var(--accent); color:var(--btn-ink); border:0; border-radius:8px;
  padding:9px 14px; font:inherit; font-weight:650; cursor:pointer;
}
.snapshot-actions .danger-btn { background:var(--fail); color:#fff; }
/* The buttons sat against the database row above them. */
#snapshot-preview-card .snapshot-actions { margin-top:16px; }
.snapshot-upload-form button:disabled, .snapshot-actions button:disabled {
  opacity:.55; cursor:not-allowed;
}
.snapshot-inline-form input { flex:1 1 260px; max-width:440px; }
.snapshot-structure, #snapshot-source-mappings { display:grid; gap:10px; margin-top:14px; }
.snapshot-package-row, .snapshot-map {
  border:1px solid var(--line); border-radius:9px; padding:12px;
  background:var(--card2);
}
.snapshot-package-head {
  display:flex; align-items:center; gap:8px; flex-wrap:wrap;
}
.snapshot-package-head input { flex:1 1 180px; font-weight:600; }
.snapshot-package-head button { padding:5px 9px; }
.snapshot-source-row {
  display:grid; grid-template-columns:minmax(160px,1fr) minmax(180px,1fr);
  gap:8px; align-items:center; margin:8px 0 0 18px; font-size:12.5px;
}
.snapshot-source-row small { color:var(--muted); }
.snapshot-map {
  display:grid; grid-template-columns:minmax(150px,1fr) minmax(220px,2fr);
  gap:8px 12px; align-items:center;
}
.snapshot-map strong { font-size:13.5px; }
.snapshot-map small { color:var(--muted); }
.snapshot-map input { grid-column:2; }
.snapshot-summary-grid {
  display:grid; grid-template-columns:repeat(auto-fit,minmax(135px,1fr));
  gap:10px; margin:16px 0;
}
.snapshot-summary-grid > div {
  border:1px solid var(--line); border-radius:8px; padding:10px 12px;
  background:var(--card2);
}
.snapshot-summary-grid b { display:block; font-size:21px; }
.snapshot-summary-grid span { color:var(--muted); font-size:12px; }
.snapshot-no-change {
  margin:12px 0; padding:10px 12px; border:1px solid var(--pass);
  border-radius:8px; background:color-mix(in srgb,var(--pass) 9%,var(--card2));
  color:var(--ink2); font-size:13px;
}
.snapshot-source-preview { margin-top:18px; }
.snapshot-source-preview h3 { margin:0 0 8px; font-size:14px; }
.snapshot-preview-table { min-width:690px; }
.snapshot-preview-table th, .snapshot-preview-table td { text-align:left; }
.snapshot-preview-table td { font-variant-numeric:tabular-nums; }
.snapshot-preview-table details { min-width:110px; }
.snapshot-preview-table summary { color:var(--accent); cursor:pointer; }
.snapshot-record-list { display:block; margin-top:6px; color:var(--muted); line-height:1.5; }
.snapshot-history-row, .snapshot-health-row {
  display:grid; grid-template-columns:minmax(180px,2fr) repeat(2,minmax(110px,1fr)) auto;
  gap:10px; align-items:center; padding:9px 0; border-bottom:1px solid var(--line);
  font-size:12.5px;
}
.snapshot-history-row small, .snapshot-health-row small { color:var(--muted); }
.snapshot-health-row { grid-template-columns:minmax(180px,2fr) 1fr 1fr; }
@media (max-width:700px) {
  .snapshot-map, .snapshot-source-row, .snapshot-history-row,
  .snapshot-health-row { grid-template-columns:1fr; }
  .snapshot-map input { grid-column:1; }
  .snapshot-source-row { margin-left:0; }
  .snapshot-installation-form, .snapshot-installation-row { grid-template-columns:1fr; }
  .snapshot-token-row { align-items:stretch; flex-direction:column; }
}

footer { text-align:center; color:var(--muted); font-size:12px; padding:10px 20px 30px; }
footer a { color:var(--ink2); text-decoration:none; border-bottom:1px solid var(--line2); }
footer a:hover { color:var(--ink); border-bottom-color:currentColor; }

/* ── Instant press feedback (respond on pointer-down, never on release) ── */
.ghost-btn, .seg button, nav.tabs button, .login-card button, #ra-submit {
  transition:transform 80ms ease-out;
}
.ghost-btn:active, .seg button:active, nav.tabs button:active,
.login-card button:active, #ra-submit:active { transform:scale(.96); }
@media (prefers-reduced-motion: reduce) {
  .ghost-btn, .seg button, nav.tabs button, .login-card button, #ra-submit,
  .ghost-btn:active, .seg button:active, nav.tabs button:active,
  .login-card button:active, #ra-submit:active { transition:none; transform:none; }
}

/* ── Tooltip — small translucent material ──────────────────────────────── */
#tip {
  position:fixed; pointer-events:none; z-index:10; display:none;
  background:color-mix(in srgb, var(--ink) 88%, transparent);
  -webkit-backdrop-filter:blur(10px);
  backdrop-filter:blur(10px);
  color:var(--page); border-radius:8px;
  padding:8px 12px; font-size:.8rem; line-height:1.55;
  box-shadow:0 4px 14px rgba(0,0,0,.25); max-width:260px;
}
@media (prefers-reduced-transparency: reduce) {
  #tip { background:var(--ink); -webkit-backdrop-filter:none; backdrop-filter:none; }
}
#tip b { font-weight:650; }

/* ── Loading splash ────────────────────────────────────────────────────── */
.loading { text-align:center; color:var(--muted); padding:80px 20px; font-size:14px; }

/* ── Header nav (engineers) ────────────────────────────────────────────── */
nav.tabs { display:flex; gap:4px; }
nav.tabs button {
  background:none; border:none; color:var(--ink2); font:inherit; font-size:13.5px;
  padding:6px 12px; border-radius:8px; cursor:pointer;
}
nav.tabs button.on { background:var(--card2); color:var(--ink); font-weight:600; }

/* ── Test devices screen ───────────────────────────────────────────────── */
.device-panel-head {
  display:flex; align-items:flex-start; justify-content:space-between; gap:18px;
  padding-bottom:13px; border-bottom:1px solid var(--line);
}
.device-panel-head h2 { margin:3px 0 0; font-size:17px; }
.device-panel-status { display:flex; align-items:center; justify-content:flex-end; gap:8px; flex-wrap:wrap; }
.device-completion-chip, #device-sync-state {
  display:inline-flex; align-items:center; min-height:28px; margin:0; padding:4px 10px;
  border-radius:999px; font-size:12px; font-weight:650; white-space:nowrap;
}
.device-completion-chip.band-low { background:var(--chip-fail-bg); color:var(--chip-fail-ink); }
.device-completion-chip.band-mid { background:var(--chip-warn-bg); color:var(--chip-warn-ink); }
.device-completion-chip.band-high { background:var(--chip-pass-bg); color:var(--chip-pass-ink); }
.device-completion-chip:not(.band-low):not(.band-mid):not(.band-high) {
  background:var(--chip-na-bg); color:var(--chip-na-ink);
}
#device-sync-state { gap:6px; background:var(--chip-pass-bg); color:var(--chip-pass-ink); }
#device-sync-state::before { content:""; width:7px; height:7px; border-radius:50%; background:currentColor; }
#device-sync-state[data-state="grace"], #device-sync-state[data-state="queued"],
#device-sync-state[data-state="syncing"] { background:var(--chip-warn-bg); color:var(--chip-warn-ink); }
#device-sync-state[data-state="failed"] { background:var(--chip-fail-bg); color:var(--chip-fail-ink); }
.device-workflow-bar:not(:has(button:not([hidden]))) { display:none; }
.device-workspace-layout {
  display:grid; grid-template-columns:250px minmax(0,1fr); gap:16px;
}
.device-scope-panel {
  align-self:start; min-width:0; padding:12px 9px; border:1px solid var(--line);
  border-radius:9px; background:var(--card2);
}
.device-scope-panel > .eyebrow { margin:2px 9px 8px; }
.device-scope-tree { display:grid; gap:2px; }
.device-scope-row {
  display:grid; grid-template-columns:16px minmax(0,1fr) auto; align-items:center; gap:8px;
  width:100%; min-height:40px; padding:7px 9px; border:0; border-radius:7px;
  background:transparent; color:var(--ink2); font-size:13px; text-align:left;
}
.device-scope-row:hover { border:0; background:var(--card); color:var(--ink); }
.device-scope-row.on {
  position:relative; background:var(--sel-bg); color:var(--ink); font-weight:650;
}
.device-scope-row.on::before {
  content:""; position:absolute; inset-block:2px; inset-inline-start:0;
  width:var(--sel-bar); border-radius:2px; background:var(--accent);
}
.device-scope-row.module { padding-left:25px; grid-template-columns:minmax(0,1fr) auto; }
.device-scope-row.module .device-scope-icon { display:none; }
.device-scope-icon { width:11px; height:11px; border:1.5px solid currentColor; border-radius:2px; opacity:.7; }
.device-scope-row b { font-weight:600; font-variant-numeric:tabular-nums; }
.device-scope-row b.band-low { color:var(--chip-fail-ink); }
.device-scope-row b.band-mid { color:var(--chip-warn-ink); }
.device-scope-row b.band-high { color:var(--data); }
.device-module-label {
  margin:12px 9px 4px; color:var(--muted); font-size:10px; font-weight:650;
  letter-spacing:.1em; text-transform:uppercase;
}
.device-results-panel { min-width:0; }
.device-results-panel > .device-panel-head { margin-bottom:12px; }
.device-mobile-scope { display:none; }
.device-filter-toolbar { align-items:center; gap:8px; margin-bottom:10px; }
.device-filter-toolbar .filter-search { flex:1 1 230px; min-width:180px; }
.device-filter-toolbar #device-sync-state { margin-left:auto; }
#page-test #device-list {
  overflow:hidden; border:1px solid var(--line); border-radius:10px;
  background:var(--card);
}
#page-test .dev-row { border-radius:0; }
#page-test .dev-row:last-child { border-bottom:0; }
#page-test .device-workflow-bar button,
#page-test .toolbar :is(input, select, button) {
  box-sizing:border-box; min-height:40px;
}
#page-test #device-tip { margin:14px 0; }
#page-test #device-tip > summary {
  min-height:40px; display:inline-flex; align-items:center; cursor:pointer;
}
@media (max-width:900px) {
  .device-workspace-layout { grid-template-columns:1fr; }
  .device-scope-panel { display:none; }
  .device-mobile-scope { display:block; margin-bottom:10px; border:1px solid var(--line); border-radius:8px; }
  .device-mobile-scope > summary { min-height:44px; padding:10px 12px; cursor:pointer; font-weight:650; }
  .device-mobile-scope-fields { display:grid; grid-template-columns:1fr 1fr; gap:8px; padding:0 10px 10px; }
  .device-mobile-scope select { width:100%; min-width:0; min-height:44px; }
}
@media (max-width:560px) {
  .device-panel-head { align-items:stretch; flex-direction:column; }
  .device-panel-status { justify-content:flex-start; }
  .device-mobile-scope-fields { grid-template-columns:1fr; }
}
/* On a phone the Undo for a result is a toast just above the bottom bar, so it
   is on screen wherever the list is scrolled. app.js hides it after the five
   seconds the result can be undone. */
@media (max-width:700px) {
  #page-test #device-undo {
    position:fixed; z-index:95; left:12px; right:12px;
    bottom:calc(66px + 10px + env(safe-area-inset-bottom));
    min-height:48px; box-shadow:0 8px 24px rgba(0,0,0,.35);
    background:var(--accent); border-color:var(--accent); color:var(--btn-ink); font-weight:650;
  }
}

/* ── Work action centre ────────────────────────────────────────────────── */
#page-action .action-heading { align-items:flex-start; }
#page-action .action-heading h1 { margin-bottom:6px; }
#page-action .action-heading p:last-child {
  max-width:68ch; margin:0; color:var(--ink2); font-size:13px; line-height:1.55;
}
.action-heading-actions {
  display:flex; flex-wrap:wrap; align-items:center; justify-content:flex-end; gap:8px;
}
.action-heading-actions button { min-height:38px; }
.action-workspace-panel { display:grid; gap:16px; min-width:0; }
.action-measures, .workspace-measures {
  display:grid; grid-template-columns:repeat(var(--measure-cols,4),minmax(0,1fr));
  overflow:hidden; border:1px solid var(--line); border-radius:10px;
  background:var(--card);
}
.action-measure, .workspace-measure {
  min-width:0; padding:15px 18px; border-inline-start:1px solid var(--line);
}
.action-measure:first-child, .workspace-measure:first-child { border-inline-start:0; }
.action-measure > p, .workspace-measure > p {
  margin:0; color:var(--muted); font-size:11px; font-weight:650;
  letter-spacing:.08em; text-transform:uppercase;
}
.action-measure > div, .workspace-measure > div {
  display:flex; align-items:baseline; gap:6px; margin-top:7px; line-height:1.1;
}
.action-measure b, .workspace-measure b {
  font-family:"Archivo",sans-serif; font-size:30px; font-weight:600;
  letter-spacing:-.03em; font-variant-numeric:tabular-nums;
}
.action-measure span, .workspace-measure span { color:var(--muted); font-size:14px; }
.action-measure small, .workspace-measure small {
  display:block; margin-top:8px; overflow:hidden; color:var(--ink2);
  font-size:12px; text-overflow:ellipsis; white-space:nowrap;
}
.action-measure.urgent b, .workspace-measure.urgent b { color:var(--fail); }
.action-measure.attention b, .workspace-measure.attention b { color:var(--progress-mid); }
.action-measure.routine b, .workspace-measure.routine b { color:var(--info); }
#page-action .action-toolbar { margin:0; }
#page-action .action-field {
  display:flex; align-items:center; gap:7px; min-height:40px; box-sizing:border-box;
  padding:6px 10px; border:1px solid var(--line2); border-radius:8px;
  background:var(--card2); color:var(--muted); font-size:13px;
}
#page-action .action-field select {
  min-height:26px; padding:0 18px 0 0; border:0; background:transparent;
  color:var(--ink); font:inherit; font-size:13.5px;
}
#page-action .action-field select option {
  background:var(--card); color:var(--ink);
}
:root[data-theme="dark"] #page-action .action-field select { color-scheme:dark; }
#page-action .action-field select:focus-visible { outline:2px solid var(--accent); outline-offset:2px; }
.action-open-count {
  margin-left:auto; color:var(--muted); font-size:12.5px; font-variant-numeric:tabular-nums;
}
#page-action #action-list { display:grid; gap:16px; min-width:0; }
#page-action .action-group-panel {
  min-width:0; overflow:hidden; border:1px solid var(--line);
  border-radius:10px; background:var(--card);
}
#page-action .action-group-head {
  display:flex; align-items:center; justify-content:space-between; gap:12px;
  padding:13px 16px; border-bottom:1px solid var(--line);
}
#page-action .action-group-head .eyebrow { margin:0 0 2px; }
#page-action .action-group-head h2 {
  margin:0; color:var(--ink); font-size:14.5px; font-weight:650;
  letter-spacing:-.01em; text-transform:none;
}
#page-action .action-group-head > .chip {
  background:var(--card2); color:var(--ink2); font-weight:500;
}
#page-action #action-list .action-row {
  display:flex; align-items:center; gap:12px; width:100%; min-height:58px;
  margin:0; padding:11px 16px 11px 13px; border:0;
  border-bottom:1px solid var(--line); border-inline-start:3px solid transparent;
  border-radius:0; background:var(--card); color:var(--ink); cursor:pointer;
}
#page-action #action-list .action-row:last-child { border-bottom:0; }
#page-action #action-list .action-row:hover { background:var(--card2); }
#page-action #action-list .action-row.urgent { border-inline-start-color:var(--fail); }
#page-action #action-list .action-row.attention { border-inline-start-color:var(--progress-mid); }
#page-action #action-list .action-row.routine { border-inline-start-color:var(--info); }
#page-action #action-list .action-row .txt { flex:1; min-width:0; }
#page-action #action-list .action-row .txt b {
  display:block; overflow:hidden; font-size:13.5px; font-weight:600;
  line-height:1.35; text-overflow:ellipsis; white-space:nowrap;
}
#page-action #action-list .action-row .txt small {
  display:block; overflow:hidden; margin-top:2px; color:var(--muted);
  font-size:12px; text-overflow:ellipsis; white-space:nowrap;
}
#page-action #action-list .action-row > .chip { flex:none; }
#page-action #action-list .action-row .chev { width:15px; height:15px; flex:none; color:var(--muted); }
#page-action #action-list > .empty-state {
  margin:0; border:1px solid var(--line); border-radius:10px; background:var(--card);
}

@media (max-width:700px) {
  .action-heading-actions { width:100%; justify-content:stretch; }
  .action-heading-actions button { flex:1; min-height:44px; }
  .action-measures, .workspace-measures { grid-template-columns:repeat(2,minmax(0,1fr))!important; }
  .action-measure, .workspace-measure { border-top:1px solid var(--line); margin-top:-1px; }
  .action-measure:nth-child(odd), .workspace-measure:nth-child(odd) { border-inline-start:0; }
  #page-action .action-field { flex:1 1 100%; min-height:44px; }
  #page-action .action-field select { flex:1; }
  .action-open-count { width:100%; margin-left:0; }
  #page-action #action-list .action-row { align-items:flex-start; flex-wrap:wrap; }
  #page-action #action-list .action-row .txt { flex-basis:calc(100% - 28px); }
  #page-action #action-list .action-row > .chip { margin-left:auto; }
  #page-action #action-list .action-row .chev { margin-top:3px; }
}

/* ── Engineering issues ────────────────────────────────────────────────── */
#page-engineering .engineering-heading {
  align-items:flex-start; flex-wrap:wrap; padding-bottom:0;
}
#page-engineering .engineering-heading h1 { margin-bottom:6px; }
#page-engineering .engineering-page-intro {
  max-width:72ch; margin:0; color:var(--ink2); font-size:13px; line-height:1.55;
}
.engineering-page-actions {
  display:flex; align-items:center; justify-content:flex-end; gap:8px; flex-wrap:wrap;
}
.engineering-page-actions > button { min-height:40px; }
.engineering-field {
  display:inline-flex; align-items:center; gap:7px; min-height:40px;
  box-sizing:border-box; padding:6px 10px; border:1px solid var(--line2);
  border-radius:8px; background:var(--card2); color:var(--muted); font-size:13px;
}
.engineering-field select {
  min-height:26px; padding:0 18px 0 0; border:0; background:transparent;
  color:var(--ink); font:inherit; font-size:13.5px;
}
.engineering-field select option { background:var(--card); color:var(--ink); }
:root[data-theme="dark"] .engineering-field select { color-scheme:dark; }
.engineering-state-tabs {
  display:flex; flex-basis:100%; gap:2px; overflow-x:auto; margin-top:4px;
}
.engineering-state-tabs button {
  min-height:42px; padding:8px 12px 10px; border:0;
  border-bottom:2px solid transparent; border-radius:0; background:transparent;
  color:var(--ink2); font:inherit; font-size:13px; cursor:pointer;
}
.engineering-state-tabs button.on {
  border-bottom-color:var(--accent); color:var(--ink); font-weight:650;
}
.engineering-state-tabs button b {
  margin-left:3px; color:var(--muted); font-size:12px; font-weight:600;
}
#page-engineering .engineering-coverage-panel { padding-bottom:0; }
#page-engineering .engineering-coverage {
  grid-template-columns:repeat(3,minmax(0,1fr)); gap:12px;
  margin:0; padding-bottom:14px;
}
#page-engineering .engineering-check-card {
  display:grid; grid-template-columns:minmax(0,1fr) auto;
  grid-template-rows:minmax(46px,auto) auto auto minmax(30px,auto);
  column-gap:10px; align-content:start; min-height:150px; margin:0; padding:14px;
  border:1px solid var(--line);
  border-radius:8px; background:var(--card2); box-shadow:none;
}
#page-engineering .engineering-check-card h3 {
  grid-column:1; grid-row:1; max-width:none; margin:0; font-size:13px;
  font-weight:650; line-height:1.45;
}
#page-engineering .engineering-check-card > .chip { grid-column:2; grid-row:1; align-self:start; }
#page-engineering .engineering-check-count {
  grid-column:1 / -1; grid-row:2;
  color:var(--ink); font-family:"Archivo",sans-serif; font-size:26px;
  font-weight:600; letter-spacing:-.03em;
}
#page-engineering .engineering-check-count.unavailable { color:var(--muted); }
#page-engineering .engineering-check-card > small:not(.engineering-coverage-summary) {
  grid-column:1 / -1; grid-row:3; font-size:11.5px;
}
#page-engineering .engineering-coverage-summary {
  grid-column:1 / -1; grid-row:4; align-self:end; margin-top:8px;
  padding-top:8px; border-top:1px solid var(--line); font-size:11.5px;
}
.engineering-help-open { min-width:44px; min-height:44px; }
.engineering-coverage-note {
  margin:0 -16px; padding:10px 16px; border-top:1px solid var(--line);
  color:var(--muted); font-size:12.5px;
}
#page-engineering .engineering-coverage-note > .count-note { margin:8px 0 0; }
.engineering-help-dialog { box-sizing:border-box; width:min(820px,92vw); max-height:84dvh; overflow:auto; }
.engineering-help-dialog form { display:grid; gap:22px; }
.engineering-help-head { display:flex; align-items:flex-start; justify-content:space-between; gap:16px; }
.engineering-help-head .eyebrow { margin:0 0 3px; }
.engineering-help-head h2 { margin:0; }
.engineering-help-dialog section > h3 { margin:0 0 10px; font-size:14px; }
.engineering-help-dialog .engineering-status-help {
  grid-template-columns:repeat(2,minmax(0,1fr)); gap:10px 20px; margin:0;
}
.engineering-help-checks { display:grid; grid-template-columns:repeat(2,minmax(0,1fr)); gap:0 22px; }
.engineering-help-checks article { padding:10px 0; border-top:1px solid var(--line); }
.engineering-help-checks h4 { margin:0 0 4px; font-size:13px; }
.engineering-help-checks p { margin:0; color:var(--ink2); font-size:12px; line-height:1.45; }
#page-engineering .engineering-findings-head {
  display:flex; align-items:center; justify-content:space-between; gap:12px;
}
#page-engineering .engineering-findings-head h2 { margin:0; }
#page-engineering .engineering-findings-head .eyebrow { margin:0 0 2px; }
#page-engineering .engineering-filters { margin:0 0 14px; }
#page-engineering .engineering-filters .filter-search { min-height:40px; }
#page-engineering .engineering-findings {
  min-width:0; gap:0; overflow:hidden; margin:0 -16px -16px;
  border-top:1px solid var(--line); background:var(--card);
}
#page-engineering .issue-group-heading {
  margin:0; padding:10px 16px; border-bottom:1px solid var(--line);
  background:var(--card2); color:var(--muted); font-size:11px;
  font-weight:650; letter-spacing:.08em; text-transform:uppercase;
}
#page-engineering .engineering-finding {
  margin:0; padding:15px 16px; border:0; border-bottom:1px solid var(--line);
  border-radius:0; background:var(--card);
}
#page-engineering .engineering-finding:last-child { border-bottom:0; }
.engineering-finding-main { display:flex; align-items:flex-start; gap:14px; }
.engineering-finding-copy { flex:1; min-width:0; }
.engineering-finding-titleline {
  display:flex; align-items:center; gap:8px; flex-wrap:wrap;
}
.engineering-finding-titleline h3 {
  margin:0; font-size:14.5px; font-weight:650; letter-spacing:-.01em;
}
.engineering-finding-summary {
  max-width:82ch; margin:6px 0 0; color:var(--ink2); font-size:13px; line-height:1.45;
}
.engineering-finding-meta {
  display:flex; flex-wrap:wrap; gap:14px; margin-top:9px; color:var(--muted);
  font-size:12px;
}
.engineering-finding-row-actions {
  display:flex; align-items:center; justify-content:flex-end; gap:7px; flex:none;
}
.engineering-finding-row-actions button { min-height:36px; white-space:nowrap; }
.engineering-finding-details {
  margin-top:11px; padding-top:9px; border-top:1px solid var(--line);
  color:var(--ink2); font-size:12.5px;
}
.engineering-finding-details > summary {
  width:max-content; color:var(--ink2); font-weight:650; cursor:pointer;
}
.engineering-finding-details > p { margin:10px 0 0; }
.engineering-finding-identity .eyebrow { display:block; margin-bottom:3px; }
#page-engineering .engineering-placements { margin-top:10px; }
#page-engineering .engineering-placements li { padding:8px 0; }

@media (max-width:700px) {
  .engineering-page-actions { width:100%; justify-content:stretch; }
  .engineering-page-actions > * { flex:1 1 100%; width:100%; min-height:44px; }
  #page-engineering .engineering-findings-head { align-items:stretch; flex-direction:column; }
  #page-engineering .engineering-findings-head .engineering-field { width:100%; }
  #page-engineering .engineering-findings-head select { flex:1; }
  #page-engineering .engineering-filters > * { flex:1 1 100%; width:100%; min-height:44px; }
  #page-engineering .engineering-coverage { grid-template-columns:1fr 1fr; gap:8px; }
  #page-engineering .engineering-check-card { min-height:132px; padding:12px; }
  .engineering-finding-main { flex-direction:column; }
  .engineering-finding-row-actions { width:100%; justify-content:stretch; }
  .engineering-finding-row-actions button { flex:1; min-height:44px; }
}
@media (max-width:1000px) and (min-width:431px) {
  #page-engineering .engineering-coverage { grid-template-columns:repeat(2,minmax(0,1fr)); }
}
@media (max-width:430px) {
  #page-engineering .engineering-coverage { grid-template-columns:1fr; }
  .engineering-help-dialog .engineering-status-help,
  .engineering-help-checks { grid-template-columns:1fr; }
}

/* ── Project history ───────────────────────────────────────────────────── */
.intelligence-page-heading .intelligence-view-tabs { border-top:0; }
#page-project-intelligence .intelligence-head > .note:first-child { margin-top:0; }
#page-project-intelligence .workspace-heading > .chip,
#page-project-intelligence .intelligence-highlight > .chip { align-self:flex-start; }
#page-project-intelligence :is(.toolbar, .section-heading)
  :is(button, input:not([type=checkbox]), select) {
  box-sizing:border-box; min-height:40px;
}
/* Not the search box's own text: the shared search box draws the border, and
   this rule, weighted by the page's id, drew a second box inside it. */
#page-project-intelligence :is(.toolbar, .section-heading)
  :is(input:not([type=checkbox]):not(.filter-search input), select) {
  padding:7px 10px; background:var(--card2); color:var(--ink);
  border:1px solid var(--line2); border-radius:8px; font:inherit;
  font-size:var(--field-font);
}
#page-project-intelligence .journal-filters > label {
  display:inline-flex; align-items:center; min-height:40px;
}
#page-project-intelligence :is(.intelligence-highlights, .journal-list):not(:empty) {
  min-width:0; gap:0; overflow:hidden; border:1px solid var(--line);
  border-radius:10px; background:var(--card);
}
#page-project-intelligence .intelligence-highlight,
#page-project-intelligence .journal-entry {
  border:0; border-bottom:1px solid var(--line); border-radius:0;
  background:var(--card);
}
#page-project-intelligence :is(.intelligence-highlight, .journal-entry):last-child {
  border-bottom:0;
}
#page-project-intelligence .intelligence-highlight { border-inline-start:5px solid var(--data); }
#page-project-intelligence .intelligence-highlight.urgent { border-inline-start-color:var(--fail); }
#page-project-intelligence .intelligence-highlight.attention { border-inline-start-color:#9a681c; }
#page-project-intelligence .journal-entry.system { border-inline-start:5px solid var(--data); }
/* The AI overview (feature 024). Information, so it stays quiet: a thin
   coloured line on the card and outlined fact chips. Only buttons are filled. */
#page-project-intelligence .ai-overview-status { margin:10px 0 0; }
#page-project-intelligence .ai-overview-card {
  margin-top:14px; padding:14px 16px; border:1px solid var(--line);
  border-inline-start:3px solid var(--data); border-radius:10px; background:var(--card);
}
#page-project-intelligence .ai-overview-card .section-heading { margin-bottom:4px; }
#page-project-intelligence .ai-overview-section h3 { margin:14px 0 6px; font-size:15px; color:var(--ink); }
#page-project-intelligence .ai-overview-section ul { margin:0; padding-inline-start:18px; display:grid; gap:10px; }
#page-project-intelligence .ai-overview-section li p { margin:0; color:var(--ink); overflow-wrap:anywhere; }
#page-project-intelligence .ai-overview-facts { display:flex; flex-wrap:wrap; gap:6px; margin-top:5px; }
#page-project-intelligence .ai-overview-fact { font-size:12px; color:var(--ink2); max-width:100%; }
#page-project-intelligence .ai-overview-fact > summary {
  display:inline-flex; align-items:center; min-height:26px; padding:1px 9px; cursor:pointer;
  border:1px solid var(--line2); border-radius:999px; background:transparent; list-style:none;
}
#page-project-intelligence .ai-overview-fact > summary::-webkit-details-marker { display:none; }
#page-project-intelligence .ai-overview-fact > summary:focus-visible { outline:2px solid var(--focus); outline-offset:2px; }
/* An opened chip takes its own line, so the chips after it do not jump. */
#page-project-intelligence .ai-overview-fact[open] { flex-basis:100%; }
#page-project-intelligence .ai-overview-fact[open] > summary { border-color:var(--data); color:var(--ink); }
#page-project-intelligence .ai-overview-fact > span {
  display:block; margin-top:4px; padding:6px 9px; border-inline-start:2px solid var(--data);
  color:var(--ink2); overflow-wrap:anywhere;
}
#page-project-intelligence .ai-overview-footer { margin:14px 0 0; padding-top:10px; border-top:1px solid var(--line); }

@media (max-width:700px) {
  #page-project-intelligence .intelligence-head .toolbar > *,
  #page-project-intelligence .journal-filters > * { flex:1 1 100%; width:100%; }
  #page-project-intelligence :is(.toolbar, .section-heading)
    :is(button, input:not([type=checkbox]), select),
  #page-project-intelligence .journal-filters > label { min-height:44px; }
}

/* ── Collector imports ─────────────────────────────────────────────────── */
#page-snapshot .imports-upload-panel > .note:first-child { margin-top:0; }
#page-snapshot :is(.snapshot-upload-form, .snapshot-installation-form,
  .snapshot-inline-form, .snapshot-actions)
  :is(input:not([type=checkbox]), select, button) {
  box-sizing:border-box; min-width:0; min-height:40px;
}
#page-snapshot .snapshot-installation-form > button {
  padding:9px 14px; background:var(--accent); color:var(--btn-ink);
  border:0; border-radius:8px; font:inherit; font-weight:650; cursor:pointer;
}
#page-snapshot :is(.snapshot-installations, #snapshot-history, #snapshot-health):not(:empty) {
  min-width:0; overflow:hidden; border:1px solid var(--line);
  border-radius:10px; background:var(--card);
}
#page-snapshot .snapshot-installations { gap:0; }
#page-snapshot :is(.snapshot-installation-row, .snapshot-history-row, .snapshot-health-row) {
  margin:0; padding:11px 12px; border:0; border-bottom:1px solid var(--line);
  border-radius:0; background:var(--card);
}
#page-snapshot :is(.snapshot-installation-row, .snapshot-history-row, .snapshot-health-row):last-child {
  border-bottom:0;
}

@media (max-width:700px) {
  #page-snapshot :is(.snapshot-upload-form, .snapshot-installation-form,
    .snapshot-inline-form, .snapshot-actions)
    :is(input:not([type=checkbox]), select, button) { min-height:44px; }
  #page-snapshot .snapshot-upload-form > *,
  #page-snapshot .snapshot-inline-form > *,
  #page-snapshot .snapshot-actions > * { flex:1 1 100%; width:100%; max-width:none; }
}

/* ── Administration workspace ──────────────────────────────────────────── */
#page-admin .admin-heading + .admin-tabs { margin-top:0; }
#page-admin > .admin-tabs {
  /* auto-fit rather than a counted three. There have been four tabs since
     Job roles was added, so the fourth was sharing a track with its
     neighbour. A band that counts its own columns cannot fall behind. */
  display:grid; grid-auto-flow:column; grid-auto-columns:minmax(0,1fr); gap:0;
  margin:0; padding:12px 0 0; border-bottom:1px solid var(--line2);
}
#page-admin > .admin-tabs button {
  min-width:0; min-height:44px; padding:8px 10px; background:transparent;
  color:var(--ink2); border:0; border-bottom:3px solid transparent;
  border-radius:0; font:inherit; font-size:13.5px; cursor:pointer;
}
#page-admin > .admin-tabs button.on {
  /* The accent is the underline, not the words. As text it is 1.7:1 against
     the light page - the selected tab was the hardest label to read on the
     screen, which is the opposite of what selected should mean. */
  background:transparent; color:var(--ink); border-color:var(--accent);
  font-weight:700;
}
#page-admin :is(.admin-invite-form, .admin-form, .toolbar,
  .people-table, #org-table, #admin-access-table)
  :is(input:not([type=checkbox]):not([type=hidden]), select, button) {
  box-sizing:border-box; min-height:40px;
}
#page-admin .tbl-wrap {
  min-width:0; overflow-x:auto; border:1px solid var(--line);
  border-radius:10px; background:var(--card);
}
#page-admin .tbl-wrap th { background:var(--card2); }
#page-admin .tbl-wrap tbody tr:last-child td { border-bottom:0; }
#page-admin .admin-project-list:not(:empty) {
  gap:0; overflow:hidden; border:1px solid var(--line);
  border-radius:10px; background:var(--card);
}
#page-admin .admin-project-list .admin-project-row {
  margin:0; border:0; border-bottom:1px solid var(--line);
  border-radius:0; background:var(--card);
}
#page-admin .admin-project-list .admin-project-row:last-child { border-bottom:0; }
#page-admin .admin-project-list .admin-project-row.on {
  outline:0; background:var(--sel-bg);
}

@media (max-width:700px) {
  #page-admin > .admin-tabs button { padding-inline:5px; font-size:12.5px; }
  #page-admin :is(.admin-invite-form, .admin-form, .toolbar,
    .people-table, #org-table, #admin-access-table)
    :is(input:not([type=checkbox]):not([type=hidden]), select, button) {
    min-height:44px;
  }
  #page-admin .toolbar input[type=search] { flex:1 1 100%; width:100%; }
}
#floor-picker, #module-picker {
  background:var(--card2); color:var(--ink); border:1px solid var(--line2);
  border-radius:8px; padding:7px 10px; font:inherit; font-size:.9rem;
  max-width:260px;
}
@media (max-width:640px) {
  #floor-picker, #module-picker { flex:1 1 45%; max-width:none; }
}

/* Swipe-to-record rows: a transformed surface over commit underlays.
   The surface tracks the finger 1:1 (fluid.js), rubber-bands past the
   reveal, and commits by momentum projection. touch-action:pan-y keeps
   vertical scrolling native while we own horizontal. */
/* Device names, short addresses and codes are data, not prose. In a
   monospaced face they line up in a column and the eye reads them as
   identifiers rather than as words. */
.dev-name, code {
  font-family:'IBM Plex Mono', ui-monospace, "Cascadia Mono", Consolas, monospace;
  letter-spacing:-.01em;
}
.dev-row {
  position:relative; overflow:hidden; border-bottom:1px solid var(--line);
  border-radius:8px;
}
.dev-under {
  position:absolute; inset:0; display:flex; align-items:center;
  font-size:.85rem; font-weight:700; letter-spacing:.04em;
  text-transform:uppercase; pointer-events:none;
}
.dev-under.commit-pass {
  justify-content:flex-start; padding-left:18px;
  background:var(--data); color:#fff;
}
.dev-under.commit-pending {
  justify-content:flex-end; padding-right:18px;
  background:var(--chip-na-bg); color:var(--ink2);
}
.dev-swipe {
  position:relative; display:flex; flex-wrap:wrap; align-items:center; gap:10px;
  padding:10px 8px; background:var(--card);
  touch-action:pan-y; will-change:transform;
}
.dev-main { flex:1 1 240px; min-width:200px; }
.dev-name { font-size:.9rem; font-weight:600; }
/* Result filter. Label above count so four thumb-sized targets fit a phone,
   and the active one borrows the colour its result already uses on the row
   buttons — so "I am looking at what's outstanding" is legible at a glance. */
.dev-filter { flex:1 1 100%; margin-top:2px; }
.dev-filter button {
  flex:1 1 0; display:flex; align-items:center;
  justify-content:center; gap:5px; padding:6px 10px; min-height:44px;
  line-height:1.2;
}
.dev-filter button b {
  font-size:12px; font-weight:600; color:var(--muted);
  font-variant-numeric:tabular-nums;
}
.dev-filter button.on b { color:inherit; opacity:.8; }
.dev-filter button.on[data-status=pass] {
  background:var(--chip-pass-bg); color:var(--chip-pass-ink);
}
.dev-filter button.on[data-status=pending] {
  background:var(--chip-warn-bg); color:var(--chip-warn-ink);
}
.dev-filter button.on[data-status=not_installed] {
  background:var(--chip-fail-bg); color:var(--chip-fail-ink);
}
@media (min-width:641px) { .dev-filter { max-width:440px; } }

.dev-meta { font-size:.8rem; color:var(--muted); }
.dev-meta .flag { color:var(--chip-fail-ink); font-weight:600; }
.dev-meta .queued { color:var(--accent-ink); font-weight:600; }
.tri {
  display:flex; border:1px solid var(--line2); border-radius:10px;
  overflow:hidden; background:var(--card2);
}
.tri button {
  background:none; border:none; border-radius:0; color:var(--ink2); font:inherit;
  font-size:.85rem; padding:10px 18px; min-height:44px; min-width:76px;
  white-space:nowrap; cursor:pointer;
  transition:transform 80ms ease-out, background 120ms ease-out;
}
.tri button:active { transform:scale(.94); }
.tri button + button { border-left:1px solid var(--line2); }
.tri button.on.pass { background:var(--chip-pass-bg); color:var(--chip-pass-ink); font-weight:650; }
.tri button.on.pending { background:var(--chip-warn-bg); color:var(--chip-warn-ink); font-weight:650; }
.tri button.on.not_installed { background:var(--chip-fail-bg); color:var(--chip-fail-ink); font-weight:650; }
/* This is NOT redundant with the site-wide button:disabled rule. `.tri button`
   sets cursor:pointer at the same specificity and later in the file, so it
   wins unless this says otherwise. Deleting it as a duplicate put the plain
   hand back on a device result that had already been recorded. */
.tri button:disabled { opacity:.55; cursor:not-allowed; }
.dev-actions { display:flex; align-items:center; gap:8px; }
.dev-actions .ghost-btn { min-height:44px; padding:7px 12px; }

/* Phones: the three results share the full row width equally — big,
   even, thumb-sized targets instead of squeezed desktop buttons. */
@media (max-width:640px) {
  .dev-actions { flex-basis:100%; }
  .tri { flex:1 1 auto; }
  .tri button {
    flex:1 1 0; min-width:0; padding:8px 4px; font-size:.82rem;
    white-space:normal; line-height:1.15;   /* "Not installed" wraps, never clips */
  }
}
.dev-error {
  flex-basis:100%; font-size:.8rem; color:var(--fail); padding:0 2px 6px;
}
@media (prefers-reduced-motion: reduce) {
  .tri button, .tri button:active { transition:none; transform:none; }
}

/* ── Network / outbox chip ─────────────────────────────────────────────── */
.net-chip {
  font-size:.78rem; font-weight:600; border-radius:999px; padding:4px 12px;
  letter-spacing:.02em; border:1px solid #4a4a4a; color:#cfcfcf;
}
.net-chip.offline { background:#3a2a1a; color:#f0b46a; border-color:#5a4020; }
.net-chip.queued  { background:#2c3618; color:#b9dd7d; border-color:#4a5a2a; }

/* ── Reassign dialog — a material that "materializes" (blur + scale in),
   over a blurred dimming scrim, per the modal-task pattern ─────────────── */
dialog {
  background:color-mix(in srgb, var(--card) 82%, transparent);
  -webkit-backdrop-filter:blur(24px) saturate(160%);
  backdrop-filter:blur(24px) saturate(160%);
  color:var(--ink); border:1px solid var(--line2);
  border-radius:14px; padding:26px 28px; width:min(430px, 92vw);
  box-shadow:0 18px 50px rgba(0,0,0,.35);
}
dialog::backdrop {
  background:rgba(0,0,0,.35);
  -webkit-backdrop-filter:blur(6px);
  backdrop-filter:blur(6px);
}
@media (prefers-reduced-motion: no-preference) {
  dialog[open] { animation:materialize 240ms cubic-bezier(.2,.9,.3,1); }
  @keyframes materialize {
    from { transform:scale(.94); opacity:0; filter:blur(6px); }
    to   { transform:scale(1);   opacity:1; filter:blur(0); }
  }
}
@media (prefers-reduced-motion: reduce) {
  dialog[open] { animation:fadein 160ms ease; }
  @keyframes fadein { from { opacity:0; } to { opacity:1; } }
}
@media (prefers-reduced-transparency: reduce) {
  dialog { background:var(--card); -webkit-backdrop-filter:none; backdrop-filter:none; }
  dialog::backdrop { -webkit-backdrop-filter:none; backdrop-filter:none; background:rgba(0,0,0,.55); }
}
@media (prefers-contrast: more) {
  dialog { background:var(--card); -webkit-backdrop-filter:none; backdrop-filter:none;
           border:2px solid var(--ink); }
}
dialog h2 { margin-top:0; }
dialog label {
  display:block; font-size:11px; font-weight:600; letter-spacing:.08em;
  text-transform:uppercase; color:var(--muted); margin:14px 0 4px;
}
dialog label .hint { text-transform:none; letter-spacing:0; font-weight:400; }
dialog input:not([type=checkbox]), dialog select, dialog textarea,
.snag-detail-panel select, .snag-detail-panel textarea {
  width:100%; background:var(--card2); color:var(--ink);
  border:1px solid var(--line2); border-radius:8px; padding:9px 12px; font:inherit;
  /* A field sits inside its label, which is 11 px capitals. The field's own
     text is the size of every other field, whatever its label looks like. */
  font-size:var(--field-font); font-weight:400; text-transform:none; letter-spacing:0;
}
dialog textarea, .snag-detail-panel textarea { resize:vertical; min-height:72px; }
.snag-detail-panel select { min-height:44px; }
.ra-manual-row {
  display:flex !important; align-items:center; gap:8px;
  text-transform:none !important; letter-spacing:0 !important;
  font-size:12.5px !important; font-weight:400 !important;
  color:var(--ink2) !important; margin:8px 0 4px !important;
}
.ra-preview {
  margin:14px 0 0; font-size:13px; background:var(--card2);
  border-radius:8px; padding:9px 12px;
}
/* Wrapping matters more than it looks. With nowrap, three buttons whose
   labels do not fit push the row LEFT out of the dialog: measured on the New
   snag form, the row had 357px and the buttons needed 418px, so Cancel began
   61px outside the dialog's own content box. It read as "Cancel is too close
   to the edge"; it was over it. Wrapping keeps every dialog inside itself at
   any width and any wording.
   One rule, carrying its own top margin: tests/test_webapp_icon_consistency.py
   requires exactly one `.dlg-actions {` block and that it is this one. */
.dlg-actions { display:flex; flex-wrap:wrap; justify-content:flex-end; gap:10px; margin-top:20px; }
/* Cancel is the way out, not one of the choices, so it takes the other end of
   the row. That also gives the two create actions room to sit together. */
#snag-form .dlg-actions #snag-cancel { margin-inline-end:auto; }
/* New snag on a phone. The form is taller than the screen, so it scrolls
   inside its dialog, and the buttons that save it must never scroll away:
   they sit in a footer that stays at the foot of the dialog. Every field is
   44px, and the description is one line until it is tapped. */
@media (max-width:700px) {
  #snag-dlg {
    box-sizing:border-box; width:calc(100vw - 16px); max-height:calc(100dvh - 16px);
    padding:16px 14px 0; background:var(--card); overflow-y:auto; overscroll-behavior:contain;
  }
  #snag-dlg h2 { margin-bottom:4px; }
  #snag-dlg :is(input:not([type=checkbox]):not([type=file]), select) { min-height:44px; }
  #snag-dlg #snag-description { min-height:44px; height:44px; resize:none; }
  #snag-dlg #snag-description:focus { height:96px; }
  #snag-dlg .file-picker-btn { min-height:44px; }
  #snag-form .dlg-actions {
    position:sticky; bottom:0; z-index:2; margin:14px -14px 0; padding:10px 14px calc(10px + env(safe-area-inset-bottom));
    display:grid; grid-template-columns:1fr 1fr; gap:8px;
    background:var(--card); border-top:1px solid var(--line2);
  }
  #snag-form .dlg-actions button { min-height:44px; margin:0; }
  #snag-form .dlg-actions #snag-cancel { grid-column:1; grid-row:1; margin-inline-end:0; }
  #snag-form .dlg-actions #snag-save { grid-column:2; grid-row:1; }
  #snag-form .dlg-actions #snag-save-mark { grid-column:1 / -1; grid-row:2; }
}
/* ── Snag drawings ───────────────────────────────────────────────────────────
   Floors as cards, each saying what is outstanding on it. Reached from Snags,
   opening the snag viewer — the same one a snag from the list opens. */
.snag-drawings-dlg { width:min(760px, 94vw); }
.snag-drawings-head { display:flex; align-items:flex-start; justify-content:space-between; gap:16px; }
.snag-drawings-head h2 { margin:0; }
/* Scrolls with the page, like the progress list. A pane of its own inside a
   page that also scrolls halves how many floors are on screen and gives the
   reader two scrollbars to choose between. */
.snag-drawings-list {
  margin-top:16px;
}
.snag-drawing-card {
  position:relative; display:flex; flex-direction:column; align-items:stretch; gap:0;
  text-align:start; padding:0; min-height:44px;
}
/* The whole card opens the floor; the tick box sits above it and is not part
   of that target, the same arrangement the progress cards use. */
.snag-drawing-open {
  position:absolute; inset:0; z-index:1; padding:0; border:0; border-radius:9px;
  background:transparent; cursor:pointer;
}
.snag-drawing-open:hover, .snag-drawing-open:active, .snag-drawing-open:focus {
  border:0; background:transparent;
}
.snag-drawing-open:focus-visible {
  outline:3px solid var(--focus) !important; outline-offset:-3px !important;
}
.snag-drawing-card .drawing-card-select { z-index:2; }
/* The preview is the same component the progress cards use, so a floor looks
   the same wherever it is listed. */
.snag-drawing-card .drawing-thumb { width:100%; }
.snag-drawing-body {
  display:flex; flex-direction:column; align-items:flex-start; gap:4px; padding:12px 14px;
}
.snag-drawing-floor { font-weight:700; color:var(--ink); }
.snag-drawing-name { color:var(--muted); font-size:11.5px; overflow-wrap:anywhere; }
.snag-drawing-counts { display:flex; flex-wrap:wrap; gap:5px; margin-top:4px; }
.snag-drawing-note { color:var(--muted); font-size:11px; }
/* The same three tones the badges and the marks use, so a count and a mark
   never disagree about what a status looks like. */
.snag-count-chip {
  border-radius:999px; padding:2px 8px; font-size:11px; font-weight:650;
  background:var(--chip-na-bg); color:var(--chip-na-ink);
}
.snag-count-chip.tone-issue { background:var(--chip-fail-bg); color:var(--chip-fail-ink); }
.snag-count-chip.tone-information { background:color-mix(in srgb,var(--info) 14%,var(--card)); color:var(--info); }
.snag-count-chip.tone-passed { background:var(--chip-pass-bg); color:var(--chip-pass-ink); }

/* New snag carries three buttons, one of them "Create and place on drawing".
   They come to 418px and the default dialog gives the row 357px. The names are
   the ones the workflow specifies, so the dialog makes room rather than the
   words getting shorter. */
#snag-dlg { width:min(520px, 92vw); }
#ra-submit, #part-submit {
  background:var(--accent); color:var(--btn-ink); border:none; border-radius:8px;
  padding:8px 18px; font:inherit; font-weight:650; cursor:pointer;
}
#part-submit:disabled { opacity:.6; cursor:not-allowed; }

/* ── Dashboard report ──────────────────────────────────────────────────────
   The screen follows the report builder in the workspace reference. The
   printable document keeps its existing rules and remains the only content
   that reaches paper. */
#page-report { gap:16px; }
.report-page-heading { align-items:flex-start; }
.report-heading-copy { max-width:650px; }
.report-heading-copy h1 { margin-bottom:6px; }
.report-heading-copy > p:last-child {
  margin:0; color:var(--ink2); font-size:13px; line-height:1.55;
}
.report-page-actions {
  display:flex; flex-wrap:wrap; align-items:center; justify-content:flex-end;
  gap:8px; max-width:58%;
}
.report-page-actions .chip { min-height:36px; display:inline-flex; align-items:center; }
.report-page-actions .ghost-btn, #report-print { min-height:38px; }
#report-print {
  background:var(--accent); color:var(--btn-ink); border:none; border-radius:8px;
  padding:8px 16px; font:inherit; font-weight:650; cursor:pointer;
}
.report-workspace {
  display:grid; grid-template-columns:minmax(230px,280px) minmax(0,1fr);
  gap:16px; align-items:start;
}
.report-toolbar {
  display:grid; gap:12px; margin:0; padding:0; max-width:none;
  align-self:start; background:transparent; border:0; border-radius:0; box-shadow:none;
}
.report-builder-panel {
  min-width:0; padding:14px 16px 16px; background:var(--card);
  border:1px solid var(--line); border-radius:10px;
}
.report-builder-panel > h2 {
  margin:0 -16px 12px; padding:0 16px 12px;
  border-bottom:1px solid var(--line); font-size:15px;
}
.report-builder-panel > .eyebrow { margin-bottom:3px; }
.report-preset-options { display:grid; gap:8px; }
.report-preset-option {
  display:flex; width:100%; min-height:38px; align-items:center;
  justify-content:flex-start; padding:8px 11px; background:transparent;
  border:1px solid var(--line); border-radius:8px; color:var(--ink2);
  font:inherit; font-size:13px; text-align:left; cursor:pointer;
}
.report-preset-option:hover { border-color:var(--line2); background:var(--card2); color:var(--ink); }
.report-preset-option.on {
  border-color:var(--accent); background:var(--chip-pass-bg);
  color:var(--accent-ink); font-weight:650;
}
#report-sections { margin:0; }
.report-toolbar .sections-list {
  position:static; min-width:0; margin:0; padding:0; display:grid; gap:0;
  background:transparent; border:0; border-radius:0; box-shadow:none;
}
.report-toolbar .check-label {
  display:grid; grid-template-columns:34px minmax(0,1fr) auto;
  align-items:center; gap:8px; min-height:42px; padding:7px 0;
  border-top:1px solid var(--line); color:var(--ink2); font-size:12.5px;
  cursor:pointer;
}
.report-toolbar .check-label input[type="checkbox"] {
  appearance:none; position:relative; width:30px; height:17px; margin:0;
  border:1px solid var(--line2); border-radius:999px; background:var(--card2);
  cursor:pointer; transition:background .15s ease,border-color .15s ease;
}
.report-toolbar .check-label input[type="checkbox"]::after {
  content:""; position:absolute; top:2px; left:2px; width:11px; height:11px;
  border-radius:50%; background:var(--muted); transition:transform .15s ease,background .15s ease;
}
.report-toolbar .check-label input[type="checkbox"]:checked {
  border-color:var(--accent); background:var(--chip-pass-bg);
}
.report-toolbar .check-label input[type="checkbox"]:checked::after {
  transform:translateX(13px); background:var(--accent);
}
.report-section-name { min-width:0; color:var(--ink); }
.report-section-status { color:var(--muted); font-size:10.5px; white-space:nowrap; }
/* The module-list scope sits under its switch, across the full width of the
   panel, with three equal buttons. It used to be pushed 42px right to line up
   with the switch's label, with no width limit, so in the narrow panel the
   last button ran past the edge and was cut off. */
.report-toolbar .sections-list .seg {
  box-sizing:border-box; width:100%; max-width:100%; margin:2px 0 8px;
}
.report-toolbar .sections-list .seg button {
  flex:1 1 0; min-width:0; padding:7px 6px; text-align:center;
}
.report-note-label {
  display:block; margin:14px 0 6px; color:var(--muted); font-size:11px;
  font-weight:600; letter-spacing:.06em; text-transform:uppercase;
}
.report-note-input {
  box-sizing:border-box; width:100%; min-width:0; background:var(--card2); color:var(--ink);
  border:1px solid var(--line2); border-radius:8px; padding:7px 11px; font:inherit;
  font-size:var(--field-font);
}
.report-hint { margin:10px 0 0; line-height:1.45; }
.report-back { width:100%; margin-top:12px; }
.report-preview-well {
  min-width:0; padding:26px; overflow-x:auto; background:var(--card2);
  border:1px solid var(--line); border-radius:10px;
}
.email-draft-dlg { width:min(720px, calc(100vw - 28px)); }
.email-draft-dlg form { display:grid; gap:10px; }
.email-draft-dlg fieldset { display:grid; gap:7px; border:1px solid var(--line); border-radius:8px; padding:10px 12px; }
.email-draft-dlg fieldset label { display:flex; align-items:center; gap:8px; }
.email-draft-dlg fieldset input { width:16px; height:16px; }
.email-draft-names { display:grid; grid-template-columns:auto 1fr; align-items:center; gap:8px 12px; }
#email-draft-preview { min-height:310px; font-family:inherit; line-height:1.45; }
@media (max-width:600px) { .email-draft-names { grid-template-columns:1fr; } }

.report {
  box-sizing:border-box; display:block; width:min(900px,100%); max-width:900px; margin:0 auto;
  background:var(--card); border:1px solid var(--line); border-radius:12px;
  box-shadow:var(--shadow); padding:34px 38px 28px;
}
#report-doc {
  --card:#ffffff; --card2:#f5f6f2; --ink:#1c1f19; --ink2:#454a3d;
  --muted:#6a705f; --line:#e2e5dc; --line2:#ccd1c5;
  --data:#7fb232; --data-track:#edf3df; --fail:#c94141;
  --progress-mid:#e3ad3d;
  --chip-pass-bg:#eef6dd; --chip-pass-ink:#56701f;
  --chip-fail-bg:#f9e7e5; --chip-fail-ink:#a92f2f;
  --chip-warn-bg:#fdf0d2; --chip-warn-ink:#8a5a12;
  --chip-info-bg:#e8f1fd; --chip-info-ink:#2c66a8;
  --chip-na-bg:#efefef; --chip-na-ink:#777d70;
  color:var(--ink); font-family:'Public Sans', "Segoe UI", system-ui, sans-serif;
}
@media (max-width:1050px) {
  .report-workspace { grid-template-columns:1fr; }
  .report-toolbar { grid-template-columns:repeat(2,minmax(0,1fr)); }
  .report-section-panel { min-width:0; }
}
@media (max-width:700px) {
  .report-page-actions { justify-content:flex-start; width:100%; max-width:none; }
  .report-page-actions > * { flex:1 1 auto; justify-content:center; }
  .report-toolbar { grid-template-columns:1fr; }
  .report-preview-well { padding:12px; }
}
/* Report header dividers: one thin line in a slightly muted Delmatic green
   (#9dc368, not #96D045), the weight of the grey dividers inside a report,
   so it accompanies the heading without competing with the wordmark. */
.rep-head { border-bottom:1px solid #9dc368; padding-bottom:18px; margin-bottom:22px; }
/* One heading scale for every printed report: a cover title 32px, a report
   or item title 21px, a section heading 15px. */
.rep-head h1 { font-size:21px; margin:10px 0 18px; letter-spacing:-.01em; }
.rep-meta { display:grid; grid-template-columns:repeat(auto-fit,minmax(190px,1fr)); gap:12px; }
.rep-meta span {
  display:block; font-size:10.5px; font-weight:600; letter-spacing:.09em;
  text-transform:uppercase; color:var(--muted); margin-bottom:2px;
}
.rep-meta b { font-size:13.5px; font-weight:600; }
.rep-user-note {
  margin:18px 0 0; font-size:13px; color:var(--ink2);
  background:var(--card2); border-radius:8px; padding:9px 13px;
}
.report-measures {
  display:grid; grid-template-columns:repeat(auto-fit,minmax(150px,1fr));
  gap:10px; margin-bottom:24px;
}
.report-measure {
  min-width:0; padding:14px 16px; border:1px solid var(--line);
  border-radius:8px; background:var(--card); break-inside:avoid;
}
.report-measure .v {
  font-size:28px; font-weight:650; letter-spacing:-.02em; line-height:1.15;
  font-variant-numeric:tabular-nums;
}
.report-measure .v small { font-size:14px; color:var(--ink2); font-weight:500; }
.report-measure .v small.unit { margin-left:3px; }
.report-measure .s { margin-top:3px; color:var(--ink2); font-size:11.5px; }
.report-progress-measure .v {
  display:inline-flex; align-items:baseline; padding:3px 10px;
  border-radius:999px;
}
.report-progress-measure.band-low .v { background:var(--chip-fail-bg); color:var(--chip-fail-ink); }
.report-progress-measure.band-mid .v { background:var(--chip-warn-bg); color:var(--chip-warn-ink); }
.report-progress-measure.band-high .v { background:var(--chip-pass-bg); color:var(--chip-pass-ink); }
.report-progress-measure .v small { color:inherit; }
.rep-sec { margin-bottom:26px; }
.rep-sec h2 { margin-bottom:12px; font-size:15px; }
.rep-note { font-size:11.5px; color:var(--muted); margin:10px 0 0; }
.rep-headline { font-size:14.5px; margin:0; color:var(--ink2); }
.rep-headline b { color:var(--ink); font-weight:650; }
.rep-subhead {
  font-size:11px; font-weight:600; letter-spacing:.09em; text-transform:uppercase;
  color:var(--muted); margin:18px 0 6px;
}
.rep-rows .rw {
  display:flex; justify-content:space-between; gap:14px; font-size:13px;
  padding:4px 0; color:var(--ink2); border-bottom:1px solid var(--line);
}
.rep-rows .rw b { color:var(--ink); font-variant-numeric:tabular-nums; font-weight:600; }
.rep-tbl th { position:static; }
.rep-tbl td, .rep-tbl th { padding:6px 8px; }
.rep-tbl tr:hover td { background:none; }
.rep-wrap { white-space:normal; min-width:200px; color:var(--ink2); }
.emergency-failure-table { margin-top:12px; width:100%; table-layout:fixed; }
.emergency-failure-table td { vertical-align:top; overflow-wrap:anywhere; white-space:normal; }
.emergency-failure-table th { white-space:normal; }
/* The locating facts and test dates sit under the value they describe. */
.emergency-failure-table td small { display:block; margin-top:2px; color:var(--muted); font-size:10px; line-height:1.35; }
.rep-floors .rep-floor-nm { white-space:normal; max-width:190px; }
.rep-bar-cell { width:44%; }
.rep-bar-cell .track {
  height:13px; background:var(--data-track); border-radius:4px; overflow:hidden;
}
.rep-bar-cell .fill { height:100%; border-radius:0 4px 4px 0; }
.rep-score { font-weight:650; }
.rep-score-chip {
  display:inline-flex; min-width:48px; justify-content:center; padding:2px 8px;
  border-radius:999px; font-size:11.5px; font-weight:650;
  font-variant-numeric:tabular-nums;
}
.rep-score-chip.band-low { background:var(--chip-fail-bg); color:var(--chip-fail-ink); }
.rep-score-chip.band-mid { background:var(--chip-warn-bg); color:var(--chip-warn-ink); }
.rep-score-chip.band-high { background:var(--chip-pass-bg); color:var(--chip-pass-ink); }
.rep-trend svg { width:100%; height:auto; display:block; color:var(--data); }
.rep-trend svg .area { stroke:none; }
.rep-modules td:first-child {
  font-family:'IBM Plex Mono', ui-monospace, "Cascadia Mono", Consolas, monospace;
  font-weight:600; letter-spacing:-.01em;
}
.rep-modules .rep-module-complete { width:24%; min-width:150px; }
.rep-modules .module-progress { min-width:120px; gap:6px; }
.rep-module-status {
  display:inline-flex; justify-content:center; min-width:68px; padding:2px 8px;
  border-radius:999px; font-size:10.5px; font-weight:650; white-space:nowrap;
}
.rep-module-status.complete { background:var(--chip-pass-bg); color:var(--chip-pass-ink); }
.rep-module-status.in-progress { background:var(--chip-warn-bg); color:var(--chip-warn-ink); }
/* ── Snapshot drawing evidence ─────────────────────────────────────────── */
.drawing-page-heading {
  align-items:flex-start; padding-bottom:10px; border-bottom:0;
}
.drawing-page-intro { max-width:610px; margin:6px 0 0; color:var(--ink2); font-size:13px; }
.drawing-page-actions {
  display:flex; flex-direction:column; align-items:flex-end; gap:9px; max-width:72%;
}
.drawing-snapshot-field {
  display:flex; align-items:center; gap:10px; min-height:38px; padding:0 10px;
  border:1px solid var(--line2); border-radius:8px; background:var(--card2);
  color:var(--muted); font-size:12.5px;
}
.drawing-snapshot-field:has(select[hidden]) { display:none; }
#drawing-request-picker {
  max-width:280px; padding:0 24px 0 0; border:0; background:transparent;
  color:var(--ink); font-weight:650;
}
.drawing-tabs {
  display:flex; gap:0; min-height:46px; margin-top:-1px; padding:0 10px;
  border-bottom:1px solid var(--line);
}
.drawing-tabs button {
  position:relative; min-height:46px; padding:0 14px; border:0; border-radius:0;
  background:transparent; color:var(--ink2); font:inherit; font-size:13px; cursor:pointer;
}
.drawing-tabs button.on { color:var(--ink); font-weight:650; }
.drawing-tabs button.on::after {
  content:""; position:absolute; right:0; bottom:-1px; left:0; height:2px;
  background:var(--accent);
}
.drawing-workspace { display:grid; gap:16px; }
.drawing-summary {
  display:grid; grid-template-columns:repeat(auto-fit,minmax(190px,1fr));
  overflow:hidden; border:1px solid var(--line); border-radius:10px; background:var(--card);
}
.drawing-measure {
  min-width:0; margin:-1px 0 0 -1px; padding:15px 18px;
  border-top:1px solid var(--line); border-left:1px solid var(--line);
}
.drawing-measure .eyebrow { margin:0; }
.drawing-measure-value {
  display:flex; align-items:baseline; gap:6px; margin-top:7px;
  color:var(--ink); font-size:30px; font-weight:650; letter-spacing:-.03em;
  font-variant-numeric:tabular-nums; line-height:1.1;
}
.drawing-measure-value small { color:var(--muted); font-size:13px; font-weight:500; letter-spacing:0; }
.drawing-measure-foot {
  min-height:22px; margin-top:8px; overflow:hidden; color:var(--ink2);
  font-size:12px; text-overflow:ellipsis; white-space:nowrap;
}
.report-family-options { display:grid; gap:7px; }
.report-family-options button {
  min-height:40px; text-align:left; background:var(--card2); color:var(--ink2);
  border:1px solid var(--line2); border-radius:8px;
}
.report-family-options button.on { border-color:var(--accent); box-shadow:inset 3px 0 var(--accent); color:var(--ink); font-weight:650; }
.snag-report-options { display:grid; gap:7px; }
.snag-report-options > label { color:var(--muted); font-size:11px; font-weight:650; }
.snag-report-options select, .snag-report-options input:not([type="checkbox"]), .snag-report-options textarea {
  box-sizing:border-box; width:100%; min-height:38px; padding:6px 8px;
  color:var(--ink); background:var(--card2); border:1px solid var(--line2); border-radius:7px;
}
.snag-report-options > .check-label { color:var(--ink2); font-size:12.5px; font-weight:500; }
.snag-report-inherited { margin:0 0 5px; padding:8px 10px; border-inline-start:3px solid var(--accent); background:var(--card2); color:var(--ink2); font-size:12px; }
.snag-report-date-fields { display:grid; grid-template-columns:1fr 1fr; gap:8px; }
.snag-report-date-fields label { display:grid; gap:4px; color:var(--muted); font-size:11px; }
.engineering-selection-bar {
  display:flex; flex-wrap:wrap; align-items:center; gap:8px; margin:12px 0;
  padding:10px 12px; border:1px solid var(--line); border-radius:9px; background:var(--card2);
}
.engineering-selection-bar[hidden] { display:none; }
.engineering-selection-bar b { margin-right:auto; }
.engineering-selection-bar p { flex-basis:100%; margin:0; color:var(--muted); font-size:12px; }
.engineering-select-control {
  display:flex; align-items:center; gap:7px; margin:0 0 9px; color:var(--ink2);
  font-size:12px; font-weight:650;
}
.engineering-select-control input { width:18px; height:18px; }
.engineering-finding.is-selecting { border-inline-start:3px solid var(--accent); }
.engineering-show-more { display:block; margin:14px auto 0; }
.admin-emergency-note { margin-top:2px; }

/* Derived Emergency evidence. It reads as a status line, not as a control,
   because nobody types it: it comes from the Collector Snapshot. */
.admin-emergency-evidence {
  margin:0 0 6px; color:var(--ink2); font-size:12px; font-weight:600;
  line-height:1.45; overflow-wrap:anywhere;
}

/* A Delmatic internal report says so on the screen and on the paper. On
   paper it is in the footer of every page (applyPrintFooter), not a line
   above the first page, where it pushed a full-page sheet onto page two. */
.report-internal-mark {
  margin:0 0 10px; padding:6px 12px; border-radius:8px;
  border:1px solid var(--warn-line, var(--line));
  background:var(--warn-bg, var(--panel2));
  color:var(--ink); font-size:12px; font-weight:700;
  letter-spacing:.04em; text-transform:uppercase;
}
@media print { .report-internal-mark { display:none!important; } }

/* Scope helper: ordinary smaller text on the form background. No icon, panel,
   border or tooltip colour: it is permanent explanation, not hidden help. */
.report-scope-helper { margin:0; color:var(--muted); font-size:12px; line-height:1.45; overflow-wrap:anywhere; }
.report-scope-count { margin:2px 0 4px; color:var(--ink2); font-size:12px; font-weight:600; line-height:1.45; overflow-wrap:anywhere; }
.engineering-report-options { display:grid; gap:7px; }
.engineering-report-options > label,
.engineering-report-check-types legend { color:var(--muted); font-size:11px; font-weight:650; }
.engineering-report-options select,
.engineering-report-options input:not([type="checkbox"]),
.engineering-report-options textarea {
  box-sizing:border-box; width:100%; min-height:38px; padding:6px 8px;
  color:var(--ink); background:var(--card2); border:1px solid var(--line2); border-radius:7px;
}
.engineering-report-options > .check-label { color:var(--ink2); font-size:12.5px; font-weight:500; }
.emergency-report-options { display:grid; gap:7px; }
.emergency-report-options > label,
.emergency-report-types legend { color:var(--muted); font-size:11px; font-weight:650; }
.emergency-report-options select,.emergency-report-options input:not([type="checkbox"]):not([type="radio"]),
.emergency-report-options textarea { box-sizing:border-box; width:100%; min-height:38px; padding:6px 8px;
  color:var(--ink); background:var(--card2); border:1px solid var(--line2); border-radius:7px; }
.emergency-report-types { display:grid; gap:7px; margin:0; padding:9px 0; border:0; }
.emergency-report-types label { display:flex; align-items:center; gap:8px; color:var(--ink2); }
.emergency-report-types input { width:17px; height:17px; }

.emergency-work-filters { display:grid; grid-template-columns:repeat(5,minmax(140px,1fr)); gap:10px; margin:12px 0; }
.emergency-work-filters label { display:grid; gap:5px; color:var(--muted); font-size:11px; font-weight:650; }
.emergency-work-filters select,.emergency-work-filters input { min-width:0; width:100%; box-sizing:border-box; }
.emergency-selection-bar { display:flex; flex-wrap:wrap; align-items:center; gap:8px; margin:12px 0; padding:10px 12px;
  border:1px solid var(--line); border-radius:9px; background:var(--card2); }
.emergency-selection-bar[hidden] { display:none; }
.emergency-selection-bar b { margin-right:auto; }
.emergency-selection-bar p { flex-basis:100%; margin:0; color:var(--muted); font-size:12px; }
.emergency-work-list { display:grid; gap:8px; }
.emergency-work-row { display:grid; grid-template-columns:minmax(220px,1.2fr) auto minmax(240px,1fr); gap:14px; align-items:center;
  padding:12px; border:1px solid var(--line); border-radius:9px; background:var(--card); }
.emergency-work-row.is-selecting { grid-template-columns:auto minmax(200px,1.2fr) auto minmax(220px,1fr); border-inline-start:3px solid var(--accent); }
.emergency-work-row h3,.emergency-work-row p { margin:0; }.emergency-work-row p { color:var(--muted); font-size:12px; }
.emergency-work-row dl { display:flex; justify-content:flex-end; gap:18px; margin:0; }
.emergency-work-row dl div { min-width:90px; }.emergency-work-row dt { color:var(--muted); font-size:10px; text-transform:uppercase; }
.emergency-work-row dd { margin:2px 0 0; }.emergency-select-control input { width:20px; height:20px; }
.emergency-work-state { font-size:12px; }.emergency-work-state.failure,.emergency-work-state.both { color:var(--fail); }
.emergency-work-state.required { color:#996000; }
@media(max-width:1050px){.emergency-work-filters{grid-template-columns:repeat(2,minmax(0,1fr));}.emergency-work-row,.emergency-work-row.is-selecting{grid-template-columns:auto minmax(0,1fr);}.emergency-work-row:not(.is-selecting)>div:first-child,.emergency-work-row:not(.is-selecting)>dl{grid-column:1/-1;}.emergency-work-row dl{justify-content:flex-start;}}
@media(max-width:600px){.emergency-work-filters{grid-template-columns:1fr}.emergency-selection-bar button{flex:1 1 140px}.emergency-work-row dl{display:grid;grid-template-columns:1fr 1fr;}}

.emergency-report-document { --sr-ink:#1b2119;--sr-muted:#66705f;--sr-line:#d9ded3;--sr-soft:#f3f5ef;
  color:var(--sr-ink);background:#fff;font:10.5px/1.4 'Public Sans','Segoe UI',system-ui,sans-serif; }
.emergency-work-sheet-head { display:flex; justify-content:space-between; align-items:baseline; gap:8mm; padding-bottom:2mm;
  margin-bottom:4mm; border-bottom:1px solid #9dc368; color:var(--sr-muted); font-size:8.5px; }
.emergency-work-sheet>h1 { margin:1mm 0 2mm; font-size:21px; line-height:1.15; }
.emergency-work-state-print { margin:0 0 3mm; padding:2.5mm 3mm; border-inline-start:4px solid #a76800; background:#fff5dd; font-size:15px; font-weight:750; }
.emergency-work-state-print.failure,.emergency-work-state-print.both { border-inline-start-color:#c22429; background:#fbe8e8; }
.emergency-work-facts { display:grid; grid-template-columns:repeat(3,minmax(0,1fr)); gap:2mm 5mm; margin:0 0 4mm; padding:3mm; border:1px solid var(--sr-line); background:var(--sr-soft); }
.emergency-work-facts dt { color:var(--sr-muted); font-size:8px; font-weight:700; letter-spacing:.06em; text-transform:uppercase; }
.emergency-work-facts dd { margin:.5mm 0 0; overflow-wrap:anywhere; }
.emergency-work-drawings h2,.emergency-drawing-unavailable h2 { margin:0 0 2mm; font-size:15px; }
.emergency-work-drawings figure { margin:0 0 3mm; break-inside:avoid; }
.emergency-work-drawings img { display:block; box-sizing:border-box; width:100%; object-fit:contain; border:1px solid var(--sr-line); background:#fff; }
.emergency-locator img { height:47mm; }.emergency-detail img { height:102mm; }
/* A failure sheet carries how to fix it, so its drawings give up some height
   to keep the sheet on one A4 page. */
.emergency-work-sheet.has-fix .emergency-locator img { height:38mm; }
.emergency-work-sheet.has-fix .emergency-detail img { height:74mm; }
.emergency-work-fix { margin:0 0 4mm; padding:3mm 3.5mm; border:1px solid var(--sr-line); border-inline-start:4px solid #91c83e; break-inside:avoid; }
.emergency-work-fix h2 { display:flex; justify-content:space-between; align-items:baseline; gap:4mm; margin:0 0 1.5mm; font-size:15px; }
.emergency-work-fix h2 span { color:var(--sr-muted); font-size:9px; font-weight:700; letter-spacing:.05em; text-transform:uppercase; }
.emergency-work-fix-causes { margin:0 0 1.5mm; color:var(--sr-muted); font-size:9px; }
.emergency-work-fix-causes b { color:var(--sr-ink); }
.emergency-work-fix ol { margin:0; padding-left:5mm; columns:2; column-gap:6mm; font-size:9.5px; line-height:1.35; }
.emergency-work-fix li { break-inside:avoid; margin-bottom:1mm; }
.emergency-work-fix-after { margin:1.5mm 0 0; font-size:9px; font-weight:650; }
.emergency-work-signoff { display:grid; grid-template-columns:auto 1.2fr 1fr 2fr; gap:4mm; margin-top:2.5mm; font-size:8.5px; color:var(--sr-muted); }
.emergency-work-signoff span { display:flex; align-items:flex-end; gap:1.5mm; min-height:6mm; border-bottom:1px solid var(--sr-line); }
.emergency-work-signoff span:first-child { border-bottom:0; font-weight:700; color:var(--sr-ink); }
.emergency-work-signoff i { width:3.5mm; height:3.5mm; border:1px solid var(--sr-ink); }
.em-report-guide { margin-top:6mm; }
.em-report-cause { margin:0 0 4mm; break-inside:avoid; }
.em-report-cause h3 { margin:0 0 1mm; font-size:12px; }
.em-report-cause h3 code { color:#66705f; font:9px "IBM Plex Mono",monospace; }
.em-report-cause h3 span { color:#66705f; font-size:9px; font-weight:700; text-transform:uppercase; letter-spacing:.05em; }
.em-report-cause p { margin:0 0 1mm; color:#454a3d; font-size:10px; }
.em-report-cause ol { margin:0; padding-left:5mm; font-size:10px; line-height:1.4; }
.emergency-work-drawings figcaption { margin-top:1mm; color:var(--sr-muted); font-size:8.5px; }
.emergency-drawing-unavailable { margin-top:5mm; padding:4mm; border-inline-start:4px solid #a76800; background:#fff5dd; }
.emergency-multiple-note { padding:2mm 3mm; border-inline-start:3px solid #a76800; background:#fff5dd; }
.emergency-status-page .rep-sec { margin-bottom:7mm; }
.engineering-report-check-types { min-width:0; margin:4px 0; padding:7px 0 0; border:0; }
.engineering-report-check-types > div { display:grid; }
.engineering-report-check-types .check-label small { justify-self:end; color:var(--muted); }

.engineering-report-document { color:#1b2119; background:#fff; }
.engineering-report-body { box-sizing:border-box; min-height:270mm; }
.engineering-report-group { margin:0 0 8mm; }
.engineering-report-group:last-child { margin-bottom:0; }
.engineering-report-group h2 {
  display:flex; justify-content:space-between; gap:10px; margin:0 0 2mm;
  padding-bottom:2mm; border-bottom:1px solid #d9ded3; font-size:15px;
}
.engineering-report-group h2 small { color:#66705f; font-size:11px; }
.engineering-report-group table { width:100%; border-collapse:collapse; table-layout:fixed; }
.engineering-report-group th {
  padding:2mm; color:#66705f; font-size:9px; letter-spacing:.07em;
  text-align:left; text-transform:uppercase; border-bottom:1px solid #d9ded3;
}
.engineering-report-group td { padding:3mm 2mm; vertical-align:top; border-bottom:1px solid #e8ebe4; }
.engineering-report-group td:first-child { width:34%; }
.engineering-report-finding td > b,
.engineering-report-finding td > span { display:block; }
.engineering-report-finding td > span { margin-top:1mm; color:#454a3d; }
.engineering-report-finding dl { display:grid; grid-template-columns:repeat(2,minmax(0,1fr)); gap:1.5mm 4mm; min-width:0; max-width:100%; margin:0; }
.engineering-report-finding dl div { min-width:0; }
.engineering-report-finding dt { color:#66705f; font-size:8.5px; letter-spacing:.06em; text-transform:uppercase; }
.engineering-report-finding dd { max-width:100%; margin:0; overflow-wrap:anywhere; word-break:break-word; white-space:normal; }
@media (max-width:600px) {
  .engineering-selection-bar > button { flex:1 1 140px; }
  .engineering-selection-bar b { flex-basis:100%; }
}

/* Shared paper model for the record, Work list and Status report. */
.snag-report-document {
  --sr-ink:#1b2119; --sr-muted:#66705f; --sr-line:#d9ded3; --sr-soft:#f3f5ef;
  box-sizing:border-box; color:var(--sr-ink); background:#fff;
  font:12px/1.45 'Public Sans','Segoe UI',system-ui,sans-serif;
}
.snag-report-page { box-sizing:border-box; padding:14mm; }
.snag-report-cover-head { display:flex; align-items:center; justify-content:space-between; gap:12px; color:var(--sr-muted); }
.snag-report-cover-rule { height:1px; margin:5mm 0 18mm; background:#9dc368; }
.snag-report-cover .snag-report-page-content > h1 { max-width:150mm; margin:2mm 0 1mm; font-size:32px; line-height:1.1; }
.snag-report-cover-client { margin:0 0 12mm; color:var(--sr-muted); font-size:16px; }
.snag-report-cover-meta { display:grid; grid-template-columns:repeat(2,minmax(0,1fr)); gap:5mm 12mm; margin:0 0 10mm; }
.snag-report-cover-note, .snag-report-cover-summary, .snag-report-cover-list, .snag-report-cover-inclusions { margin:0 0 8mm; }
.snag-report-cover h2 { margin:0 0 2mm; font-size:14px; }
.snag-report-cover-note { padding:4mm; border-inline-start:3px solid #91c83e; background:var(--sr-soft); white-space:pre-wrap; }
.snag-report-cover-summary > div { display:flex; flex-wrap:wrap; gap:3mm 8mm; }
.snag-report-cover-summary span b { font-size:18px; }
.snag-report-cover-list ol { margin:0; padding-inline-start:6mm; }
.snag-report-cover-list li { margin-bottom:2mm; padding-inline-start:2mm; }
.snag-report-cover-list li span { display:block; color:var(--sr-muted); }
.snag-report-cover-inclusions { padding-top:4mm; border-top:1px solid var(--sr-line); }
.snag-report-cover-inclusions p { margin:1mm 0; }
.snag-report-page + .snag-report-page { border-top:8px solid #ecefe8; }
.snag-report-running { display:grid; grid-template-columns:auto auto minmax(0,1fr); align-items:baseline; gap:4mm; padding-bottom:2mm; margin-bottom:5mm; border-bottom:1px solid #9dc368; color:#4f574b; font-size:8.5px; }
.snag-report-running > span:last-child { text-align:right; overflow-wrap:anywhere; }
.snag-report-headline { border-bottom:1px solid #9dc368; padding-bottom:15px; margin-bottom:20px; }
.snag-report-headline > p { margin:12px 0 2px; color:var(--sr-muted); }
.snag-report-headline h1 { margin:0 0 14px; font-size:21px; letter-spacing:-.025em; }
.snag-report-headline dl, .snag-report-details { display:grid; grid-template-columns:repeat(3,minmax(0,1fr)); gap:8px 18px; margin:0; }
.snag-report-headline dl div, .snag-report-details div { min-width:0; }
.snag-report-document dt { color:var(--sr-muted); font-size:9.5px; font-weight:700; text-transform:uppercase; letter-spacing:.07em; }
.snag-report-document dd { margin:2px 0 0; overflow-wrap:anywhere; }
.snag-report-measures { display:grid; grid-template-columns:repeat(3,minmax(0,1fr)); gap:8px; margin-bottom:20px; }
.snag-report-status-measures { grid-template-columns:repeat(5,minmax(0,1fr)); }
.snag-report-measures > div { padding:10px 12px; border:1px solid var(--sr-line); background:var(--sr-soft); break-inside:avoid; }
.snag-report-measures b { display:block; font-size:24px; line-height:1.15; }
.snag-report-measures span { color:var(--sr-muted); }
.snag-report-warning, .snag-report-drawing-message { padding:9px 11px; border-inline-start:4px solid #c98a18; background:#fff6dc; }
.snag-report-group { margin:0 0 20px; }
.snag-report-group h2 {
  display:flex; justify-content:space-between; gap:10px; margin:0; padding:8px 10px;
  border-top:1px solid #a7b59b; border-bottom:1px solid var(--sr-line);
  border-inline-start:3px solid #7fb232; background:#f1f4ec; color:var(--sr-ink); font-size:13px;
}
.snag-report-group h2 small { color:var(--sr-muted); }
.snag-report-document table { width:100%; border-collapse:collapse; font-size:10.5px; }
.snag-report-document th { color:var(--sr-muted); text-align:left; font-weight:700; }
.snag-report-document td, .snag-report-document th { padding:7px 8px; border-bottom:1px solid var(--sr-line); vertical-align:top; }
.snag-report-document td small { display:block; color:var(--sr-muted); margin-top:2px; }
.snag-report-badge { display:inline-flex; align-items:center; min-width:42px; color:#b42323; }
.snag-report-badge.tone-information { color:#3479df; }
.snag-report-badge.tone-passed { color:#709929; }
.snag-report-badge svg { display:block; max-width:58px; }
.snag-report-state { font-weight:700; }
.snag-report-state.tone-issue { color:#9e2020; }.snag-report-state.tone-information { color:#2866b5; }.snag-report-state.tone-passed { color:#52741d; }
.snag-report-status-grid { display:grid; grid-template-columns:1fr 1fr .7fr; gap:14px; margin-bottom:22px; }
.snag-report-status-grid > div { padding:12px; border:1px solid var(--sr-line); break-inside:avoid; }
.snag-report-status-grid h2 { margin:0 0 8px; font-size:13px; }
.snag-report-status-grid dl { margin:0; }.snag-report-status-grid dl div { display:flex; justify-content:space-between; border-bottom:1px solid var(--sr-line); padding:6px 0; }
.snag-report-record-title { display:flex; align-items:center; gap:14px; margin-bottom:18px; }
.snag-report-record-title p { margin:0; color:var(--sr-muted); font-size:10px; font-weight:700; letter-spacing:.08em; }
.snag-report-record-title h2 { margin:2px 0 0; font-size:21px; }
.snag-report-record-identity { margin-bottom:3mm; }
.snag-report-record-identity h1 { margin:1mm 0 0; font-size:21px; line-height:1.15; }
.snag-report-prepared { margin:2mm 0 3mm; color:var(--sr-muted); font-size:9px; }
.snag-report-details { grid-template-columns:repeat(4,minmax(0,1fr)); padding:12px; border:1px solid var(--sr-line); background:var(--sr-soft); }
.snag-report-description { white-space:pre-wrap; }
.snag-report-description-section { margin:0; }
.snag-report-description-section h2 { margin-top:0; }
.snag-report-work-description { margin-top:4mm; }
.snag-report-work-description.is-continuation { margin-top:0; }
.snag-report-work-instruction { margin-bottom:4mm; }
.snag-report-work-instruction .snag-report-record-title { margin-bottom:3mm; }
.snag-report-work-instruction .snag-report-details { grid-template-columns:repeat(5,minmax(0,1fr)); padding:8px 10px; }
.snag-report-sheet img { display:block; width:100%; object-fit:contain; border:1px solid var(--sr-line); }
.snag-report-sheet figure { margin:5mm 0; break-inside:avoid; }
.snag-report-sheet h3 { margin:0 0 2mm; font-size:11px; text-transform:uppercase; letter-spacing:.06em; }
.snag-report-sheet figcaption { margin-top:1.5mm; color:var(--sr-muted); font-size:9.5px; }
.snag-report-locator img { height:54mm; }
.snag-report-detail img { height:105mm; }
.snag-report-document[data-snag-report-type="record"] .snag-report-sheet figure { margin:3mm 0; }
.snag-report-document[data-snag-report-type="record"] .snag-report-locator img { height:48mm; }
.snag-report-document[data-snag-report-type="record"] .snag-report-detail img { height:118mm; }
.snag-report-drawing-stack { break-inside:avoid; page-break-inside:avoid; }
.snag-report-work-evidence { margin-top:4mm; }
.snag-report-work-evidence figure { display:inline-block; width:48%; margin:2mm 1% 2mm 0; vertical-align:top; break-inside:avoid; }
.snag-report-work-evidence img, .snag-report-work-evidence svg { display:block; width:100%; height:42mm; object-fit:contain; }
.snag-report-continuation h2 { margin:0 0 4mm; }
.snag-report-history ol { list-style:none; padding:0; margin:8px 0; }
.snag-report-history li { padding:9px 0 9px 11px; border-inline-start:3px solid var(--sr-line); break-inside:avoid; }
.snag-report-history li.tone-issue { border-inline-start-color:#b42323; }
.snag-report-history li.tone-information { border-inline-start-color:#3479df; }
.snag-report-history li.tone-passed { border-inline-start-color:#709929; }
.snag-report-history li.has-evidence { break-inside:auto; page-break-inside:auto; }
.snag-report-event-line { display:flex; justify-content:space-between; gap:12px; }
.snag-report-event-line span { color:var(--sr-muted); font-size:10px; }
.snag-report-history li p { margin:4px 0 0; }
.snag-report-history li.has-evidence > figure { display:inline-block; width:48%; margin:3mm 1% 1mm 0; vertical-align:top; }
.snag-report-audit { margin-top:5mm; }
.snag-report-history figure { break-inside:avoid; }.snag-report-history img { max-width:100%; max-height:105mm; object-fit:contain; }
.snag-report-history li.has-evidence img,
.snag-report-history li.has-evidence svg { display:block; width:auto !important; max-width:100%; height:82mm; object-fit:contain; }
.snag-report-sheet h2 { margin-top:0; }
.snag-report-foot { margin-top:22px; padding-top:7px; border-top:1px solid var(--sr-line); color:var(--sr-muted); font-size:9px; }
.snag-report-empty { padding:22px; border:1px dashed var(--line2); color:var(--muted); text-align:center; }
.standalone-snag-report { margin:0; padding:14mm; background:#fff; }
.snag-report-option {
  box-sizing:border-box; min-height:40px; padding:0 10px;
  border:1px solid var(--line2); border-radius:8px; background:var(--card2);
  color:var(--ink); font-weight:600;
}
@media (max-width:700px) {
  .snag-report-headline dl, .snag-report-details, .snag-report-status-grid { grid-template-columns:1fr; }
  .snag-report-status-measures { grid-template-columns:repeat(2,minmax(0,1fr)); }
  .snag-report-document { overflow-x:auto; }
  .snag-report-document table { min-width:680px; }
  .snag-report-work-instruction .snag-report-details { grid-template-columns:1fr 1fr; }
  .snag-selection-bar > button { flex:1 1 auto; }
}
.drawing-measure.snag-status-measure {
  background:linear-gradient(180deg,
    color-mix(in srgb,var(--snag-status-colour) 11%,var(--card)),
    var(--card) 76%);
  box-shadow:inset 0 3px 0 var(--snag-status-colour);
}
.snag-status-measure.tone-issue { --snag-status-colour:var(--snag-ink-issue); }
.snag-status-measure.tone-information { --snag-status-colour:var(--snag-ink-information); }
.snag-status-measure.tone-passed { --snag-status-colour:var(--snag-ink-passed); }
.drawing-context-error {
  grid-column:1 / -1; margin:0; padding:10px 18px; border-top:1px solid var(--line);
  color:var(--chip-warn-ink); font-size:12.5px;
}
.drawing-kind-panel { min-width:0; }
.drawing-list, .snag-drawings-list, .precom-drawing-grid {
  display:grid; grid-template-columns:repeat(auto-fill,minmax(min(100%,240px),1fr)); gap:14px;
}
.drawing-tools { display:flex; justify-content:space-between; align-items:center; gap:12px;
  flex-wrap:wrap; margin:0 0 14px; color:var(--ink2); font-size:12.5px; }
.drawing-tools .seg { display:flex; gap:3px; }
/* The snag action line names several statuses at once, so it wraps rather
   than squeezing the filters. The drawing count is a separate, quieter line:
   a drawing total and a snag total are different things and must never read
   as one running sentence. */
.drawing-tools .drawing-totals { min-width:0; }
.drawing-totals-scope { display:block; color:var(--muted); font-size:11.5px; }
.drawing-tools .seg button { padding:5px 10px; }
.drawing-tool-controls { display:flex; align-items:center; gap:8px; flex-wrap:wrap; max-width:100%; }
/* Five status filters are wider than a phone. The row scrolls sideways
   inside the screen instead of pushing the page wider (051). */
.drawing-tool-controls .seg { max-width:100%; overflow-x:auto; scrollbar-width:none; }
.drawing-tool-controls .seg::-webkit-scrollbar { display:none; }
.drawing-select-all {
  display:inline-flex; align-items:center; gap:6px; min-height:36px; padding:0 6px;
  color:var(--ink2); cursor:pointer; white-space:nowrap;
}
.drawing-select-all input, .drawing-card-select input {
  width:18px; height:18px; margin:0; accent-color:var(--accent); cursor:pointer;
}
/* The sentence that tells a full pack from a selected one. It sits on the page
   rather than in a tooltip, which a touch screen cannot reach at all - but it
   belongs to the button, so it lines up under it and stops at its width rather
   than running off across the header. */
.drawing-zip-scope {
  /* flex:0 0 100% and not flex-basis alone: a max-width would let it share the
     line with the buttons and shove the main action leftwards. It keeps its
     own line and hangs off the right edge, under the button it describes. */
  flex:0 0 100%;
  color:var(--muted); font-size:11.5px; line-height:1.35; text-align:right;
}
.drawing-download-selected { min-height:36px; }
.drawing-download-selected:not(:disabled) {
  border-color:var(--accent); background:var(--accent); color:var(--btn-ink);
}
.drawing-download-selected:disabled { opacity:.45; cursor:not-allowed; }
.drawing-heading { align-items:center; gap:18px; }
.drawing-heading > div { min-width:0; }
.drawing-heading .eyebrow { margin:0 0 3px; }
.drawing-heading h2 { font-size:14.5px; }

/* Contextual help link beside the drawings panel heading. */
.help-link {
  display:inline-flex; align-items:center; gap:6px; margin-top:9px;
  font-size:12.5px; color:var(--ink2); text-decoration:none;
  border-bottom:1px solid var(--line2); padding-bottom:2px; min-height:24px;
}
.help-link svg { flex-shrink:0; }
fieldset .help-link { margin:2px 0 10px; }
.help-link:hover { color:var(--ink); border-bottom-color:currentColor; }
.drawing-key-link { flex:0 0 auto; margin:0; border-bottom:0; }
.drawing-row, .snag-drawing-card {
  position:relative; min-width:0; overflow:hidden; border:1px solid var(--line); border-radius:9px;
  background:var(--card); transition:border-color .16s, transform .16s, box-shadow .16s;
}
.drawing-row:hover, .snag-drawing-card:hover {
  border-color:var(--line2); transform:translateY(-1px); box-shadow:var(--shadow);
}
.drawing-row.selected, .snag-drawing-card.selected {
  background:var(--sel-bg); border-color:var(--accent);
  box-shadow:0 0 0 1px var(--accent);
}
.drawing-card-open {
  position:absolute; z-index:2; inset:0; width:100%; min-height:0; padding:0;
  border:0; border-radius:9px; background:transparent; cursor:pointer;
}
.drawing-card-open:hover, .drawing-card-open:active, .drawing-card-open:focus {
  border:0; background:transparent;
}
.drawing-card-open:focus-visible { outline:2px solid var(--accent); outline-offset:-3px; }
/* The snag chip has to sit ABOVE the card's full-size open overlay, or the
   overlay swallows the click and the chip looks broken. Same reason the
   select checkbox carries z-index:3. */
.drawing-snag-chip {
  position:relative; z-index:3; min-height:0; padding:3px 9px;
  border:0; font: inherit; cursor:pointer;
}
.drawing-snag-chip:hover { filter:brightness(1.08); }
.drawing-card-select {
  position:absolute; z-index:3; top:9px; left:9px; display:grid; width:34px; height:34px;
  place-items:center; border:1px solid var(--line2); border-radius:7px;
  background:color-mix(in srgb,var(--card) 92%,transparent); box-shadow:var(--shadow);
}
.drawing-thumb {
  position:relative; display:grid; width:100%; aspect-ratio:4 / 3; min-height:0;
  place-items:center; overflow:hidden; padding:0; border:0; border-bottom:1px solid var(--line);
  border-radius:0; background:var(--card2); color:var(--muted);
}
.drawing-thumb-placeholder { display:grid; width:100%; height:100%; place-items:center; }
.drawing-thumb-placeholder svg { width:82%; height:82%; stroke:var(--line2); stroke-width:1.2; }
.drawing-thumb-placeholder svg circle { fill:var(--data); stroke:none; }
.drawing-thumbnail { width:100%; height:100%; object-fit:contain; background:#fff; }
.drawing-thumb-state {
  position:absolute; right:8px; bottom:8px; padding:3px 7px; border-radius:12px;
  background:color-mix(in srgb,var(--card) 88%,transparent); color:var(--ink2); font-size:10.5px;
}
.drawing-thumb-unavailable { cursor:default; opacity:.72; }
.drawing-card-body { display:grid; gap:9px; padding:11px 13px 12px; }
.drawing-card-title { display:flex; align-items:flex-start; justify-content:space-between; gap:8px; }
.drawing-row-name { min-width:0; }
.drawing-row-name b, .drawing-row-name small { display:block; overflow-wrap:anywhere; }
.drawing-row-name small { margin-top:2px; }
.drawing-row-name small, .drawing-meta { color:var(--muted); font-size:11.5px; }
.drawing-completion { display:grid; grid-template-columns:minmax(60px,1fr) auto; align-items:center; gap:8px; }
.drawing-completion .track { height:6px; overflow:hidden; border-radius:4px; background:var(--data-track); }
.drawing-completion .fill { display:block; height:100%; border-radius:4px; }
.drawing-completion b { font-size:12px; font-variant-numeric:tabular-nums; }
.drawing-card-chips { display:flex; align-items:center; gap:6px; min-height:22px; flex-wrap:wrap; }
.drawing-card-chips small { color:var(--muted); font-size:11.5px; }
.drawing-findings { min-height:34px; margin:0; color:var(--muted); font-size:11.5px; line-height:1.45; }
.drawing-failure { color:var(--fail); font-size:12px; overflow-wrap:anywhere; }
.drawing-row-actions { flex-wrap:nowrap; }
.drawing-row-actions .ghost-btn { min-height:34px; padding:5px 9px; font-size:12px; }
@media (prefers-reduced-motion:reduce) {
  .drawing-row, .snag-drawing-card { transition:none; }
}
.drawing-review { margin:10px 0 0; padding:9px 11px; border-left:3px solid var(--chip-warn-ink);
  background:var(--chip-warn-bg); color:var(--ink2); }
.floor-separator { color:var(--muted); }
.drawing-row-actions, .drawing-package-actions, .drawing-viewer-actions {
  display:flex; align-items:center; gap:8px; flex-wrap:wrap;
}
.drawing-package-actions { justify-content:flex-end; margin:0; }
.drawing-page-actions .drawing-package-actions > button {
  min-height:38px; padding:7px 13px; border:1px solid var(--line2); border-radius:8px;
  background:var(--card); color:var(--ink); font:inherit; font-size:12.5px; font-weight:650;
  cursor:pointer;
}
/* The tab's own pack is the main action, so it wears the accent and it sits at
   the right-hand end of the row, where the eye and the hand come back to. The
   row is right-aligned, so ordering the combined pack before it keeps that
   edge still whether or not the combined pack is on offer. */
.drawing-page-actions .drawing-package-actions > button { order:1; }
.drawing-page-actions .drawing-package-actions > #drawing-zip-both,
.drawing-page-actions .drawing-package-actions > #drawing-zip-cancel { order:0; }
/* The buttons keep the first line to themselves. The option and the two notes
   are full-width, so without an order of their own they take that line and
   push the buttons below it - and the main action then moved down the page
   every time a tab hid one of them. */
.drawing-package-actions > :is(.drawing-download-option, .count-note) { order:2; }
.drawing-page-actions .drawing-package-actions > :is(#drawing-zip, #emergency-zip, #snag-zip) {
  border-color:var(--accent); background:var(--accent); color:var(--btn-ink);
}
.drawing-download-option {
  display:flex; align-items:center; justify-content:flex-end; gap:9px;
  flex-basis:100%; min-height:44px; color:var(--ink2); cursor:pointer;
}
.drawing-download-option > span { display:grid; gap:1px; text-align:left; line-height:1.25; }
.drawing-download-option b { color:var(--ink); font-size:12.5px; font-weight:600; }
.drawing-download-option small { color:var(--muted); font-size:11.5px; }
.drawing-package-actions .marker-visibility-control,
.drawing-package-actions .count-note { flex-basis:100%; justify-content:flex-end; }
/* Filled green makes a file. An outline button takes you somewhere: the
   Work sheets shortcut and "Open in a new tab" sit together on the left, the
   downloads together on the right. */
.drawing-viewer-actions > button:not(.ghost-btn) {
  background:var(--accent); color:var(--btn-ink); border:none; border-radius:8px;
  padding:8px 16px; font:inherit; font-weight:650; cursor:pointer;
}
.drawing-viewer-actions > .ghost-btn { font-weight:600; }
.drawing-viewer-actions > #drawing-viewer-new { margin-right:auto; }
.drawing-package-actions button:disabled { opacity:.6; cursor:not-allowed; }
.drawing-viewer-dlg {
  box-sizing:border-box; width:100dvw; max-width:none; height:100dvh; max-height:none;
  margin:0; padding:max(14px,env(safe-area-inset-top)) max(28px,env(safe-area-inset-right))
    max(14px,env(safe-area-inset-bottom)) max(14px,env(safe-area-inset-left));
  border:0; border-radius:0; overflow:hidden;
  grid-template-columns:minmax(0,1fr);
  grid-template-rows:auto auto minmax(0,1fr) auto; gap:6px;
  /* Lists and the toolbar sheet still scroll, but two fingers anywhere in the
     viewer never zoom the page behind it. Touch only. */
  touch-action:pan-x pan-y;
}
.drawing-viewer-dlg[open] { display:grid; }
.drawing-viewer-dlg > * { grid-column:1; }
.drawing-viewer-dlg button,
.drawing-viewer-dlg .drawing-viewer-actions a { box-sizing:border-box; min-width:44px; min-height:44px; }
/* "Open in a new tab" is a link, not a button. Without this its label sits on the
   text baseline while the 44px tap target grows below it, so it reads as
   off-centre beside the two download buttons. */
.drawing-viewer-dlg .drawing-viewer-actions a {
  display:inline-flex; align-items:center; justify-content:center; text-decoration:none;
}
/* A disabled download button must look disabled. Without this it keeps the full
   accent green, so a user clicks it and nothing happens. */
.drawing-viewer-actions > button:disabled {
  opacity:.45; cursor:not-allowed; filter:grayscale(.5);
}
.drawing-viewer-dlg .eyebrow,
.drawing-viewer-dlg .note { color:var(--ink2); }
/* Title, status and Close share one band. The status line used to have a row of
   its own, most of it empty, on every screen wider than a phone. */
.drawing-viewer-head { display:flex; justify-content:space-between; gap:16px; align-items:baseline; flex-wrap:wrap; }
.drawing-viewer-head > div:first-child, .drawing-viewer-title-group {
  flex:0 0 auto; display:flex; align-items:baseline; gap:10px;
}
/* "Progress drawing" and the floor name on one line, not stacked. */
.drawing-viewer-head .eyebrow { margin:0; white-space:nowrap; }
.drawing-viewer-head h2 { margin:0; white-space:nowrap; }
.drawing-viewer-head #drawing-viewer-message { flex:1 1 240px; margin:0; min-width:0; }
/* The two control bands sit side by side while there is width for them, and
   stack only when there is not. */
.drawing-toolbars {
  display:flex; flex-wrap:wrap; align-items:center; gap:6px 12px; padding:5px 7px;
  border:1px solid var(--line); border-radius:9px; background:var(--card2);
}
.drawing-toolbars > * { flex:0 0 auto; }
.drawing-viewer-head .eyebrow { margin:0 0 2px; }
.drawing-viewer-head h2 { margin:0; }
#drawing-viewer-frame {
  display:block; grid-row:3; width:100%; height:100%; min-height:0;
  border:1px solid var(--line2); border-radius:8px; background:#fff;
}
.drawing-mode-toolbar { display:flex; align-items:center; gap:4px; flex-wrap:nowrap; }
.drawing-mode-toolbar button { min-width:44px; min-height:44px; padding-inline:12px; }
/* The chosen view is a choice, so it wears the solid fill and the others stay
   plain (docs/design-rules.md, rule 1). A pale grey read as "unavailable". */
.drawing-mode-toolbar button.on {
  background:var(--accent); color:var(--btn-ink); border-color:var(--accent);
}
.drawing-mode-toolbar button:disabled { opacity:.42; cursor:not-allowed; }
.drawing-mode-toolbar label { font-size:12px; color:var(--ink2); white-space:nowrap; }
.drawing-mode-toolbar select { min-height:44px; max-width:220px; }
.drawing-target-toolbar {
  display:flex; align-items:center; justify-content:flex-start; flex-wrap:wrap; gap:7px;
  min-width:0; max-width:100%;
  margin:0 0 0 auto;
}
.drawing-snag-selection-tools {
  display:flex; flex-wrap:wrap; align-items:center; gap:7px; min-width:0; max-width:100%;
  padding-inline-start:10px; border-inline-start:1px solid var(--line2);
}
.drawing-snag-selection-tools > span { flex:1 1 150px; min-width:0; max-width:260px; overflow-wrap:anywhere; font-weight:650; }
.drawing-status-footer { display:none; grid-column:1 / -1; grid-row:4; min-width:0; }
.drawing-status-footer:has(> :not(:empty)) { display:flex; flex-wrap:wrap; gap:4px 16px; }
.drawing-status-footer > span { min-width:0; max-width:100%; white-space:normal; overflow-wrap:anywhere; }
.drawing-status-footer > span:empty { display:none; }
.drawing-target-toolbar span { color:var(--ink2); font-size:12px; }
.drawing-target-label { display:inline-flex; align-items:center; gap:6px; flex:0 0 auto; }
.drawing-target-label:empty { display:none; }
.marker-visibility-control {
  display:inline-flex; align-items:center; gap:6px; min-height:44px; padding:0 4px;
  color:var(--ink2); font-size:12px; white-space:nowrap; cursor:pointer;
}
.marker-visibility-control input { width:18px; height:18px; accent-color:var(--accent); }
.marker-visibility-control:has(input:disabled) { opacity:.45; cursor:not-allowed; }
#drawing-markers-status { color:var(--ink); font-weight:650; white-space:nowrap; }
.drawing-target-toolbar button { min-width:44px; min-height:44px; padding:6px 10px; }
.drawing-help-btn {
  display:inline-flex; align-items:center; justify-content:center;
  width:36px; min-width:36px; height:36px; min-height:36px; padding:0!important;
  background:transparent; color:var(--muted); border:1px solid transparent;
  border-radius:8px; text-decoration:none; cursor:pointer;
  transition:background 120ms ease, border-color 120ms ease, color 120ms ease;
}
.drawing-viewer-head > #drawing-legend-open {
  box-sizing:border-box; flex:0 0 44px; width:44px; min-width:44px;
  height:44px; min-height:44px; padding:0!important;
}
.drawing-help-btn:hover {
  background:var(--card2); color:var(--ink); border-color:var(--line2);
}
.drawing-help-btn:focus-visible {
  background:var(--card2); color:var(--ink); border-color:var(--accent);
  outline:2px solid color-mix(in srgb,var(--accent) 35%,transparent); outline-offset:2px;
}
.drawing-help-btn svg {
  width:20px; height:20px; fill:none; stroke:currentColor; stroke-width:1.6;
  stroke-linecap:round; stroke-linejoin:round;
}
.drawing-target-toolbar output {
  min-width:52px; color:var(--ink2); font-size:12px; text-align:center;
  font-variant-numeric:tabular-nums;
}
.drawing-target-stage {
  grid-row:3; width:100%; height:100%; min-height:0; overflow:auto;
  overflow-anchor:none;
  /* See-through: the grey is the window's (.drawing-stage-wrap), and the sheet
     picture is painted behind the stage into #drawing-target-canvas. */
  border:1px solid var(--line2); border-radius:8px; background:transparent;
  cursor:grab; user-select:none;
  /* A finger on the drawing belongs to the drawing: app.js pans it with one
     finger and zooms it with two. Left to the browser, a pinch zoomed the
     whole page and a drag both scrolled and dropped a mark. Touch only; a
     mouse is not affected. */
  touch-action:none;
}
.drawing-target-stage.is-panning { cursor:grabbing; }
/* Position reads must see the new value at once, including under the global
   reduced-motion rule, which sets a short nonzero transition duration. */
.drawing-target-page, .drawing-target-page * { transition:none !important; }
/* The sheet holds the marks only. It is the page's rectangle, so its shadow
   is the page's; the picture is painted into the window canvas under it. */
.drawing-target-page { position:relative; width:max-content; height:max-content; margin:12px 0;
  box-shadow:0 2px 14px rgba(0,0,0,.22); }
/* The previous drawing's line work sits over the current drawing, tinted pink.
   The current drawing keeps its full colour: nothing is faded, because the fill
   that was hiding everything is discarded rather than seen through. It is a
   window canvas beside the stage (037, visible area); app.js fits it to the
   stage's inside. Its z-index keeps it where it always was: over the sheet and
   its plain marks, under a selected or hovered mark. */
.drawing-underlay-canvas { position:absolute; left:0; top:0; z-index:1; }
.drawing-underlay-canvas { pointer-events:none; border-radius:7px; }
.drawing-underlay-canvas[hidden] { display:none; }
.drawing-target-page.previous-only #drawing-teal-layer,
.drawing-target-page.previous-only #drawing-target-layer,
.drawing-target-page.previous-only #drawing-snag-layer,
.drawing-target-page.previous-only #drawing-graphic-layer,
.drawing-target-page.previous-only #snag-mark-layer { display:none; }
.drawing-overlay-strength {
  display:inline-flex; align-items:center; gap:8px; min-height:44px;
  color:var(--ink2); font-size:12px; white-space:nowrap;
}
.drawing-overlay-strength[hidden] { display:none; }
.drawing-overlay-strength input {
  --ratio:0; --thumb:18px;
  width:132px; height:18px; margin:0; padding:0; cursor:pointer;
  -webkit-appearance:none; appearance:none; background:none;
}
.drawing-overlay-strength input::-webkit-slider-runnable-track {
  height:6px; border-radius:3px;
  background:linear-gradient(to right, #d6006e 0 calc(var(--ratio) * 100%),
    var(--line2) calc(var(--ratio) * 100%) 100%);
}
.drawing-overlay-strength input::-moz-range-track {
  height:6px; border-radius:3px;
  background:linear-gradient(to right, #d6006e 0 calc(var(--ratio) * 100%),
    var(--line2) calc(var(--ratio) * 100%) 100%);
}
.drawing-overlay-strength input::-webkit-slider-thumb {
  -webkit-appearance:none; appearance:none;
  width:var(--thumb); height:var(--thumb); margin-top:-6px;
  border:2px solid #fff; border-radius:50%; background:#d6006e;
  box-shadow:0 1px 3px rgba(0,0,0,.35);
}
.drawing-overlay-strength input::-moz-range-thumb {
  width:var(--thumb); height:var(--thumb); box-sizing:border-box;
  border:2px solid #fff; border-radius:50%; background:#d6006e;
  box-shadow:0 1px 3px rgba(0,0,0,.35);
}
.drawing-overlay-strength input:focus-visible { outline-offset:6px; }
.drawing-overlay-strength output { min-width:38px; font-variant-numeric:tabular-nums; }

/* Zoom floats on the drawing, bottom left. */
/* The window's grey is here, under the window canvas, so it stays when the
   current drawing is hidden. */
.drawing-stage-wrap { position:relative; grid-row:3; min-height:0; border-radius:8px; background:#e4e4e4; }
.drawing-stage-wrap[hidden] { display:none; }
.drawing-stage-wrap > .drawing-target-stage { width:100%; height:100%; }
/* The window onto the sheet (037, visible area): the size of the stage's
   inside, never scaled. app.js places it and paints the visible part of the
   one sheet picture into it; the page's own white is painted with it. It sits
   under the see-through stage, so the sheet's marks are always above it. */
#drawing-target-canvas { position:absolute; left:0; top:0; display:block; pointer-events:none; border-radius:7px; }
#drawing-target-canvas[hidden] { display:none; }
/* The sharp layer (sharp-sheet.js): the visible part of the sheet drawn from
   the PDF once zoom has settled. app.js sets its place and size inline, in
   page units through the sheet's scale. It is only looked at: taps go through. */
.sheet-sharp-layer { position:absolute; display:block; pointer-events:none; background:#fff; }
.drawing-target-page.previous-only .sheet-sharp-layer { display:none; }
#drawing-target-layer { position:absolute; inset:0; pointer-events:none; }
#drawing-target-layer[hidden] { display:none; }

/* Feature 007: teal new-work layer. Static, below the markers, above the page. */
#drawing-teal-layer { position:absolute; inset:0; pointer-events:none; }
#drawing-teal-layer[hidden] { display:none; }
.drawing-teal-highlight {
  position:absolute; box-sizing:border-box;
  background:rgba(0,167,157,.34); border:2px solid rgba(0,89,84,1);
  animation:none; transition:none;
}
.drawing-teal-highlight.luminaire { border-radius:50%; }
.drawing-teal-highlight.local-control { border-radius:6px; }
@media (forced-colors:active) {
  .drawing-teal-highlight { border-color:Highlight; background:transparent; }
}

/* Marker types are a drawing palette. The real marker shapes carry the first
   meaning; the short labels make the less familiar states unambiguous. */
.drawing-marker-types { position:relative; flex:0 1 auto; min-width:0; }
.drawing-marker-types > summary {
  cursor:pointer; min-height:44px; display:inline-flex; align-items:center; gap:7px;
  padding:0 12px; border:1px solid var(--line2); border-radius:8px;
  color:var(--ink); font-size:13px; font-weight:650; white-space:nowrap;
}
.drawing-marker-types > summary::-webkit-details-marker { display:none; }
.drawing-marker-types > summary::marker { content:""; }
.drawing-marker-types > summary > svg {
  width:18px; height:18px; fill:none; stroke:currentColor; stroke-width:1.6;
  stroke-linecap:round; stroke-linejoin:round;
}
.drawing-marker-types[open] > summary {
  background:var(--line); border-color:var(--line2);
}
.marker-selection-count {
  display:inline-flex; align-items:center; justify-content:center; min-width:20px; height:20px;
  padding:0 5px; border-radius:999px; background:var(--card); color:var(--ink2);
  font-size:11px; font-variant-numeric:tabular-nums;
}
.drawing-marker-types fieldset {
  position:absolute; z-index:12; top:calc(100% + 7px); left:0;
  box-sizing:border-box; width:420px; margin:0; padding:10px;
  border:1px solid var(--line2); border-radius:10px; background:var(--card,#fff);
  box-shadow:0 12px 32px rgba(0,0,0,.35);
  display:grid; grid-template-columns:repeat(2,minmax(0,1fr)); gap:6px;
}
.drawing-marker-types label {
  position:relative; display:flex; align-items:center; gap:9px; min-height:44px;
  padding:5px 30px 5px 8px; border:1px solid transparent; border-radius:8px;
  margin:0; font-size:12.5px; font-weight:600; letter-spacing:0; text-transform:none;
  color:var(--ink2); white-space:nowrap; cursor:pointer;
}
.drawing-marker-types label[hidden] { display:none; }
.drawing-marker-types label:hover { background:var(--card2); color:var(--ink); }
.drawing-marker-types label:has(input:checked) {
  background:color-mix(in srgb,var(--accent) 11%,var(--card2));
  border-color:color-mix(in srgb,var(--accent) 38%,var(--line2)); color:var(--ink);
}
.drawing-marker-types label::after {
  content:"✓"; position:absolute; right:10px; color:var(--accent); font-weight:800;
  opacity:0;
}
.drawing-marker-types label:has(input:checked)::after { opacity:1; }
.drawing-marker-types input {
  position:absolute; inset:0; width:100%; height:100%; margin:0; opacity:0;
  cursor:pointer;
}
.drawing-marker-types label:has(input:focus-visible) {
  outline:2px solid var(--accent); outline-offset:2px;
}
.marker-option-icon {
  display:grid; place-items:center; flex:0 0 26px; width:26px; height:26px;
  pointer-events:none;
}
.marker-option-icon.progress { color:#007f78; }
.marker-option-icon.fault { color:var(--fail); }
.marker-option-icon.resolved { color:#26843b; }
.marker-option-icon.retest { color:#246bb2; }
.marker-option-icon.structure { color:#7d5aa6; }
.marker-option-icon.readdressed { color:#8a6100; }
@media (max-width:700px) {
  #page-project-intelligence .intelligence-view-tabs { gap:16px; scrollbar-width:none; }
  #page-project-intelligence .intelligence-view-tabs::-webkit-scrollbar { display:none; }
  .drawing-marker-types { position:relative; }
  .drawing-marker-types fieldset {
    position:fixed; z-index:30; top:auto; left:8px; right:8px; bottom:72px;
    width:auto; max-height:55dvh; overflow:auto; grid-template-columns:1fr;
  }
}

/* The marker key, reachable from the toolbar instead of the foot of the list. */
.drawing-legend-dlg {
  box-sizing:border-box; width:min(520px,92vw); max-width:none; max-height:82vh;
  padding:16px 18px; border:1px solid var(--line2); border-radius:12px;
  background:var(--card,#fff); color:var(--ink); overflow:auto;
}
.drawing-legend-dlg::backdrop { background:rgba(0,0,0,.5); }
.drawing-legend-head { display:flex; align-items:center; justify-content:space-between; gap:16px; }
.drawing-legend-head h2 { margin:0; font-size:17px; }
.drawing-legend-dlg .drawing-marker-legend { margin-top:6px; border-top:0; padding-top:0; }
.legend-teal {
  display:inline-block; width:24px; height:24px; border-radius:50%; vertical-align:middle;
  background:rgba(0,167,157,.34); border:2px solid rgba(0,89,84,1);
}
.drawing-marker-legend .grouped dt, .drawing-marker-legend .teal dt { color:var(--ink); }

/* The change list uses a normal toolbar control. The old vertical edge tab was
   hard to discover and looked detached from the panel. */
.drawing-change-panel { position:relative; }
#drawing-change-body { flex:1 1 auto; min-height:0; overflow:auto; }
.drawing-panel-toggle {
  display:inline-flex; align-items:center; gap:7px; min-height:44px; padding:6px 10px;
  white-space:nowrap;
}
/* One icon at a time, chosen by the button's state. See setDrawingPanelCollapsed
   for why this is not done with the `hidden` attribute. */
.drawing-panel-toggle .drawing-panel-toggle-eye-off,
.drawing-panel-toggle.is-collapsed .drawing-panel-toggle-eye { display:none; }
.drawing-panel-toggle.is-collapsed .drawing-panel-toggle-eye-off { display:inline; }
.drawing-panel-toggle svg {
  width:18px; height:18px; fill:none;
  stroke:currentColor; stroke-width:1.5; stroke-linecap:round; stroke-linejoin:round;
}
.drawing-panel-toggle.on {
  background:var(--line); color:var(--ink); border-color:var(--line2);
}
@media (max-width:700px) {
  .drawing-panel-toggle-text { position:absolute; width:1px; height:1px; overflow:hidden; clip:rect(0 0 0 0); }
}

/* Changes fold by type, so the summary lines answer "what kinds are here" before
   any scrolling. */
.drawing-change-group { border-bottom:1px solid var(--line2); }
.drawing-change-group:last-of-type { border-bottom:0; }
.drawing-change-group > summary {
  display:flex; align-items:center; gap:8px; min-height:44px;
  cursor:pointer; color:var(--ink); font-size:13px;
}
.drawing-change-group > summary .count-note { margin-left:auto; }
.drawing-change-group > summary .marker-symbol { flex:0 0 auto; }
.drawing-change-group[open] > summary { border-bottom:1px solid var(--line2); }
.drawing-change-group > .snapshot-change-row { margin-top:8px; }

/* The card matching the marker on the drawing, so the two are read together. */
.snapshot-change-row.is-selected {
  background:var(--sel-bg); border-color:var(--accent);
  box-shadow:0 0 0 1px var(--accent);
}

/* Feature 007: New work chip on affected floor rows. */
.drawing-new-work { display:flex; align-items:center; gap:8px; flex-wrap:wrap; }
.drawing-new-work small { color:var(--ink2); }
.chip.new-work { background:rgba(0,167,157,.16); color:#00655f; border:1px solid rgba(0,167,157,.55); }
/* The marker you asked for, picked out without changing what its colour means.
   Static, like every other marker. */
/* The halo and the picked-out ring are drawn inside the marker, following its
   own outline. A CSS shadow is always a rounded rectangle, so it would have put
   a square glow around a triangle. */
.drawing-target-ring.is-selected { z-index:2; }
.drawing-target-ring {
  position:absolute; box-sizing:border-box; min-width:28px; min-height:28px;
  pointer-events:auto;
}
.marker-glyph {
  display:inline-flex; align-items:center; justify-content:center;
  min-width:1em; line-height:1; font-family:Arial,'Segoe UI Symbol',sans-serif;
  transform:translateY(-.04em);
}
/* Group headings show the same marker chip the rows and the drawing use. Without
   this the summary showed a bare character with no ring. */
/* The ring is now only a box that carries the colour. The shape itself is an
   SVG from marker-shapes.js, which the downloaded PDF draws from too, so the
   paper and the screen cannot drift apart. The old border and border-radius
   made every marker a circle, which is exactly what this change undoes. */
:where(.drawing-target-ring,.snapshot-change-row .marker-symbol,.legend-marker,
       .drawing-change-group > summary .marker-symbol) {
  box-sizing:border-box; display:grid; place-items:center;
  border:0; background:none; line-height:0;
}
.marker-shape { display:block; width:100%; height:100%; overflow:visible; }
/* The chosen marker draws a target ring outside itself. The ring must grow from
   the centre, or the marker slides off the fitting it points at. */
.marker-shape-picked {
  position:absolute; top:50%; left:50%; translate:-50% -50%;
  width:156%; height:156%;
}
.drawing-target-ring { position:absolute; }
:where(.drawing-target-ring,.snapshot-change-row .marker-symbol,.legend-marker,
       .drawing-change-group > summary .marker-symbol).progress { color:#007f78; }
:where(.drawing-target-ring,.snapshot-change-row .marker-symbol,.legend-marker,
       .drawing-change-group > summary .marker-symbol).fault { color:var(--fail); }
:where(.drawing-target-ring,.snapshot-change-row .marker-symbol,.legend-marker,
       .drawing-change-group > summary .marker-symbol).resolved { color:#26843b; }
:where(.drawing-target-ring,.snapshot-change-row .marker-symbol,.legend-marker,
       .drawing-change-group > summary .marker-symbol).retest { color:#246bb2; }
:where(.drawing-target-ring,.snapshot-change-row .marker-symbol,.legend-marker,
       .drawing-change-group > summary .marker-symbol).structure { color:#7d5aa6; }
:where(.drawing-target-ring,.snapshot-change-row .marker-symbol,.legend-marker,
       .drawing-change-group > summary .marker-symbol).readdressed { color:#8a6100; }
.drawing-change-panel {
  grid-row:3; z-index:3; justify-self:end; align-self:stretch; width:min(360px,42vw);
  display:flex; flex-direction:column; overflow:hidden;
  margin:10px; padding:12px; border:1px solid var(--line2); border-radius:10px;
  background:color-mix(in srgb,var(--card) 94%,transparent); box-shadow:var(--shadow);
}
.drawing-change-panel-head { padding:0 0 10px; border-bottom:1px solid var(--line2); }
.drawing-change-panel-head .eyebrow { margin:0 0 3px; }
.drawing-change-panel-head h3 { margin:0; font-size:14px; }
.drawing-change-panel-head + .note { margin-top:10px; }
.drawing-issue-summary h3 { margin:4px 0 8px; }
.drawing-issue-summary p { margin:0 0 8px; }
.drawing-issue-summary details { margin-top:12px; border-top:1px solid var(--line2); padding-top:10px; }
.drawing-issue-summary summary { cursor:pointer; color:var(--ink2); font-weight:650; }
.drawing-issue-summary details p { margin:8px 0 0; color:var(--ink2); }
.drawing-marker-legend { margin-top:14px; border-top:1px solid var(--line2); padding-top:10px; }
.drawing-marker-legend summary { cursor:pointer; color:var(--ink2); font-weight:650; }
.drawing-marker-legend dl { display:grid; gap:10px; margin:12px 0 0; }
.drawing-marker-legend dl > div { display:grid; gap:2px; }
.drawing-marker-legend dt { display:flex; align-items:center; gap:8px; font-weight:700; }
.drawing-marker-legend dd { margin:0 0 0 34px; color:var(--ink2); font-size:13px; }
.legend-marker { width:26px; height:26px; }
.drawing-marker-legend .progress { color:#007f78; }
.drawing-marker-legend .fault { color:var(--fail); }
.drawing-marker-legend .resolved { color:#26843b; }
.drawing-marker-legend .retest { color:#246bb2; }
.drawing-marker-legend .readdressed { color:#8a6100; }
.drawing-marker-legend .structure { color:#7d5aa6; }
.drawing-marker-legend dd { color:var(--ink2); }
.drawing-viewer-actions { grid-row:6; justify-content:flex-end; margin-top:2px; }
.drawing-viewer-actions a { text-decoration:none; }
@media (max-width:760px) {
  .drawing-page-heading { display:flex; }
  .drawing-page-actions { align-items:stretch; width:100%; max-width:none; }
  .drawing-snapshot-field { justify-content:space-between; }
  #drawing-request-picker { width:auto; max-width:70%; }
  .drawing-package-actions { justify-content:flex-start; }
  .drawing-download-option { justify-content:flex-start; }
  .drawing-package-actions .marker-visibility-control,
  .drawing-package-actions .count-note { justify-content:flex-start; }
  .drawing-tabs { overflow-x:auto; overflow-y:hidden; padding-inline:0; scrollbar-width:none; }
  .drawing-tabs::-webkit-scrollbar { display:none; }
  .drawing-tabs button { white-space:nowrap; }
  .drawing-summary { grid-template-columns:repeat(2,minmax(0,1fr)); }
  .drawing-heading { align-items:flex-start; }
  .drawing-key-link { max-width:150px; text-align:right; }
  .drawing-viewer-dlg { padding:max(8px,env(safe-area-inset-top)) max(8px,env(safe-area-inset-right)) max(8px,env(safe-area-inset-bottom)) max(8px,env(safe-area-inset-left)); }
  .drawing-viewer-head > div:first-child, .drawing-viewer-title-group { flex-wrap:wrap; }
  .drawing-toolbars { display:grid; grid-template-columns:minmax(0,1fr); align-items:start; }
  .drawing-mode-toolbar, .drawing-target-toolbar {
    width:100%; min-width:0; margin:0; flex-wrap:wrap; justify-content:flex-start;
  }
  .drawing-mode-toolbar select { flex:1 1 190px; max-width:none; }
  .drawing-change-panel { z-index:5; width:calc(100% - 20px); max-height:45%; align-self:end; }
}
@media (max-width:520px) {
  .drawing-summary { grid-template-columns:1fr; }
  .drawing-list, .snag-drawings-list, .precom-drawing-grid { grid-template-columns:1fr; }
  .drawing-row-actions { width:100%; }
  .drawing-row-actions .ghost-btn { flex:1; }
}
@media (max-width:640px) {
  .report { padding:22px 18px 20px; }
  .rep-bar-cell { width:30%; }
}

/* ── Administration: People / Organisations / Projects ─────────────────── */
.admin-tabs { display:flex; gap:6px; margin-bottom:16px; flex-wrap:wrap; }
.admin-tabs button {
  background:var(--card); border:1px solid var(--line); border-radius:9px;
  color:var(--ink2); font:inherit; font-size:13.5px; padding:7px 16px;
  cursor:pointer;
}
.admin-tabs button:hover { color:var(--ink); }
.admin-tabs button.on {
  background:var(--accent); border-color:var(--accent); color:var(--btn-ink);
  font-weight:650;
}
.people-group { margin-top:18px; }
.people-group .rep-subhead { margin:0 0 6px; text-transform:none;
  letter-spacing:.02em; font-size:12.5px; color:var(--ink2); }
.people-group .rep-subhead .chip { margin-left:6px; vertical-align:1px; }
.people-table td { white-space:nowrap; vertical-align:middle; }
.people-table select, .people-table input[type=text], .people-table .p-job {
  background:var(--card2); color:var(--ink); border:1px solid var(--line2);
  border-radius:7px; padding:5px 8px; font:inherit; font-size:12.5px;
  max-width:190px;
}
.people-table .p-job { width:170px; }
.people-projects { white-space:normal; max-width:230px; font-size:12px;
  color:var(--ink2); }
#org-table td { vertical-align:middle; }
@media (max-width:900px) {
  .people-table select, .people-table .p-job { max-width:130px; }
}

/* ── Print ─────────────────────────────────────────────────────────────────
   Only the report prints, and it prints as paper: a white sheet with black
   text, from Light, Dark or Delmatic alike.

   The light tokens below used to be declared on `:root` alone. That loses
   the cascade: `:root[data-theme="dark"]` is an attribute selector as well
   as a pseudo-class, so it is MORE specific than `:root`, and its dark
   values survived into print. A reader in Dark got a dark frame around a
   white report and was told to switch to Light first. Every screen-theme
   selector is therefore matched here, at equal specificity, and print
   comes last so it wins.

   The colour scheme needs !important, which nothing else in this file does.
   index.html sets `color-scheme` as an INLINE style on <html> before the
   stylesheet loads, so a dark reader never sees a white flash. An inline
   declaration beats every ordinary rule in a stylesheet, media query or
   not, so `color-scheme:light` here was simply ignored on paper. The page
   canvas is painted by the user agent from the colour scheme - the root's
   own white background box covers only its content, and everything outside
   it took the dark canvas. That is the dark frame: not a shell, not a
   border and not a token, but the sheet itself.

   It has to be beaten in the stylesheet rather than unset in the script,
   because a browser or a service worker may still be holding an older
   index.html with the old line in it.

   print-color-adjust keeps the bars and chips from dropping their fill. */
@media print {
  :root,
  :root[data-theme="light"],
  :root[data-theme="dark"],
  :root[data-theme="delmatic"] {
    color-scheme:light !important;
    --page:#ffffff; --card:#ffffff; --card2:#f4f4f4;
    --ink:#1f1f1f; --ink2:#454545; --muted:#6d6d6d;
    --line:#dcdcdc; --line2:#c4c4c4;
    --accent:#96d045; --accent-ink:#4e5d1d; --focus:#4e5d1d;
    --btn-ink:#263311;
    --data:#7fb232; --data-track:#e6eed6;
    --fail:#c23434;
    --progress-mid:#e3ad3d;
    --info:#2563c4;
    --chip-pass-bg:#eef6dd; --chip-pass-ink:#4a6118;
    --chip-fail-bg:#f9e7e5; --chip-fail-ink:#93292a;
    --chip-na-bg:#efefef; --chip-na-ink:#5d5d5d;
    --chip-warn-bg:#fdf0d2; --chip-warn-ink:#7a4f10;
    --chip-info-bg:#e6efff; --chip-info-ink:#1f4f9c;
    --shadow:none;
    /* The rail is not printed at all, but its tokens are inherited by
       anything that borrowed one, so they go light here too. */
    --rail-bg:#ffffff; --rail-ink:#1f1f1f; --rail-ink2:#5d5d5d;
    --rail-line:#dcdcdc; --rail-edge:#c4c4c4;
    --rail-hover-bg:#f4f4f4; --rail-hover-ink:#1f1f1f;
    --rail-sel-bg:#eef6dd; --rail-sel-ink:#243206; --rail-mark:#4e5d1d;
    --rail-count-bg:#efefef; --rail-count-ink:#454545;
    --rail-brand-ink:#1f1f1f; --rail-brand-sub:#5d5d5d; --rail-brand-iq:#4e5d1d;
  }
  * { -webkit-print-color-adjust:exact !important; print-color-adjust:exact !important; }
  /* The screen shell is a frame around the document. On paper there is no
     frame: the page itself is the white, and nothing between it and the
     report may contribute a ground, an edge, a corner, a shadow or a height
     that the sheet would then have to carry. */
  html, body {
    background:#fff !important; background-image:none !important;
    margin:0; padding:0; min-height:0; box-shadow:none;
  }
  #view-dash, .app-shell, .app-stage, main, .workspace-page,
  .report-workspace, .report-preview-well, .report {
    background:transparent !important; background-image:none !important;
    border:0 !important; border-radius:0 !important; box-shadow:none !important;
    outline:0 !important; min-height:0 !important;
  }
  header.top, nav.tabs, .app-rail, .environment-banner, .no-print, #tip, #foot,
  #page-dash, #page-test, #page-snapshot, #page-admin, #view-login { display:none !important; }
  /* The shell is a screen device. On paper it must not reserve the rail's
     column, or every printed page would carry a charcoal band down the
     left and a narrowed document beside it - print-color-adjust:exact
     above means that band would really be inked. */
  .app-shell { display:block !important; min-height:0; }
  .app-stage, #page-report { display:block !important; min-height:0; }
  body.printing-engineering #page-report { display:none !important; }
  body.printing-engineering #page-engineering { display:block !important; }
  body.printing-engineering #page-engineering > :not(#engineering-report-doc) { display:none !important; }
  body.printing-engineering #engineering-report-doc { display:block !important; }
  body.printing-completion #page-report { display:none !important; }
  body.printing-completion #page-closeout { display:block !important; }
  body.printing-completion #page-closeout > :not(.closeout-layout),
  body.printing-completion .closeout-layout > :not(.completion-preview-well) { display:none !important; }
  body.printing-completion .closeout-layout,.completion-preview-well { display:block!important;margin:0;padding:0;overflow:visible; }
  body.printing-completion .completion-document { width:auto;min-height:0;padding:0;border:0;box-shadow:none; }
  body.printing-completion .completion-certificate { min-height:270mm; }
  body.printing-completion .completion-module-report { break-before:page; }
  body.printing-completion .completion-module-report:first-child { break-before:auto; }
  body.printing-completion .completion-module-report .completion-report-section { break-inside:auto; }
  body.printing-completion .completion-module-report thead { display:table-header-group; }
  body.printing-completion .completion-module-report tr { break-inside:avoid; }
  body.printing-completion .completion-module-report .completion-report-foot { display:none; }
  main { max-width:none; margin:0; padding:0; }
  .report-workspace, .report-preview-well {
    display:block; margin:0; padding:0; overflow:visible;
  }
  .report { width:auto; max-width:none; padding:0; }
  /* Deliberately NOT .rep-sec: keeping a whole section together pushes a
     tall one (the floor table) onto a fresh page and leaves half a page of
     white under the figures. Sections flow and fill the page; only the small
     units that look broken when split are held together. */
  .rep-head, .report-measure, .em-stat, .rep-rows .rw, tr { break-inside:avoid; }
  /* The module appendix can run to several pages, so its head repeats and the
     numeric columns stay narrow enough for the name to keep its width. */
  .rep-modules thead { display:table-header-group; }
  .emergency-failure-table thead { display:table-header-group; }
  .rep-sec.report-appendix { break-before:page; page-break-before:always; }
  .report-appendix tr { break-inside:avoid; page-break-inside:avoid; }
  .rep-modules th.num, .rep-modules td.num { width:9%; }
  .rep-modules td, .rep-modules th { padding:3px 5px; font-size:10.5px; }
  .rep-modules .rep-module-complete { width:22%; min-width:100px; }
  .rep-modules .module-progress { min-width:90px; gap:5px; }
  .rep-modules .module-progress .track { min-width:44px; }
  .rep-modules .module-complete-value { min-width:30px; font-size:9.5px; }
  .rep-modules .module-score { min-width:34px; padding:1px 4px; font-size:9.5px; }
  .rep-module-status { min-width:54px; padding:1px 5px; font-size:9px; }
  .rep-sec h2, .rep-subhead, .rep-headline { break-after:avoid; }
  .rep-sec { break-before:auto; }
  thead { break-after:avoid; }
  .report-measures { grid-template-columns:repeat(4,1fr); gap:8px; }
  .report-measure { padding:10px 12px; border:1px solid var(--line); box-shadow:none; }
  .report-measure .v { font-size:22px; }
  .report-measure .v small { font-size:13px; }
  .report-measure .s { font-size:10.5px; }
  .card { box-shadow:none; }
  thead { display:table-header-group; }
  .scroll-y { max-height:none; overflow:visible; }
  a { text-decoration:none; color:var(--ink); }
  .engineering-report-body { min-height:0; }
  .engineering-report-group { break-inside:auto; page-break-inside:auto; }
  .engineering-report-group h2 { break-after:avoid; page-break-after:avoid; }
  .engineering-report-group thead { display:table-header-group; }
  .engineering-report-group tr { break-inside:avoid; page-break-inside:avoid; }
  .engineering-report-document .snag-report-cover { break-after:page; page-break-after:always; }
  @page { size:A4; margin:14mm; }
}
/* Workflow redesign: accessible navigation, progressive disclosure and safe areas. */
.sr-only{position:absolute!important;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}
.skip-link{position:fixed;z-index:1000;left:12px;top:8px;transform:translateY(-160%);background:var(--card,#fff);color:var(--text,#111);padding:12px 16px;border-radius:8px}
.skip-link:focus{transform:none}
:where(button,a,input,select,textarea,summary):focus-visible{outline:3px solid var(--focus)!important;outline-offset:3px}
.bottom-nav{display:none}
.more-groups{display:grid;grid-template-columns:repeat(auto-fit,minmax(220px,1fr));gap:16px}.more-groups section{display:flex;flex-direction:column;align-items:stretch;gap:8px}.more-groups h2{font-size:13px;text-transform:uppercase;letter-spacing:.06em}.button-link{display:flex;align-items:center;justify-content:center;min-height:44px;border:1px solid currentColor;border-radius:8px;text-decoration:none}
/* A long destination ("People, Companies, Job roles and Projects") wraps
   inside its button instead of running out of it (051). */
.more-groups section > button { white-space:normal; text-align:center; }
/* Feature 035: a More group whose pages are all hidden for this viewer shows no heading, like the side panel. */
.more-groups section:not(.more-first):not(:has(button:not([hidden]),a:not([hidden]))){display:none}
.device-workflow-bar{display:flex;align-items:center;gap:10px;flex-wrap:wrap}.device-workflow-bar p{margin:0;margin-right:auto;font-size:13px}.device-workflow-bar [data-state="failed"],.status-warning{font-weight:700}.status-warning::first-letter{color:var(--fail,#b42318)}.status-ok{font-weight:600}.undo-action{min-height:44px}.summary-grid{display:grid;grid-template-columns:repeat(3,1fr);gap:12px}.summary-grid p{display:flex;flex-direction:column;margin:0;padding:16px;border:1px solid var(--line,#777);border-radius:10px}.summary-grid b{font-size:1.5rem}.summary-grid span{font-size:13px}
.needs-attention .section-heading{display:flex;justify-content:space-between;align-items:start;gap:16px}.needs-attention-list,#needs-attention-list{display:grid;gap:8px}#needs-attention-list button,.action-row{display:flex;justify-content:space-between;align-items:center;text-align:left;min-height:52px;width:100%;gap:12px}.action-row span:first-child{display:flex;flex-direction:column}.action-row small{font-size:13px}.action-row.urgent{border-inline-start:5px solid var(--fail,#b42318)}.action-row.attention{border-inline-start:5px solid #b7791f}.action-row.routine{border-inline-start:5px solid #3b82f6}.empty-state{padding:24px;text-align:center}
.closeout-checks{list-style:none;padding:0;display:grid;gap:8px}.closeout-checks li{display:grid;grid-template-columns:28px 1fr auto;align-items:center;min-height:52px;padding:8px 12px;border:1px solid var(--line,#777);border-radius:8px}.closeout-checks small{font-size:13px;text-transform:capitalize}.closeout-checks .incomplete,.closeout-checks .unavailable{border-inline-start:5px solid #b7791f}
.admin-tabs [role="tab"]{min-height:44px}
.closeout-layout{display:grid;grid-template-columns:minmax(260px,340px) minmax(0,1fr);gap:16px;align-items:start}.closeout-builder{display:grid;gap:12px}.completion-issue-fields{display:grid;gap:7px}.completion-issue-fields label{color:var(--muted);font-size:11px;font-weight:600;letter-spacing:.05em;text-transform:uppercase}.completion-issue-fields input{box-sizing:border-box;width:100%;min-height:40px;padding:7px 10px;border:1px solid var(--line2);border-radius:8px;background:var(--card2);color:var(--ink);font:inherit}.completion-options .check-label{display:grid;grid-template-columns:34px minmax(0,1fr) auto;align-items:center;gap:8px;min-height:44px;padding:7px 0;border-top:1px solid var(--line);cursor:pointer}.completion-options .check-label input{appearance:none;position:relative;width:30px;height:17px;margin:0;border:1px solid var(--line2);border-radius:999px;background:var(--card2)}.completion-options .check-label input::after{content:"";position:absolute;top:2px;left:2px;width:11px;height:11px;border-radius:50%;background:var(--muted);transition:transform .15s ease}.completion-options .check-label input:checked{border-color:var(--accent);background:var(--chip-pass-bg)}.completion-options .check-label input:checked::after{transform:translateX(13px);background:var(--accent)}.completion-nested{margin-left:42px}.completion-options .seg{display:flex}.completion-options .seg button{min-height:44px}.completion-preview-well{min-height:720px}#completion-preview{width:min(210mm,100%);margin:0 auto}.completion-document{box-sizing:border-box;min-height:275mm;padding:17mm 18mm 15mm;background:#fff;color:#20251d;border:1px solid #dfe3d8;box-shadow:var(--shadow);font:11pt/1.5 'Public Sans','Segoe UI',sans-serif}.completion-doc-head{border-bottom:2px solid #7fb232;padding-bottom:8mm}.completion-wordmark{color:#76a82a;font-size:21pt;font-weight:800;letter-spacing:.12em}.completion-doc-head>p{margin:2mm 0 0;color:#5f6757;font-size:9pt;letter-spacing:.12em;text-transform:uppercase}.completion-doc-head h1{margin:10mm 0 0;font-size:24pt;line-height:1.15}.completion-control{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:5mm 8mm;margin:9mm 0}.completion-control div{min-width:0}.completion-control dt,.completion-signoff span{color:#697160;font-size:8pt;font-weight:700;letter-spacing:.08em;text-transform:uppercase}.completion-control dd{margin:1mm 0 0;font-weight:650;overflow-wrap:anywhere}.completion-statement{display:flex;min-height:92mm;align-items:center;padding:12mm 8mm;border-block:1px solid #dfe3d8;font-size:16pt;line-height:1.55;text-align:center}.completion-signoff{display:grid;grid-template-columns:1fr 1fr;gap:18mm;margin-top:20mm}.completion-signoff div{border-top:1px solid #697160;padding-top:3mm}.completion-signoff span,.completion-signoff strong{display:block}.completion-intro{margin:0 0 9mm;padding:4mm;background:#f3f6ed;border-left:3px solid #7fb232}.completion-report-section{margin:0 0 8mm;break-inside:avoid}.completion-report-section h2{margin:0 0 3mm;padding-bottom:2mm;border-bottom:1px solid #dfe3d8;font-size:15px}.completion-report-section table{width:100%;border-collapse:collapse}.completion-report-section th,.completion-report-section td{padding:2.5mm 2mm;border-bottom:1px solid #e5e8e0;text-align:left}.completion-report-section th{background:#f3f6ed;color:#3f463b}.completion-report-section th:last-child,.completion-report-section td:last-child{text-align:right}.completion-unavailable{color:#62695b;font-style:italic}.completion-report-foot{margin-top:12mm;padding-top:3mm;border-top:1px solid #9ba390;color:#62695b;font-size:8.5pt}@media(max-width:900px){.closeout-layout{grid-template-columns:1fr}}@media(max-width:500px){.completion-control{grid-template-columns:1fr 1fr}.completion-nested{margin-left:20px}}
.completion-snag-selection,.completion-module-selection{display:grid;max-height:240px;overflow:auto;border:1px solid var(--line);border-radius:8px}.completion-snag-selection label,.completion-module-selection label{display:grid;grid-template-columns:22px 1fr;gap:8px;align-items:center;min-height:44px;padding:6px 8px;border-bottom:1px solid var(--line);cursor:pointer}.completion-snag-selection label:last-child,.completion-module-selection label:last-child{border-bottom:0}.completion-snag-selection input,.completion-module-selection input{width:18px;height:18px}.completion-snag-selection span,.completion-snag-selection small,.completion-module-selection span,.completion-module-selection small{display:block;min-width:0}.completion-snag-selection small,.completion-module-selection small{color:var(--muted);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.completion-snag-record{margin:6mm 0;padding:5mm;border:1px solid #dfe3d8;break-inside:avoid}.completion-snag-record header p{margin:0;color:#697160;font-size:8.5pt;font-weight:700;letter-spacing:.08em;text-transform:uppercase}.completion-snag-record h3{margin:1mm 0 3mm;font-size:13pt}.completion-snag-record dl{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:3mm}.completion-snag-record dt{color:#697160;font-size:8pt;font-weight:700;text-transform:uppercase}.completion-snag-record dd{margin:1mm 0 0}.completion-snag-description{white-space:pre-wrap}.completion-snag-crop{margin:4mm 0 0}.completion-snag-crop img{display:block;width:100%;max-height:115mm;object-fit:contain;border:1px solid #dfe3d8}.completion-snag-crop figcaption{margin-top:1.5mm;color:#62695b;font-size:8.5pt}.completion-module-facts{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:4mm}.completion-module-facts dt{color:#697160;font-size:8pt;font-weight:700;text-transform:uppercase}.completion-module-facts dd{margin:1mm 0 0;overflow-wrap:anywhere}.completion-module-report+.completion-module-report{margin-top:12px}
@media (max-width:700px){body{padding-bottom:calc(74px + env(safe-area-inset-bottom))}.desktop-nav{display:none!important}.app-rail{display:none}.app-shell,.app-shell.rail-collapsed{grid-template-columns:minmax(0,1fr)}header.top{min-height:58px;padding:0 12px}.mobile-brand{display:flex;font-size:16px;gap:8px}.mobile-brand .logo-mark{width:27px;height:27px}.rail-toggle{display:none}.project-context{margin-left:auto;max-width:calc(100vw - 145px)}.project-context-status{display:none}.top-right #report-btn,.top-right #signout{display:none}.bottom-nav{position:fixed;z-index:90;display:flex;inset:auto 0 0;justify-content:space-around;gap:2px;padding:6px 4px calc(6px + env(safe-area-inset-bottom));background:var(--card,#282828);border-top:1px solid var(--line,#777)}.bottom-nav button{display:flex;flex:1;min-width:44px;min-height:48px;padding:4px;flex-direction:column;align-items:center;justify-content:center;font-size:12px;border:0;background:none;border-radius:0}.bottom-nav button[hidden]{display:none}.bottom-nav button span{font-size:12px}.bottom-nav-ico{width:20px;height:20px}.bottom-nav button[aria-current="page"]{font-weight:800;text-decoration:underline;text-underline-offset:4px}.summary-grid{grid-template-columns:1fr}.needs-attention .section-heading{align-items:stretch;flex-direction:column}.admin-project-layout,.admin-invite-form{grid-template-columns:1fr!important}.admin-table-wrap table,.admin-table-wrap tbody,.admin-table-wrap tr,.admin-table-wrap td{display:block;width:100%}.admin-table-wrap th{position:absolute;clip:rect(0,0,0,0)}.admin-table-wrap tr{border:1px solid var(--line,#777);border-radius:8px;margin-block:8px;padding:8px}.admin-table-wrap td::before{content:attr(data-label);display:block;font-size:12px;font-weight:700}}
/* ── Workspace search on a narrow window ─────────────────────────────────
   The same element, a different shape. Closed it is a 40px target in the
   toolbar; open it takes the toolbar row and drops its results the full
   width beneath, because a 340px dropdown hung off a 40px button is
   unusable on a handset. Nothing is duplicated: one input, one listbox,
   one set of keyboard rules.

   980px, not 700px. Between those two widths the toolbar could not hold a
   field, the project name and the account controls at once, and it was the
   account controls — Reports and Sign out — that were pushed off the right
   edge of the window. A field nobody asked for must not take the controls
   everybody needs.

   The open panel is absolute against the toolbar, NOT a fixed full-screen
   sheet. header.top carries a backdrop-filter, and a filter makes an element
   the containing block for every fixed-position descendant — so a sheet
   asking for inset:0 was trapped inside a 57px toolbar and showed one line
   of results. Position fixed is not available under a filtered ancestor. */
@media (max-width:980px) {
  .workspace-search { flex:0 0 auto; min-width:0; margin-inline:0; }
  .workspace-search-open {
    display:grid; place-items:center; width:40px; min-width:40px; height:40px;
    padding:0; border:1px solid transparent; border-radius:8px;
    background:none; color:var(--ink2); cursor:pointer;
  }
  .workspace-search-open svg { width:19px; height:19px; }
  .workspace-search-open:hover { border-color:var(--line2); background:var(--card2); color:var(--ink); }
  .workspace-search .workspace-search-field { display:none; }

  .workspace-search[data-open="true"] { position:static; flex:1 1 auto; max-width:none; }
  .workspace-search[data-open="true"] .workspace-search-open { display:none; }
  .workspace-search[data-open="true"] .workspace-search-field {
    display:flex; min-height:44px; background:var(--card);
  }
  /* 16px, because anything smaller makes iOS zoom the page on focus. */
  .workspace-search[data-open="true"] input[type="search"] { height:42px; font-size:16px; }
  .workspace-search[data-open="true"] .workspace-search-close { width:34px; height:34px; }
  .workspace-search[data-open="true"] .workspace-search-panel {
    left:0; right:0; width:auto; max-width:none; max-height:min(70vh, 520px);
  }
  /* The project name gives up its room while a search is open, and takes it
     back the moment the panel closes. */
  header.top:has(.workspace-search[data-open="true"]) .mobile-brand,
  header.top:has(.workspace-search[data-open="true"]) .project-context { display:none; }
  .workspace-search-option { padding:11px 8px; min-height:52px; }
  .workspace-search-recent button { min-height:36px; }
}
/* The phone toolbar shows the brand as well, so the project name has to give
   the search trigger its room. */
@media (max-width:700px) {
  .project-context { max-width:calc(100vw - 190px); }
}
@media (prefers-reduced-motion:reduce){*,*::before,*::after{scroll-behavior:auto!important;animation-duration:.01ms!important;transition-duration:.01ms!important}}
@media (prefers-contrast:more){:where(button,input,select,textarea,.card){border-width:2px!important}.action-row{border-inline-start-width:7px}}

/* Applied Collector Snapshot changes. */
.snapshot-change-metrics { display:grid; grid-template-columns:repeat(auto-fit,minmax(125px,1fr)); gap:9px; margin:12px 0; }
.snapshot-change-metrics > div { display:flex; flex-direction:column; gap:3px; padding:12px; border:1px solid var(--line2); border-radius:9px; background:var(--card2); }
.snapshot-change-metrics b { font-size:1.45rem; font-variant-numeric:tabular-nums; }
.snapshot-change-metrics span { color:var(--ink2); font-size:12px; }
.snapshot-change-metrics .regression { border-inline-start:5px solid var(--fail); }
.snapshot-change-metrics .progress { border-inline-start:5px solid #007f78; }
.snapshot-change-locations { display:grid; gap:7px; margin:12px 0; }
.snapshot-change-location-list { display:flex; flex-wrap:wrap; gap:7px; }
.snapshot-change-location-list button { min-height:44px; }
.snapshot-change-list { display:grid; gap:7px; margin-top:10px; }
.snapshot-change-row { display:grid; grid-template-columns:auto minmax(0,1fr) auto; align-items:center; gap:10px; min-height:52px; padding:8px 10px; border:1px solid var(--line2); border-radius:8px; background:var(--card2); }
.snapshot-change-row .marker-symbol { width:28px; height:28px; }
.snapshot-change-row.regression { border-inline-start:5px solid var(--fail); }
.snapshot-change-row.progress { border-inline-start:5px solid #007f78; }
.snapshot-change-row.resolved { border-inline-start:5px solid #26843b; }
.snapshot-change-row.retest,.snapshot-change-row.unchanged_activity { border-inline-start:5px solid #246bb2; }
.snapshot-change-row small { display:block; color:var(--muted); margin-top:2px; }
#snapshot-comparison-label { display:grid; gap:4px; min-width:min(320px,100%); font-size:12px; color:var(--ink2); }
#snapshot-comparison { min-height:44px; }
.snapshot-change-filters { display:grid; grid-template-columns:repeat(auto-fit,minmax(150px,1fr)); gap:9px; margin:14px 0; padding:12px; border:1px solid var(--line2); border-radius:9px; }
.snapshot-change-filters label { display:grid; gap:4px; color:var(--ink2); font-size:12px; }
.snapshot-change-filters select { min-height:44px; min-width:0; }
.snapshot-filter-actions { display:flex; align-items:flex-end; gap:7px; }
.snapshot-filter-actions button { min-height:44px; }
.snapshot-change-paging { display:flex; justify-content:center; align-items:center; gap:10px; margin-top:12px; }
.snapshot-change-paging button { min-width:88px; min-height:44px; }
.snapshot-change-paging output { min-width:150px; text-align:center; color:var(--ink2); font-size:12px; }
@media(max-width:620px){.snapshot-change-row{grid-template-columns:auto minmax(0,1fr)}.snapshot-change-row button{grid-column:1/-1;width:100%}}

/* Project Intelligence uses the same cards and controls as the main tracker. */
#page-project-intelligence .section-heading,
#intelligence-overview .section-heading {
  display:flex; align-items:flex-start; justify-content:space-between; gap:16px;
}
#page-project-intelligence .eyebrow,
#page-project-intelligence .note { color:var(--ink2); }
.intelligence-metrics {
  display:grid; grid-template-columns:repeat(auto-fit,minmax(170px,1fr)); gap:12px;
}
.intelligence-metrics > div {
  display:flex; flex-direction:column; gap:4px; min-height:82px; padding:14px;
  border:1px solid var(--line2); border-radius:10px; background:var(--card2);
}
.intelligence-metrics span { color:var(--ink2); font-size:12px; }
.intelligence-metrics b { font-size:1.35rem; font-variant-numeric:tabular-nums; }
.intelligence-highlights, .journal-list { display:grid; gap:10px; margin-top:14px; }
.intelligence-highlight {
  display:flex; align-items:center; justify-content:space-between; gap:14px;
  border:1px solid var(--line2); border-inline-start:5px solid var(--data);
  border-radius:9px; padding:12px 14px;
}
.intelligence-highlight.urgent { border-inline-start-color:var(--fail); }
.intelligence-highlight.attention { border-inline-start-color:#9a681c; }
.intelligence-highlight p { margin:4px 0 0; overflow-wrap:anywhere; }
#intelligence-freshness[data-state="failed_latest"],
#intelligence-freshness[data-state="partial"],
#intelligence-freshness[data-state="stale"] { background:var(--chip-warn-bg); color:var(--chip-warn-ink); }
#intelligence-freshness[data-state="current"] { background:var(--chip-pass-bg); color:var(--chip-pass-ink); }
.evidence-identity { display:grid; grid-template-columns:max-content 1fr; gap:6px 14px; }
.evidence-identity dt { font-weight:700; }
.evidence-identity dd { margin:0; overflow-wrap:anywhere; }
.journal-filters input[type="search"] { flex:1; min-width:min(240px,100%); }
.journal-entry { border:1px solid var(--line2); border-radius:10px; padding:14px; overflow-wrap:anywhere; }
.journal-entry.system { border-inline-start:5px solid var(--data); background:var(--card2); }
.journal-entry > header { display:flex; justify-content:space-between; align-items:flex-start; gap:12px; }
.journal-entry h3 { margin:7px 0 0; }
.journal-entry time, .journal-entry small { color:var(--ink2); font-size:12px; }
.journal-entry footer, .journal-links { display:flex; flex-wrap:wrap; align-items:center; gap:12px; margin-top:12px; }
.journal-entry footer label { margin-right:auto; }
.journal-entry .danger { color:var(--fail); }
#journal-history-list { display:grid; gap:12px; max-height:55vh; overflow:auto; }
#journal-history-list article { border-bottom:1px solid var(--line); padding-bottom:10px; }
.project-update-print pre { white-space:pre-wrap; overflow-wrap:anywhere; font:11pt/1.45 system-ui,sans-serif; }

@media (max-width:700px) {
  #page-project-intelligence .section-heading,
  #intelligence-overview .section-heading,
  .journal-entry > header, .intelligence-highlight { flex-direction:column; align-items:stretch; }
  .journal-filters > * { width:100%; }
  .evidence-identity { grid-template-columns:1fr; }
  .evidence-identity dd { margin-bottom:8px; }
}

@media print {
  /* Strip everything back to the printable article, one level at a time.
     The workspace shell put two containers between #view-dash and the
     page, so a single child selector on #view-dash now hides the shell
     and the printout inside it. Each level is listed explicitly, which
     keeps the original intent: print this article and nothing else. */
  body.print-project-update #view-dash > :not(.app-shell),
  body.print-project-update .app-shell > :not(.app-stage),
  body.print-project-update .app-stage > :not(#page-project-intelligence),
  body.print-project-update #page-project-intelligence > :not(#project-update-print) { display:none!important; }
  body.print-project-update .app-shell,
  body.print-project-update .app-stage { display:block!important; }
  body.print-project-update #page-project-intelligence,
  body.print-project-update #project-update-print { display:block!important; }
  .journal-entry, .intelligence-highlight { break-inside:avoid; }
  .project-update-print { max-width:180mm; margin:0 auto; }
}

@media (prefers-contrast:more) {
  .intelligence-highlight, .journal-entry, .intelligence-metrics > div { border-width:2px; }
}

/* ── Remaining workspace pages: mockup alignment ───────────────────────── */
#page-project-intelligence .intelligence-head {
  display:flex; align-items:center; justify-content:space-between; gap:14px;
  padding-block:12px;
}
#page-project-intelligence .intelligence-head .toolbar { margin:0; flex:none; }
#page-project-intelligence #intelligence-content {
  display:grid; grid-template-columns:minmax(0,2fr) minmax(270px,1fr);
  gap:var(--workspace-gap);
}
#page-project-intelligence :is(.history-measures-panel, .history-change-detail-panel, .history-journal) {
  grid-column:1 / -1;
}
#page-project-intelligence .history-change-detail-panel > .section-heading { margin-bottom:14px; }
#page-project-intelligence .history-change-detail-panel .snapshot-change-filters { margin-top:0; }
#page-project-intelligence #intelligence-current {
  grid-template-columns:repeat(5,minmax(0,1fr)); gap:0;
  overflow:hidden; border:1px solid var(--line); border-radius:9px;
}
#page-project-intelligence #intelligence-current > div {
  min-height:110px; padding:14px 16px; border:0; border-radius:0;
  border-inline-start:1px solid var(--line); background:transparent;
}
#page-project-intelligence #intelligence-current > div:first-child { border-inline-start:0; }
#page-project-intelligence #intelligence-current > div.regression { box-shadow:inset 0 3px 0 var(--fail); }
#page-project-intelligence #intelligence-current > div.resolved { box-shadow:inset 0 3px 0 var(--pass); }
#page-project-intelligence #intelligence-current > div.progress { box-shadow:inset 0 3px 0 var(--accent); }
#page-project-intelligence #intelligence-current b {
  margin-top:4px; font:650 25px/1.15 'Archivo', sans-serif; letter-spacing:-.025em;
}
#page-project-intelligence #intelligence-current small {
  margin-top:auto; color:var(--muted); font-size:11.5px; line-height:1.35;
}
.history-view-hidden, .imports-view-hidden { display:none !important; }

#page-snapshot .snapshot-drop-zone {
  display:grid; grid-template-columns:minmax(0,1fr);
  gap:12px; justify-items:center; margin-top:0; padding:18px;
  border:1px dashed var(--line2); border-radius:9px; background:var(--card2);
  transition:border-color 120ms ease, background 120ms ease;
}
#page-snapshot .snapshot-drop-zone.drag-over {
  border-color:var(--accent); background:color-mix(in srgb,var(--accent) 9%,var(--card2));
}
#page-snapshot .snapshot-drop-copy {
  grid-column:1 / -1; padding:8px 8px 12px; text-align:center;
}
#page-snapshot .snapshot-drop-copy b { font:650 15px/1.3 'Archivo', sans-serif; }
#page-snapshot .snapshot-drop-copy p {
  max-width:68ch; margin:5px auto 0; color:var(--muted); font-size:12.5px;
}
/* The project the backup goes into, said before anything is chosen. */
#page-snapshot .snapshot-target {
  margin:0 0 12px; padding:10px 14px; border-inline-start:3px solid var(--accent);
  background:var(--card2); color:var(--ink2); font-size:13.5px;
}
#page-snapshot .snapshot-target b { color:var(--ink); font-size:15px; }
#page-snapshot .snapshot-target span { display:block; margin-top:2px; color:var(--muted); font-size:12.5px; }
#page-snapshot .snapshot-steps {
  display:grid; grid-template-columns:repeat(3,minmax(0,1fr)); gap:10px;
  margin:0 0 14px; padding:0; list-style:none; counter-reset:step;
}
#page-snapshot .snapshot-steps li {
  counter-increment:step; display:grid; grid-template-columns:auto 1fr; gap:2px 10px;
  color:var(--muted); font-size:12.5px; line-height:1.4;
}
#page-snapshot .snapshot-steps li::before {
  content:counter(step); grid-row:span 2; display:grid; place-items:center;
  width:24px; height:24px; border-radius:50%; background:var(--card2);
  border:1px solid var(--line2); color:var(--ink); font-weight:700; font-size:12px;
}
#page-snapshot .snapshot-steps b { color:var(--ink); }
#page-snapshot .snapshot-pick { display:flex; flex-wrap:wrap; justify-content:center; gap:10px; }
#page-snapshot .snapshot-pick .ghost-btn,
#page-snapshot .snapshot-drop-zone.has-package #snapshot-pick-zip,
#page-snapshot .snapshot-drop-zone.has-package #precom-import-pick {
  background:var(--card); color:var(--ink); border:1px solid var(--line2); font-weight:600;
}
#page-snapshot .snapshot-package { justify-self:stretch; }
#page-snapshot .snapshot-package > .note { margin:8px 0 0; text-align:center; }
#page-snapshot .snapshot-package-checks {
  display:grid; gap:0; margin:0; padding:0; list-style:none;
  border:1px solid var(--line); border-radius:9px; background:var(--card); overflow:hidden;
}
#page-snapshot .snapshot-package-checks li {
  display:grid; grid-template-columns:22px 150px minmax(0,1fr); gap:10px; align-items:baseline;
  padding:10px 14px; border-top:1px solid var(--line); font-size:13px;
}
#page-snapshot .snapshot-package-checks li:first-child { border-top:0; }
#page-snapshot .snapshot-package-checks li::before {
  content:"\2713"; color:var(--data); font-weight:800; text-align:center;
}
#page-snapshot .snapshot-package-checks li.warn::before { content:"!"; color:var(--progress-mid); }
/* A pre-commissioning drawing that failed, or that is still waiting its turn. */
#page-snapshot .snapshot-package-checks li.fail::before { content:"\2715"; color:var(--chip-fail-ink); }
#page-snapshot .snapshot-package-checks li.wait::before { content:"\2022"; color:var(--muted); }
#page-snapshot .snapshot-package-checks li.fail span { color:var(--chip-fail-ink); }
#page-snapshot .snapshot-package-checks li span { color:var(--ink2); overflow-wrap:anywhere; }
#page-snapshot .snapshot-package-error {
  margin:0; padding:10px 14px; border-inline-start:3px solid var(--fail);
  background:var(--chip-fail-bg); color:var(--chip-fail-ink); font-size:13px;
}
#page-snapshot :is(#snapshot-upload, #precom-import-run) { justify-self:center; min-width:220px; }
/* The pre-commissioning import's status, above its list: a fact, so a thin
   line along the top and a soft fade, never a solid fill (design rules 1).
   Blue while it runs, green when every drawing went in, amber when one
   failed. The bar counts drawings. */
#page-snapshot .precom-import-status {
  --import-tone:var(--chip-info-ink, var(--info));
  justify-self:stretch; display:flex; flex-wrap:wrap; align-items:center; gap:8px 14px;
  padding:10px 14px; border:1px solid var(--line); border-top:3px solid var(--import-tone); border-radius:9px;
  background:linear-gradient(to bottom, color-mix(in srgb, var(--import-tone) 9%, var(--card)), var(--card));
}
#page-snapshot .precom-import-status.is-done { --import-tone:var(--chip-pass-ink); }
#page-snapshot .precom-import-status.is-partial { --import-tone:var(--chip-warn-ink); }
#precom-import-message { flex:1 1 220px; margin:0; font-weight:650; font-size:14px; color:var(--ink); }
#page-snapshot .precom-import-status.is-done #precom-import-message::before {
  content:"\2713"; margin-right:8px; color:var(--chip-pass-ink); font-weight:800;
}
#precom-import-bar { flex:1 1 100%; order:2; width:100%; height:8px; margin:0; accent-color:var(--chip-info-ink, var(--info)); }
/* The way on from the message: outlined, with an arrow, as a link from a fact
   is (design rules 1), not a solid main action. */
#page-snapshot #precom-import-open {
  display:inline-flex; align-items:center; gap:6px; min-height:40px;
  background:var(--card); color:var(--ink); border:1px solid var(--line2); font-weight:600;
}
#page-snapshot #precom-import-open:hover { background:var(--card2); }
#precom-import-open .chev { width:16px; height:16px; }
@media (max-width:700px) {
  #page-snapshot .snapshot-steps { grid-template-columns:1fr; }
  #page-snapshot .snapshot-package-checks li { grid-template-columns:22px minmax(0,1fr); }
  #page-snapshot .snapshot-package-checks li span { grid-column:2; }
  #page-snapshot .snapshot-pick > * { flex:1 1 100%; }
}

#page-snapshot .snapshot-summary-grid {
  grid-template-columns:repeat(5,minmax(120px,1fr)); gap:0;
  overflow:hidden; border:1px solid var(--line); border-radius:9px;
}
#page-snapshot .snapshot-summary-grid > div {
  min-height:92px; border:0; border-inline-start:1px solid var(--line);
  border-radius:0; background:transparent;
}
#page-snapshot .snapshot-summary-grid > div:first-child { border-inline-start:0; }

#page-admin .admin-heading { align-items:flex-start; }
#page-admin > .admin-tabs {
  display:flex; gap:28px; padding-top:0; overflow-x:auto;
}
#page-admin > .admin-tabs button { flex:0 0 auto; padding-inline:1px; }
#page-admin .admin-pane > .note { max-width:84ch; }
#page-admin #people-groups { margin-top:14px; }
#page-admin #admin-invite-form #invite-cancel {
  background:transparent; border:1px solid var(--line2); color:var(--ink2); font-weight:500;
}

#page-admin .admin-section-head {
  display:flex; align-items:flex-start; justify-content:space-between; gap:16px;
}
#page-admin .admin-section-head .eyebrow { margin:0 0 3px; }
#page-admin .admin-section-head h2 { margin:0; }
#page-admin .admin-help-btn { flex:0 0 36px; }
#page-admin .admin-form fieldset { position:relative; padding-top:16px; }
#page-admin .admin-form fieldset > legend { padding-right:38px; }
#page-admin .admin-fieldset-help { position:absolute; top:5px; right:8px; }
.admin-help-dialog { box-sizing:border-box; width:min(560px,92vw); }
.admin-help-dialog form { display:grid; gap:18px; }
.admin-help-body { color:var(--ink2); font-size:13px; line-height:1.55; }
.admin-help-body p { margin:0 0 10px; }
.admin-help-body p:last-child { margin-bottom:0; }

/* A switch represents one stored on/off state. Long rule lists keep standard
   checkboxes because the user is selecting items from a set. */
input.ui-switch,
#page-admin .admin-form fieldset input.ui-switch {
  appearance:none; -webkit-appearance:none; box-sizing:border-box;
  width:32px; min-width:32px; height:18px; min-height:18px; flex:0 0 32px;
  margin:0; padding:2px; border:1px solid var(--line2); border-radius:999px;
  background:var(--line2); cursor:pointer; vertical-align:middle;
  transition:background 130ms ease, border-color 130ms ease;
}
input.ui-switch::before {
  content:""; display:block; width:12px; height:12px; border-radius:50%;
  background:var(--ink); box-shadow:0 1px 2px rgba(0,0,0,.3);
  transition:transform 130ms ease;
}
input.ui-switch:checked,
#page-admin .admin-form fieldset input.ui-switch:checked {
  background:var(--accent); border-color:var(--accent);
}
input.ui-switch:checked::before { transform:translateX(14px); background:var(--btn-ink); }
input.ui-switch:focus-visible { outline:2px solid var(--accent); outline-offset:3px; }
input.ui-switch:disabled { opacity:.45; cursor:not-allowed; }

#page-admin .people-table {
  width:100%; min-width:940px; table-layout:fixed;
}
#page-admin .people-table th:nth-child(1) { width:22%; }
#page-admin .people-table th:nth-child(2) { width:14%; }
#page-admin .people-table th:nth-child(3) { width:15%; }
#page-admin .people-table th:nth-child(4) { width:16%; }
#page-admin .people-table th:nth-child(5) { width:8%; }
#page-admin .people-table th:nth-child(6) { width:17%; }
#page-admin .people-table th:nth-child(7) { width:8%; }
#page-admin .people-table :is(th,td) { box-sizing:border-box; vertical-align:middle; }
#page-admin .people-table :is(.p-org,.p-job) { width:100%; max-width:none; }
#page-admin .people-table td:nth-child(5),
#page-admin #admin-access-table td:nth-child(3),
#page-admin #admin-access-table td:nth-child(4) { text-align:center; }
.people-identity { display:flex; align-items:center; gap:9px; min-width:0; }
.people-identity > span:last-child { min-width:0; }
.people-identity b, .people-identity small { display:block; overflow:hidden; text-overflow:ellipsis; }
.people-avatar {
  display:inline-flex; align-items:center; justify-content:center; flex:0 0 26px;
  width:26px; height:26px; border-radius:50%; background:var(--card2);
  color:var(--ink2); font-size:10px; font-weight:750; letter-spacing:.03em;
}

.people-table .p-level, .role-chip {
  box-sizing:border-box; display:inline-flex; align-items:center; width:auto; max-width:100%;
  border:1px solid transparent; border-radius:999px; font-size:11.5px; font-weight:700;
}
.role-chip { min-height:24px; padding:3px 9px; }
#page-admin .people-table select.p-level {
  width:auto; min-height:34px; padding:5px 28px 5px 10px; border-radius:999px;
}
.role-engineer { background:color-mix(in srgb,#6fb72f 18%,var(--card2))!important; color:color-mix(in srgb,#6fb72f 40%,var(--ink))!important; border-color:color-mix(in srgb,#6fb72f 34%,transparent)!important; }
.role-manager { background:color-mix(in srgb,#3b82f6 18%,var(--card2))!important; color:color-mix(in srgb,#3b82f6 40%,var(--ink))!important; border-color:color-mix(in srgb,#3b82f6 34%,transparent)!important; }
.role-admin { background:color-mix(in srgb,#a78bfa 18%,var(--card2))!important; color:color-mix(in srgb,#a78bfa 40%,var(--ink))!important; border-color:color-mix(in srgb,#a78bfa 34%,transparent)!important; }
.role-client { background:var(--card2)!important; color:var(--ink2)!important; border-color:var(--line)!important; }
.people-table .p-level[data-role="engineer"] { background:color-mix(in srgb,#6fb72f 18%,var(--card2))!important; color:color-mix(in srgb,#6fb72f 40%,var(--ink))!important; border-color:color-mix(in srgb,#6fb72f 34%,transparent)!important; }
.people-table .p-level[data-role="manager"] { background:color-mix(in srgb,#3b82f6 18%,var(--card2))!important; color:color-mix(in srgb,#3b82f6 40%,var(--ink))!important; border-color:color-mix(in srgb,#3b82f6 34%,transparent)!important; }
.people-table .p-level[data-role="admin"] { background:color-mix(in srgb,#a78bfa 18%,var(--card2))!important; color:color-mix(in srgb,#a78bfa 40%,var(--ink))!important; border-color:color-mix(in srgb,#a78bfa 34%,transparent)!important; }
.people-table .p-level[data-role="client"] { background:var(--card2)!important; color:var(--ink2)!important; border-color:var(--line)!important; }
.people-table .p-level:disabled { opacity:.75; cursor:not-allowed; }

#page-admin #admin-access-table { width:100%; min-width:820px; table-layout:fixed; }
#page-admin #admin-access-table th:nth-child(1) { width:28%; }
#page-admin #admin-access-table th:nth-child(2) { width:18%; }
#page-admin #admin-access-table th:nth-child(3),
#page-admin #admin-access-table th:nth-child(4) { width:15%; text-align:center; }
#page-admin #admin-access-table th:nth-child(5) { width:14%; }
#page-admin #admin-access-table th:nth-child(6) { width:10%; }

@media (max-width:1000px) {
  #page-project-intelligence #intelligence-current { grid-template-columns:repeat(2,minmax(0,1fr)); }
  #page-project-intelligence #intelligence-current > div:nth-child(odd) { border-inline-start:0; }
  #page-project-intelligence #intelligence-content { grid-template-columns:1fr; }
  #page-project-intelligence :is(.history-measures-panel, .history-change-detail-panel, .history-journal) { grid-column:auto; }
  #page-snapshot .snapshot-drop-zone { grid-template-columns:1fr 1fr; }
  #page-snapshot .snapshot-drop-copy { grid-column:1 / -1; }
  #page-snapshot .snapshot-summary-grid { grid-template-columns:repeat(2,minmax(0,1fr)); }
}

@media (max-width:700px) {
  #page-project-intelligence .intelligence-head { align-items:stretch; flex-direction:column; }
  #page-project-intelligence .intelligence-head .toolbar { width:100%; }
  #page-project-intelligence #intelligence-current { grid-template-columns:1fr; }
  #page-project-intelligence #intelligence-current > div { border-inline-start:0; border-top:1px solid var(--line); }
  #page-project-intelligence #intelligence-current > div:first-child { border-top:0; }
  #page-snapshot .snapshot-drop-zone,
  #page-snapshot .snapshot-summary-grid { grid-template-columns:1fr; }
  #page-snapshot .snapshot-drop-zone > * { grid-column:1; }
  #page-snapshot .snapshot-summary-grid > div { border-inline-start:0; border-top:1px solid var(--line); }
  #page-snapshot .snapshot-summary-grid > div:first-child { border-top:0; }
  #page-admin > .admin-tabs { gap:20px; }
}

/* History is one chronological project record. Evidence and export tools are
   secondary, so they stay closed until the reader asks for them. */
#page-project-intelligence .intelligence-page-heading { border-bottom:0; }
#page-project-intelligence .intelligence-view-tabs {
  margin-top:10px; border-top:0; border-bottom:1px solid var(--line2);
}
#page-project-intelligence .intelligence-head {
  padding:0; border:0; background:transparent;
}
#page-project-intelligence .intelligence-head > .note { flex:1 1 280px; }
#page-project-intelligence .history-primary-filters {
  display:flex; align-items:end; justify-content:flex-end; gap:8px; margin:0;
}
#page-project-intelligence .history-primary-filters .filter-search {
  width:min(300px,32vw); min-width:190px;
}
#page-project-intelligence .history-primary-filters label:not(.filter-search) {
  display:grid; gap:3px; color:var(--ink2); font-size:11px;
}
#history-help { font-size:0; }
#history-help::before {
  content:"?"; display:grid; place-items:center; width:16px; height:16px;
  border:1px solid currentColor; border-radius:50%; font-size:11px; line-height:1;
}
.history-export-menu { position:relative; }
.history-export-menu > summary {
  display:flex; align-items:center; min-height:38px; list-style:none; user-select:none;
}
.history-export-menu > summary::-webkit-details-marker { display:none; }
.history-export-menu > summary::after { content:"⌄"; margin-left:8px; color:var(--muted); }
.history-export-menu[open] > summary { color:var(--ink); background:var(--card2); }
.history-export-menu > div {
  position:absolute; z-index:20; top:calc(100% + 7px); right:0; display:grid; gap:5px;
  width:210px; padding:7px; border:1px solid var(--line2); border-radius:9px;
  background:var(--card); box-shadow:var(--shadow);
}
.history-export-menu > div button { width:100%; text-align:left; }

#page-project-intelligence #intelligence-content { display:grid; grid-template-columns:1fr; gap:var(--workspace-gap); }
#page-project-intelligence .history-journal { grid-column:1; padding-bottom:6px; }
#page-project-intelligence .history-journal > .section-heading { align-items:center; }
.history-timeline { position:relative; margin:0; padding:0 0 6px; }
.history-date-heading {
  position:relative; z-index:1; width:max-content; margin:18px 0 5px 42px;
  padding:0 8px; color:var(--ink2); background:var(--card);
  font:600 10.5px/1.5 'Public Sans',sans-serif; letter-spacing:.07em; text-transform:uppercase;
}
.history-date-heading:first-child { margin-top:2px; }
.history-event {
  position:relative; display:grid; grid-template-columns:34px minmax(0,1fr); gap:12px;
  min-width:0; padding:13px 0;
}
.history-event::before {
  content:""; position:absolute; left:16px; top:0; bottom:0; width:1px; background:var(--line2);
}
.history-event-marker {
  position:relative; z-index:1; display:grid; place-items:center; align-self:start;
  width:28px; height:28px; margin:1px 0 0 2px; border:1px solid var(--line2); border-radius:50%;
  background:var(--card); color:var(--muted); font:700 10px/1 'Archivo',sans-serif;
}
.history-event-testing .history-event-marker {
  border-color:color-mix(in srgb,var(--info) 58%,var(--line2)); color:var(--info);
  background:color-mix(in srgb,var(--info) 8%,var(--card));
}
.history-event-snapshot .history-event-marker {
  border-color:color-mix(in srgb,var(--accent) 62%,var(--line2)); color:var(--accent-ink);
  background:color-mix(in srgb,var(--accent) 10%,var(--card));
}
.history-event-issues .history-event-marker {
  border-color:color-mix(in srgb,var(--progress-mid) 64%,var(--line2)); color:var(--chip-warn-ink);
  background:var(--chip-warn-bg);
}
.history-event-content {
  min-width:0; padding:0 0 13px; border-bottom:1px solid var(--line);
}
.history-event:last-child .history-event-content { border-bottom:0; }
.history-event-content > header {
  display:flex; align-items:flex-start; justify-content:space-between; gap:16px;
}
.history-event-content h3 { margin:2px 0 0; font-size:14px; line-height:1.35; }
.history-event-content time { flex:none; color:var(--ink2); font-size:11.5px; font-variant-numeric:tabular-nums; }
.history-kind {
  color:var(--ink2); font-size:10px; font-weight:650; letter-spacing:.07em; text-transform:uppercase;
}
.history-event-content > p { max-width:95ch; margin:6px 0 0; color:var(--ink2); font-size:12.5px; line-height:1.5; }
.history-event-content > .history-event-meta { color:var(--ink2); font-size:11.5px; }
.history-event-detail { margin-top:5px; }
.history-event-detail > summary {
  display:inline-flex; align-items:center; min-height:34px; color:var(--ink2); cursor:pointer;
  font-size:12px; font-weight:600;
}
.history-event-detail > summary::after { content:"⌄"; margin-left:6px; color:var(--ink2); }
.history-event-detail[open] > summary::after { content:"⌃"; }
.history-event-detail > div {
  display:grid; gap:9px; max-width:900px; margin:2px 0 4px; padding:11px 13px;
  border:1px solid var(--line); border-radius:8px; background:var(--card2);
  color:var(--ink2); font-size:12px;
}
.history-event-detail dl { display:grid; grid-template-columns:max-content 1fr; gap:4px 12px; margin:0; }
.history-event-detail dt { font-weight:650; color:var(--ink); }
.history-event-detail dd { margin:0; }
.history-event-detail ul { margin:0; padding-left:18px; }
.history-event-actions { display:flex; flex-wrap:wrap; align-items:center; gap:10px; }
.history-event-actions label { margin-right:auto; }

.history-evidence-shell {
  overflow:hidden; border:1px solid var(--line); border-radius:10px; background:var(--card);
}
.history-evidence-shell > summary {
  display:flex; align-items:center; min-height:62px; padding:10px 16px; cursor:pointer;
}
.history-evidence-shell > summary span { display:grid; gap:3px; }
.history-evidence-shell > summary b { font:650 14px/1.3 'Archivo',sans-serif; }
.history-evidence-shell > summary small { color:var(--ink2); font-size:11.5px; }
.history-evidence-shell > summary::after { content:"⌄"; margin-left:auto; color:var(--ink2); }
.history-evidence-shell[open] > summary::after { content:"⌃"; }
.history-evidence-shell[open] > summary { border-bottom:1px solid var(--line); }
.history-evidence-grid {
  display:grid; grid-template-columns:minmax(0,2fr) minmax(270px,1fr); gap:var(--workspace-gap);
  padding:var(--workspace-gap);
}
#page-project-intelligence .history-evidence-grid .history-measures-panel,
#page-project-intelligence .history-evidence-grid .history-change-detail-panel { grid-column:1 / -1; }

@media (max-width:900px) {
  #page-project-intelligence .intelligence-head { align-items:stretch; flex-direction:column; }
  #page-project-intelligence .intelligence-head > .note { flex:0 1 auto; }
  #page-project-intelligence .history-primary-filters { justify-content:flex-start; flex-wrap:wrap; width:100%; }
  #page-project-intelligence .history-primary-filters .filter-search { flex:1 1 260px; width:auto; }
  .history-evidence-grid { grid-template-columns:1fr; }
  #page-project-intelligence .history-evidence-grid .history-measures-panel,
  #page-project-intelligence .history-evidence-grid .history-change-detail-panel { grid-column:1; }
}
@media (max-width:700px) {
  #page-project-intelligence .workspace-heading-actions #intelligence-freshness {
    flex:0 0 auto; align-self:flex-start; min-height:28px;
  }
  .history-export-menu { width:100%; }
  .history-export-menu > summary { justify-content:center; width:100%; box-sizing:border-box; }
  .history-export-menu > div { position:static; width:auto; margin-top:6px; }
  #page-project-intelligence .history-primary-filters > *,
  #page-project-intelligence .history-primary-filters .filter-search { flex:1 1 100%; width:100%; }
  #page-project-intelligence .history-primary-filters #history-help {
    flex:0 0 44px; width:44px; align-self:flex-end;
  }
  #page-project-intelligence .history-journal > .section-heading {
    align-items:center; flex-direction:row; text-align:left;
  }
  .history-event-content > header { flex-direction:column; gap:4px; }
  .history-event-content time { order:-1; }
  .history-event-detail > summary { min-height:44px; }
  .history-event-actions { align-items:stretch; flex-direction:column; }
  .history-event-actions > * { width:100%; box-sizing:border-box; }
  .history-evidence-grid { padding:12px; gap:12px; }
}

/* The line under a panel that says what the panel is for. Same weight and
   colour everywhere it appears. */
.panel-foot-note {
  margin:14px 0 0; padding-top:12px; border-top:1px solid var(--line);
  color:var(--muted); font-size:12px; line-height:1.5;
}

/* ── The person editor ───────────────────────────────────────────────────────
   A dialog, not an inline row of controls, so that changing somebody is a
   deliberate act with one Save at the end of it. */
.person-dialog {
  width:min(560px, calc(100vw - 32px)); max-height:min(88vh, 760px);
  padding:0; border:1px solid var(--line2); border-radius:14px;
  background:var(--card); color:var(--ink);
}
.person-dialog::backdrop { background:rgba(0,0,0,.55); }
.person-dialog form { display:flex; flex-direction:column; max-height:inherit; }
.person-dialog .engineering-help-head { padding:16px 20px 12px; border-bottom:1px solid var(--line); }
.person-dialog-body { overflow:auto; padding:16px 20px; display:grid; gap:16px; }
.person-dialog-who { padding-bottom:2px; }
.person-dialog-who .people-avatar { flex:0 0 34px; width:34px; height:34px; font-size:12px; }
.person-dialog-who b { font-size:15px; }
.person-dialog-who small { color:var(--muted); }
.person-fields { display:grid; grid-template-columns:1fr 1fr; gap:14px; }
.person-fields > label {
  display:flex; flex-direction:column; gap:6px;
  font-size:12px; color:var(--ink2);
}
/* A label here is a flex column, so every child of it takes a row. A bare
   "(optional)" beside the caption therefore became a row of its own and
   pushed that field's box a line below the box beside it - First name and
   Last name sit in the same pair and started at different heights. The
   caption and its note are one item, so they share one line and the two
   boxes start level. It wraps on a narrow window rather than overflowing. */
.person-fields > label > .field-caption {
  display:flex; align-items:baseline; flex-wrap:wrap; gap:6px;
}
.person-fields .person-switch-row {
  flex-direction:row; align-items:center; justify-content:space-between;
  gap:10px; min-height:40px; padding:0 12px;
  border:1px solid var(--line); border-radius:9px; background:var(--card2);
}
.person-fields select, .person-fields input[type=text], .person-fields .p-job {
  min-height:40px; padding:6px 10px; border:1px solid var(--line2);
  border-radius:8px; background:var(--card2); color:var(--ink); font:inherit;
  font-size:var(--field-font);
}
/* The access level keeps the pill and the colour it has in the People row,
   so the same fact looks the same wherever you meet it. */
.person-fields .p-level {
  min-height:40px; width:auto; align-self:start; max-width:100%;
  padding:5px 30px 5px 12px; border-radius:999px;
  border:1px solid transparent; font-size:12px; font-weight:700;
}
.person-fields .p-level[data-role="engineer"] { background:color-mix(in srgb,#6fb72f 18%,var(--card2))!important; color:color-mix(in srgb,#6fb72f 40%,var(--ink))!important; border-color:color-mix(in srgb,#6fb72f 34%,transparent)!important; }
.person-fields .p-level[data-role="manager"] { background:color-mix(in srgb,#3b82f6 18%,var(--card2))!important; color:color-mix(in srgb,#3b82f6 40%,var(--ink))!important; border-color:color-mix(in srgb,#3b82f6 34%,transparent)!important; }
.person-fields .p-level[data-role="admin"] { background:color-mix(in srgb,#a78bfa 18%,var(--card2))!important; color:color-mix(in srgb,#a78bfa 40%,var(--ink))!important; border-color:color-mix(in srgb,#a78bfa 34%,transparent)!important; }
.person-fields .p-level[data-role="client"] { background:var(--card2)!important; color:var(--ink2)!important; border-color:var(--line)!important; }
/* The control wears the colour of the level it is showing, and an option
   inherits its colour from the control it sits in - so opening the list gave
   four choices all in the same green, which reads as four Engineers rather
   than as four different levels. The list is plain; the closed control is the
   only place the colour means anything. */
.person-fields .p-level option, .people-table .p-level option {
  background:var(--card); color:var(--ink); font-weight:600;
}
.person-fields .p-level:disabled { opacity:.75; cursor:not-allowed; }
#person-level-note { margin:0; }

/* Project participation.
   A closed control that says how many, and a bounded panel that opens under
   it. The panel is anchored rather than floating: inside a dialog that already
   scrolls, a floating layer would be clipped or would escape the dialog, and
   neither of those is a thing a reader should have to fight. */
.project-picker { position:relative; }
.project-picker-toggle {
  display:flex; align-items:center; justify-content:space-between; gap:10px;
  width:100%; min-height:40px; padding:8px 12px; text-align:start;
  border:1px solid var(--line2); border-radius:9px;
  background:var(--card2); color:var(--ink); font:inherit; font-size:13px;
  text-transform:none; letter-spacing:0; font-weight:600; cursor:pointer;
}
.project-picker-toggle:hover { border-color:var(--line); }
.project-picker-chevron {
  width:16px; height:16px; flex:none; fill:none; stroke:currentColor;
  stroke-width:1.6; stroke-linecap:round; stroke-linejoin:round;
  transition:transform .15s ease;
}
.project-picker-toggle[aria-expanded="true"] .project-picker-chevron { transform:rotate(180deg); }
.project-picker-panel {
  margin-top:6px; padding:10px; border:1px solid var(--line2); border-radius:10px;
  background:var(--card); display:grid; gap:8px;
}
/* The shared filter control, sized for the dialog. One rule still says what
   it looks like; this only says how wide it is here. */
.project-picker-panel .filter-search { width:100%; max-width:none; }
.project-picker-bar {
  display:flex; align-items:center; justify-content:space-between;
  gap:10px; flex-wrap:wrap; font-size:11.5px;
}
.project-picker-bar .hint { text-transform:none; letter-spacing:0; }
.project-picker-bulk { display:flex; gap:12px; flex-wrap:wrap; }
.project-picker-bulk .text-btn { font-size:11.5px; }
/* Bounded, so a person on fifty projects does not get a fifty-row dialog. */
.project-picker-list {
  max-height:210px; overflow-y:auto; display:grid; gap:2px;
  border-top:1px solid var(--line2); padding-top:6px;
}
.project-picker-option {
  display:flex; align-items:center; gap:10px; min-height:40px;
  padding:4px 6px; border-radius:8px; cursor:pointer;
  text-transform:none; letter-spacing:0; font-weight:400; font-size:13px;
  color:var(--ink);
}
.project-picker-option:hover { background:var(--card2); }
.project-picker-option input { width:16px; height:16px; flex:none; margin:0; accent-color:var(--accent); }
.project-picker-option span { display:grid; min-width:0; }
.project-picker-option b { font-weight:600; }
.project-picker-option small { color:var(--muted); font-size:11.5px; }
.project-picker-option:focus-within { outline:2px solid var(--accent); outline-offset:1px; }
#person-project-empty { margin:0; }
@media (max-width:640px) {
  /* A phone gets a shorter list and bigger targets, and the two bulk actions
     move under the count rather than squeezing onto its line. */
  .project-picker-list { max-height:46vh; }
  .project-picker-option { min-height:44px; }
  .project-picker-bar { align-items:flex-start; flex-direction:column; gap:6px; }
}
.person-projects {
  margin:0; padding:12px 14px; border:1px solid var(--line); border-radius:10px;
}
.person-projects legend {
  padding:0 6px; font-size:11px; letter-spacing:.06em; text-transform:uppercase;
  color:var(--muted);
}
#person-project-list { display:grid; gap:0; }
/* A project row carries a name, not a caption, so it drops the dialog's
   uppercase label styling. */
.person-project-row {
  display:flex; align-items:center; gap:11px; min-height:44px;
  margin:0; padding:6px 2px; border-bottom:1px solid var(--line);
  cursor:pointer; text-transform:none; letter-spacing:normal;
  color:var(--ink); font-weight:400;
}
.person-project-row:last-child { border-bottom:0; }
.person-project-row b { display:block; font-size:13px; font-weight:600; }
.person-project-row small { display:block; color:var(--muted); font-size:11.5px; }
.person-project-row .ui-switch { flex:0 0 auto; }
#person-project-note { margin:8px 0 0; }
.person-dialog-actions {
  display:flex; justify-content:flex-end; gap:10px;
  padding:14px 20px; border-top:1px solid var(--line); background:var(--card2);
}
.person-dialog-actions button { min-height:40px; }
.people-row-action { text-align:right; }
@media (max-width:560px) {
  .person-fields { grid-template-columns:1fr; }
}

/* ── Emergency ───────────────────────────────────────────────────────────────
   The same parts as every other workspace page: one heading with view tabs, a
   measure band, and panels. Nothing here is styled specially; it uses the page
   treatment the rest of the workspace already has. */
#page-emergency { display:grid; gap:16px; min-width:0; align-content:start; }
/* The sub-line under a measure carries the part that explains the number —
   "31 failed both, 2 duration only", or the sensor that is oldest. Cutting it
   off with an ellipsis loses exactly the useful half, so it wraps instead. */
.workspace-measure small {
  display:-webkit-box; -webkit-line-clamp:2; -webkit-box-orient:vertical;
  overflow:hidden; white-space:normal; line-height:1.35;
}
/* Five narrow columns beside the rail cannot hold five numbers on a laptop.
   Below 1180px the band folds to three, then to two on a phone. */
@media (max-width:1180px) and (min-width:701px) {
  .workspace-measures { grid-template-columns:repeat(3,minmax(0,1fr))!important; }
  .workspace-measure:nth-child(3n+1) { border-inline-start:0; }
  .workspace-measure:nth-child(n+4) { border-top:1px solid var(--line); }
}
.emergency-view-hidden { display:none!important; }

/* The floor bars share the report's track and fill, so a bar means the same
   thing on the screen and on paper. */
/* ONE count bar, used in three places: the emergency floor bars, the
   emergency causes on Overview, and the module outstanding counts. Written
   once on purpose. A bar that answers "how much of this is left" has to be
   the same size and shape wherever it is read, and a second hand-drawn copy
   is a second drawing that drifts — the fault the icon sprite exists to stop.
   These bars are shares of the WORST row, not of a total, so the shape
   answers "where is the work" and the number beside it is the real count. */
.emergency-floor-bars, .overview-bars { display:grid; gap:2px; }
.emergency-floor-row, .overview-bar-row {
  display:grid; grid-template-columns:minmax(90px,150px) 1fr auto;
  align-items:center; gap:14px; min-height:36px;
  padding:5px 0; border-bottom:1px solid var(--line);
}
.emergency-floor-row:last-child, .overview-bar-row:last-child { border-bottom:0; }
.emergency-floor-nm, .overview-bar-name {
  overflow:hidden; color:var(--ink2); font-size:13px;
  text-overflow:ellipsis; white-space:nowrap;
}
/* A neutral track. The fill carries the meaning, so a green track would read
   as a pass share, which none of these are. */
.emergency-floor-row .track, .overview-bar-row .track {
  height:10px; border-radius:4px; overflow:hidden;
  background:color-mix(in srgb,var(--line2) 45%,transparent);
}
/* Amber by default: outstanding WORK, which is not the same claim as a
   failure. "Drivers not addressed" is a job nobody has done yet; red would
   say something is broken. --progress-mid is scoreBand's middle band, so the
   colour already means "in progress" everywhere else on the page. */
.emergency-floor-row .fill, .overview-bar-row .fill {
  display:block; height:100%; border-radius:4px; background:var(--progress-mid);
}
/* Every emergency floor row IS a failure count, and a cause bar is marked. */
.emergency-floor-row .fill, .overview-bar-row .fill.fail { background:var(--fail); }
/* Progress by work type is a percentage, so it takes the one red/amber/green
   scale the rest of the page uses. The amber default above belongs to the
   outstanding-work bars, which are counts; these rules are written here, and
   with the row in front of them, because that default would otherwise win on
   order alone. */
.overview-bar-row .fill.band-low  { background:var(--fail); }
.overview-bar-row .fill.band-mid  { background:var(--progress-mid); }
.overview-bar-row .fill.band-high { background:var(--data); }
/* Module completion counts how many incomplete modules each item affects.
   That is magnitude - not completion and not severity - and a module can be
   counted under more than one item, so red, amber and green would all be
   claims the figure does not make. A neutral information blue, from the
   theme, over the same neutral track. */
.count-bars .overview-bar-row .fill { background:var(--info); }
.emergency-floor-row b, .overview-bar-row b {
  min-width:26px; color:var(--ink); font-size:13px; font-weight:650;
  font-variant-numeric:tabular-nums; text-align:right;
}

#fail-table .emergency-sensor { font-family:"IBM Plex Mono",monospace; font-size:12.5px; }
#fail-table .emergency-module { color:var(--ink2); font-size:12.5px; }
#fail-table .emergency-since {
  color:var(--ink2); font-size:12.5px; white-space:nowrap;
  font-variant-numeric:tabular-nums;
}
#fail-table .emergency-since small { display:block; color:var(--muted); font-size:11px; }

/* ── Emergency failure follow-up ──────────────────────────────────────────
   A failing sensor opens in place: how to fix it on the left, where the
   follow-up stands on the right. The table no longer scrolls inside itself,
   because an open row would otherwise be read through a letterbox. */
.em-failure-tools { display:flex; flex-wrap:wrap; align-items:center; gap:10px 12px; margin:4px 0 12px; }
.em-failure-tools .seg button { display:inline-flex; align-items:center; gap:6px; min-height:36px; }
.em-failure-tools .seg button b { color:var(--muted); font-weight:600; font-variant-numeric:tabular-nums; }
.em-failure-tools .seg button.on b { color:var(--ink2); }
.em-failure-hint { margin:0 0 0 auto; color:var(--muted); font-size:12px; }
.em-failure-elsewhere { margin:0 0 12px; padding:8px 12px; border-inline-start:3px solid var(--line2);
  background:var(--card2); color:var(--ink2); font-size:13px; }
.em-failure-wrap { max-height:none; overflow-x:auto; }
#fail-table .em-failure-row { cursor:pointer; }
#fail-table .em-failure-row:hover > td { background:var(--card2); }
#fail-table .em-failure-row.is-open > td { background:var(--card2); border-bottom-color:transparent; }
.em-row-toggle { display:inline-flex; align-items:center; gap:6px; padding:4px 0; border:0; background:none;
  color:var(--ink); font:inherit; text-align:left; cursor:pointer; }
.em-row-toggle svg { width:14px; height:14px; flex:none; fill:none; stroke:var(--muted); stroke-width:2;
  stroke-linecap:round; stroke-linejoin:round; transition:transform .15s ease; }
.em-row-toggle[aria-expanded="true"] svg { transform:rotate(90deg); stroke:var(--accent-ink); }
.em-row-toggle:focus-visible { outline:2px solid var(--focus); outline-offset:2px; border-radius:4px; }
#fail-table .em-owner-cell { color:var(--ink2); font-size:12.5px; white-space:nowrap; }
.em-status-chip { white-space:nowrap; }
.em-failure-empty td { padding:18px 12px; color:var(--muted); text-align:center; }
.fail-types .rw .em-cause-owner { margin-left:8px; color:var(--muted); font-size:11px; }

#fail-table .em-failure-detail > td { padding:0 12px 16px; background:var(--card2); }
.em-fix { display:grid; grid-template-columns:minmax(0,1.35fr) minmax(260px,1fr); gap:16px; white-space:normal;
  padding:14px 16px 16px 26px; border-inline-start:3px solid var(--accent); background:var(--card);
  border-radius:0 8px 8px 0; cursor:auto; }
.em-fix h3 { display:flex; align-items:center; gap:8px; margin:0 0 10px; font-size:13px; font-weight:700;
  letter-spacing:.04em; text-transform:uppercase; color:var(--ink2); }
.em-fix-cause + .em-fix-cause { margin-top:14px; padding-top:12px; border-top:1px solid var(--line); }
.em-fix-cause header { display:flex; flex-wrap:wrap; align-items:baseline; gap:4px 10px; }
.em-fix-cause header b { font-size:14px; color:var(--ink); }
.em-fix-cause code { color:var(--muted); font:11px "IBM Plex Mono",monospace; }
.em-fix-cause p { margin:4px 0 8px; color:var(--ink2); font-size:13px; }
.em-fix-cause ol { margin:0; padding-left:22px; display:grid; gap:5px; font-size:13px; line-height:1.45; color:var(--ink); }
.em-fix-cause ol li::marker { color:var(--accent-ink); font-weight:700; }
.em-fix-after { margin:12px 0 0; color:var(--ink2); font-size:12.5px; }
.em-fix-after a { margin-left:6px; color:var(--accent-ink); font-weight:600; }
.em-owner-tag { display:inline-flex; align-items:center; padding:2px 8px; border-radius:999px; font-size:11px;
  font-weight:650; letter-spacing:0; text-transform:none; background:var(--chip-na-bg); color:var(--chip-na-ink); }
.em-owner-tag.contractor { background:var(--chip-warn-bg); color:var(--chip-warn-ink); }
.em-owner-tag.delmatic { background:var(--chip-pass-bg); color:var(--chip-pass-ink); }
.em-fix-progress { padding-left:16px; border-inline-start:1px solid var(--line); }
.em-fix-status { margin:0 0 10px; font-size:13.5px; font-weight:600; color:var(--ink); }
.em-fix-status.fixed { color:var(--chip-info-ink); }
.em-fix-status.retest { color:var(--fail); }
.em-fix-actions { display:grid; gap:8px; }
.em-fix-note { width:100%; box-sizing:border-box; min-height:58px; resize:vertical; font:inherit; font-size:13px; }
.em-fix-buttons { display:flex; flex-wrap:wrap; align-items:center; gap:8px; }
.em-fix-buttons button { min-height:40px; }
.em-handover { margin-left:auto; padding:6px 4px; border:0; background:none; color:var(--accent-ink);
  font:inherit; font-size:12.5px; font-weight:600; text-decoration:underline; text-underline-offset:3px; cursor:pointer; }
.em-handover:disabled { opacity:.5; cursor:not-allowed; }
.em-fix-message { min-height:1em; margin:0; color:var(--ink2); font-size:12.5px; }
.em-events { list-style:none; margin:14px 0 0; padding:12px 0 0; border-top:1px solid var(--line); display:grid; gap:10px; }
.em-event p { margin:0; color:var(--ink2); font-size:12px; }
.em-event p b { color:var(--ink); }
.em-event.fixed p b { color:var(--chip-info-ink); }
.em-event blockquote { margin:4px 0 0; padding:6px 10px; border-inline-start:2px solid var(--line2);
  background:var(--card2); color:var(--ink); font-size:13px; white-space:pre-wrap; overflow-wrap:anywhere; }
.em-event.is-earlier { opacity:.72; }
.em-event-earlier { font-style:italic; }
.emergency-work-state .em-status-chip { margin-left:8px; vertical-align:1px; }

@media (max-width:900px) {
  .em-fix { grid-template-columns:1fr; padding-left:16px; }
  .em-fix-progress { padding:14px 0 0; border-inline-start:0; border-top:1px solid var(--line); }
  .em-failure-hint { margin-left:0; flex-basis:100%; }
}
@media (max-width:700px) {
  .em-failure-tools .seg { flex:1 1 100%; }
  .em-failure-tools .seg button { flex:1; justify-content:center; min-height:44px; }
  .em-fix-buttons button { flex:1 1 140px; min-height:44px; }
  .em-handover { margin-left:0; }
}

@media (max-width:700px) {
  .emergency-page-actions { width:100%; justify-content:stretch; }
  /* A flex basis of 0 (the old `flex:1`) stopped the three buttons wrapping, so
     together they were wider than the phone and stretched the whole page. The
     basis is a real width: two fit a row, the third wraps. */
  .emergency-page-actions button { flex:1 1 140px; min-width:0; min-height:44px; }
  /* The page is a one-column grid. A grid child will not shrink below its
     widest unbreakable line, so one wide child made every card 440px. */
  #page-emergency > * { min-width:0; }
  .emergency-floor-row,
  .overview-bar-row { grid-template-columns:minmax(70px,110px) 1fr auto; gap:10px; }
}

/* ── Zoom to a box: Shift + drag (042) ───────────────────────────────────────
   In the Drawings viewer the band is drawn on the page, not on the window, so
   it stays where it was put while the sheet scrolls under it. In the
   pre-commissioning viewer it is drawn on the stage, which does not scroll. */
.viewer-zoom-band {
  position:absolute; z-index:4; pointer-events:none;
  border:1.5px dashed #111111;
  outline:1.5px dashed #ffffff; outline-offset:-1.5px;
  background:rgba(255,255,255,.22);
}
.viewer-zoom-band[hidden] { display:none; }

/* What has come back. Quiet by default — it is a summary, not an alarm — and
   absent entirely on a job where nothing has been reopened. */
.snag-recurrence { margin:0 0 10px; padding:8px 12px; border:1px solid var(--line);
  border-radius:8px; background:var(--card); }
.snag-recurrence > summary { cursor:pointer; font-weight:600; }
.snag-recurrence .note { margin:8px 0 4px; color:var(--muted); font-size:12px; }
.snag-recurrence-list { list-style:none; margin:0; padding:0; }
.snag-recurrence-list li { display:flex; flex-wrap:wrap; gap:4px 10px;
  align-items:baseline; padding:4px 0; border-top:1px solid var(--line); }
.snag-recurrence-list button { background:none; border:0; padding:0; cursor:pointer;
  color:inherit; font:inherit; text-align:left; text-decoration:underline; }
.snag-recurrence-list small { color:var(--muted); }

/* Which snag types come up most. Information, so it is quiet: a thin line for
   each count, no fill behind a row. Only the CHOSEN row is solid, because that
   is a selected choice, the same fill the pressed zoom button uses. Every
   colour is a theme token, so dark follows without a rule of its own. */
.snag-types { margin:0 0 12px; padding:10px 14px 8px; border:1px solid var(--line);
  border-radius:8px; background:var(--card); }
.snag-types[hidden] { display:none; }
.snag-types h2 { margin:0 0 6px; font-size:14px; }
.snag-types .note { margin:4px 0; color:var(--muted); font-size:12px; }
.snag-type-list { list-style:none; margin:0; padding:0; }
.snag-type-row {
  display:grid; grid-template-columns:minmax(0,min(14rem, 40%)) minmax(60px,1fr) auto;
  align-items:center; gap:4px 14px; width:100%; padding:7px 8px; border:0;
  border-radius:6px; background:transparent; color:var(--ink); font:inherit;
  text-align:start; cursor:pointer;
}
.snag-type-row:hover { background:color-mix(in srgb,var(--accent) 6%,transparent); }
.snag-type-name { min-width:0; white-space:normal; overflow-wrap:anywhere; }
.snag-type-bar { display:block; height:4px; border-radius:2px;
  background:color-mix(in srgb,var(--data) 22%,var(--card)); overflow:hidden; }
.snag-type-bar i { display:block; height:100%; background:var(--data); }
.snag-type-numbers { white-space:nowrap; font-variant-numeric:tabular-nums; }
.snag-type-numbers small { color:var(--muted); font-size:11.5px; }
.snag-type-row.is-selected { background:var(--accent); color:var(--btn-ink); }
.snag-type-row.is-selected .snag-type-bar { background:color-mix(in srgb,var(--btn-ink) 22%,transparent); }
.snag-type-row.is-selected .snag-type-bar i { background:var(--btn-ink); }
.snag-type-row.is-selected .snag-type-numbers small { color:inherit; }
.snag-types-more { margin:4px 0 2px 8px; }
@media (max-width:560px) {
  .snag-type-row { grid-template-columns:minmax(0,1fr) auto; }
  .snag-type-bar { grid-column:1 / -1; grid-row:2; }
}

/* Snag Activity follows the existing theme tokens. */
.snag-status-row { border-bottom:1px solid var(--line2); padding:12px 0; }
.snag-status-row header { display:flex; flex-wrap:wrap; align-items:center; gap:8px; }
.snag-status-row small { display:block; color:var(--muted); }
.snag-status-row summary { cursor:pointer; color:var(--ink); padding:8px 0; }
.snag-status-row p { color:var(--ink); white-space:pre-wrap; overflow-wrap:anywhere; }
.snag-attachment-list { display:grid; grid-template-columns:repeat(auto-fit,minmax(100px,1fr));gap:8px; }
.snag-attachment-list > button {
  display:grid; min-width:0; width:100%; gap:2px; white-space:normal;
  text-align:start; justify-items:start; overflow-wrap:anywhere;
}
.snag-attachment-list > button span,
.snag-attachment-list > button small { display:block; min-width:0; overflow-wrap:anywhere; }
.snag-attachment-list img { width:100%; max-height:180px; object-fit:contain; }
.snag-file-draft { padding:8px 0;border-bottom:1px solid var(--line2);overflow-wrap:anywhere; }
.snag-file-draft input { width:100%; }
#snag-evidence-outbox article,
#snag-page-outbox article { border:1px solid var(--line2);padding:10px;margin-top:8px;overflow-wrap:anywhere; }
.person-project-row select { width:auto;max-width:55%; }

@media print {
  .skip-link { display:none !important; }
  .snag-report-document { font-size:10.5px; padding:0; }
  /* Use the printable A4 height and keep the footer inside that box. This
     prevents Chromium from moving only the footer to a blank extra sheet. */
  /* 297mm less the 8mm top and 13mm footer margins of the page rule below. */
  .snag-report-page { display:flex; flex-direction:column; box-sizing:border-box; height:276mm; min-height:0; overflow:hidden; padding:0; break-inside:avoid; page-break-inside:avoid; break-after:page; page-break-after:always; }
  .snag-report-page:last-child { break-after:auto; page-break-after:auto; }
  .snag-report-page + .snag-report-page { border-top:0; }
  .snag-report-page-content { flex:1 1 auto; min-height:0; }
  /* The page margin carries the footer in print, with the page number. The
     line inside the page is the on-screen preview's footer only. */
  .snag-report-foot { display:none; }
  .snag-report-headline, .snag-report-record-title, .snag-report-details,
  .snag-report-group h2, .snag-report-document thead { break-after:avoid; }
  .snag-report-document thead { display:table-header-group; }
  .snag-report-document tr, .snag-report-history li,
  .snag-report-drawing-stack { break-inside:avoid; page-break-inside:avoid; }
  .print-brand-lockup { -webkit-print-color-adjust:exact; print-color-adjust:exact; }
  .emergency-report-document { padding:0; }
  .emergency-work-sheet,.emergency-status-page { color:#1b2119; background:#fff; }
  .emergency-work-state-print,.emergency-drawing-unavailable,.emergency-multiple-note {
    -webkit-print-color-adjust:exact; print-color-adjust:exact;
  }
  .emergency-work-drawings,.emergency-work-drawings figure { break-inside:avoid; page-break-inside:avoid; }
  @media (monochrome) {
    .print-brand-product strong, .print-brand-attribution b { color:#111; }
    .print-brand-product strong { background:transparent; }
  }
  /* A group can contain more rows than one sheet. Keep its heading with the
     repeated table head, then allow rows to continue on the next sheet. */
  .snag-report-group { break-inside:auto; page-break-inside:auto; }
  .standalone-snag-report { padding:0; }
  /* One footer on every printed page of every report. The words on the left
     are added per report by applyPrintFooter (print-brand.js); the count is
     the browser's own, so it runs through the whole document. */
  @page {
    size:A4; margin:8mm 14mm 13mm;
    @bottom-left {
      content:"CommissionIQ by Delmatic"; width:150mm; vertical-align:top; padding-top:2.5mm;
      border-top:.25mm solid #cfd4ca; color:#5f6757;
      font:600 7.5pt 'Public Sans','Segoe UI',sans-serif;
    }
    @bottom-right {
      content:"Page " counter(page) " of " counter(pages);
      width:32mm; vertical-align:top; padding-top:2.5mm; text-align:right;
      border-top:.25mm solid #cfd4ca; color:#5f6757;
      font:600 7.5pt 'Public Sans','Segoe UI',sans-serif;
    }
  }
}

/* ══ Section surfaces ════════════════════════════════════════════
   An ordinary section shares the page canvas and is held apart by its
   outline alone. It is a region OF the page, not a card lying on it.

   This was compared against the older filled treatment behind a temporary
   switch and chosen; it is now simply what the application looks like. It
   is not a theme and not a preference - the rules below declare no colour
   of their own and read whatever Light, Dark or Delmatic has set.

   A surface that is not an ordinary section keeps its own fill, because it
   is a separate thing rather than a part of the page:
     * Needs attention - an independent action surface;
     * the report preview well, which holds a document;
     * bounded edit forms and their groups, where the boundary protects
       unsaved work.
   Dialogs, drawers, popovers, report documents, drawing tiles and drop
   targets are already their own material and are left alone here.
   ═════════════════════════════════════════════════════════════════════════ */
:root {
  /* The ordinary section ground IS the page ground. The outline, the radius,
     the padding and the internal rules all stay, so the region is still a
     region. */
  --section-bg:var(--page);
}
.workspace-page .workspace-section,
.workspace-page > .card.block,
.workspace-page > section.card.block,
.workspace-page > #intelligence-content > .card.block {
  background:var(--section-bg);
}
/* A table container, a list group and a chart well are part of their
   section, not separate things sitting inside it. */
.workspace-page .tbl-wrap,
.workspace-page .admin-table-wrap {
  background:var(--section-bg);
}
/* The exceptions named above, stated once. */
.workspace-page #needs-attention,
.workspace-page .needs-attention,
.report-preview-well,
.admin-form,
.admin-group {
  background:var(--card);
}

/* Delmatic green on white must meet the large-text print contrast threshold. */
.completion-wordmark { color:#5d861f; font-weight:850; letter-spacing:-.045em; }
.completion-wordmark { width:42mm; height:auto; color:initial; font-weight:initial; letter-spacing:initial; }
.completion-options .check-label[hidden] { display:none; }
.completion-module-report .completion-control { margin-block:6mm; gap:3mm 8mm; }
.completion-module-report .completion-report-section { margin-bottom:5mm; }
.completion-module-report .completion-report-foot { margin-top:6mm; }
/* A module report is an item in the pack: its title is an item title. */
.completion-module-report .completion-doc-head h1 { margin-top:6mm; font-size:21px; }
.completion-module-report { width:100%; max-width:none; }
.completion-module-head h1 { overflow-wrap:anywhere; }
.completion-module-head h1 strong { font-weight:800; }
.completion-module-details { display:grid; grid-template-columns:repeat(4,minmax(0,1fr)); gap:4mm 6mm; }
.completion-module-details div { min-width:0; }
.completion-module-details dt { color:#697160; font-size:8pt; font-weight:700; text-transform:uppercase; }
.completion-module-details dd { margin:1mm 0 0; overflow-wrap:anywhere; }
.completion-module-details .completion-module-detail-wide { grid-column:1/-1; padding-top:3mm; border-top:1px solid #e5e8e0; }
.completion-module-apb dd { overflow-wrap:normal; word-break:normal; }
@media(max-width:700px) { .completion-module-details { grid-template-columns:repeat(2,minmax(0,1fr)); } }

/* Recipient-report accents use the exact Delmatic brand green. */
.completion-doc-head { border-bottom:1px solid #9dc368; }
.completion-intro { border-left-color:#96D045; }

/* Completion controls keep one aligned rhythm at narrow builder widths. */
.completion-options .completion-nested:not([hidden]) { display:grid; gap:8px; }
.completion-options .seg,
#completion-preview-choice { width:100%; box-sizing:border-box; }
.completion-options .seg.completion-nested { width:auto; }
.completion-options .seg button,
#completion-preview-choice button {
  flex:1 1 0; min-width:0; padding-inline:10px; white-space:normal;
  line-height:1.25; text-align:center;
}
.completion-options .completion-nested > .note { margin:0; }
.completion-preview-controls #completion-preview-choice {
  display:grid; grid-template-columns:repeat(auto-fit,minmax(86px,1fr));
}
.completion-preview-controls #completion-print,
.completion-preview-controls #completion-download-drawings { width:100%; min-height:44px; margin-top:8px; }
.completion-preview-controls #completion-status { margin:0; padding-top:2px; }

/* ── Documents (feature 016) ─────────────────────────────────────────────────
   One list with a category filter. The filter is the Modules filter, so the
   two read as one family; it scrolls sideways on a phone rather than wrap. */
#page-documents .documents-toolbar { display:flex; flex-wrap:wrap; align-items:center; gap:8px; margin-bottom:6px; }
#page-documents .filter-search { width:260px; }
#page-documents .seg { gap:2px; padding:2px; border:0; background:var(--card2);
  overflow-x:auto; scrollbar-width:none; max-width:100%; }
#page-documents .seg::-webkit-scrollbar { display:none; }
#page-documents .seg button { min-height:40px; padding:5px 11px; border-radius:6px; white-space:nowrap; }
#page-documents .seg button.on { background:var(--card); box-shadow:var(--shadow); }
#page-documents .seg button b { color:var(--muted); font-size:12px; font-weight:600;
  font-variant-numeric:tabular-nums; margin-left:4px; }
#page-documents .seg button.on b { color:var(--ink2); }
.documents-list { list-style:none; margin:14px 0 0; padding:0; }
/* The buttons may take at most 45% of the row and wrap there. Sized to
   their content alone, five buttons on one line left the document's own
   column 44px wide on an upright iPad, and "Earlier versions" ran out of
   it (051). */
.document-row {
  display:grid; grid-template-columns:auto minmax(0,1fr) fit-content(45%); gap:14px; align-items:start;
  padding:14px 4px; border-top:1px solid var(--line);
}
.document-row:first-child { border-top:0; }
.document-type {
  display:grid; place-items:center; width:42px; height:50px; border-radius:6px;
  background:var(--card2); border:1px solid var(--line2); color:var(--ink2);
  font-size:10.5px; font-weight:700; letter-spacing:.04em;
}
.document-type[data-kind="PDF"] { background:var(--chip-fail-bg); color:var(--chip-fail-ink); border-color:transparent; }
.document-type[data-kind="Image"] { background:var(--chip-pass-bg); color:var(--chip-pass-ink); border-color:transparent; }
.document-heading { margin:0; display:flex; flex-wrap:wrap; align-items:center; gap:6px 10px; }
.document-title {
  background:none; border:0; padding:0; font:inherit; font-size:15px; font-weight:650;
  color:var(--ink); text-align:left; cursor:pointer; overflow-wrap:anywhere;
}
.document-title:hover { text-decoration:underline; text-underline-offset:3px; }
.document-tag {
  font-size:11.5px; font-weight:600; padding:2px 8px; border-radius:999px;
  background:var(--chip-warn-bg); color:var(--chip-warn-ink);
}
.document-meta { margin:4px 0 0; font-size:12.5px; color:var(--muted); }
.document-description { margin:6px 0 0; font-size:13.5px; color:var(--ink2); max-width:70ch; }
.document-versions { margin-top:8px; font-size:12.5px; color:var(--ink2); }
.document-versions summary { cursor:pointer; color:var(--muted); }
.document-versions ul { list-style:none; margin:6px 0 0; padding:0; display:grid; gap:4px; }
.document-versions li span { color:var(--muted); margin-left:6px; }
.document-version {
  background:none; border:0; padding:0; font:inherit; color:var(--accent-ink);
  text-decoration:underline; text-underline-offset:2px; cursor:pointer;
}
.document-actions { display:flex; flex-wrap:wrap; justify-content:flex-end; gap:6px; }
.document-actions button { min-height:36px; }
.documents-empty { margin-top:14px; }
.document-dlg { width:min(480px, 92vw); }
.document-dlg .document-file-hint { margin:4px 0 0; font-size:12px; color:var(--muted); }
.document-choice { border:0; margin:14px 0 0; padding:0; }
.document-choice legend {
  font-size:11px; font-weight:600; letter-spacing:.08em; text-transform:uppercase;
  color:var(--muted); margin-bottom:4px; padding:0;
}
dialog .document-choice label {
  display:flex; align-items:center; gap:8px; margin:6px 0 0;
  font-size:14px; font-weight:400; letter-spacing:0; text-transform:none; color:var(--ink);
}
dialog .document-choice input[type=radio] { width:auto; margin:0; accent-color:var(--accent-ink); }
@media (max-width: 700px) {
  #page-documents .filter-search { width:100%; }
  .document-row { grid-template-columns:auto minmax(0,1fr); }
  .document-actions { grid-column:1 / -1; justify-content:flex-start; }
  /* An earlier version is a full-width, finger-sized row, with its date under
     the name, so it can never run into the buttons below it. */
  .document-versions summary { display:flex; align-items:center; min-height:44px; }
  .document-versions ul { gap:2px; }
  .document-versions li { display:grid; }
  .document-versions li span { margin-left:0; }
  .document-version { display:block; min-height:44px; padding:6px 0; text-align:left; overflow-wrap:anywhere; }
}

/* ── Documents, step two: module types and documents kept offline ─────────── */
.documents-for-type {
  display:flex; flex-wrap:wrap; align-items:center; gap:6px 10px; margin:10px 0 0;
  padding:9px 12px; border-radius:8px; background:var(--chip-pass-bg); color:var(--chip-pass-ink);
  font-size:13.5px;
}
.documents-for-type[hidden] { display:none; }
.documents-for-type button {
  background:none; border:0; padding:0; font:inherit; color:inherit; cursor:pointer;
  text-decoration:underline; text-underline-offset:2px; margin-left:auto;
}
.document-kept { background:var(--chip-pass-bg); color:var(--chip-pass-ink); }
.document-types-line { margin:6px 0 0; display:flex; flex-wrap:wrap; align-items:center; gap:4px 6px;
  font-size:12.5px; color:var(--muted); }
.document-type-chip {
  background:var(--card2); border:1px solid var(--line2); border-radius:999px; padding:1px 8px;
  font:inherit; font-size:12px; color:var(--ink2); cursor:pointer;
}
.document-type-chip:hover { border-color:var(--accent-ink); color:var(--ink); }
.document-keep.is-kept { border-color:var(--accent-ink); color:var(--accent-ink); }
.document-types { margin:14px 0 0; border:1px solid var(--line2); border-radius:8px; padding:8px 12px; }
.document-types summary {
  cursor:pointer; font-size:11px; font-weight:600; letter-spacing:.08em; text-transform:uppercase;
  color:var(--muted);
}
.document-types summary .hint { text-transform:none; letter-spacing:0; font-weight:400; }
.document-types > p.hint { margin:8px 0 0; font-size:12px; color:var(--muted); }
.document-types-list { display:grid; gap:2px; margin-top:8px; max-height:180px; overflow:auto; }
dialog .document-types-list label {
  display:flex; align-items:center; gap:8px; margin:0; padding:3px 0;
  font-size:13.5px; font-weight:400; letter-spacing:0; text-transform:none; color:var(--ink);
}
dialog .document-types-list input[type=checkbox] { margin:0; accent-color:var(--accent-ink); }
dialog .document-types-list .hint { color:var(--muted); font-size:12px; margin-left:auto; }
.module-guide {
  margin-left:8px; padding:1px 8px; border-radius:999px; border:1px solid var(--line2);
  background:var(--card); color:var(--accent-ink); font:inherit; font-size:12px; font-weight:600;
  cursor:pointer; vertical-align:1px;
}
.module-guide:hover { border-color:var(--accent-ink); }
.em-fix-documents { margin-top:12px; }
.em-fix-documents h4 { margin:0 0 6px; font-size:13px; }
.em-fix-documents ul { list-style:none; margin:0; padding:0; display:grid; gap:4px; }
.em-fix-documents li span { color:var(--muted); font-size:12px; margin-left:6px; }
.document-link {
  background:none; border:0; padding:0; font:inherit; color:var(--accent-ink); cursor:pointer;
  text-decoration:underline; text-underline-offset:2px; text-align:left;
}

/* ── Areas (feature 018) ─────────────────────────────────────────────────────
   Each state has one colour, used for its pill, its share of a bar and its
   outline on the drawing, where it is a strong border with a light wash of
   the same colour inside. The colour comes from areas.js through
   --area-colour, so the page, the drawing and the printed sheets agree. */
.areas-summary-head { display:flex; flex-wrap:wrap; align-items:baseline; justify-content:space-between; gap:4px 16px; }
.areas-summary-head h2 { margin:0; font-size:16px; }
.areas-summary-head .note { margin:0; }
.areas-summary { margin-top:12px; }
.areas-summary-figures { display:flex; flex-wrap:wrap; gap:6px 28px; margin-bottom:10px; }
.areas-headline { margin:0; color:var(--ink2); font-size:14px; }
.areas-headline b { color:var(--ink); font-size:26px; font-weight:700; margin-right:4px; font-variant-numeric:tabular-nums; }
.area-bar { display:flex; height:12px; border-radius:6px; overflow:hidden; background:var(--card2); gap:2px; }
.area-bar-part { background:var(--area-colour); min-width:4px; flex-basis:0; }
.area-bar-empty { flex:1; }
.area-legend { list-style:none; display:flex; flex-wrap:wrap; gap:6px; margin:10px 0 0; padding:0; }
.area-legend button {
  display:inline-flex; align-items:center; gap:6px; min-height:36px; padding:4px 10px;
  border:1px solid var(--line2); border-radius:999px; background:var(--card); color:var(--ink2); font:inherit; font-size:13px;
}
.area-legend button b { color:var(--ink); font-variant-numeric:tabular-nums; }
.area-legend button small { color:var(--muted); font-variant-numeric:tabular-nums; }
.area-legend button.on { border-color:var(--area-colour, var(--accent-ink)); box-shadow:inset 0 0 0 1px var(--ink2); }
.area-swatch {
  display:inline-block; width:12px; height:12px; flex:none; border-radius:3px;
  border:2px solid var(--area-colour); background:color-mix(in srgb, var(--area-colour) 22%, transparent);
}
.areas-floors { margin-top:18px; overflow-x:auto; }
.areas-floor-table, .areas-table { width:100%; border-collapse:collapse; font-size:13.5px; }
.areas-floor-table th, .areas-floor-table td, .areas-table th, .areas-table td {
  padding:8px 10px; border-top:1px solid var(--line); text-align:left; vertical-align:middle;
}
.areas-floor-table thead th, .areas-table thead th {
  border-top:0; color:var(--muted); font-size:12px; font-weight:600; white-space:nowrap;
}
.areas-floor-table tbody th { font-weight:650; white-space:nowrap; }
.areas-floor-bar { width:32%; min-width:140px; }
.areas-floor-table td:last-child { text-align:right; }
.areas-floor-table .ghost-btn { min-height:36px; white-space:nowrap; }
.areas-outside { color:var(--chip-warn-ink); }
.muted { color:var(--muted); }
#page-areas .areas-toolbar { display:flex; flex-wrap:wrap; align-items:center; gap:8px; margin-bottom:8px; }
#page-areas .filter-search { width:240px; }
#page-areas .seg { gap:2px; padding:2px; border:0; background:var(--card2);
  overflow-x:auto; scrollbar-width:none; max-width:100%; }
#page-areas .seg::-webkit-scrollbar { display:none; }
#page-areas .seg button { min-height:40px; padding:5px 11px; border-radius:6px; white-space:nowrap; }
#page-areas .seg button.on { background:var(--card); box-shadow:var(--shadow); }
#page-areas .seg button b { color:var(--muted); font-size:12px; font-weight:600;
  font-variant-numeric:tabular-nums; margin-left:4px; }
#page-areas .seg button.on b { color:var(--ink2); }
.areas-floor-select select { min-height:40px; }
.areas-bulk {
  display:flex; flex-wrap:wrap; align-items:center; gap:8px 12px; margin:6px 0 10px;
  padding:10px 12px; border:1px solid var(--line2); border-radius:10px; background:var(--card2);
}
.areas-bulk[hidden] { display:none; }
.areas-bulk input[type="text"] { flex:1 1 220px; min-height:38px; }
.areas-bulk select { min-height:38px; }
.areas-outbox { margin:14px 0; padding:12px; border:1px solid var(--line2); border-radius:10px; background:var(--card2); }
.areas-outbox h2 { margin:0 0 8px; font-size:14px; }
.area-outbox-list { display:grid; gap:10px; margin:0; padding:0; list-style:none; }
.area-outbox-list li { display:grid; gap:3px; padding:8px 0; border-top:1px solid var(--line2); }
.area-operation-status, .area-operation-note { color:var(--muted); font-size:12px; white-space:pre-wrap; }
.area-operation-actions { display:flex; flex-wrap:wrap; gap:10px; margin-top:3px; }
.area-sync-label { display:block; margin-top:3px; color:var(--muted); font-size:11px; }
.area-sync-label.is-conflict { color:var(--chip-warn-ink); font-weight:650; }
.areas-table-wrap { overflow-x:auto; }
.areas-select-col { width:36px; display:none; }
.areas-table.can-select .areas-select-col { display:table-cell; }
.areas-table tbody tr.is-selected { background:color-mix(in srgb, var(--accent) 10%, transparent); }
.areas-table td:nth-child(n+5) { font-variant-numeric:tabular-nums; white-space:nowrap; }
.area-open { font-weight:650; white-space:nowrap; }
.area-name { color:var(--ink2); font-size:13px; }
/* Number and name on one line; a long name wraps under itself, not under the number. */
.area-title-line { display:flex; align-items:baseline; gap:10px; }
.area-title-line .area-open { flex:0 0 auto; }
.area-title-line .area-name { min-width:0; }
.area-floor-links { display:flex; flex-direction:column; align-items:flex-start; gap:2px; }
.area-show-drawing {
  display:inline-flex; align-items:center; gap:6px; padding:3px 8px 3px 6px; margin:-3px 0 -3px -6px;
  border:0; border-radius:6px; background:none; color:var(--ink); font:inherit; text-align:left; cursor:pointer;
}
.area-show-drawing svg { width:14px; height:14px; flex:0 0 auto; fill:var(--muted); }
.area-show-drawing:hover, .area-show-drawing:focus-visible { background:var(--card2); color:var(--accent); }
.area-show-drawing:hover svg, .area-show-drawing:focus-visible svg { fill:var(--accent); }
.area-complete { color:var(--chip-pass-ink); font-weight:600; }
.area-snags { color:var(--chip-fail-ink); font-weight:650; }
.areas-empty { margin-top:14px; }
.area-state-pill {
  display:inline-flex; align-items:center; gap:6px; padding:2px 9px 2px 7px; border-radius:999px;
  font-size:12px; font-weight:650; white-space:nowrap; color:var(--ink);
  background:color-mix(in srgb, var(--area-colour) 16%, var(--card));
  border:1px solid color-mix(in srgb, var(--area-colour) 55%, transparent);
}
.area-state-pill::before { content:""; width:8px; height:8px; border-radius:50%; background:var(--area-colour); }

.area-dlg { width:min(640px, 94vw); padding:0; }
.area-dlg-head {
  display:flex; align-items:flex-start; justify-content:space-between; gap:12px;
  padding:18px 20px 12px; border-bottom:1px solid var(--line);
}
.area-dlg-head h2 { margin:2px 0 6px; font-size:20px; }
.area-dlg-head .eyebrow { margin:0; }
.area-dlg-body { padding:6px 20px 18px; max-height:calc(92dvh - 90px); overflow:auto; }
.area-dlg-section { padding:14px 0; border-bottom:1px solid var(--line); }
.area-dlg-section h3 { margin:0 0 10px; font-size:14px; }
/* Fact tiles (docs/design-rules.md). A tile is read only, so it is never a
   solid fill: a thin coloured line on top and a soft fade, the same idiom as
   the Snags tab measures (.drawing-measure.snag-status-measure). The colour
   comes from the tone areas.js decided: green done, amber work left, red a
   fault, grey nothing to count, blue information. Theme tokens only. */
.area-evidence { display:grid; grid-template-columns:repeat(auto-fit, minmax(136px, 1fr)); gap:8px; margin:0; }
.area-fact {
  --fact-colour:var(--chip-na-ink);
  display:flex; flex-direction:column; justify-content:flex-start; gap:2px;
  padding:10px 12px 9px; border:1px solid var(--line2); border-radius:8px;
  background:linear-gradient(180deg, color-mix(in srgb, var(--fact-colour) 11%, var(--card)), var(--card) 76%);
  box-shadow:inset 0 3px 0 var(--fact-colour);
}
.area-fact.tone-passed { --fact-colour:var(--chip-pass-ink); }
.area-fact.tone-attention { --fact-colour:var(--chip-warn-ink); }
.area-fact.tone-issue { --fact-colour:var(--chip-fail-ink); }
.area-fact.tone-none { --fact-colour:var(--chip-na-ink); }
.area-fact.tone-information { --fact-colour:var(--chip-info-ink, var(--info)); }
.area-evidence dt { color:var(--muted); font-size:12px; }
.area-evidence dd { margin:2px 0 0; font-size:16px; font-weight:650; font-variant-numeric:tabular-nums; }
.area-evidence .tone-none dd { color:var(--ink2); font-size:14px; font-weight:600; }
.area-evidence dd.area-fact-foot { margin:0; color:var(--ink2); font-size:12px; font-weight:500; }
.area-state-choices { display:grid; grid-template-columns:repeat(auto-fit, minmax(170px, 1fr)); gap:6px; }
/* A choice wraps its words: "Tested — ready to witness now" is wider than
   its column, and the site-wide button rule keeps a label on one line, so
   "now" ran out of the button (051). */
.area-state-choice {
  display:flex; align-items:center; justify-content:center; gap:7px; min-height:44px; padding:6px 12px;
  border:1px solid var(--line2); border-radius:8px; background:var(--card); color:var(--ink); font:inherit; font-size:13.5px;
  text-align:center; white-space:normal; min-width:0;
}
.area-state-witness-hint { margin:8px 0 0; }
.area-state-choice .area-swatch { border-color:var(--area-colour); }
.area-state-choice.on { border-color:var(--area-colour); box-shadow:inset 0 0 0 1px var(--area-colour);
  background:color-mix(in srgb, var(--area-colour) 12%, var(--card)); }
.area-state-choice.is-current { cursor:default; color:var(--muted); }
.area-state-choice small { color:var(--muted); font-size:11.5px; }
.area-field { display:grid; gap:4px; margin-top:10px; font-size:13px; font-weight:600; color:var(--ink2); }
.area-field input, .area-field textarea, .area-field select { font:inherit; font-weight:400; font-size:var(--field-font); }
.area-field-hint { font-weight:400; color:var(--muted); font-size:12px; }
.area-dlg-actions { display:flex; justify-content:flex-end; gap:8px; margin-top:10px; }
.area-dlg-foot { justify-content:flex-start; border-top:0; padding-top:6px; }
/* On the drawings: one row for each drawing, in columns. The name, then Show
   on drawing, Redraw and Remove outline, each in a column of its own so they
   line up from one row to the next. */
.area-outlines { list-style:none; margin:0; padding:0; display:grid; gap:6px; }
.area-outlines li {
  display:grid; grid-template-columns:minmax(0, 1fr) repeat(3, minmax(0, 9.5rem)); align-items:center; gap:6px 10px;
}
.area-outlines li.muted { display:block; }
.area-outlines .area-outline-name { font-weight:600; overflow-wrap:anywhere; }
/* The column sets the width, so the words wrap inside it (050: "Show on
   drawing" spilled out of a phone's column). */
.area-outlines li > button { min-height:40px; width:100%; height:auto; padding-inline:8px;
  white-space:normal; line-height:1.2; text-align:center; overflow-wrap:anywhere; }
@media (max-width:560px) {
  .area-outlines li { grid-template-columns:repeat(3, minmax(0, 1fr)); }
  .area-outlines .area-outline-name { grid-column:1 / -1; }
}
/* A separate, labelled row for the next drawing: the label, the drawing, Draw. */
.area-draw-on {
  display:flex; flex-wrap:wrap; align-items:center; gap:8px 10px;
  margin-top:12px; padding-top:12px; border-top:1px solid var(--line);
}
.area-draw-on[hidden] { display:none; }
/* The dialog rule gives every label a top margin and small capitals; here the
   label is a plain sentence beside the control, so it must not push the row
   taller. */
.area-draw-on label {
  margin:0; font-size:13.5px; font-weight:600; color:var(--ink2); text-transform:none; letter-spacing:0;
}
.area-draw-on select { width:auto; flex:0 1 240px; min-width:0; min-height:40px; font-size:13.5px; text-transform:none; letter-spacing:0; }
.area-draw-on button { min-height:40px; }
.area-history { list-style:none; margin:0; padding:0; display:grid; gap:8px; }
.area-history li { display:grid; gap:1px; padding-left:10px; border-left:2px solid var(--line2); }
.area-history-what { font-weight:600; font-size:13.5px; }
.area-history-when { color:var(--muted); font-size:12px; }
.area-history-note { color:var(--ink2); font-size:13px; white-space:pre-wrap; }
.area-add-dlg { width:min(440px, 92vw); }

/* On the drawing. The layer sits under the snags, so a snag balloon is never
   hidden by an area label. Labels take clicks only on the area drawing; in
   the snag and progress drawings a click belongs to the drawing. */
#drawing-area-layer { position:absolute; inset:0; pointer-events:none; }
#drawing-area-layer[hidden] { display:none; }
#drawing-area-layer svg { position:absolute; inset:0; overflow:visible; }
/* Every area has the same see-through fill in its stage colour, drawn as
   its own shape, and a border clipped inside it (051). */
#drawing-area-layer polygon.area-fill {
  fill:color-mix(in srgb, var(--area-colour) 16%, transparent); stroke:none;
}
#drawing-area-layer polygon.area-border {
  fill:none; stroke:var(--area-colour); stroke-linejoin:round;
}
#drawing-area-layer polygon.is-subdued { opacity:.45; }
.drawing-area-label {
  position:absolute; transform:translate(-50%, -50%); display:grid; justify-items:center; gap:0;
  min-width:30px; min-height:30px; max-width:160px; padding:3px 8px; border-radius:8px;
  border:2px solid var(--area-colour); background:#ffffff; color:#1f1f1f;
  font:600 12px/1.15 'Public Sans', "Segoe UI", system-ui, sans-serif; text-align:center;
  box-shadow:0 1px 3px rgba(0,0,0,.18); pointer-events:none;
}
.drawing-area-label b { font-size:14px; }
.drawing-area-label span { font-weight:500; font-size:11px; max-width:150px; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
.drawing-area-label.is-subdued { opacity:.5; }
#drawing-area-layer.is-interactive .drawing-area-label { pointer-events:auto; cursor:pointer; }
.drawing-viewer-dlg button.drawing-area-label { min-width:30px; min-height:30px; -webkit-tap-highlight-color:transparent; }
/* The label is a sign on the sheet, not a page button. The site-wide
   button:hover fill (--card2, near black in Dark and Delmatic) must never
   reach it, and a touch screen keeps :hover after a tap, so the fill stayed
   until the next tap (049). The label stays white in every state; a mouse
   gets a lifted shadow, and a selected label wears the shared selected
   outline (.drawing-located). */
.drawing-viewer-dlg button.drawing-area-label:is(:hover, :active, :focus) {
  background:#ffffff; color:#1f1f1f; border-color:var(--area-colour);
}
@media (hover:hover) {
  #drawing-area-layer.is-interactive .drawing-area-label:hover { box-shadow:0 2px 6px rgba(0,0,0,.32); }
}
.drawing-target-page.marking .drawing-area-label, .drawing-target-page.filling .drawing-area-label { opacity:.35; }
.drawing-target-page.filling { cursor:crosshair; }
#area-draw-layer { position:absolute; inset:0; pointer-events:none; overflow:visible; }
.area-draw-fill { fill:color-mix(in srgb, #3b82f6 14%, transparent); stroke:none; }
#area-draw-layer .snag-mark-join { stroke:#1f5fbf; }
#area-draw-layer .snag-mark-dot { stroke:#1f5fbf; }
#area-draw-layer .snag-mark-dot.last { fill:#1f5fbf; }
#area-draw-layer .snag-mark-dot.snapped { fill:#6c972a; stroke:#ffffff; }
.area-barrier { stroke:#d03b3b; stroke-linecap:round; stroke-dasharray:6 5; }
.area-draw-toolbar .area-draw-name { display:flex; }
.area-draw-toolbar .area-draw-name input { width:min(220px, 60vw); padding-inline:10px; }
.drawing-tool-btn.on { background:var(--card2); box-shadow:inset 0 0 0 1px var(--ink2); }

/* The area drawing: the progress comparison and the change list are not part
   of it. CSS only adds hiding, for the reason given above the snag drawing. */
.drawing-viewer-dlg.area-viewer #drawing-mode-toolbar,
.drawing-viewer-dlg.area-viewer #drawing-newwork-control,
.drawing-viewer-dlg.area-viewer #drawing-newwork-status,
.drawing-viewer-dlg.area-viewer #drawing-markers-status,
.drawing-viewer-dlg.area-viewer #drawing-current-control,
.drawing-viewer-dlg.area-viewer #drawing-overlay-control,
.drawing-viewer-dlg.area-viewer #drawing-overlay-strength-control,
.drawing-viewer-dlg.area-viewer #drawing-overlay-status,
.drawing-viewer-dlg.area-viewer #drawing-change-panel,
.drawing-viewer-dlg.area-viewer #drawing-panel-collapse,
.drawing-viewer-dlg.area-viewer #drawing-snag-mark-edit,
.drawing-viewer-dlg.area-viewer #drawing-emergency-work-list,
.drawing-viewer-dlg.area-viewer #drawing-viewer-download-markers { display:none; }
.drawing-area-panel { grid-row:3; }
.drawing-area-panel[hidden] { display:none; }
.drawing-area-summary { padding:10px 0; border-bottom:1px solid var(--line2); }
.drawing-area-summary .note { margin:8px 0 0; }
.drawing-area-selected { padding:10px 0; border-bottom:1px solid var(--line2); }
.drawing-area-selected[hidden] { display:none; }
.drawing-area-selected-title { margin:0; display:flex; flex-wrap:wrap; align-items:center; gap:6px 10px; }
.drawing-area-selected .note { margin:6px 0 0; }
.drawing-area-selected-actions { display:flex; flex-wrap:wrap; gap:6px; margin:8px 0 0; }
.drawing-area-list { list-style:none; margin:8px 0 0; padding:0; overflow:auto; display:grid; gap:4px; }
.drawing-area-row {
  display:grid; grid-template-columns:auto auto minmax(0,1fr) auto; align-items:center; gap:8px;
  width:100%; padding:8px 10px; border:1px solid var(--line2); border-radius:8px;
  background:transparent; color:var(--ink); font:inherit; font-size:13px; text-align:left; cursor:pointer;
}
.drawing-area-row span:not(.area-swatch) { overflow:hidden; text-overflow:ellipsis; white-space:nowrap; color:var(--ink2); }
.drawing-area-row small { color:var(--muted); font-size:11.5px; }
.drawing-area-row.is-selected { border-color:var(--accent); background:var(--chip-pass-bg); }
@media (max-width:760px) {
  #page-areas .filter-search { width:100%; }
  .areas-floor-bar { display:none; }
}
.areas-floor-table tbody th { text-transform:none; letter-spacing:0; color:var(--ink); font-size:13.5px; font-weight:650; }

/* ── Witnessing (feature 018, phase 3) ─────────────────────────────────────── */
#areas-visits-card .areas-summary-head { align-items:center; }
.witness-visits { list-style:none; margin:10px 0 0; padding:0; }
.witness-visit {
  display:grid; grid-template-columns:minmax(0,1fr) auto; gap:10px 16px; align-items:start;
  padding:12px 4px; border-top:1px solid var(--line);
}
.witness-visit:first-child { border-top:0; }
.witness-visit-title { margin:0; font-size:14px; }
.witness-visit-title b { margin-right:6px; }
.witness-visit .note { margin:3px 0 0; }
.witness-visit-areas { display:flex; flex-wrap:wrap; gap:4px; margin:6px 0 0; }
.witness-chip {
  display:inline-flex; align-items:center; gap:4px; padding:2px 8px; border-radius:999px;
  border:1px solid var(--line2); font-size:12px; font-weight:600; color:var(--ink2);
}
.witness-chip small { color:var(--muted); font-weight:500; }
.witness-chip.is-passed, .witness-chip.is-passed_with_snags { background:var(--chip-pass-bg); color:var(--chip-pass-ink); border-color:transparent; }
.witness-chip.is-failed { background:var(--chip-fail-bg); color:var(--chip-fail-ink); border-color:transparent; }
.witness-chip.is-not_witnessed { background:var(--chip-na-bg); color:var(--chip-na-ink); border-color:transparent; }
.witness-visit-actions { display:flex; flex-wrap:wrap; justify-content:flex-end; gap:6px; }
.witness-visit-actions button { min-height:36px; }
.witness-visit-dlg { width:min(720px, 94vw); }
.witness-visit-dlg h2 { margin:14px 0 6px; }
.witness-visit-fields { display:grid; grid-template-columns:repeat(auto-fit, minmax(200px, 1fr)); gap:0 12px; }
.witness-visit-picker { margin-top:14px; border-top:1px solid var(--line); padding-top:10px; }
.witness-visit-picker-head { display:flex; flex-wrap:wrap; align-items:center; gap:6px 12px; margin:0 0 8px; }
.witness-visit-picker-head .marker-visibility-control { margin-left:auto; }
.witness-visit-areas { max-height:40dvh; overflow:auto; }
.witness-area-group { border:0; margin:0 0 8px; padding:0; }
.witness-area-group legend { font-size:12px; font-weight:700; color:var(--muted); padding:0 0 4px; }
.witness-area-choice { display:flex; flex-wrap:wrap; align-items:center; gap:6px 8px; padding:6px 4px; border-top:1px solid var(--line); font-size:13.5px; }
.witness-area-choice span { color:var(--ink2); }
.witness-again { color:var(--chip-fail-ink); font-weight:700; }
.witness-record-dlg { width:min(760px, 94vw); padding:0; }
.witness-record-area { padding:14px 0; border-bottom:1px solid var(--line); }
.witness-record-area header { display:flex; flex-wrap:wrap; align-items:baseline; gap:4px 12px; }
.witness-record-area h3 { margin:0; font-size:15px; }
.witness-outcomes { display:flex; flex-wrap:wrap; gap:6px 16px; margin:10px 0 2px; font-size:13.5px; }
.witness-outcomes label { display:inline-flex; align-items:center; gap:6px; min-height:36px; }
.witness-failed-items { margin-top:10px; }
.witness-failed-head { margin:0 0 6px; font-weight:600; font-size:13px; }
.witness-failed-row { display:grid; grid-template-columns:minmax(0,1fr) minmax(120px,200px) auto; gap:6px; margin-bottom:6px; }
.witness-failed-row input, .witness-failed-row select { min-height:36px; }
.witness-scans { list-style:none; margin:0; padding:0; display:grid; gap:4px; }
.witness-scans li { display:flex; flex-wrap:wrap; gap:8px; align-items:baseline; }
.area-print-dlg { width:min(520px, 94vw); }
.area-print-kinds { border:0; margin:10px 0; padding:0; display:grid; gap:6px; }
.area-print-kinds .check-label { align-items:flex-start; padding:8px 10px; border:1px solid var(--line2); border-radius:8px; }
.area-print-kinds .check-label span { display:grid; gap:2px; }
.area-print-kinds small { color:var(--muted); font-size:12px; }
.area-print-choices { border:0; margin:10px 0; padding:0; }
.area-print-choices legend { font-size:12px; font-weight:700; color:var(--muted); padding:0 0 4px; }
.area-print-choices > div { display:flex; flex-wrap:wrap; gap:4px 16px; }
.area-report-dlg { box-sizing:border-box; width:min(1000px,96vw); height:92dvh; max-width:none; }
#area-report-frame, #precom-report-frame { width:100%; height:calc(100% - 70px); border:1px solid var(--line2); background:white; }
#precom-work-report-frame { width:100%; height:calc(100% - 70px); border:1px solid var(--line2); background:white; }

/* The contractor check work sheet (036 delivery c). Its own classes only, so
   no other report family changes. It sits inside .snag-report-document and
   takes that paper model: A4, the running head, the page footer. The image
   sizes are the ones precom-work-sheet.js sizes its marks and labels for:
   a close-up is printed 182 mm wide (PRINT_WIDTH_MM) and the whole floor is
   fitted into 182 x 236 mm (ADDENDUM_BOX_MM). */
.precom-work-head { display:grid; grid-template-columns:minmax(0,1fr) 64mm; gap:5mm; align-items:start; margin-bottom:3mm; }
.precom-work-head h1, .precom-work-addendum-head h1 { margin:1mm 0; font-size:20px; line-height:1.15; overflow-wrap:anywhere; }
.precom-work-head p, .precom-work-addendum-head p { margin:0; color:var(--sr-muted); }
.precom-work-head .eyebrow, .precom-work-addendum-head .eyebrow { color:var(--sr-muted); font-size:9.5px; font-weight:700; letter-spacing:.08em; text-transform:uppercase; }
.precom-work-locator, .precom-work-detail, .precom-work-floor { margin:0; }
.precom-work-locator img { display:block; box-sizing:border-box; width:64mm; height:40mm; object-fit:contain; border:1px solid var(--sr-line); background:#fff; }
.precom-work-locator figcaption { margin-top:1mm; color:var(--sr-muted); font-size:8.5px; }
.precom-work-detail { margin-bottom:3mm; }
.precom-work-detail img { display:block; box-sizing:border-box; width:100%; height:auto; border:1px solid var(--sr-line); background:#fff; }
.precom-work-addendum-head { margin-bottom:3mm; }
.precom-work-floor img { display:block; width:100%; height:236mm; object-fit:contain; background:#fff; }
.snag-report-document table.precom-work-rows { table-layout:fixed; }
.precom-work-rows th:first-child { width:13mm; }
.precom-work-rows th:nth-child(2) { width:24mm; }
.precom-work-rows th:nth-child(3) { width:25mm; }
.precom-work-rows th.precom-work-done { width:13mm; text-align:center; }
.precom-work-rows th.precom-work-graphic { width:44mm; }
.precom-work-rows td.precom-work-done { text-align:center; }
.precom-work-number { font-weight:800; }
.precom-work-note { overflow-wrap:anywhere; white-space:pre-wrap; }
.precom-work-results { display:flex; flex-direction:column; align-items:flex-start; gap:3px; white-space:normal; }
.precom-work-result { font-weight:700; }
.precom-work-tick { display:inline-block; box-sizing:border-box; width:4.5mm; height:4.5mm; border:1.5px solid #1b2119; background:#fff; vertical-align:middle; }
.precom-work-continued h2, .precom-work-unavailable h2 { margin:0 0 3mm; font-size:15px; }
.precom-work-unavailable p { margin:0 0 3mm; padding:2mm 3mm; border-inline-start:4px solid #a76800; background:#fff5dd; }
@media print {
  .precom-work-detail img, .precom-work-floor img, .precom-work-locator img { break-inside:avoid; }
  .precom-work-unavailable p, .precom-work-tick { -webkit-print-color-adjust:exact; print-color-adjust:exact; }
}

/* The printed documents. They sit inside .snag-report-document, so they take
   its type, colours and page frame, and the running head and footer. */
.area-print-kicker { margin:0; color:var(--sr-muted); font-size:9.5px; font-weight:700; letter-spacing:.08em; text-transform:uppercase; }
.area-print-head { display:flex; justify-content:space-between; align-items:flex-start; gap:10px; margin-bottom:4mm; }
.area-print-head h1 { margin:1mm 0 0; font-size:21px; line-height:1.15; }
.area-print-head h1 span { font-weight:500; color:#39412f; }
.area-print-state {
  display:inline-flex; align-items:center; gap:5px; padding:2px 8px 2px 6px; border-radius:999px; white-space:nowrap;
  font-size:10px; font-weight:700; border:1px solid var(--area-colour); color:#1b2119;
  background:color-mix(in srgb, var(--area-colour) 14%, #fff);
  -webkit-print-color-adjust:exact; print-color-adjust:exact;
}
.area-print-state::before { content:""; width:7px; height:7px; border-radius:50%; background:var(--area-colour); }
.area-print-drawings { display:grid; grid-template-columns:1fr; gap:2mm; margin-bottom:3mm; break-inside:avoid; }
.area-print-drawings figure { margin:0; }
.area-print-drawings img, .area-print-overview img { display:block; width:100%; object-fit:contain; border:1px solid var(--sr-line); }
.area-print-locator img { height:46mm; }
.area-print-detail img { height:78mm; }
.area-print-drawings figcaption { margin-top:1mm; color:var(--sr-muted); font-size:9px; }
.area-print-overview { margin:0 0 3mm; }
.area-print-overview img { max-height:120mm; }
.area-print-overview.is-full img { max-height:210mm; }
.area-print-block { margin:0 0 3.5mm; break-inside:avoid; }
.area-print-block h3 { margin:0 0 1.5mm; font-size:10.5px; text-transform:uppercase; letter-spacing:.06em; color:#39412f; }
.area-print-facts { display:grid; grid-template-columns:repeat(5,minmax(0,1fr)); gap:2mm; margin:0; }
.area-print-facts div { padding:2mm 2.5mm; border:1px solid var(--sr-line); background:var(--sr-soft); }
.area-print-facts div.is-complete { border-color:#9dc368; }
.area-print-facts dt { color:var(--sr-muted); font-size:8.5px; font-weight:700; text-transform:uppercase; letter-spacing:.05em; }
.area-print-facts dd { margin:1mm 0 0; font-size:13px; font-weight:700; }
.area-print-muted { color:var(--sr-muted); font-size:9.5px; margin:1mm 0; }
.area-print-history { margin:0; padding-inline-start:5mm; }
.area-print-history li span { display:block; color:var(--sr-muted); }
.area-print-signoff { padding:3mm; border:1px solid #9dc368; }
.area-print-ticks { display:flex; flex-wrap:wrap; gap:3mm 8mm; margin:0 0 3mm; font-size:11px; font-weight:600; }
.area-print-tick { display:inline-flex; align-items:center; gap:2mm; }
.area-print-box { display:inline-block; width:4.2mm; height:4.2mm; border:.4mm solid #1b2119; box-sizing:border-box; }
.area-print-comments { height:24mm; margin-bottom:3mm; border:1px solid var(--sr-line);
  background:repeating-linear-gradient(to bottom, transparent 0 7.6mm, #e3e7de 7.6mm 7.9mm); }
.area-print-comments span { display:block; padding:1mm 2mm; color:var(--sr-muted); font-size:8.5px; }
.area-print-sign { margin-top:2mm; }
.area-print-sign-role { margin:0 0 1mm; font-size:9px; font-weight:700; text-transform:uppercase; letter-spacing:.06em; color:#39412f; }
.area-print-sign-grid { display:grid; grid-template-columns:1.2fr 1.4fr .8fr; gap:3mm; }
.area-print-sign-grid div { border-bottom:.3mm solid #1b2119; min-height:9mm; display:flex; flex-direction:column; justify-content:space-between; }
.area-print-sign-grid span { color:var(--sr-muted); font-size:8px; }
.area-print-sign-grid b { font-size:10.5px; font-weight:600; }
.area-print-legend { list-style:none; display:flex; flex-wrap:wrap; gap:2mm 6mm; margin:0 0 3mm; padding:0; font-size:9.5px; }
.area-print-legend li { display:inline-flex; align-items:center; gap:1.5mm; }
.area-print-swatch { display:inline-block; width:4mm; height:3mm; border:.5mm solid var(--area-colour);
  background:color-mix(in srgb, var(--area-colour) 22%, #fff); -webkit-print-color-adjust:exact; print-color-adjust:exact; }
.area-print-worklist td small { display:block; color:var(--sr-muted); }
.area-print-done { width:12mm; text-align:center; }
.area-print-index td:first-child b { margin-right:2mm; }
.area-print-index-outcome { width:34mm; border-bottom:1px solid var(--sr-line); }
.area-print-worklist { table-layout:fixed; }
.area-print-worklist th { font-size:8.5px; letter-spacing:.03em; white-space:normal; }
.area-print-worklist th:nth-child(1) { width:26%; }
.area-print-worklist th:nth-child(2) { width:17%; }
.area-print-worklist th:nth-child(3), .area-print-worklist th:nth-child(4),
.area-print-worklist th:nth-child(5), .area-print-worklist th:nth-child(6) { width:8%; }
.area-print-worklist th:nth-child(7) { width:19%; }
.area-print-worklist th:nth-child(8) { width:6%; }
.area-print-worklist .area-print-state { white-space:normal; }

/* ── Names from drawings (feature 018, phase 4) ────────────────────────────── */
#drawing-name-layer { position:absolute; inset:0; pointer-events:none; }
#drawing-name-layer[hidden] { display:none; }
#drawing-name-layer svg { position:absolute; inset:0; overflow:visible; }
#drawing-name-layer polygon {
  fill:rgba(59,130,246,.06); stroke:#1f5fbf; stroke-width:2; stroke-dasharray:7 5;
  pointer-events:visiblePainted; cursor:pointer;
}
#drawing-name-layer polygon:hover { fill:rgba(59,130,246,.16); }
.drawing-name-marker {
  position:absolute; transform:translate(-50%, -50%); pointer-events:auto; cursor:pointer;
  max-width:180px; padding:2px 8px; border-radius:999px; border:1.5px dashed #1f5fbf;
  background:#ffffff; color:#1f3f7a; font:600 11px/1.3 'Public Sans', "Segoe UI", system-ui, sans-serif;
  white-space:nowrap; overflow:hidden; text-overflow:ellipsis; box-shadow:0 1px 3px rgba(0,0,0,.15);
}
.drawing-viewer-dlg button.drawing-name-marker { min-width:0; min-height:24px; }
.drawing-name-marker:hover, .drawing-name-marker:focus-visible { background:#eaf1fd; }
#drawing-names-hint { font-size:12.5px; }
.area-names-dlg { width:min(640px, 94vw); }
.area-names-list { display:grid; gap:4px; max-height:55dvh; overflow:auto; margin:8px 0; }
.area-name-layer {
  display:grid; grid-template-columns:auto minmax(140px, 220px) minmax(0,1fr); gap:10px; align-items:start;
  padding:8px; border:1px solid var(--line2); border-radius:8px;
}
.area-name-layer-main { display:grid; gap:2px; }
.area-name-layer-main small { color:var(--muted); font-size:12px; }
.area-name-layer-examples { display:flex; flex-wrap:wrap; gap:4px; }
.area-name-layer-examples span { padding:1px 7px; border-radius:999px; background:var(--card2); font-size:12px; color:var(--ink2); }
/* The area drawing carries more tools than the others, so its toolbar wraps
   rather than pushing the heading off the left of the screen. Keeping a
   drawing for offline belongs to the site views, not to drawing areas. */
.drawing-viewer-dlg.area-viewer .drawing-target-toolbar { flex-wrap:wrap; justify-content:flex-end; min-width:0; }
.drawing-viewer-dlg.area-viewer #drawing-offline-control,
.drawing-viewer-dlg.area-viewer #drawing-offline-status { display:none; }
.drawing-viewer-dlg.area-viewer .drawing-toolbars > #drawing-target-toolbar { flex:1 1 100%; }
.drawing-viewer-dlg.area-viewer #drawing-snags-status { flex:1 1 220px; min-width:0; white-space:normal; text-align:right; }

/* ── The drawing viewer on a phone (feature 027, phase 2) ─────────────────────
   Measured on a 393x659 iPhone, the drawing got 9% of the screen: two stacked
   toolbars, a row of downloads and a panel floating over the zoom buttons left
   it a 61px strip. On a phone the drawing comes first:

     row 1  the title, Controls and Close, with the status as one line below
     row 3  the drawing, which takes everything the other rows do not
     row 4  the general drawing information
     row 5  the area, change or snag panel, under the drawing, never over it
     row 6  the marking strip, then the toolbars when Controls is open
     row 7  the downloads, when Controls is open

   While a tool is armed, rows 4 and 5 are empty. The information moves to
   row 7, after the marking strip, and the downloads move to row 8.

   Row 2 is where the toolbars sit on a wide screen; here it is empty. The
   panels give way while Controls is open or a tool is armed, so the drawing
   keeps more than half the screen in every state. Desktop is not affected:
   everything here is inside the phone width. */
.drawing-viewer-controls { display:none; }
.drawing-viewer-controls svg {
  width:18px; height:18px; fill:none; stroke:currentColor; stroke-width:1.6;
  stroke-linecap:round; stroke-linejoin:round; flex:none;
}
@media (max-width:760px) {
  /* See-through dialogs let the page behind show through the title. */
  dialog { background:var(--card); }
  .drawing-viewer-dlg,
  .drawing-viewer-dlg.has-snag-selection {
    background:var(--page);
    grid-template-columns:minmax(0,1fr);
    grid-template-rows:auto 0 minmax(0,1fr) auto auto auto auto;
    row-gap:0; overflow:hidden;
  }

  .drawing-viewer-head {
    display:grid; grid-template-columns:minmax(0,1fr) auto auto auto; align-items:center;
    column-gap:8px; row-gap:2px; margin-bottom:6px;
  }
  .drawing-viewer-head > div:first-child {
    display:grid; grid-template-columns:auto minmax(0,1fr); grid-template-areas:"eyebrow label" "title title";
    align-items:center; column-gap:8px; min-width:0;
  }
  .drawing-viewer-head .eyebrow { grid-area:eyebrow; margin:0; font-size:10.5px; }
  .drawing-viewer-head h2 {
    grid-area:title; min-width:0; margin:0; font-size:16px; line-height:1.25;
    overflow:hidden; text-overflow:ellipsis; white-space:nowrap;
  }
  .drawing-viewer-head .drawing-target-label { grid-area:label; justify-self:start; min-width:0; overflow:hidden; }
  .drawing-viewer-head #drawing-viewer-message {
    grid-column:1 / -1; grid-row:2; margin:0; font-size:12px; line-height:1.35;
    white-space:nowrap; overflow:hidden; text-overflow:ellipsis;
  }
  .drawing-viewer-head #drawing-viewer-message:empty { display:none; }
  .drawing-viewer-dlg.controls-open #drawing-viewer-message { white-space:normal; }
  .drawing-viewer-head #drawing-viewer-controls { grid-row:1; grid-column:2; }
  .drawing-viewer-head #drawing-legend-open { grid-row:1; grid-column:3; }
  .drawing-viewer-head #drawing-viewer-close { grid-row:1; grid-column:4; }
  .drawing-viewer-controls {
    display:inline-flex; align-items:center; gap:6px; padding-inline:10px; white-space:nowrap;
  }
  /* Open is a chosen state, so it wears the solid fill (design rule 1). */
  .drawing-viewer-controls[aria-expanded="true"] {
    background:var(--accent); color:var(--btn-ink); border-color:var(--accent);
  }

  /* Under the drawing, never over it: the zoom buttons stay free (F02). */
  .drawing-viewer-dlg > .drawing-change-panel,
  .drawing-viewer-dlg > .snag-detail-panel {
    grid-row:5; grid-column:1; justify-self:stretch; align-self:stretch; z-index:auto;
    box-sizing:border-box; width:auto; height:auto; max-height:30dvh; margin:6px 0 0;
    overflow:auto;
  }
  .drawing-viewer-dlg.controls-open > :is(.drawing-change-panel, .snag-detail-panel),
  .drawing-viewer-dlg:has(#snag-mark-toolbar:not([hidden]), #area-draw-toolbar:not([hidden]), #graphic-select-toolbar:not([hidden]))
    > :is(.drawing-change-panel, .snag-detail-panel) { display:none; }

  .drawing-viewer-dlg > .drawing-toolbars {
    grid-row:6; display:flex; flex-direction:column; flex-wrap:nowrap; align-items:stretch; gap:8px;
    margin-top:6px; padding:0; border:0; background:none;
  }
  .drawing-viewer-dlg:not(.controls-open) :is(#drawing-mode-toolbar, #drawing-target-toolbar),
  .drawing-viewer-dlg:not(.controls-open) > .drawing-viewer-actions { display:none; }
  .drawing-viewer-dlg:not(.controls-open) #drawing-target-toolbar:has(#drawing-snag-selection-tools:not([hidden])) { display:flex; }
  .drawing-viewer-dlg:not(.controls-open) #drawing-target-toolbar:has(#drawing-snag-selection-tools:not([hidden])) > :not(#drawing-snag-selection-tools) { display:none; }
  .drawing-viewer-dlg.controls-open > .drawing-toolbars {
    max-height:45dvh; overflow:auto; padding:8px;
    border:1px solid var(--line); border-radius:10px; background:var(--card2);
  }
  .drawing-viewer-dlg.controls-open > .drawing-viewer-actions { grid-row:7; margin-top:6px; }
  .drawing-viewer-dlg.controls-open > .drawing-viewer-actions > * { flex:1 1 auto; }
  .drawing-viewer-dlg:has(#snag-mark-toolbar:not([hidden]), #area-draw-toolbar:not([hidden]), #graphic-select-toolbar:not([hidden]))
    > .drawing-status-footer { grid-row:7; }
  .drawing-viewer-dlg.controls-open:has(#snag-mark-toolbar:not([hidden]), #area-draw-toolbar:not([hidden]), #graphic-select-toolbar:not([hidden]))
    > .drawing-viewer-actions { grid-row:8; }

  /* The marking strip: right under the drawing, three short rows at most.
       Spots | Corners | Rectangle      Remove last
       Marking #12 - subject             Cancel  Save mark
       Tap the drawing where the fault is.
     The area strip adds its name field above. */
  .drawing-toolbars > .snag-mark-toolbar:not([hidden]) {
    order:-1; display:grid; grid-template-columns:minmax(0,1fr) auto auto;
    grid-template-areas:"name name name" "shape shape undo" "what end end" "status end end";
    align-items:center; gap:4px 8px; margin:0; padding:6px 8px;
  }
  .snag-mark-toolbar > .area-draw-name { grid-area:name; }
  .snag-mark-toolbar > .area-draw-name input { width:100%; }
  .snag-mark-toolbar > .shape-choice { grid-area:shape; display:flex; min-width:0; }
  .snag-mark-toolbar > .shape-choice button { flex:1 1 0; min-width:0; padding-inline:6px; }
  .snag-mark-toolbar > #snag-mark-undo, .snag-mark-toolbar > #area-draw-undo { grid-area:undo; padding-inline:10px; }
  .snag-mark-toolbar > .snag-mark-what {
    grid-area:what; align-self:end; min-width:0; font-size:12px;
    overflow:hidden; text-overflow:ellipsis; white-space:nowrap;
  }
  .snag-mark-toolbar > .snag-mark-status { grid-area:status; align-self:start; line-height:1.3; }
  .snag-mark-toolbar > .snag-mark-end { grid-area:end; justify-self:end; margin:0; }
  #graphic-select-toolbar { grid-template-columns:minmax(0,1fr); grid-template-areas:"shape" "status" "end"; }
  #graphic-select-toolbar .snag-mark-end { justify-self:stretch; justify-content:space-between; flex-wrap:wrap; }
  #graphic-select-panel:not([hidden]) { order:-1; max-height:24dvh; overflow:auto; }
}

/* Review, 28 September 2026. */
/* One scroll bar: the dialog holds still and only its body scrolls. */
.area-dlg[open] { display:flex; flex-direction:column; max-height:92dvh; overflow:hidden; }
.area-dlg > .area-dlg-body, .area-dlg > form.area-dlg-body { flex:1 1 auto; min-height:0; max-height:none; overflow:auto; }
.area-dlg-head { flex:0 0 auto; }
/* Choices read left to right: the control first, then its words. The
   dialog rule gives every input full width and upper-cases every label,
   which stood a radio button alone above its sentence. */
.area-print-dlg .check-label, .witness-visit-dlg .check-label {
  display:grid; grid-template-columns:auto minmax(0,1fr); align-items:start; gap:10px;
  margin:0; text-transform:none; letter-spacing:0; font-size:13.5px; font-weight:500; color:var(--ink);
}
.area-print-dlg input[type=radio], .area-print-dlg input[type=checkbox] { width:auto; margin:2px 0 0; }
.area-print-kinds .check-label b { font-weight:650; }
.area-print-kinds .check-label small { text-transform:none; letter-spacing:0; }
.area-print-choices > div:not(.area-floor-picker-list) { display:flex; flex-wrap:wrap; gap:6px 18px; }
.area-print-choices .check-label { display:inline-grid; }
.area-floor-picker { border:1px solid var(--line2); border-radius:8px; background:var(--card2); }
.area-floor-picker > summary { cursor:pointer; padding:9px 12px; font-size:13.5px; list-style:none; }
.area-floor-picker > summary::-webkit-details-marker { display:none; }
.area-floor-picker > summary::after { content:"▾"; float:right; color:var(--muted); }
.area-floor-picker-panel { padding:8px 10px 10px; border-top:1px solid var(--line2); }
.area-floor-picker-actions { display:flex; gap:14px; margin:6px 0; font-size:12.5px; }
.area-floor-picker-list { display:grid; gap:4px; max-height:32dvh; overflow:auto; }
.area-floor-picker-list .check-label[hidden] { display:none; }
/* The worksheet: every column has room, and the tick box has its own. */
.area-print-worklist th { letter-spacing:0; }
.area-print-worklist td { overflow-wrap:anywhere; }
.area-print-worklist th:nth-child(1) { width:20%; }
.area-print-worklist th:nth-child(2) { width:15%; }
.area-print-worklist th:nth-child(3) { width:10%; }
.area-print-worklist th:nth-child(4) { width:9%; }
.area-print-worklist th:nth-child(5) { width:10%; }
.area-print-worklist th:nth-child(6) { width:7%; }
.area-print-worklist th:nth-child(7) { width:21%; }
.area-print-worklist th:nth-child(8) { width:8%; }
.area-print-worklist td.area-print-done { text-align:center; padding-left:0; padding-right:0; }
.area-floor-picker .filter-search { width:100%; margin:0; text-transform:none; letter-spacing:0; }
.area-floor-picker .filter-search input { width:100%; }
.area-print-worklist td { white-space:normal; }
.area-print-worklist td:nth-child(7) { padding-right:3mm; }
.area-print-worklist .area-print-done { width:auto; }

/* Walls from drawings (feature 018, phase 5): the layer list beside a
   preview of what the fill will treat as walls. */
.area-walls-dlg { width:min(1100px, 96vw); }
.area-walls-body { display:grid; grid-template-columns:minmax(240px, 340px) minmax(0,1fr); gap:16px; align-items:start; }
.area-wall-layer { grid-template-columns:auto minmax(0,1fr); }
.area-walls-figure { margin:0; display:grid; gap:6px; }
.area-walls-figure canvas { width:100%; height:auto; border:1px solid var(--line2); border-radius:8px; background:#fff; }
@media (max-width: 720px) { .area-walls-body { grid-template-columns:minmax(0,1fr); } }
#drawing-walls-hint { font-size:12.5px; }
/* The dialog rule upper-cases every label; layer names and counts read as written. */
.area-walls-dlg .area-wall-layer, .area-walls-dlg .area-wall-layer small { text-transform:none; letter-spacing:0; }
.area-walls-dlg .area-wall-layer b { font-weight:650; color:var(--ink); }
.area-walls-dlg .area-wall-layer input { width:auto; margin:2px 0 0; }

/* ── Every list and text field starts from one look ─────────────────────────
   Before this, a drop-down or field that no rule styled fell back to the
   browser's own box: square, white, a 2 px border on dates. The controls sweep
   (tests/browser/controls.local.mjs) found them on Snags, Action Centre,
   Database checks and Drawings. :where() gives these rules no weight at all,
   so any control that already has its own style keeps it; only the unstyled
   ones change. */
:root { --field-font:14px; --field-height:38px; }
:where(select, textarea,
  input:not([type=checkbox], [type=radio], [type=range], [type=color], [type=file],
            [type=hidden], [type=submit], [type=button], [type=reset], [type=image])) {
  box-sizing:border-box; min-height:var(--field-height); padding:7px 10px;
  background:var(--card2); color:var(--ink); border:1px solid var(--line2); border-radius:8px;
  font:inherit; font-size:var(--field-font); font-weight:400; text-transform:none; letter-spacing:0;
}
:where(textarea) { min-height:72px; }
:where(select, textarea, input):where(:focus-visible) { outline:2px solid var(--accent); outline-offset:-1px; }

/* Drawings: the sort beside the filters, and the tag on a floor with no
   devices yet (feature 018, phase 6). */
.drawing-sort { display:inline-flex; align-items:center; gap:6px; color:var(--muted); font-size:12.5px; }
.drawing-sort select { min-height:34px; padding:5px 8px; }
.chip.neutral { background:var(--card2); color:var(--muted); border:1px solid var(--line2); }
.drawing-card:has(.drawing-blank-chip) .drawing-thumb { opacity:.55; }

/* Areas: the worked-out build stage, and the sort beside the filters
   (feature 018, phase 6). Quiet tones: the engineer's state is the loud one. */
.areas-sort-select { display:inline-flex; align-items:center; gap:6px; color:var(--muted); font-size:12.5px; }
.areas-sort-select select { min-height:40px; }
.areas-hide-done { white-space:nowrap; }
.area-build-pill { display:inline-block; padding:2px 9px; border-radius:999px; font-size:12px; white-space:nowrap;
  border:1px solid var(--line2); color:var(--ink2); background:var(--card2); }
.area-build-pill[data-build="dropped"] { border-color:color-mix(in srgb, #3b82f6 45%, var(--line2)); }
.area-build-pill[data-build="partly"] { border-color:color-mix(in srgb, #d18b00 55%, var(--line2)); }
.area-build-pill[data-build="addressed"] { border-color:color-mix(in srgb, #6c972a 60%, var(--line2)); color:var(--ink); }
.areas-floor-build { font-size:12.5px; color:var(--ink2); }
.area-build-count { white-space:nowrap; margin-right:8px; }
.area-build-count b { color:var(--ink); }
/* With the Build column the tables must still fit the page: headings wrap
   onto two lines, the floor bar gives up width first, and the build counts
   stack one under another. */
.areas-floor-table thead th, .areas-table thead th { white-space:normal; vertical-align:bottom; }
.areas-floor-table:has(.areas-floor-build) .areas-floor-bar { width:18%; min-width:90px; }
.areas-floor-build .area-build-count { display:block; margin:0; }

/* The room checklist (feature 018, phase 6, experimental). */
.room-checklist .section-heading { display:flex; justify-content:space-between; align-items:end; gap:12px; flex-wrap:wrap; }
.room-checklist-toolbar { display:flex; flex-wrap:wrap; align-items:center; gap:8px; margin:8px 0; }
.room-checklist-toolbar .filter-search { width:240px; }
.room-floor { margin-top:14px; }
.room-floor-head { display:flex; align-items:center; gap:12px; flex-wrap:wrap; padding:6px 0; border-bottom:1px solid var(--line); }
.room-floor-head h3 { margin:0; font-size:14px; }
.room-floor-head .ghost-btn { margin-left:auto; }
.room-list { list-style:none; margin:0; padding:0; }
.room-row { display:grid; grid-template-columns:22px minmax(0,1fr) auto auto; align-items:center; gap:10px;
  padding:3px 4px; border-bottom:1px solid var(--line); font-size:13.5px; }
.room-row[data-room-status="ignored"] .room-name, .room-row[data-room-status="not_ours"] .room-name { color:var(--muted); }
.room-row input[type=checkbox] { width:16px; height:16px; margin:0; }
.room-name { overflow-wrap:anywhere; }
.room-actions { display:flex; gap:6px; }
.room-actions .ghost-btn { min-height:28px; padding:3px 10px; font-size:12.5px; }
.room-chip { display:inline-block; padding:2px 9px; border-radius:999px; font-size:12px; white-space:nowrap;
  border:1px solid var(--line2); background:var(--card2); color:var(--ink2); }
button.room-chip { cursor:pointer; min-height:0; font:inherit; font-size:12px; }
.room-chip.is-mapped { border-color:color-mix(in srgb, #6c972a 60%, var(--line2)); color:var(--ink); }
.room-chip.is-open { border-color:color-mix(in srgb, #d18b00 55%, var(--line2)); }
.area-names-checklist { margin-top:12px; }
@media (max-width:640px) {
  .room-row { grid-template-columns:22px minmax(0,1fr) auto; }
  .room-actions { grid-column:2 / -1; }
}
/* A part of the floor that is not Delmatic's: grey hatching under the areas. */
#drawing-area-layer polygon.drawing-not-ours { fill:rgba(120,120,120,.18);
  stroke:rgba(120,120,120,.8); stroke-dasharray:6 4; }
/* Names from drawings: layer names, counts and examples read as written. The
   dialog rule upper-cases every label, which turned the drawing's own text
   into capitals it never had. */
.area-names-dlg .area-name-layer, .area-names-dlg .area-name-layer small,
.area-names-dlg .area-name-layer-examples span, .area-names-dlg .area-names-checklist,
.area-names-dlg .area-names-checklist small { text-transform:none; letter-spacing:0; }
.area-names-dlg .area-name-layer b { font-weight:650; color:var(--ink); font-size:13px; }
.area-names-dlg .area-name-layer input { width:auto; margin:2px 0 0; }
.area-names-dlg .area-names-checklist { display:grid; grid-template-columns:auto minmax(0,1fr); gap:10px; align-items:start;
  font-size:13.5px; font-weight:500; color:var(--ink); }
.area-names-dlg .area-names-checklist input { width:auto; margin:3px 0 0; }
.area-names-dlg .area-names-checklist small { color:var(--muted); font-size:12.5px; font-weight:400; }

/* Imports: the history reads as a table. Five places in every row; the file
   name wraps if anything does, and the action always sits at the right. */
#page-snapshot .snapshot-history-row {
  grid-template-columns:minmax(0,2fr) minmax(96px,.8fr) minmax(0,1.5fr) minmax(0,1.1fr) minmax(104px,auto);
}
.snapshot-history-file { min-width:0; overflow-wrap:anywhere; }
.snapshot-history-state, .snapshot-history-drawings { min-width:0; }
.snapshot-history-row .chip { white-space:normal; }
.snapshot-history-action { justify-self:end; display:flex; justify-content:flex-end; }
.snapshot-history-action .ghost-btn { min-width:96px; }
.snapshot-history-action .snapshot-open-above { max-width:240px; text-align:right; }
@media (max-width:700px) {
  #page-snapshot .snapshot-history-row { grid-template-columns:1fr; }
  .snapshot-history-action { justify-self:start; }
}
/* A database the project has never had: said plainly, confirmed by a tick. */
.snapshot-map-stranger { grid-column:1 / -1; padding:10px 12px; border-radius:8px;
  border:1px solid var(--chip-warn-ink, #d18b00); background:color-mix(in srgb, #d18b00 10%, var(--card2)); }
.snapshot-map-stranger p { margin:0 0 8px; font-size:13px; color:var(--ink); }
.snapshot-map-stranger .check-label { display:grid; grid-template-columns:auto minmax(0,1fr); gap:8px; align-items:start;
  font-size:13px; font-weight:600; text-transform:none; letter-spacing:0; color:var(--ink); }
.snapshot-map-stranger input { width:auto; margin:2px 0 0; }
.snapshot-map-stranger[hidden] { display:none; }
/* The mapping rows place every input in their second column; the tick box in
   the warning stays beside its own words. */
.snapshot-map .snapshot-map-stranger input.snapshot-map-confirm { grid-column:auto; width:auto; min-height:0; padding:0; }
/* The open list of a drop-down. A drop-down with a see-through background
   (the project picker) left the browser to draw its list on white, with the
   theme's pale text on it: unreadable in the dark and Delmatic themes. Every
   list now takes the theme's own card and ink. */
select option, select optgroup { background-color:var(--card); color:var(--ink); }
select option:disabled { color:var(--muted); }

/* ── Pre-commissioning checks (feature 019) ─────────────────────────────────
   A list of module cards, grouped by floor, that works on a phone: the
   contractor declares with two taps, so the choices are full-size buttons. */
.precom-legend .chip { pointer-events:none; }
.precom-toolbar { display:flex; flex-wrap:wrap; gap:8px 12px; align-items:center; }
.precom-list { display:grid; gap:18px; margin-top:12px; }
.precom-floor h3 { margin:0 0 8px; font-size:14px; color:var(--ink2); }
.precom-floor { display:grid; gap:8px; }
.precom-row {
  display:grid; gap:4px; padding:12px 14px; border:1px solid var(--line2); border-radius:10px;
  background:var(--card); border-left-width:4px;
}
.precom-row.precom-ready { border-left-color:var(--chip-pass-ink, var(--accent)); }
.precom-row.precom-waiting { border-left-color:var(--chip-warn-ink, var(--line2)); }
.precom-row.precom-not_ready { border-left-color:var(--chip-fail-ink, var(--fail)); }
.precom-row.precom-addressed { border-left-color:var(--chip-info-ink, var(--info)); }
.precom-row-head { display:flex; flex-wrap:wrap; align-items:center; justify-content:space-between; gap:6px 12px; }
.precom-row-name {
  padding:0; border:0; background:none; color:var(--ink); font:inherit; font-size:15px; font-weight:700;
  text-align:left; cursor:pointer; min-height:0;
}
.precom-row-name:hover { text-decoration:underline; }
.precom-row p { margin:0; font-size:13px; color:var(--ink2); }
.precom-row-facts { display:flex; flex-wrap:wrap; align-items:center; gap:6px; }
.precom-row-decl { color:var(--ink) !important; }
.precom-row-pending, .precom-row-snags { font-weight:600; }
.precom-row-snags { color:var(--chip-fail-ink, var(--fail)) !important; }
.precom-row-actions { display:flex; flex-wrap:wrap; gap:8px; margin-top:6px; }
.precom-choice { flex:1 1 120px; min-height:44px; }
.precom-choice-not_ready { background:var(--card); color:var(--ink); border:1px solid var(--line2); }
.precom-add-file { display:flex; flex-wrap:wrap; align-items:center; gap:8px 16px; margin-top:10px; }
.precom-print-dates { display:grid; grid-template-columns:1fr 1fr; gap:10px; }
.precom-link { display:flex; flex-wrap:wrap; align-items:end; gap:8px; }
.snag-precom { margin-top:10px; display:grid; gap:6px; }
.precom-snag-module { display:grid; gap:4px; font-size:13px; font-weight:600; color:var(--ink2); }
.precom-snag-counted { background:var(--chip-fail-bg); color:var(--chip-fail-ink); }
.precom-snag-check { background:var(--chip-warn-bg); color:var(--chip-warn-ink); }
.precom-snag-exceptions { margin:0; font-size:13px; color:var(--ink2); }
.precom-snag-actions { display:flex; flex-wrap:wrap; gap:8px; }
.snapshot-precom-line { margin-top:10px; }
@media (max-width:600px) {
  .precom-row { padding:12px; }
  .precom-print-dates { grid-template-columns:1fr; }
}
/* On a phone the module filter wraps onto more rows instead of running past
   the edge of its box, where the last choices could not be reached. */
@media (max-width:700px) {
  #precom-filter { flex-wrap:wrap; max-width:100%; }
  #precom-filter button { flex:1 1 auto; min-height:44px; white-space:normal; }
}

/* The printed record. */
.precom-record { max-width:900px; margin:0 auto; padding:24px; color:#111; font-size:12.5px; }
.precom-record h1 { margin:2px 0 4px; font-size:22px; }
.precom-record h2 { margin:22px 0 8px; font-size:15px; }
.precom-record .precom-auto-other { break-inside:avoid; }
.precom-record-table { width:100%; border-collapse:collapse; }
.precom-record-table th, .precom-record-table td { text-align:left; vertical-align:top; padding:6px 8px; border-bottom:1px solid #ccc; }
.precom-record-table hr { border:0; border-top:1px dashed #bbb; margin:6px 0; }
/* One focus ring per field. A search box is a rounded frame with the text box
   inside it; the frame shows the ring. The site-wide focus rule also ringed
   the text box itself, which drew a second, square ring inside the first. */
.filter-search input:focus-visible,
.workspace-search-field input:focus-visible { outline:none !important; }
.workspace-search-field:focus-within { outline:2px solid var(--accent); outline-offset:-1px; }

/* Outstanding work: every row has the same columns, so the state and the
   Functional and Duration results line up down the list. Each row used to
   size its own middle column, and the results drifted with it. */
@media (min-width:1051px) {
  .emergency-work-row { grid-template-columns:minmax(0,1.3fr) 220px minmax(0,1fr); }
  .emergency-work-row.is-selecting { grid-template-columns:auto minmax(0,1.3fr) 220px minmax(0,1fr); }
  .emergency-work-row dl { display:grid; grid-template-columns:repeat(2, minmax(0,1fr)); justify-content:stretch; }
  .emergency-work-row dl div { min-width:0; }
}

/* A search field is always one line: icon, then the text box. Filter rows
   that lay their labels out as a stack (caption above the field) stacked the
   search field too, which put the icon on a line of its own. In such a row the
   search field sits on the same baseline as the drop-downs beside it. */
label.filter-search { display:flex; align-items:center; gap:7px; }
.emergency-work-filters .filter-search { align-self:end; min-height:var(--field-height, 38px); font-size:inherit; color:var(--muted); }
.emergency-work-filters .filter-search input[type="search"] { min-height:calc(var(--field-height, 38px) - 2px); }

/* Opening a page moves focus to its heading, so a screen reader announces
   the new page. The heading is not something to press, so it shows no focus
   box: the browser's default white box appeared until the next click. The
   same holds for a page or panel that takes focus for the same reason. */
:is(h1, h2, h3, main, section, aside, article)[tabindex="-1"]:focus { outline:none; }

/* The keyboard ring is for the keyboard (050). The page moves focus itself in
   many places: a heading after a page change, a dialog's first control, a
   control given back when a panel closes. A browser draws the ring on such a
   move whenever the last focus was not a mouse press, and an iPhone never
   focuses what it taps, so a green ring appeared after load and after a page
   change, and went at the next tap. app.js marks <html> with
   data-focus-ring="keyboard" from a navigation key (Tab, the arrows, Home,
   End, Page Up and Page Down) until the next press of a mouse, pen or finger.
   Until then no ring is drawn. A text field keeps its outline: it shows where
   typing goes. */
html:not([data-focus-ring="keyboard"]) :focus-visible:not(textarea, input:is(:not([type]), [type=text], [type=search],
  [type=email], [type=password], [type=number], [type=tel], [type=url], [type=date], [type=time], [type=datetime-local])),
html:not([data-focus-ring="keyboard"]) .drawing-marker-types label:has(input:focus-visible),
html:not([data-focus-ring="keyboard"]) .file-picker-input:focus-visible + .file-picker-btn { outline:none !important; }

/* The report audience switch fills its panel, so its two buttons share the
   width. They used to sit at the left and leave an empty strip inside the
   frame on the right. */
#report-audience button { flex:1 1 0; }

/* ── DALI zone drawings (feature 019, phase 2) ──────────────────────────────
   A viewer for a phone first: the whole screen, one finger to pan, two to
   pinch, and buttons big enough to tap. The sheet is drawn once at a fixed
   size and moved with a transform; names and marks ride on it and are scaled
   back so they stay readable at any zoom. */
.zone-list { display:grid; gap:8px; margin-top:12px; }
.zone-item {
  display:flex; flex-wrap:wrap; align-items:center; justify-content:space-between; gap:8px 16px;
  padding:12px 14px; border:1px solid var(--line2); border-radius:10px; background:var(--card);
}
.zone-item small { display:block; color:var(--muted); margin-top:2px; }
.zone-item-actions { display:flex; gap:8px; }
/* The riser schematic row on the Module map tab (feature 045): two outlined
   download buttons, each at least 44px high (design rule 2). */
.zone-row {
  display:flex; flex-wrap:wrap; align-items:center; justify-content:space-between; gap:8px 16px; margin-top:12px;
  padding:12px 14px; border:1px solid var(--line2); border-radius:10px; background:var(--card);
}
.zone-row > div:first-child { flex:1 1 320px; min-width:0; }
.zone-row .note { margin:4px 0 0; }
.zone-row-actions { display:flex; gap:8px; }
.zone-row-actions button { min-height:44px; min-width:64px; }
.zone-row > [role="status"] { flex:1 1 100%; margin:0; }
.zone-row > [role="status"]:empty { display:none; }
.zone-viewer-dlg {
  box-sizing:border-box; width:100vw; max-width:100vw; height:100dvh; max-height:100dvh; margin:0;
  padding:0; border:0; border-radius:0; display:flex; flex-direction:column; background:var(--page);
}
.zone-viewer-dlg:not([open]) { display:none; }
.zone-viewer-head {
  display:flex; flex-wrap:wrap; align-items:center; justify-content:space-between; gap:8px 16px;
  padding:10px 16px; border-bottom:1px solid var(--line);
}
.zone-viewer-name h2 { margin:0; font-size:17px; }
.zone-viewer-name .eyebrow { margin:0; }
.zone-viewer-tools { display:flex; flex-wrap:wrap; gap:6px; }
.zone-viewer-tools button { min-height:40px; min-width:40px; }
.zone-viewer-tools [aria-pressed="true"] { background:var(--accent); color:var(--btn-ink, #10210a); border-color:var(--accent); }
.zone-viewer-status { margin:0; padding:0 16px; min-height:0; }
.zone-viewer-status:empty { display:none; }
.zone-stage {
  position:relative; flex:1 1 auto; overflow:hidden; touch-action:none; background:#e9e9e9;
  cursor:grab; user-select:none; overflow-anchor:none;
}
/* The sheet holds the marks, names and redlines: it is the page's rectangle,
   placed by its left and top and scaled about its corner. Position reads must
   see the new value at once, also under the global reduced-motion rule, which
   sets a short nonzero transition duration (012 zoom-settle evidence).
   The picture is not in it. #zone-canvas is the window onto the sheet: it
   fills the stage, is never scaled, and the viewer paints the visible part of
   the picture into it (037, visible area). A sheet-sized canvas under a
   transform crashed iPhones. */
.zone-sheet { position:absolute; left:0; top:0; transform-origin:0 0; --zone-inverse:1; }
.zone-sheet, .zone-sheet * { transition:none !important; }
#zone-canvas { position:absolute; left:0; top:0; display:block; width:100%; height:100%; }
/* The drawing and the panel: side by side on a wide screen, the panel at the
   right and the drawing shrinking to the rest, so the panel never covers it. */
.zone-body { position:relative; flex:1 1 auto; min-height:0; display:flex; }
.zone-body > .zone-stage-wrap { flex:1 1 auto; min-width:0; }
.zone-overlay { position:absolute; inset:0; pointer-events:none; }
.zone-chip, .zone-mark {
  position:absolute; pointer-events:auto; transform:translate(-50%, -50%) scale(var(--zone-inverse));
  transform-origin:center; white-space:nowrap; cursor:pointer;
}
.zone-chip {
  padding:3px 8px; min-height:0; border-radius:999px; border:1.5px solid currentColor;
  font:600 12px/1.2 'Public Sans', sans-serif; background:#fff;
}
.zone-chip.tone-pass { color:#3d5a10; background:#eef6dd; }
.zone-chip.tone-warn { color:#7a4e0c; background:#fdf0d2; }
.zone-chip.tone-fail { color:#a92f2f; background:#f9e7e5; }
.zone-chip.tone-info { color:#1d4f91; background:#e4eefb; }
.zone-chip.tone-na { color:#666; background:#f1f1f1; border-style:dashed; }
.zone-mark {
  width:26px; height:26px; min-height:0; padding:0; border-radius:50%; border:2px solid #fff;
  font:700 16px/22px 'Public Sans', sans-serif; text-align:center; color:#fff; box-shadow:0 1px 4px rgba(0,0,0,.35);
}
.zone-mark-not_working { background:#c22429; }
.zone-mark-not_installed { background:#a76800; }
.zone-mark-pending { background:var(--accent); color:#10210a; pointer-events:none; }
.zone-panel {
  flex:0 0 clamp(300px, 30vw, 400px); box-sizing:border-box; min-width:0; overflow-y:auto; overscroll-behavior:contain;
  padding:14px 16px; border:0; border-left:1px solid var(--line); background:var(--card);
  display:grid; gap:8px; align-content:start;
}
.zone-panel[hidden] { display:none; }
.zone-panel p { margin:0; }
.zone-panel-title { display:flex; flex-wrap:wrap; align-items:center; gap:8px; font-size:15px; }
.zone-panel-actions { display:flex; flex-wrap:wrap; gap:8px; }
.zone-panel-actions button { flex:1 1 110px; min-height:44px; }
.zone-kind [aria-pressed="true"] { background:var(--accent); color:var(--btn-ink, #10210a); border-color:var(--accent); }
@media (max-width:600px) {
  .zone-viewer-head { padding:8px 12px; }
  .zone-viewer-tools { width:100%; }
  .zone-viewer-tools button { flex:1 1 auto; }
}
/* On a phone the panel is a sheet under the drawing instead of beside it. The
   drawing shrinks to the room that is left, so every part of it can still be
   tapped. A pull down on the handle closes the sheet; the buttons that finish
   the job stay at its foot however tall the form is. */
@media (max-width:700px) {
  .zone-viewer-tools button { min-height:44px; min-width:44px; }
  .zone-body { flex-direction:column; }
  .zone-body > .zone-stage-wrap { min-width:0; min-height:0; }
  .zone-panel {
    flex:0 0 auto; width:auto; max-height:46dvh;
    padding:0 14px; border-width:1px 0 0; border-style:solid; border-color:var(--line2);
    border-radius:14px 14px 0 0; box-shadow:0 -6px 18px rgba(0,0,0,.12);
  }
  .zone-panel > .zone-panel-actions:last-child {
    position:sticky; bottom:0; z-index:1; margin:0 -14px; padding:8px 14px calc(8px + env(safe-area-inset-bottom));
    background:var(--card);
  }
  .zone-stage { min-height:0; }
}

/* Redlines on a DALI zone drawing (feature 019, phase 3). The layer is the
   sheet's size and moves with it; the stroke keeps its width at any zoom. */
.zone-lines { position:absolute; inset:0; width:100%; height:100%; pointer-events:none; overflow:visible; }
/* The same 22 % shade as a snag area, so a redline stands out the same way;
   a rejected one is lighter, so old answers fall back. */
.zone-redline {
  fill:rgba(194,36,41,.22); stroke:#c22429; stroke-width:3; stroke-dasharray:10 6;
  vector-effect:non-scaling-stroke; pointer-events:visiblePainted; cursor:pointer;
}
.zone-redline-accepted { fill:rgba(61,90,16,.22); stroke:#3d5a10; stroke-dasharray:none; }
.zone-redline-rejected { fill:rgba(120,120,120,.10); stroke:#777; }
.zone-sketch { fill:rgba(194,36,41,.08); stroke:#c22429; stroke-width:3; vector-effect:non-scaling-stroke; }
.zone-sketch-corner { fill:#fff; stroke:#c22429; stroke-width:2; vector-effect:non-scaling-stroke; }
.zone-decide { display:grid; gap:6px; margin:0; padding:8px 10px; border:1px solid var(--line2); border-radius:8px; }
.zone-decide legend { font-size:12px; font-weight:650; color:var(--ink2); padding:0 4px; }
.zone-decide label { display:flex; align-items:center; gap:8px; font-size:13.5px; }
.zone-redline-status { font-weight:650; }
.zone-redline-status-open { color:var(--chip-warn-ink); }
.zone-redline-status-accepted { color:var(--chip-pass-ink); }
.zone-redline-status-rejected { color:var(--muted); }
.zone-waiting { color:var(--chip-warn-ink); }
/* The viewer's panel is a sheet of controls, not a form: its labels read as
   sentences, as on the module cards, not as the capitalised captions dialogs
   give their form fields. */
.zone-panel label, .zone-panel .area-field, .zone-panel .area-field-hint {
  text-transform:none; letter-spacing:normal; font-size:13.5px;
}
.zone-panel .area-field-hint, .zone-panel label small { color:var(--muted); font-weight:400; }
.zone-decide label { margin:0; }

/* The module map (feature 020): each luminaire a dot in its module's colour,
   ringed in white so it reads on the drawing's linework; an emergency driver
   has a white centre. Module names are white labels edged in the colour. */
.map-dot { stroke:#fff; stroke-width:1.5; vector-effect:non-scaling-stroke; pointer-events:none; }
.map-dot-em { fill:#fff; pointer-events:none; }
.zone-chip.map-label { color:#111; background:#fff; border:2px solid var(--map-colour); border-style:solid; }
.map-swatch { display:inline-block; width:14px; height:14px; border-radius:50%; background:var(--map-colour); flex:none; }

/* The DALI zone viewer's pointer: the hand to drag the sheet, the grabbing
   hand while dragging, and the ordinary arrow while a mark or a zone is being
   placed, as when a snag is placed on a progress drawing. */
.zone-stage.is-placing { cursor:default; }
.zone-stage.is-panning { cursor:grabbing; }

/* Pre-commissioning tabs: the Drawings tabs, with a count after each name. */
.precom-tabs { margin:4px 0 2px; padding:0; }
.precom-tabs button b { margin-left:4px; font-variant-numeric:tabular-nums; color:var(--ink2); }
.precom-tabs button b:empty { display:none; }
.precom-tabs button.on b { color:var(--accent-ink, var(--accent)); }
.precom-panel { display:grid; gap:var(--workspace-gap, 16px); }
.precom-panel[hidden] { display:none; }

/* A redline's balloon: its number and module in the middle of the zone, in
   the colour of its answer. A waiting one has a ring that pulses; with reduced
   motion the ring stays still. */
.zone-chip.redline-balloon {
  display:inline-flex; align-items:center; gap:6px; padding:3px 10px 3px 3px;
  border:2px solid #c22429; background:#fff; color:#111; font-weight:650;
  box-shadow:0 2px 8px rgba(0,0,0,.25);
}
.redline-ref {
  display:inline-grid; place-items:center; min-width:24px; height:22px; padding:0 4px; border-radius:999px;
  background:#c22429; color:#fff; font-size:11.5px; font-weight:750; letter-spacing:.02em;
}
.redline-balloon-accepted { border-color:#3d5a10; }
.redline-balloon-accepted .redline-ref { background:#3d5a10; }
.redline-balloon-rejected { border-color:#888; color:#555; }
.redline-balloon-rejected .redline-ref { background:#888; }
.redline-balloon-open::after {
  content:""; position:absolute; inset:-6px; border-radius:999px; border:3px solid rgba(194,36,41,.55);
  animation:redline-pulse 1.8s ease-out infinite; pointer-events:none;
}
@keyframes redline-pulse {
  0% { transform:scale(.92); opacity:.9; }
  70% { transform:scale(1.18); opacity:0; }
  100% { transform:scale(1.18); opacity:0; }
}
@media (prefers-reduced-motion: reduce) {
  .redline-balloon-open::after { animation:none; opacity:.8; transform:none; }
}

/* Contractor checks on a DWG drawing (036). Three marks told apart by shape
   and by area as well as colour, so they read at their real size and in
   black and white: Available is a filled disc with a tick, Not available a
   light ring with a cross, Address dial set a square with A. Theme tokens
   only; a white halo keeps each one off the drawing's linework. */
.zone-check {
  --check-face:var(--card); --check-ink:var(--ink);
  position:absolute; pointer-events:auto; transform:translate(-50%, -50%) scale(var(--zone-inverse));
  transform-origin:center; cursor:pointer;
  box-sizing:border-box; width:28px; height:28px; min-height:0; min-width:0; padding:0; display:grid; place-items:center;
  border-radius:50%; border:2.5px solid var(--check-ink); background:var(--check-face); color:var(--check-ink);
  box-shadow:0 0 0 2px #fff, 0 1px 5px rgba(0,0,0,.35);
}
.zone-check > svg:not(.snag-badge-shape), .zone-check-key > svg:not(.snag-badge-shape) { width:20px; height:20px; fill:none; stroke:currentColor;
  stroke-width:3; stroke-linecap:round; stroke-linejoin:round; }
.zone-check-key > svg:not(.snag-badge-shape) { width:14px; height:14px; stroke-width:3.4; }
.zone-check-available { --check-face:var(--chip-pass-ink); --check-ink:var(--chip-pass-ink); color:var(--chip-pass-bg); }
.zone-check-not_available { --check-face:var(--chip-warn-bg); --check-ink:var(--chip-warn-ink); }
.zone-check-address_dial_set { --check-face:var(--chip-info-bg, var(--card)); --check-ink:var(--chip-info-ink, var(--info));
  border-radius:5px; }
/* A mark keeps its drawn size on a touch screen, where every button is made at
   least 44px high (the phone shell block at the end): stretched, a circle
   becomes an oval and a square a bar. The finger gets its 44px from an
   invisible ring round the mark instead. */
#zone-overlay .zone-check { min-height:0 !important; min-width:0 !important; height:28px; width:28px;
  -webkit-tap-highlight-color:transparent; }
.zone-check::before { content:""; position:absolute; inset:-8px; border-radius:50%; }
/* The generic button hover must not repaint a mark: its face is its meaning. */
.zone-check:hover { background:var(--check-face); border-color:var(--check-ink); }
/* Saving: faded and ringed with a dashed edge. Not saved: a broken red edge
   and a red halo, never the look of a saved mark. */
.zone-check.save-saving { opacity:.6; border-style:dashed; }
.zone-check.save-failed { border-style:dashed; border-color:var(--chip-fail-ink);
  box-shadow:0 0 0 3px var(--chip-fail-ink), 0 1px 5px rgba(0,0,0,.35); }
.zone-check.is-moving { cursor:grabbing; box-shadow:0 0 0 3px var(--accent), 0 2px 10px rgba(0,0,0,.45); }
/* The small key beside a result's name, in the Checks control and a panel. */
.zone-check-key {
  display:inline-grid; place-items:center; box-sizing:border-box; width:20px; height:20px; flex:none;
  vertical-align:-5px; border-radius:50%; border:2px solid var(--check-ink, var(--ink));
  background:var(--check-face, var(--card)); color:var(--check-ink, var(--ink)); margin-right:6px;
}
.zone-check-key.zone-check-available { color:var(--chip-pass-bg); }
.zone-check-key.zone-check-address_dial_set { border-radius:4px; }
/* A local control is a square whatever its result, so Not available on a
   local control is a square with a cross (036 brief 2). */
.zone-check.zone-check-control { border-radius:5px; }
.zone-check-key.zone-check-control { border-radius:4px; }

/* The Checks control: one row under the drawing's toolbar. Every control is
   44px high on the same centre line; the status text takes the spare width;
   Done stays at the right (docs/design-rules.md 2). */
.zone-checks-bar {
  display:flex; flex-wrap:wrap; align-items:center; gap:8px 10px;
  padding:8px 16px; border-bottom:1px solid var(--line); background:var(--card);
}
.zone-checks-bar[hidden] { display:none; }
.zone-checks-bar > button { min-height:44px; }
/* Luminaire results, then local-control results: two labelled groups, each a
   joined control under a heading that shows the device's shape (048b). */
.zone-check-choice { display:flex; flex-wrap:wrap; align-items:flex-end; gap:8px 12px; }
.zone-check-group { display:flex; flex-direction:column; gap:3px; min-width:0; }
.zone-check-group-head { display:inline-flex; align-items:center; gap:6px; font-size:12px; font-weight:600; color:var(--ink2); }
/* A minimal line icon of the device before its name (a bulb, a wall keypad),
   in the text colour, so it reads in every theme. Not the lamp symbol, a
   circle with a cross: that is the Not available mark. */
.zone-check-device { width:18px; height:18px; flex:none; fill:none; stroke:currentColor; stroke-width:1.8;
  stroke-linecap:round; stroke-linejoin:round; }
.zone-check-shape { box-sizing:border-box; width:12px; height:12px; flex:none; border:2px solid currentColor; border-radius:50%; }
.zone-check-shape.zone-check-control { border-radius:2px; }
.zone-checks-bar .shape-choice button { min-height:42px; display:inline-flex; align-items:center; padding-block:0; }
.zone-checks-status { flex:1 1 180px; margin:0; font-size:13.5px; color:var(--ink2); min-width:0; }
.zone-checks-status:empty { display:none; }
#zone-checks-done { margin-left:auto; }
/* 048: after a choice the row folds to one strip, the chosen device and
   result, Undo and Done, so the drawing keeps the screen (design rule 2).
   The chosen result opens the choices and the help again. The status line is
   still read out; it is shown only when the marks need attention. While a
   tool is active, the drawing's top bar folds away: one tool strip at a time.
   048b: only on a narrow screen, where the panels are sheets. The script
   decides with bottom-sheet.js's one narrow test and sets is-folded and
   is-tool-strip; a wide screen keeps the whole row and the top bar.
   Redline a change folds the same way: the step, Remove last, Cancel, Next. */
.zone-checks-chosen { display:none; }
.zone-checks-bar.is-folded { flex-wrap:nowrap; }
.zone-checks-bar.is-folded > .zone-checks-chosen {
  display:inline-flex; align-items:center; gap:6px; flex:1 1 auto; min-width:0; justify-content:flex-start;
  padding:2px 10px; text-align:left;
}
.zone-checks-chosen .zone-check-key { margin-right:0; }
/* "Local control: Not available" may take two lines rather than be cut off. */
.zone-checks-chosen-label { min-width:0; overflow:hidden; white-space:normal; overflow-wrap:anywhere; line-height:1.2;
  display:-webkit-box; -webkit-box-orient:vertical; -webkit-line-clamp:2; line-clamp:2; }
.zone-checks-chosen-more { flex:none; width:16px; height:16px; margin-left:auto; fill:none; stroke:currentColor; stroke-width:2;
  stroke-linecap:round; stroke-linejoin:round; }
.zone-checks-bar.is-folded > #zone-check-choice, .zone-checks-bar.is-folded > #zone-checks-help,
.zone-checks-bar.is-folded > #zone-redline-shape { display:none; }
.zone-checks-bar.is-folded > #zone-checks-undo, .zone-checks-bar.is-folded > #zone-checks-done,
.zone-checks-bar.is-folded > #zone-redline-undo, .zone-checks-bar.is-folded > .zone-bar-end { flex:0 0 auto; margin-left:0; }
.zone-checks-bar.is-folded > .zone-bar-end { gap:6px; }
.zone-checks-bar.is-folded > .zone-bar-end > button { flex:0 0 auto; }
/* A phone has room for four buttons in one row only with a little less side
   padding; each stays 44px high. */
.zone-checks-bar.is-folded > button:not(.zone-checks-chosen), .zone-checks-bar.is-folded > .zone-bar-end > button { padding-inline:10px; }
.zone-checks-bar.is-folded > .zone-checks-status:not(.is-notice) {
  position:absolute; width:1px; height:1px; overflow:hidden; clip:rect(0 0 0 0); white-space:nowrap;
}
.zone-checks-bar.is-folded { position:relative; column-gap:6px; }
.zone-checks-bar.is-folded > .zone-checks-status.is-notice { order:9; flex:1 1 100%; }
.zone-checks-bar.is-folded:has(> .zone-checks-status.is-notice:not(:empty)) { flex-wrap:wrap; }
.zone-viewer-dlg.is-tool-strip .zone-viewer-tools { display:none; }
/* Redline a change uses the same row: Cancel and Next stay together at the
   right (design rules 2). */
.zone-bar-end { display:flex; gap:8px; margin-left:auto; }
.zone-bar-end > button { min-height:44px; }
.zone-redline-bar .shape-choice button { padding-inline:14px; }
.zone-revision-field { display:flex; margin:0; }
.zone-revision-field[hidden] { display:none; }
.zone-revision-field select { min-height:40px; font-size:var(--field-font, 14px); }
@media (max-width:700px) {
  .zone-checks-bar { padding:8px 12px; }
  .zone-checks-bar .shape-choice, .zone-checks-bar .zone-check-choice, .zone-check-group { flex:1 1 100%; }
  .zone-check-group > .shape-choice { flex:none; }
  /* Each device's results share a row; a long name wraps inside its own button. */
  .zone-checks-bar .shape-choice button {
    flex:1 1 0; justify-content:center; min-width:0; padding:4px 6px; gap:4px;
    white-space:normal; line-height:1.2; text-align:center; font-size:13px;
  }
  .zone-checks-bar .shape-choice .zone-check-key { margin-right:0; }
  .zone-checks-bar > button { flex:1 1 auto; }
  .zone-bar-end { flex:1 1 100%; }
  .zone-bar-end > button { flex:1 1 0; }
  .zone-revision-field, .zone-revision-field select { flex:1 1 100%; min-height:44px; }
}

/* A check's panel: its save state, the result history and the check card. */
.zone-save-state { font-weight:650; font-size:13.5px; }
.zone-save-saving { color:var(--ink2); }
.zone-save-saved { color:var(--chip-pass-ink); }
.zone-save-failed { color:var(--chip-fail-ink); }
.zone-check-notice { padding:8px 10px; border-radius:8px; background:var(--chip-warn-bg); color:var(--chip-warn-ink); font-size:13.5px; }
.zone-check-set { justify-self:start; }
.zone-check-set button { min-height:44px; }
.zone-check-history-title { font-size:12px; font-weight:650; color:var(--ink2); margin-top:4px !important; }
.zone-check-history { margin:0; padding:0; list-style:none; display:grid; gap:4px; font-size:13.5px; }
.zone-check-history span { color:var(--muted); }
.zone-check-card { margin:0; padding-left:20px; display:grid; gap:6px; font-size:14px; line-height:1.45; }
.zone-check-card-note { font-weight:650; color:var(--chip-warn-ink); }

/* Imports opened only for the pre-commissioning drawing import: nothing of the
   Snapshot import shows. */
#page-snapshot.imports-precom-only .imports-view-tabs,
#page-snapshot.imports-precom-only .workspace-heading-actions,
#page-snapshot.imports-precom-only .workspace-page-intro,
#page-snapshot.imports-precom-only > :not(.workspace-heading):not(#precom-import-card) { display:none !important; }

/* ── Phone shell (spec 027, phase 2, helper B) ───────────────────────────────
   F04 F07 F08 F09 F16 F18. This block is last on purpose: it has to win over
   about 80 older rules that each set their own small size. The sizes use
   !important for the same reason: an id selector elsewhere (#device-tip
   summary, #action-source) would otherwise beat them, and one rule here is
   easier to keep true than 80 edits that the next new page forgets. */

/* F08 — a finger needs 44px. Touch screens only, so the mouse layout keeps
   its denser sizes. */
@media (pointer: coarse) {
  :is(button, .ghost-btn, a.button-link, a.help-link, summary, select,
      input:not([type=checkbox]):not([type=radio]):not([type=range]):not([type=file]):not([type=hidden]),
      [role=button], [role=tab]) {
    min-height:44px !important;
  }
  /* A file chooser is a control a finger presses, so it gets the same height. */
  input[type=file] { min-height:44px !important; box-sizing:border-box; }
  /* Width: only the few short buttons that fall under 44px. A blanket
     min-width would replace the automatic one that keeps a row of tabs from
     squeezing its labels into each other. */
  #page-admin > .admin-tabs button, .seg button, .document-type-chip, .workspace-view-tabs button { min-width:44px !important; }
  /* That 44px replaces the automatic minimum, and a row of filter buttons
     then squeezed each label out of its button ("Witness failed 1" on
     Areas, 051). A button with words keeps at least the width of its words;
     the row scrolls or wraps instead. */
  .seg button:not(:empty) { flex-shrink:0 !important; flex-basis:auto !important; }
  /* Icon buttons that fix their own size (help "?", drawing tools). */
  :is(.drawing-help-btn, .admin-help-btn, .emergency-help-open, .engineering-help-open) {
    width:44px !important; height:44px !important; flex:0 0 44px !important; min-width:44px !important;
  }
  /* A switch or tick box is pressed through its label, so the label is the
     hit area. The drawn switch keeps its size. */
  label:has(> input[type=checkbox], > input[type=radio]) { min-height:44px !important; min-width:44px !important; }
  label:has(> input[type=checkbox], > input[type=radio]):not(.drawing-card-select) { display:flex; align-items:center; gap:8px; }
  label.drawing-card-select { width:44px; height:44px; top:4px; left:4px; }
  /* The footer Guide link sits in a line of text. */
  #foot a { display:inline-flex; align-items:center; min-height:44px !important; min-width:44px !important; justify-content:center; }
  /* More rows. */
  #page-more button, #page-more a.button-link { min-height:48px !important; }
}

@media (max-width:700px) {
  /* F09 — iPhone zooms the page in on a field under 16px and does not zoom
     back out. */
  :is(input, select, textarea) { font-size:16px !important; }
  /* A larger font makes a field's natural width larger too. A file chooser
     has a fixed natural width that the browser sizes from its font, so at
     16px it ran 17px past a 390px screen on Imports. It takes its row's
     width instead, and no field may be wider than its row. */
  input[type=file] { width:100%; }
  :is(input, select, textarea):not([type=checkbox]):not([type=radio]) { max-width:100%; min-width:0; }

  /* F16 — slimmer fixed chrome. Header 52px (was 58), bar 53px (was 66). */
  header.top { min-height:52px; padding:0 8px; gap:6px; }
  .bottom-nav { padding:4px 4px calc(4px + env(safe-area-inset-bottom)); }
  .bottom-nav button { min-height:44px; padding:2px 4px; gap:2px; }
  body { padding-bottom:calc(62px + env(safe-area-inset-bottom)); }
  /* The banner scrolls away with the page. Sticky, it sat over the header. */
  .environment-banner { position:static; padding:3px 12px; }

  /* F07 — the brand is the mark alone, so the project select has the width. */
  .mobile-brand .brand-name { display:none; }
  .mobile-brand { flex:0 0 auto; }
  .project-context { flex:1 1 0; min-width:0; max-width:none; margin-left:0; }
  .project-context-copy { flex:1 1 auto; }
  .project-context select.proj-pill { width:100%; max-width:100%; min-height:44px; }
  .top-right { flex:0 0 auto; gap:4px; }
  .theme-toggle, .workspace-search-open { width:44px; height:44px; min-width:44px; }

  /* F04 F18 — the first thing on More is the Action Center and Sign out. */
  .more-head { display:flex; align-items:flex-start; justify-content:space-between; gap:12px; }
  .more-head > div > :is(p, h1) { margin-top:0; }
  .more-action-center { position:relative; }
  .more-action-center .rail-count { position:absolute; right:12px; top:50%; transform:translateY(-50%); margin:0; }
}
/* Guided notes and saved project reports. */
.journal-rough-fields,
.guided-link-picker { display:grid; gap:.55rem; padding:.8rem; border:1px solid var(--line); border-radius:var(--radius, 8px); }
.guided-link-picker { margin:.6rem 0; }
/* The Notes page: the note list, or one note open across the whole width.
   The two take turns; there is no side list while writing. */
.guided-notes-page { display:grid; gap:.8rem; }
.guided-notes-page > .note:empty { display:none; }
.guided-note-form { display:grid; align-content:start; gap:.55rem; min-width:0; }
.guided-note-form > textarea, .guided-note-form > input:not([type=checkbox]), .guided-note-form > select,
.guided-note-form .journal-rough-fields textarea {
  width:100%; max-width:100%; box-sizing:border-box; }
/* Further action sits in a wrapper (it hides for Diary): it must look exactly
   like Subject and Description, label above and full width. */
#journal-further-field { display:grid; gap:.55rem; min-width:0; }
#journal-further-field textarea { width:100%; box-sizing:border-box; }
/* Annotate opens the extract editor: a clear outlined button with an icon,
   readable on the dark drawing area in every theme. */
.guided-extract-markup-open { border:2px solid var(--ink) !important; color:var(--ink) !important;
  background:var(--card) !important; font-weight:700; min-height:44px; display:inline-flex; align-items:center; gap:6px; }
.guided-extract-markup-open::before { content:"\270E" / ""; font-size:1.05em; }
.guided-note-form-head { display:flex; flex-wrap:wrap; align-items:center; gap:.6rem 1rem; }
.guided-note-form-head h2 { margin:0; font-size:1.25rem; }
.guided-note-form-head .ghost-btn { min-height:44px; }
.guided-note-index { display:grid; align-content:start; gap:.55rem; }
.guided-note-index > #guided-note-new { justify-self:start; min-height:44px; }
@media(max-width:700px) {
  .guided-note-form textarea, .guided-note-form input:not([type=checkbox]), .guided-note-form select { font-size:16px; }
  .guided-note-index > #guided-note-new { justify-self:stretch; }
}
/* The note form follows the order of the work: numbered steps, then the AI button. */
.guided-step { margin:.7rem 0 0; font-size:1rem; font-weight:700; }
.journal-ai-block { display:grid; gap:.4rem; }
.journal-ai-block .dlg-actions { justify-content:flex-start; }
.ai-sparkle { width:1em; height:1em; margin-right:.4em; vertical-align:-.12em; flex:none; }
#history-ai-overview, #history-ai-analysis { display:inline-flex; align-items:center; justify-content:center; }
#history-ai-overview .ai-sparkle, #history-ai-analysis .ai-sparkle { vertical-align:baseline; }

/* ── The AI write-up button (brief 038) ───────────────────────────────────
   From specs/038-ai-prompt-editor/design: the framed "AI" logo with three
   sparkles, a cyan-to-violet edge and the label "Write-Up". Every size
   follows --ai-button-height (46px). The label uses the application's own
   font. Dark: the designed dark fill and pale text. Light and Delmatic: a
   pale tinted fill, the same edge and dark text. The logo never changes. */
.ai-button {
  --ai-button-height:46px;
  --ai-fill:linear-gradient(110deg, #e3fbfc 0%, #eaf2fb 49%, #f1e9ff 100%);
  --ai-fill-hover:linear-gradient(110deg, #d0f7f9 0%, #dde9f9 49%, #e8dbff 100%);
  --ai-fill-active:linear-gradient(110deg, #bff1f4 0%, #cfdff5 49%, #dccbfb 100%);
  --ai-edge:linear-gradient(110deg, #00edf5 0%, #28dbff 49%, #b46dff 100%);
  --ai-edge-hover:linear-gradient(110deg, #00d4dc 0%, #1fc4ec 49%, #a157f5 100%);
  --ai-edge-shimmer:linear-gradient(110deg, #00edf5 0%, #b46dff 16.667%, #00edf5 33.333%,
    #b46dff 50%, #00edf5 66.667%, #b46dff 83.333%, #00edf5 100%);
  --ai-text:#14212a;
  --ai-glow:0 0 1.15em rgb(0 200 214 / 14%), 0 0 .7em rgb(150 80 240 / 10%);
  --ai-focus:var(--focus);
  box-sizing:border-box; display:inline-flex; align-items:center; justify-content:center;
  gap:.411765em; width:fit-content; height:2.705882em; min-height:0; padding:0 .882353em;
  border:.058824em solid transparent; border-radius:.529412em;
  background:var(--ai-fill) padding-box, var(--ai-edge) border-box;
  box-shadow:var(--ai-glow);
  color:var(--ai-text); font-family:inherit;
  font-size:calc(var(--ai-button-height) * .3695652174); font-weight:700;
  line-height:1; letter-spacing:-.025em; white-space:nowrap; vertical-align:middle;
  cursor:pointer; appearance:none; -webkit-tap-highlight-color:transparent;
}
:root[data-theme="dark"] .ai-button, :root[data-theme="delmatic"] .ai-button {
  --ai-fill:linear-gradient(110deg, #00383e 0%, #112936 49%, #2b154b 100%);
  --ai-fill-hover:linear-gradient(110deg, #06474c 0%, #1b3645 49%, #3b205f 100%);
  --ai-fill-active:linear-gradient(110deg, #002a30 0%, #0c1e2a 49%, #201039 100%);
  --ai-edge-hover:linear-gradient(110deg, #81fcff 0%, #87eaff 49%, #d0a1ff 100%);
  --ai-text:#fafbff;
  --ai-glow:0 0 1.15em rgb(0 227 238 / 13%), 0 0 .7em rgb(166 92 255 / 9%), inset 0 0 .16em rgb(146 243 255 / 15%);
  --ai-focus:#c2faff;
}
/* The logo's white "AI" letters are made for the dark button, which Dark and
   Delmatic use (Clint, 22 October 2026). On the pale Light button they read as a deep teal-to-indigo instead;
   the frame and sparkles are unchanged. */
.ai-button .ai-letters-top { stop-color:#0b5f73; }
.ai-button .ai-letters-mid { stop-color:#0e7490; }
.ai-button .ai-letters-end { stop-color:#4338ca; }
:root[data-theme="dark"] .ai-button .ai-letters-top, :root[data-theme="delmatic"] .ai-button .ai-letters-top { stop-color:#ffffff; }
:root[data-theme="dark"] .ai-button .ai-letters-mid, :root[data-theme="delmatic"] .ai-button .ai-letters-mid { stop-color:#e0faff; }
:root[data-theme="dark"] .ai-button .ai-letters-end, :root[data-theme="delmatic"] .ai-button .ai-letters-end { stop-color:#00d8f5; }
.ai-button__logo { display:block; width:1.764706em; height:1.764706em; flex:0 0 1.764706em; }
.ai-button__label { display:block; }
.ai-button:hover:not(:disabled):not([aria-busy="true"]) {
  background:var(--ai-fill-hover) padding-box, var(--ai-edge-hover) border-box;
  box-shadow:0 0 1.2em rgb(0 235 245 / 22%), 0 0 .85em rgb(172 104 255 / 15%);
  border-color:transparent;
}
.ai-button:focus-visible { outline:.117647em solid var(--ai-focus); outline-offset:.176471em; }
.ai-button:active:not(:disabled):not([aria-busy="true"]) {
  background:var(--ai-fill-active) padding-box, var(--ai-edge) border-box;
  box-shadow:inset 0 .117647em .235294em #0003;
}
:root[data-theme="dark"] .ai-button:active:not(:disabled):not([aria-busy="true"]), :root[data-theme="delmatic"] .ai-button:active:not(:disabled):not([aria-busy="true"]) {
  background:var(--ai-fill-active) padding-box,
    linear-gradient(110deg, #00c3d0 0%, #32b7ed 49%, #9455e0 100%) border-box;
  box-shadow:inset 0 .117647em .235294em #0005;
}
.ai-button:disabled { box-shadow:none; opacity:1; cursor:not-allowed; }
.ai-button:disabled .ai-button__logo { opacity:.55; }
/* Writing: a gentle shimmer runs along the edge only. The fill and the label
   stay still, and the shimmer is off for anybody who asks for less motion. */
.ai-button[aria-busy="true"] {
  cursor:wait;
  background:var(--ai-fill) padding-box, var(--ai-edge-shimmer) border-box;
  background-size:100% 100%, 300% 100%;
  animation:ai-button-edge 3s linear infinite;
}
@keyframes ai-button-edge {
  from { background-position:0 0, 0% 0; }
  to { background-position:0 0, 100% 0; }
}
@media (prefers-reduced-motion: reduce) {
  .ai-button[aria-busy="true"] { animation:none; background:var(--ai-fill) padding-box, var(--ai-edge) border-box; }
}
/* The shared button hover paints a grey border and a card fill. The edge is
   this button's border, so the hover must never cover it, busy or not. */
.ai-button:hover { border-color:transparent; }
#journal-ai-prompt { margin:0; }

/* ── The AI write-up prompt page (brief 038) ─────────────────────────── */
/* Plain block flow, one item under another. */
.ai-prompt-page .workspace-section { display:block; }
.ai-prompt-page .workspace-section > * + * { margin-top:.5rem; }
.ai-prompt-page .workspace-section > label { display:block; }
.ai-prompt-page label { font-weight:600; color:var(--ink); }
.ai-prompt-facts { display:flex; flex-wrap:wrap; gap:.4rem; }
.ai-prompt-page .note { margin:0; }
#ai-prompt-text, #ai-prompt-note, #ai-prompt-draft-version {
  box-sizing:border-box; width:100%; background:var(--card2); color:var(--ink);
  border:1px solid var(--line2); border-radius:8px; padding:9px 11px;
  font:inherit; font-size:var(--field-font);
}
#ai-prompt-text { min-height:22rem; resize:vertical; line-height:1.5; }
#ai-prompt-note, #ai-prompt-draft-version { display:block; min-height:44px; min-width:0; max-width:min(100%, 40rem); }
/* Safari lets the text of a long choice spill outside a list and widen the
   page. Paint containment keeps it inside the list's own box. */
#ai-prompt-draft-version { contain:paint; }
.ai-prompt-file-actions, .ai-prompt-save-row, .ai-prompt-version-actions { display:flex; flex-wrap:wrap; gap:.5rem; }
.ai-prompt-page button { min-height:44px; }
.ai-prompt-page .workspace-section > .ai-prompt-switch { display:flex; width:fit-content; }
.ai-prompt-switch { display:inline-flex; align-items:center; gap:.6rem; min-height:44px; cursor:pointer; }
.ai-prompt-versions { list-style:none; margin:0; padding:0; display:grid; gap:.6rem; }
.ai-prompt-version { display:grid; gap:.25rem; padding:.7rem .8rem; border:1px solid var(--line); border-radius:8px; }
.ai-prompt-version-head { display:flex; flex-wrap:wrap; align-items:center; gap:.45rem; }
.ai-prompt-version-meta { margin:0; color:var(--muted); font-size:13px; }
.ai-prompt-version-note { margin:0; overflow-wrap:anywhere; }
@media (max-width:700px) {
  #ai-prompt-text, #ai-prompt-note, #ai-prompt-draft-version { font-size:16px; }
  #ai-prompt-text { min-height:16rem; }
  .ai-prompt-file-actions button, .ai-prompt-save-row button { flex:1 1 auto; }
}
.guided-link-levels { display:grid; grid-template-columns:minmax(0, 1fr); gap:.35rem; }
.guided-link-levels select { width:100%; min-height:44px; }
@media(min-width:701px) { .guided-link-levels { grid-template-columns:max-content minmax(0, 1fr); align-items:center; gap:.45rem .8rem; } }
#journal-links-selected { display:flex; flex-wrap:wrap; gap:.35rem; }
#journal-links-selected button { min-height:44px; }
.guided-report-workspace { margin:0 0 1rem; }
.guided-report-workspace > summary { display:flex; flex-wrap:wrap; align-items:center; gap:.7rem; cursor:pointer; }
.guided-report-workspace > summary span { color:var(--muted); font-size:.9rem; }
.guided-report-grid { display:grid; grid-template-columns:minmax(0, 1.3fr) minmax(240px, .7fr); gap:1.2rem; padding-top:1rem; }
.guided-report-grid form { display:grid; align-content:start; gap:.55rem; }
.guided-report-grid fieldset { min-width:0; border:1px solid var(--line); border-radius:var(--radius, 8px); }
.guided-report-note-list { max-height:240px; overflow:auto; }
.guided-report-note-list .check-label { display:flex; align-items:center; gap:.5rem; min-height:44px; }
.guided-report-note-list small { margin-left:auto; color:var(--muted); }
.guided-report-list-item { display:flex; flex-direction:column; width:100%; gap:.25rem; margin:.25rem 0; padding:.6rem; text-align:left; background:transparent; color:inherit; border:1px solid var(--line); border-radius:var(--radius, 8px); cursor:pointer; }
.guided-report-list-item span { color:var(--muted); font-size:.85rem; }
/* The issued report is read by people outside the app. The cover is a block
   at the top of page one, notes follow at once, and only a figure or a short
   block refuses to split across a page. A whole note may split; a figure may not. */
/* A drawing extract spans the row: the floor locator small, the crop large. */
.guided-report-extracts { display:grid; gap:.55rem; }
/* Attached to this note: one row per drawing extract or photo. */
.guided-attach-summary { margin:0; font-weight:600; }
.guided-attach-list { list-style:none; margin:0; padding:0; display:grid; gap:.5rem; }
.guided-attach-list:empty { display:none; }
.guided-attach-item { display:grid; grid-template-columns:88px minmax(0, 1fr); gap:.4rem .7rem; align-items:center;
  padding:.55rem; border:1px solid var(--line); border-radius:8px; }
.guided-attach-item > img, .guided-attach-missing { width:88px; height:66px; object-fit:contain; background:#fff;
  border:1px solid var(--line); border-radius:4px; }
.guided-attach-missing { display:grid; place-items:center; color:var(--muted); font-size:.8rem; background:transparent; }
.guided-attach-body { display:grid; gap:.3rem; min-width:0; }
.guided-attach-body b { overflow-wrap:anywhere; }
.guided-attach-body input { width:100%; min-height:40px; box-sizing:border-box; }
.guided-attach-item-actions { grid-column:1 / -1; display:flex; flex-wrap:wrap; gap:.35rem; justify-content:flex-end; }
.guided-attach-item-actions .ghost-btn { min-height:40px; min-width:44px; }
.guided-attach-actions { display:flex; flex-wrap:wrap; gap:.5rem; }
.guided-attach-actions .ghost-btn { min-height:44px; font-weight:600; color:var(--ink); }
.guided-extract-panel { display:grid; gap:.6rem; padding:.8rem; border:1px solid var(--line2); border-radius:8px; }
.guided-extract-panel h4 { margin:0; }
/* The editor in the panel may shrink to the panel; nothing inside it may push
   the panel wider (a long drawing name, a wide picture). */
.guided-extract-panel > * { min-width:0; max-width:100%; }
.guided-extract-source select { min-width:0; max-width:100%; text-overflow:ellipsis; }
.guided-extract-source { display:grid; gap:.35rem; }
.guided-extract-source select { min-height:44px; }
@media(min-width:701px) { .guided-extract-source { grid-template-columns:max-content minmax(0, 1fr); align-items:center; gap:.45rem .8rem; } }
@media(max-width:700px) {
  .guided-attach-item { grid-template-columns:72px minmax(0, 1fr); }
  .guided-attach-item > img, .guided-attach-missing { width:72px; height:56px; }
  .guided-attach-body input { min-height:44px; font-size:16px; }
  .guided-attach-item-actions .ghost-btn { min-height:44px; }
  .guided-attach-actions .ghost-btn { flex:1 1 12rem; }
}
@media(max-width:700px) { .guided-report-grid { grid-template-columns:1fr; } .guided-report-workspace > summary { min-height:44px; } }
@media print { .guided-report-workspace { display:none !important; } }
/* The issued preview fills its dialog. */
#guided-report-issue-dlg[open] { display:flex; flex-direction:column; gap:8px; padding:12px; }
#guided-report-issue-frame { flex:1 1 auto; width:100%; min-height:0; border:1px solid var(--line2); background:white; }
.guided-report-saved h2 { font-size:1rem; margin:.4rem 0; }

/* ── Project report family (028) ─────────────────────────────────────────
   Options sit in the report builder; the document uses the shared snag
   report frame. Sizes in print are page units, never screen measurements. */
.guided-report-options form { display:grid; align-content:start; gap:.55rem; }
.guided-report-options fieldset { min-width:0; border:1px solid var(--line); border-radius:var(--radius, 8px); }
.guided-report-save-actions { display:flex; flex-wrap:wrap; gap:.5rem; padding-top:.6rem; border-top:1px solid var(--line); }
.guided-report-save-actions > button, #guided-report-new { min-height:44px; }
.guided-report-options .guided-report-saved { margin-top:.8rem; padding-top:.6rem; border-top:1px solid var(--line); }
.guided-report-options .guided-report-saved h3 { font-size:.95rem; margin:.4rem 0 .2rem; }
.guided-report-options .guided-report-saved > div { max-height:220px; overflow:auto; }
.guided-note-row { display:flex; align-items:stretch; gap:.5rem; }
.guided-note-row > .guided-report-list-item { flex:1 1 auto; min-width:0; }
.guided-note-row > :is(.guided-note-delete, .guided-note-discard) { flex:0 0 auto; }
/* A long note title wraps inside its row; it never makes the list wider than
   the screen (a button keeps its text on one line unless told otherwise). */
.guided-note-index, .guided-note-index > * { min-width:0; max-width:100%; }
.guided-note-row > .guided-report-list-item { align-items:flex-start; white-space:normal; text-align:left; }
.guided-note-row > .guided-report-list-item b, .guided-note-row > .guided-report-list-item span { max-width:100%; overflow-wrap:anywhere; text-align:left; }
.guided-draft-mark { margin:0 0 8px; padding:6px 10px; border:1px dashed #c98a18; color:#7a5200; background:#fff6dc; font-weight:700; text-align:center; letter-spacing:.04em; }
.guided-cover-title { margin:0 0 8mm; padding:4mm 0; border-top:1px solid var(--sr-line); border-bottom:1px solid var(--sr-line); }
.guided-cover-title h2 { margin:0 0 1mm; font-size:20px; }
.guided-cover-title p { margin:0; color:var(--sr-muted); font-weight:700; }
/* Project report look: green section headings with a green underline, plain
   numbered item headings, green Description / Further action sub-headings.
   No grey bands. Segoe UI for this report only. */
.guided-issued-report { --gr-green:#52741d; --gr-rule:#7fb232; font-family:'Segoe UI', 'Segoe UI Variable Text', system-ui, -apple-system, 'Helvetica Neue', Arial, sans-serif; }
.guided-issued-report :is(h1, h2, h3, h4, h5) { font-family:inherit; }
/* One heading hierarchy. Level 1: green text, green underline (section titles,
   "Report contents"). Level 2: the numbered note heading. Level 3: green, small
   ("Description", "Further action"). Each level has one rule only. */
.guided-issued-report :is(.guided-section-title, .snag-report-cover-inclusions > h2) { margin:2mm 0 3mm; padding:0 0 1.5mm; border-bottom:1.5px solid var(--gr-rule, #7fb232); background:none; color:var(--gr-green, #52741d); font-size:17px; font-weight:600; line-height:1.25; }
.guided-issued-report .snag-report-cover-inclusions { padding-top:0; border-top:0; }
.guided-issued-report .guided-cover-title { border-bottom:0; padding-bottom:0; margin-bottom:6mm; }
.guided-section-title small { color:var(--sr-muted); font-weight:400; }
.guided-report-actions p { margin:0 0 2mm; }
.guided-report-action-list { list-style:none; margin:0 0 1.5mm; padding:0; }
.guided-report-action-list a { display:block; padding:1.5mm 2mm; border-bottom:1px solid var(--sr-line); color:inherit; text-decoration:none; }
.guided-report-action-list b { color:#52741d; }
.guided-action-link { color:#2866b5; font-weight:700; white-space:nowrap; }
.guided-report-intro p, .guided-item-part p { margin:0 0 2mm; white-space:normal; }
/* A Further action written as "- " lines prints as a real list (033).
   guided-report.js places it from these sizes (BULLET_CHARS, BULLET_GAP_MM):
   a 5 mm indent, 1 mm under each item and 2 mm under the list. */
.guided-text-list { margin:0 0 2mm; padding:0 0 0 5mm; list-style:disc outside; }
.guided-text-list li { margin:0 0 1mm; white-space:normal; }
.guided-text-list li.is-continued { list-style:none; }
.guided-report-action-list .guided-text-list { margin:1mm 0 0; }
.guided-action-para { display:block; margin-top:1mm; }
.guided-item-head { margin:5mm 0 3mm; break-inside:avoid; }
.guided-item-heading { padding:0 0 1.5mm; background:none; border:0; }
.guided-item-heading h3 { margin:0; font-size:14.5px; line-height:1.25; font-weight:400; color:var(--sr-ink, #1f2a37); }
.guided-item-number { color:var(--gr-green, #52741d); font-weight:700; letter-spacing:.04em; margin-inline-end:2.5mm; }
.guided-item-heading h3 b { font-weight:700; }
.guided-item-layout { display:grid; grid-template-columns:minmax(0,70mm) minmax(0,1fr); gap:5mm; align-items:start; }
.guided-item-details { width:100%; border-collapse:collapse; border-bottom:1px solid var(--sr-line); }
.guided-item-details tr { border-top:1px solid var(--sr-line); }
.guided-item-details th, .guided-item-details td { padding:1.2mm 1mm; text-align:left; vertical-align:top; overflow-wrap:anywhere; }
.guided-item-details th { width:22mm; font-weight:600; }
.guided-item-part h4 { margin:3mm 0 1mm; font-size:12px; line-height:1.25; font-weight:600; text-transform:none; letter-spacing:0; color:var(--gr-green, #52741d); }
.guided-item-part h4 small { text-transform:none; letter-spacing:0; color:var(--sr-muted); font-weight:400; }
/* Running text at 10 pt, the paragraph size of Delmatic's Word documents,
   on screen and on paper. This report only: every rule is scoped under
   .guided-issued-report, because the report shares .snag-report-* classes
   with the snag reports. guided-report.js places text on pages from these
   sizes (LINE_MM, LINE_CHARS, headMm); change both together. */
.guided-issued-report :is(.guided-item-part, .guided-report-intro, .guided-report-actions) :is(p, li),
.guided-issued-report .guided-report-action-list a { font-size:10pt; line-height:1.4; }
.guided-issued-report .guided-item-part h4 { font-size:10.5pt; }
.guided-issued-report .guided-item-details th { font-size:8pt; }
.guided-issued-report .guided-item-details td { font-size:10pt; line-height:1.4; }
.guided-item-figure { margin:4mm 0; break-inside:avoid; page-break-inside:avoid; text-align:center; }
.guided-band { padding:2mm 0; border-top:1px solid var(--sr-line); }
.guided-band h3 { margin:0 0 1.5mm; font-size:9.5px; text-transform:uppercase; letter-spacing:.07em; color:var(--sr-muted); text-align:left; }
.guided-band img { display:block; margin:0 auto; width:auto; max-width:100%; object-fit:contain; border:1px solid var(--sr-line); background:#fff; }
.guided-band-locator img { height:62mm; }
.guided-band-detail img { height:120mm; }
.guided-band-photo img { height:120mm; }
.guided-item-figure figcaption { margin-top:1.5mm; color:var(--sr-ink); font-size:10.5px; font-weight:600; }
.guided-item-missing { padding:9px 11px; border-inline-start:4px solid #c98a18; background:#fff6dc; }
.guided-issued-report.snag-report-document { max-width:none; padding:0; }
@media print { .guided-draft-mark { display:none; } }
@media (max-width:600px) {
  .guided-band-locator img { height:auto; max-height:40vh; }
  .guided-band-detail img, .guided-band-photo img { height:auto; max-height:60vh; }
  .guided-item-layout { grid-template-columns:minmax(0,1fr); }
}
.guided-report-options .guided-report-note-list .check-label { display:grid; grid-template-columns:auto minmax(0,1fr); align-items:center; column-gap:.6rem; row-gap:.1rem; min-height:44px; margin:0; padding:.3rem 0; text-align:left; }
.guided-report-options .guided-report-note-list .check-label input { margin:0; }
.guided-report-options .guided-report-note-list .check-label small { grid-column:2; margin:0; }
.guided-report-options .guided-report-list-item { align-items:flex-start; white-space:normal; text-align:left; min-height:44px; }
.guided-report-options .guided-report-list-item b, .guided-report-options .guided-report-list-item span { overflow-wrap:anywhere; text-align:left; }

/* ── Report references and kept copies (028) ─────────────────────────────── */
.report-reference-line { margin:2px 0 0; color:var(--muted); font-size:12px; }
.report-reference-line b { color:inherit; font-weight:700; letter-spacing:.02em; }
.report-sales-order-reminder { margin:10px 0 0; }
.generated-reports-panel summary { display:flex; align-items:baseline; gap:8px; min-height:44px; cursor:pointer; }
.generated-reports-panel summary .eyebrow { margin:0; }
.generated-reports-list { max-height:320px; overflow:auto; }
.generated-reports-list .guided-report-list-item { align-items:flex-start; text-align:left; min-height:44px; }
.generated-reports-list .guided-report-list-item b, .generated-reports-list .guided-report-list-item span { overflow-wrap:anywhere; }
.generated-reports-list .guided-report-list-item:disabled { opacity:.7; }
#generated-report-dlg { display:none; flex-direction:column; }
#generated-report-dlg[open] { display:flex; }
#generated-report-frame { flex:1 1 auto; width:100%; min-height:0; border:1px solid var(--line2); background:white; }
.guided-report-filters { display:grid; grid-template-columns:minmax(0, 1fr); gap:4px; margin:0 0 10px; min-width:0; }
.guided-report-options form { grid-template-columns:minmax(0, 1fr); }
.guided-report-options form, .guided-report-options fieldset { min-width:0; max-width:100%; }
.guided-report-options form > :is(input:not([type=checkbox]), select, textarea) { width:100%; min-width:0; max-width:100%; box-sizing:border-box; }
.guided-report-filters > *, .guided-report-filters label { min-width:0; max-width:100%; }
.guided-report-filters select, .guided-report-filters input { width:100%; min-width:0; max-width:100%; box-sizing:border-box; text-overflow:ellipsis; }
.guided-report-filters label { margin:6px 0 0; }
.guided-report-filters select, .guided-report-filters input { min-height:44px; }
.guided-report-period-range { display:grid; grid-template-columns:repeat(2,minmax(0,1fr)); gap:8px; }
.guided-report-period-range[hidden] { display:none; }
.guided-report-filter-actions { display:flex; flex-wrap:wrap; gap:8px; }
.guided-report-filter-actions button { min-height:44px; }
/* ── Note picker for many notes (034) ─────────────────────────────────────
   The list scrolls in its own box, about six rows high on a desktop and five
   on a phone; the panel around it stays still. A row is compact: the title on
   one line (cut with an ellipsis, the whole title on hover), then the date
   and flags in small text. The whole row is the 44px finger target for the
   switch. Show (All, Picked, Not picked) is a joined choice: only the chosen
   option is filled (docs/design-rules.md 1). */
.guided-report-show { display:flex; flex-wrap:wrap; align-items:center; gap:6px 10px; margin:2px 0 8px; }
.guided-report-show-label { color:var(--muted); font-size:11px; font-weight:600; letter-spacing:.05em; text-transform:uppercase; }
.guided-report-show .shape-choice { display:flex; width:100%; min-width:0; }
.guided-report-show .shape-choice button { flex:1 1 auto; min-width:0; min-height:44px; padding:0 8px; white-space:nowrap; }
.guided-report-options .guided-report-note-list { --note-row:48px; max-height:calc(var(--note-row) * 6 + 2px); overflow-y:auto;
  overscroll-behavior:contain; border:1px solid var(--line); border-radius:8px; padding:0 10px; }
.guided-report-options .guided-report-note-list > .note { margin:10px 0; }
.guided-report-options .guided-report-note-list .check-label { grid-template-rows:auto auto; min-height:var(--note-row);
  box-sizing:border-box; padding:4px 0; row-gap:0; }
.guided-report-options .guided-report-note-list .check-label:first-child { border-top:0; }
.guided-report-options .guided-report-note-list .check-label input { grid-row:1 / span 2; }
.guided-report-options .guided-report-note-list .check-label > span { min-width:0; overflow:hidden; white-space:nowrap;
  text-overflow:ellipsis; color:var(--ink); font-size:13px; line-height:1.35; }
.guided-report-options .guided-report-note-list .check-label > small { min-width:0; overflow:hidden; white-space:nowrap;
  text-overflow:ellipsis; color:var(--muted); font-size:11.5px; line-height:1.3; }
@media (max-width:700px) {
  .guided-report-options .guided-report-note-list { max-height:calc(var(--note-row) * 5 + 2px); }
}
.kept-report-copy .report-preview-well, .kept-report-copy .completion-preview-well { padding:0; }
/* 036 delivery b: contractor checks matched to Lightscape graphics (Delmatic).
   The Checks list, the links on the Overview card, and on the drawing the
   line from each mark to its graphic and the ring round the selected one. */
.precom-checks-filter { flex-wrap:wrap; max-width:100%; }
.precom-checks-filter button { min-height:44px; }
.precom-checks-filter button small { color:var(--muted); font-variant-numeric:tabular-nums; margin-left:2px; }
.precom-checks-list { display:grid; gap:14px; }
.precom-checks-module { display:grid; gap:6px; }
.precom-checks-module h4 { margin:4px 0 0; font-size:13.5px; color:var(--ink2); }
.precom-checks-module h4 small { color:var(--muted); font-weight:500; margin-left:4px; font-variant-numeric:tabular-nums; }
.precom-check-row {
  display:grid; grid-template-columns:auto minmax(0, 1fr) auto auto; align-items:center; gap:6px 10px;
  padding:8px 10px; border:1px solid var(--line2); border-radius:8px; background:var(--card);
}
.precom-check-text p { margin:0; overflow-wrap:anywhere; }
.precom-check-text span { color:var(--ink2); }
.precom-check-text small { display:block; margin-top:2px; color:var(--muted); font-size:12px; }
.precom-check-row > button { min-height:44px; }
.precom-check-row.precom-check-row-availability {
  grid-template-columns:auto minmax(0, 1fr) 180px 120px 76px;
}
.precom-check-row-availability .precom-check-text { min-width:0; }
.precom-check-row-availability .precom-check-text p {
  overflow:hidden; white-space:nowrap; text-overflow:ellipsis;
}
.precom-check-row-availability > .chip {
  grid-column:3; grid-row:1; justify-self:end;
}
.precom-check-row-availability > [data-precom-raise-snag] { grid-column:4; width:100%; }
.precom-check-row-availability > [data-precom-check-open] { grid-column:5; width:76px; }
@media (max-width:900px) {
  .precom-check-row.precom-check-row-availability {
    grid-template-columns:auto minmax(0, 1fr) 180px 120px;
  }
  .precom-check-row-availability > [data-precom-check-open] {
    grid-column:2; grid-row:2; justify-self:start;
  }
  .precom-check-row-availability > [data-precom-raise-snag] {
    grid-column:4; grid-row:1;
  }
  .precom-check-row-availability > .chip { grid-column:3; grid-row:1; justify-self:end; }
}
@media (max-width:700px) {
  .precom-checks-filter button { flex:1 1 auto; white-space:normal; }
  .precom-check-row { grid-template-columns:auto minmax(0, 1fr) auto; }
  .precom-check-row.precom-check-row-availability { grid-template-columns:auto minmax(0, 1fr) 76px; }
  .precom-check-row-availability .precom-check-text p { overflow:visible; white-space:normal; }
  .precom-check-row > .chip { grid-column:2; grid-row:2; justify-self:start; }
  .precom-check-row > button { grid-column:3; grid-row:1 / span 2; }
  .precom-check-row-availability > .chip { grid-column:2; grid-row:2; justify-self:start; }
  .precom-check-row-availability > [data-precom-check-open] { grid-column:3; grid-row:1 / span 2; }
  .precom-check-row-availability > [data-precom-raise-snag] { grid-column:2; grid-row:3; justify-self:start; width:auto; }
}
/* Fact tiles that are also links (docs/design-rules.md): the soft style, a
   small arrow and a hover state. */
.precom-overview-checks { display:flex; flex-wrap:wrap; gap:8px; margin:4px 0 12px; }
.precom-overview-checks[hidden] { display:none; }
.precom-check-link {
  --fact-colour:var(--chip-info-ink, var(--info));
  display:inline-flex; align-items:center; gap:6px; min-height:44px; padding:6px 10px 6px 12px;
  border:1px solid var(--line2); border-radius:8px; color:var(--ink); font:inherit; font-size:13.5px; cursor:pointer;
  background:linear-gradient(180deg, color-mix(in srgb, var(--fact-colour) 11%, var(--card)), var(--card) 76%);
  box-shadow:inset 0 3px 0 var(--fact-colour);
}
.precom-check-link.tone-attention { --fact-colour:var(--chip-warn-ink); }
.precom-check-link b { font-variant-numeric:tabular-nums; }
.precom-check-link .chev { width:14px; height:14px; color:var(--muted); }
.precom-check-link:hover { border-color:var(--fact-colour); background:color-mix(in srgb, var(--fact-colour) 14%, var(--card)); }
.precom-check-link:focus-visible { outline:2px solid var(--accent); outline-offset:2px; }
/* On the drawing. The line keeps its width at any zoom. */
.zone-match-line { stroke:var(--chip-info-ink, var(--info)); stroke-width:2; vector-effect:non-scaling-stroke; }
.zone-match-line.is-unclear { stroke:var(--chip-warn-ink); stroke-dasharray:5 4; }
.zone-match-ring {
  position:absolute; width:30px; height:30px; border-radius:50%; pointer-events:none; box-sizing:border-box;
  transform:translate(-50%, -50%) scale(var(--zone-inverse));
  border:3px solid var(--chip-info-ink, var(--info)); box-shadow:0 0 0 2px #fff, 0 0 8px rgba(0,0,0,.35);
}
.zone-match-ring.is-unclear { border-color:var(--chip-warn-ink); border-style:dashed; }
.zone-match-ring.is-snap { width:48px; height:48px; border-width:4px; }
/* The light theme has no info chip colours of its own; these fall back to
   --info there and use the theme's own everywhere else. */
.chip.match-info { background:var(--chip-info-bg, color-mix(in srgb, var(--info) 12%, var(--card)));
  color:var(--chip-info-ink, color-mix(in srgb, var(--info) 70%, var(--ink))); }
.zone-check-match { display:grid; gap:4px; padding:8px 10px; border:1px solid var(--line2); border-radius:8px; font-size:13.5px; }
.zone-check-match .chip { margin-left:4px; vertical-align:middle; }
.zone-check-match.needs-attention { border-color:var(--chip-warn-ink); }
/* Project total leads floor figures. These are facts, not selectable controls. */
.precom-graphics-done { display:grid; grid-template-columns:minmax(0,1fr); gap:12px; margin:0 0 12px; }
.precom-graphics-done[hidden] { display:none; }
.precom-graphics-project, .precom-graphics-floors { min-width:0; }
.precom-graphics-project h3, .precom-graphics-floors h3 { margin:0 0 6px; font-size:14px; }
.precom-graphics-project .area-fact { max-width:320px; }
.precom-graphics-floors dl { display:grid; grid-template-columns:repeat(auto-fit,minmax(min(190px,100%),1fr)); gap:8px; margin:0; }
.precom-graphics-floors .area-fact { min-width:0; }
.precom-graphics-done-line { flex:1 1 100%; margin:0; }
.precom-tick-summary { min-width:0; margin:0 0 12px; }
.precom-tick-summary h3 { margin:0 0 6px; font-size:15px; }
.precom-tick-total { display:flex; flex-wrap:wrap; gap:4px 12px; align-items:baseline; margin:0 0 8px; }
.precom-tick-total b { font-size:20px; }
.precom-tick-total span, .precom-tick-summary > p { color:var(--muted); }
.precom-tick-parts { display:grid; grid-template-columns:repeat(auto-fit,minmax(min(205px,100%),1fr)); gap:8px; margin:0 0 10px; }
.precom-tick-parts > div { min-width:0; }
.precom-tick-parts dt { color:var(--muted); font-size:12px; }
.precom-tick-parts dd { margin:3px 0 0; font-weight:700; }
.precom-tick-parts dd.precom-tick-part-foot { color:var(--muted); font-size:12px; font-weight:400; }
.precom-tick-ready { margin:0 0 6px; }
.precom-tick-summary > p { margin:4px 0; font-size:13px; }
.precom-tick-floor { min-width:0; }
@media (max-width:600px) {
  .precom-graphics-done { grid-template-columns:minmax(0,1fr); }
  .precom-graphics-floors dl, .precom-tick-parts { grid-template-columns:minmax(0,1fr); }
  .precom-graphics-project .area-fact { max-width:none; }
}
.zone-check-snag-badge { position:absolute; right:-9px; top:-9px; box-sizing:border-box;
  width:18px; height:18px; border:2px solid var(--card); border-radius:50%;
  background:var(--chip-fail-ink); color:var(--chip-fail-bg); font:bold 12px/14px sans-serif; text-align:center; }
/* Numbered snags own their SVG geometry. They never inherit a check's disc or glyph stroke. */
#zone-overlay .zone-linked-snag { pointer-events:auto; transform:translate(-50%, -50%) scale(var(--zone-inverse));
  transform-origin:center; width:44px; height:44px; min-width:44px; min-height:44px; padding:0;
  display:grid; place-items:center; border:0; border-radius:0; background:transparent;
  box-shadow:none; overflow:visible; cursor:pointer; }
#zone-overlay .zone-linked-snag:hover { background:transparent; }
#zone-overlay .zone-linked-snag:focus-visible { outline:2px solid var(--chip-info-ink, var(--info)); outline-offset:2px; }
#drawing-availability-layer{position:absolute;inset:0;pointer-events:none}
.drawing-viewer-dlg.layer-off-availability #drawing-availability-control,
.drawing-viewer-dlg.layer-off-availability #drawing-availability-layer{display:none!important}

/* Automatic pre-commissioning facts. Marks and graphics stay separate. */
.precom-auto-row h3 { margin:0; font-size:17px; }
.precom-auto-row h4 { margin:0 0 8px; font-size:14px; }
.precom-auto-facts { display:grid; grid-template-columns:repeat(2,minmax(0,1fr)); gap:16px; margin:14px 0; }
.precom-auto-facts section { border-top:1px solid var(--line2); padding-top:12px; }
.precom-auto-facts p { margin:5px 0; }
.precom-auto-warning { color:var(--chip-warn-ink); }
.precom-auto-other { display:grid; gap:12px; }
@media(max-width:600px) { .precom-auto-facts { grid-template-columns:1fr; } .precom-auto-row .precom-row-head { align-items:flex-start; flex-wrap:wrap; gap:8px; } }
@media print {
  .precom-record .precom-record-table { table-layout:fixed; }
  .precom-record .precom-record-table th, .precom-record .precom-record-table td { padding:6px 10px; white-space:normal; overflow-wrap:anywhere; }
  .precom-record h2, .precom-record h3, .precom-record h4 { break-after:avoid; page-break-after:avoid; }
  .precom-record .precom-tick-summary, .precom-record .precom-tick-project-summary,
  .precom-record .precom-row, .precom-record .precom-saved-declaration { break-inside:avoid; page-break-inside:avoid; }
}

/* Current pre-commissioning drawing cards. Facts are marks, not fittings. */
.precom-drawing-grid { margin-top:14px; }
.precom-drawing-thumb img { width:100%; height:100%; object-fit:contain; background:#fff; }
.precom-drawing-facts { margin:0; }
.precom-drawing-facts dt { font:inherit; }
.precom-drawing-facts dd { order:-1; margin:0; font:inherit; font-variant-numeric:tabular-nums; }
/* Not available and Snagged open the drawing's Checks list (043). The Progress
   card chip, with a hit area of 44px for a finger that does not change its look. */
/* One chip for every count on a card (048): a fact or a chip that opens the
   list, on a phone or a desktop, has the same height, padding and type. The
   id outweighs the touch rule that makes every button 44px high (phone
   shell, below), which once made the chips that open the list twice as tall
   on a phone. Their finger target is the invisible ring instead. */
#zone-list .chip.precom-card-chip {
  box-sizing:border-box; min-height:0 !important; height:auto; margin:0; padding:2px 9px; border:0;
  font-size:11.5px; font-weight:600; line-height:1.6; letter-spacing:.02em; font-variant-numeric:tabular-nums;
}
#zone-list .chip.precom-card-chip.na { font-weight:500; }
.precom-card-chip:focus-visible { outline:2px solid var(--accent); outline-offset:2px; }
@media (pointer:coarse) {
  button.precom-card-chip::after { content:""; position:absolute; inset:-11px -3px; }
}
/* The marks on a card's preview (048): an SVG with the page as its viewBox
   over the picture, fitted the same way, so each mark sits on its device.
   Shown once the picture has loaded. The viewer's colours, a white halo. */
.precom-card-marks { position:absolute; inset:0; z-index:1; display:none; width:100%; height:100%; pointer-events:none; overflow:hidden; }
.precom-drawing-thumb[data-preview-ready] .precom-card-marks { display:block; }
.precom-card-mark-halo { fill:#fff; }
.precom-card-mark-face { fill:var(--check-face); stroke:var(--check-ink); }
.precom-card-mark-glyph { fill:none; stroke:var(--check-ink); stroke-linecap:round; stroke-linejoin:round; }
.precom-card-mark.zone-check-available .precom-card-mark-glyph { stroke:var(--chip-pass-bg); }
.precom-card-mark-snag circle { fill:var(--chip-fail-ink); stroke:#fff; }
.precom-card-mark-snag path { fill:none; stroke:var(--chip-fail-bg); stroke-linecap:round; }
.precom-checks-active { display:flex; flex-wrap:wrap; gap:6px; margin:10px 0 0; }
.precom-checks-active .chip { min-height:32px; padding:4px 11px; border:1px solid var(--line2); cursor:pointer; font:inherit; font-size:12px; }
@media (pointer:coarse) { .precom-checks-active .chip { min-height:44px; } }
@media (max-width:600px) {
  .precom-tabs { overflow:visible; }
  .precom-tabs button { flex:1 1 0; min-width:0; padding:6px 7px; white-space:normal; }
  .precom-tabs button b { display:block; margin-left:0; font-size:11px; }
}
.precom-module-filter { max-width:360px; margin:12px 0; }
#precom-history-details > summary { padding:8px 0; font-weight:700; font-size:18px; cursor:pointer; min-height:44px; }
.precom-work-result.is-snagged { display:inline-block; box-sizing:border-box; max-width:100%; line-height:1.25; color:var(--chip-fail-ink); background:var(--chip-fail-bg); border:1px solid currentColor; border-radius:99px; padding:3px 8px; white-space:nowrap; }

/* The drawing owns the space. Menus open only when requested. */
.drawing-viewer-dlg,
.drawing-viewer-dlg.has-snag-selection { grid-template-rows:auto 0 minmax(0,1fr) auto; gap:4px; }
.drawing-viewer-dlg > .drawing-viewer-head {
  grid-row:1; display:flex; align-items:center; flex-wrap:nowrap; gap:6px; min-width:0; margin:0;
  padding:6px 7px;
}
.drawing-viewer-head > div:first-child { display:block; flex:1 1 auto; min-width:0; }
.drawing-viewer-head h2 { font-size:16px; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
.drawing-viewer-head .eyebrow { display:none; }
.drawing-viewer-head .drawing-target-label { font-size:11px; }
.drawing-viewer-head > button { flex:0 0 auto; padding-inline:10px; }
.drawing-viewer-head .drawing-viewer-controls { display:inline-flex; gap:5px; align-items:center; }
.drawing-viewer-dlg > .drawing-toolbars {
  position:absolute; z-index:30; top:68px; right:18px; width:min(560px,calc(100% - 36px));
  max-height:calc(100dvh - 150px); box-sizing:border-box; overflow:auto;
  display:none; grid-row:auto; margin:0; padding:12px; background:var(--card);
  border:1px solid var(--line); border-radius:10px; box-shadow:var(--shadow);
}
.drawing-viewer-dlg.controls-open > .drawing-toolbars { display:flex; flex-direction:column; align-items:stretch; }
.drawing-viewer-dlg .drawing-toolbars :where(#drawing-mode-toolbar,#drawing-target-toolbar):not([hidden]) {
  display:flex; flex-wrap:wrap; width:100%; margin:0;
}
.drawing-viewer-dlg > .drawing-viewer-actions:not([hidden]) {
  position:absolute; z-index:30; top:68px; right:18px; display:flex; flex-direction:column;
  align-items:stretch; gap:8px; box-sizing:border-box; width:min(320px,calc(100% - 36px));
  max-height:calc(100dvh - 150px); overflow:auto; margin:0; padding:12px;
  background:var(--card); border:1px solid var(--line); border-radius:10px; box-shadow:var(--shadow);
}
.drawing-viewer-actions > #drawing-viewer-new { margin:0; }
.drawing-viewer-dlg > .drawing-status-footer { grid-row:4; display:flex; flex-wrap:wrap; gap:2px 12px; margin:0; padding:2px; }
.drawing-status-footer .note { margin:0; font-size:12px; }
.drawing-active-tools {
  z-index:16; width:100%; max-width:100%;
  box-sizing:border-box; padding:5px; border:1px solid var(--line); border-radius:10px;
  background:var(--card); box-shadow:var(--shadow); display:none;
}
.drawing-active-tools:has(> .snag-mark-toolbar:not([hidden])) { display:block; }
.drawing-active-tools > .snag-mark-toolbar:not([hidden]) {
  display:flex; flex-wrap:wrap; gap:5px; padding:0; margin:0; border:0; background:none;
}
.drawing-active-tools .snag-mark-status { flex:1 1 180px; font-size:12px; }
.drawing-active-tools .snag-mark-what { font-size:12px; }
.drawing-active-tools .snag-mark-end { display:flex; flex-wrap:wrap; gap:5px; margin-left:auto; }
.drawing-active-tools .shape-choice { max-width:100%; }
.drawing-active-tools button { min-height:44px; padding-inline:10px; }
#snag-availability-choices:not([hidden]) { display:grid; gap:6px; margin-block:8px; }
@media (max-width:760px) {
  .drawing-viewer-dlg { padding:6px; }
  .drawing-viewer-dlg > .drawing-viewer-head { flex-wrap:wrap; gap:4px; }
  .drawing-viewer-head > div:first-child { flex-basis:100%; display:block; }
  .drawing-viewer-head .drawing-target-label { display:none; }
  .drawing-viewer-head #drawing-viewer-controls,
  .drawing-viewer-head #drawing-viewer-close { grid-row:auto; grid-column:auto; }
  .drawing-viewer-head > button { flex:1 1 auto; }
  .drawing-viewer-dlg > .drawing-toolbars,
  .drawing-viewer-dlg > .drawing-viewer-actions:not([hidden]) { top:86px; right:6px; max-width:calc(100% - 12px); }

  .drawing-active-tools > .snag-mark-toolbar:not([hidden]) { display:flex; gap:4px; }
  .drawing-active-tools .shape-choice { display:flex; flex:1 1 100%; }
  .drawing-active-tools .shape-choice button { flex:1 1 auto; min-width:0; font-size:12px; }
  .drawing-active-tools .snag-mark-status { flex:1 1 100%; }
  .drawing-active-tools .snag-mark-end { flex:1 1 auto; justify-content:flex-end; }
  .drawing-viewer-dlg.controls-open > .snag-detail-panel { display:none; }
}

.drawing-viewer-dlg:has(#snag-mark-toolbar:not([hidden]), #area-draw-toolbar:not([hidden]), #graphic-select-toolbar:not([hidden])) > .drawing-status-footer { grid-row:4; }

/* Active tools dock below the sheet. An inactive strip takes no space. */
.drawing-viewer-dlg,
.drawing-viewer-dlg.has-snag-selection { grid-template-rows:auto 0 minmax(0,1fr) auto auto auto; row-gap:0; }
.drawing-viewer-dlg > .drawing-active-tools {
  position:static; grid-column:1 / -1; grid-row:4; width:100%; max-width:100%;
  margin-top:4px; box-shadow:none;
}
.drawing-active-tools:has(> .snag-mark-toolbar:not([hidden])) { display:flex; align-items:center; flex-wrap:wrap; gap:4px; }
.drawing-active-tools > .snag-mark-toolbar:not([hidden]) { flex:1 1 auto; }
.drawing-viewer-dlg > .drawing-status-footer,
.drawing-viewer-dlg:has(#snag-mark-toolbar:not([hidden]), #area-draw-toolbar:not([hidden]), #graphic-select-toolbar:not([hidden])) > .drawing-status-footer { grid-row:5; }
@media(max-width:760px) {
  .drawing-active-tools > .snag-mark-toolbar:not([hidden]) {
    display:grid; grid-template-columns:minmax(0,1fr) auto auto;
    grid-template-areas:"name name name" "shape shape undo" "what end end" "status end end";
    align-items:center; gap:4px 8px;
  }
  .drawing-active-tools > #graphic-select-toolbar:not([hidden]) { grid-template-columns:minmax(0,1fr); grid-template-areas:"shape" "status" "end"; }
  .drawing-active-tools > #graphic-select-toolbar .snag-mark-end { justify-self:stretch; justify-content:space-between; }
  .drawing-viewer-dlg > :is(.drawing-change-panel,.snag-detail-panel) { grid-row:6; }
}

/* Menus use the viewer edge, not an empty grid row below the sheet. */
.drawing-viewer-dlg > .drawing-viewer-actions:not([hidden]) { grid-row:auto; grid-column:auto; }

@media(min-width:761px) {
  .drawing-active-tools > #graphic-select-toolbar:not([hidden]) { flex:1 1 0; }
}

/* Selected facts use drawing width only while their panel is open. */
.drawing-viewer-dlg.has-graphic-selection { grid-template-columns:minmax(0,1fr) minmax(300px,360px); }
.drawing-viewer-dlg > .graphic-select-panel { grid-column:2; grid-row:3; min-height:0; overflow:auto; margin:0; box-sizing:border-box; }
.drawing-viewer-dlg.has-graphic-selection > .drawing-change-panel { display:none; }
.graphic-select-head { display:flex; align-items:center; justify-content:space-between; gap:8px; }
.graphic-select-head h3 { margin:0; font-size:15px; }
.graphic-select-panel ul { display:flex; flex-direction:column; max-height:none; margin-top:8px; }
.graphic-select-panel li { justify-content:space-between; }
.graphic-select-panel li span { overflow-wrap:anywhere; }
#drawing-snag-mark-edit { display:inline-flex; align-items:center; justify-content:center; gap:6px; }
#drawing-snag-mark-edit[hidden] { display:none; }
#drawing-snag-mark-edit svg { width:16px; height:16px; flex:none; }
@media(max-width:760px) {
  .drawing-viewer-dlg.has-graphic-selection { grid-template-columns:minmax(0,1fr); }
  .drawing-viewer-dlg > .graphic-select-panel { grid-column:1; grid-row:6; max-height:30dvh; margin-top:6px; }
}

/* Good news, not a task, sits apart from the to-do chips, top right of the
   preview: New work on a Progress card, and the Available and Address dial
   set mark counts on a pre-commissioning card (048b). One overlay for both.
   Top left is selection; bottom right is offline. */
.drawing-preview-facts { position: absolute; right: 8px; top: 8px; z-index: 2; pointer-events: none;
  display: flex; flex-direction: column; align-items: flex-end; gap: 4px; max-width: calc(100% - 64px); }
/* Over a busy drawing a see-through tint lets the lines run through the
   words. A preview chip is solid in every theme, with a line of its own ink
   and a light shadow to lift it off the sheet. */
.drawing-thumb .chip.drawing-preview-fact {
  max-width: 100%; overflow: hidden; text-overflow: ellipsis;
  border: 1px solid color-mix(in srgb, currentColor 45%, transparent);
  box-shadow: 0 1px 2px rgba(0,0,0,.18); }
.drawing-thumb .chip.new-work.drawing-preview-fact {
  background: var(--chip-new-bg); color: var(--chip-new-ink); border-color: var(--chip-new-line); }
/* One neutral fact on each drawing preview. The card keeps its own controls. */
.drawing-offline-pill { position: absolute; right: 8px; bottom: 8px; z-index: 2; pointer-events: none;
  border: 1px solid var(--line2); border-radius: 999px; padding: 4px 8px;
  background: var(--card); color: var(--ink2); font-size: 11px; line-height: 1.3; }
/* The project preparation note is one line in the header. It takes its own
   width when the header has room. In a narrow window it shortens to fit and
   never widens the page; the other header controls keep their size. */
.site-preparation-status { font-size: 11px; color: var(--ink2); max-width: 28rem;
  flex: 0 1 auto; min-width: 0; overflow: hidden; overflow-wrap: anywhere;
  display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 1; line-clamp: 1; }
.site-preparation-status[hidden] { display: none; }
.top-right:has(> .site-preparation-status:not([hidden])) { flex: 0 1 auto; }
.top-right:has(> .site-preparation-status:not([hidden])) > :not(.site-preparation-status) { flex-shrink: 0; }
/* A phone header is one slim row for the project name. Each drawing card
   still shows its own Available offline or Preparing… pill. */
@media (max-width: 700px) { .site-preparation-status { display: none; } }
/* One active gesture owns the cursor, including the page above the stage. */

.drawing-target-stage.is-panning .drawing-target-page { cursor:grabbing; }

/* One neutral outline identifies the item located on either drawing viewer.
   The inner white edge and dark outer edge survive coloured sheet linework. */
.drawing-viewer-dlg .drawing-located:not(.drawing-graphic-target),
.zone-viewer-dlg .drawing-located {
  box-shadow:0 0 0 3px var(--drawing-selected-inner),
    0 0 0 6px var(--drawing-selected-outer) !important;
  /* No z-index lift: a located mark must not cover a snag badge or another
     control beside it (it hid a tick's own snag; gate 24 Oct 2026). */
}
.drawing-viewer-dlg .drawing-target-ring.drawing-located {
  box-shadow:none !important;
}
.zone-match-ring.is-selected { border-color:var(--drawing-selected-inner); }
.drawing-viewer-dlg .drawing-snag-badge.drawing-located,
.drawing-viewer-dlg .drawing-target-ring.drawing-located,
.drawing-viewer-dlg .drawing-area-label.drawing-located,
.drawing-viewer-dlg .zone-check.drawing-located,
.zone-viewer-dlg .zone-check.drawing-located,
.zone-viewer-dlg .redline-balloon.drawing-located,
.zone-viewer-dlg .zone-linked-snag.drawing-located,
.zone-viewer-dlg .zone-match-ring.drawing-located {
  isolation:isolate;
}
.drawing-locating::before {
  content:""; position:absolute; inset:-10px; border-radius:inherit;
  border:3px solid var(--drawing-selected-inner);
  box-shadow:0 0 0 2px var(--drawing-selected-outer);
  opacity:0; pointer-events:none;
  animation:drawing-locate-pulse 1.1s ease-out 3;
  animation-delay:var(--drawing-locate-delay, 0ms);
}
.drawing-target-ring.drawing-locating::before,
.drawing-snag-badge.drawing-locating::before,
.zone-check.drawing-locating::before,
.zone-linked-snag.drawing-locating::before,
.zone-match-ring.drawing-locating::before { border-radius:50%; }
.zone-check-control.drawing-locating::before { border-radius:7px; }
@keyframes drawing-locate-pulse {
  0% { transform:scale(.88); opacity:.95; }
  75%, 100% { transform:scale(1.2); opacity:0; }
}
/* SVG polygons need their own outline; pseudo-elements do not render on them. */
.drawing-located-outline {
  fill:none; stroke:var(--drawing-selected-inner); stroke-width:4px;
  vector-effect:non-scaling-stroke; pointer-events:none;
  filter:drop-shadow(0 0 1px var(--drawing-selected-outer));
}
#drawing-area-layer polygon.drawing-located-outline,
.drawing-snag-area polygon.drawing-located-outline {
  fill:none; stroke:var(--drawing-selected-inner); stroke-width:4px;
}
.drawing-located-outline.drawing-locating {
  transform-box:fill-box; transform-origin:center;
  animation:drawing-locate-pulse 1.1s ease-out 3;
  animation-delay:var(--drawing-locate-delay, 0ms);
}
/* Reduce motion: no growing ring, but the found item still flashes its
   outline three times in place, then settles (Clint, 24 Oct 2026). The
   !important beats the site-wide reduced-motion rule that shortens every
   animation; a flash has no movement. */
@keyframes drawing-locate-flash { 0%, 49% { opacity:1; } 50%, 100% { opacity:0; } }
@media (prefers-reduced-motion:reduce) {
  .drawing-locating::before {
    transform:none !important; opacity:0;
    animation:drawing-locate-flash .7s step-end 3 !important;
    animation-duration:.7s !important;
    animation-delay:var(--drawing-locate-delay, 0ms) !important;
  }
  .drawing-located-outline.drawing-locating {
    transform:none !important;
    animation:drawing-locate-flash .7s step-end 3 reverse !important;
    animation-duration:.7s !important;
  }
}
/* A snag badge is a square box round a round marker: its outline and ring
   follow the marker, not the box. */
.drawing-viewer-dlg .drawing-snag-badge.drawing-located,
.zone-viewer-dlg .zone-linked-snag.drawing-located { border-radius:50%; }

/* ── Drawing viewer controls (042, part A) ────────────────────────────────────
   One floating group at the bottom right of every drawing viewer, from
   viewer-controls.js: a vertical + / - pair and Fit. A finger gets Fit only;
   it has pinch, double-tap, a two-finger tap and the one-finger slide. The
   input decides, not the width: data-input is set from the last press. The
   group rises above a panel sheet by the height the sheet covers
   (--sheet-cover) and moves left of a side panel floating over the drawing
   (--side-cover); the viewer measures both. There is no zoom percentage. */
.zone-stage-wrap { position:relative; flex:1 1 auto; min-width:0; min-height:0; display:flex; flex-direction:column; }
.zone-stage-wrap > .zone-stage { flex:1 1 auto; min-height:0; }
.viewer-controls {
  position:absolute; z-index:6; right:calc(12px + var(--side-cover, 0px)); bottom:calc(12px + var(--sheet-cover, 0px));
  display:flex; flex-direction:column; align-items:center; gap:8px; pointer-events:none;
}
.viewer-controls > * { pointer-events:auto; }
.viewer-control-pair, .viewer-controls .viewer-control-fit {
  border:1px solid var(--line2); border-radius:10px; box-shadow:var(--shadow);
  background:color-mix(in srgb,var(--card) 94%,transparent);
}
.viewer-control-pair { display:flex; flex-direction:column; overflow:hidden; }
.viewer-controls .viewer-control {
  display:inline-flex; align-items:center; justify-content:center; flex:0 0 auto;
  box-sizing:border-box; width:44px; height:44px; min-width:44px; min-height:44px; margin:0; padding:0;
  color:var(--ink2); cursor:pointer;
}
.viewer-control-pair .viewer-control { border:0; border-radius:0; background:transparent; box-shadow:none; }
.viewer-control-pair .viewer-control + .viewer-control { border-top:1px solid var(--line2); }
.viewer-controls .viewer-control:hover:not(:disabled) { background:var(--line); color:var(--ink); }
.viewer-controls .viewer-control:disabled { opacity:.4; cursor:not-allowed; }
.viewer-control svg { width:20px; height:20px; fill:none; stroke:currentColor;
  stroke-width:1.8; stroke-linecap:round; stroke-linejoin:round; }
.viewer-controls[data-input="touch"] .viewer-control-pair { display:none; }

/* One tool strip at a time (042): while a marking or drawing tool has its
   strip, View and More wait. The active strip stays. */
.drawing-viewer-dlg.tool-active :is(#drawing-viewer-controls, #drawing-viewer-more) { display:none; }

/* ── Panels as sheets (042, part B) ───────────────────────────────────────────
   bottom-sheet.js puts .bottom-sheet on each panel beside a drawing. Wide: the
   side panel it was, with no fold or dock control (051): it closes with its
   own Close details. Narrow (.is-narrow: a phone, or an iPad held upright):
   a sheet over the foot of the drawing at peek, half or full height
   (data-sheet). At peek only the title shows (051: no action at peek). The
   viewer's own hiding rules still win, so a sheet never shows while View is
   open or a marking strip is in use: display is set at low specificity on
   purpose, and every other property here is geometry. */
.sheet-grip { display:none; }
.bottom-sheet:not(.is-narrow) { position:relative; }

.drawing-viewer-dlg:has(> .bottom-sheet.is-narrow) { grid-template-columns:minmax(0,1fr); }
/* A tool strip keeps Cancel and its save action in reach on every narrow
   screen, not only on a phone (051): the details and change sheets give way
   to it, and the selected-graphics sheet stands on it (app.js,
   syncToolStripCover). */
.drawing-viewer-dlg:has(#snag-mark-toolbar:not([hidden]), #area-draw-toolbar:not([hidden]), #graphic-select-toolbar:not([hidden]))
  > :is(.drawing-change-panel, .snag-detail-panel).bottom-sheet.is-narrow { display:none; }
.drawing-viewer-dlg > .bottom-sheet.is-narrow { bottom:var(--strip-cover, 0px) !important; }
.bottom-sheet.is-narrow {
  --sheet-peek:calc(64px + env(safe-area-inset-bottom, 0px));
  position:absolute !important; inset:auto 0 0 0 !important; z-index:25 !important;
  box-sizing:border-box !important; width:auto !important; min-width:0 !important; max-width:none !important;
  height:var(--sheet-drag, 45dvh) !important; max-height:none !important;
  margin:0 !important; padding:0 14px calc(12px + env(safe-area-inset-bottom, 0px)) !important;
  border:0 !important; border-top:1px solid var(--line2) !important; border-radius:14px 14px 0 0 !important;
  background:var(--card) !important; box-shadow:0 -6px 18px rgba(0,0,0,.16) !important;
  overflow:auto !important; overscroll-behavior:contain;
  grid-row:auto !important; grid-column:auto !important; order:0 !important;
}
.bottom-sheet.is-narrow[data-sheet="full"] { height:var(--sheet-drag, min(calc(100dvh - 72px), 100%)) !important; }
.bottom-sheet.is-narrow[data-sheet="peek"] {
  height:var(--sheet-drag, var(--sheet-peek)) !important; overflow:hidden !important;
  padding-top:14px !important; padding-bottom:env(safe-area-inset-bottom, 0px) !important; touch-action:none;
}
.bottom-sheet:where(.is-narrow[data-sheet="peek"]) {
  display:flex; flex-direction:row; flex-wrap:nowrap; align-items:center; gap:10px;
}
.bottom-sheet.is-narrow > .sheet-grip {
  display:block; position:sticky; top:0; z-index:3; flex:none; align-self:stretch; justify-self:stretch;
  height:20px; margin:0 -14px 4px; background:var(--card); touch-action:none; cursor:grab;
}
.bottom-sheet.is-narrow > .sheet-grip::before {
  content:""; position:absolute; left:50%; top:7px; width:40px; height:5px; margin-left:-20px;
  border-radius:3px; background:var(--line2);
}
.bottom-sheet.is-narrow[data-sheet="peek"] > .sheet-grip {
  position:absolute; top:0; left:0; right:0; margin:0; background:transparent;
}
.bottom-sheet.is-narrow[data-sheet="peek"] > :not(.sheet-grip, .sheet-peek-title, .sheet-peek-path),
.bottom-sheet.is-narrow[data-sheet="peek"] .sheet-peek-path > :not(.sheet-peek-title, .sheet-peek-path) {
  display:none !important;
}
.bottom-sheet.is-narrow[data-sheet="peek"] .sheet-peek-path { display:contents !important; }
.bottom-sheet.is-narrow[data-sheet="peek"] .sheet-peek-title {
  display:block !important; flex:1 1 auto; min-width:0; margin:0 !important; padding:0 !important;
  overflow:hidden; white-space:nowrap; text-overflow:ellipsis; font-size:15px; line-height:1.3;
}
.bottom-sheet.is-narrow[data-sheet="peek"] .sheet-peek-title > * { vertical-align:middle; }
@media (prefers-reduced-motion: no-preference) {
  .bottom-sheet.is-narrow:not(.is-dragging) { transition:height 160ms ease; }
}

/* ── View, grouped (052) ──────────────────────────────────────────────────────
   The View panel holds its controls in groups, in one order everywhere:
   Layers, Drawing, Tools (the area drawing), then Changes (Delmatic). On a
   desktop and a sideways iPad the panel spans the viewer and each group is one
   row: its name, then its controls. Opened, the Markers filter is a full-width
   row of its own, not a box that scrolls inside the panel, and the panel
   itself never scrolls at 1180 px and up. On a phone and an upright iPad the
   groups stack in one column, a control to a line. A contractor's status
   drawing has no Changes group: both change layers are off, so the whole
   group goes, not just its buttons. */
.drawing-viewer-dlg.layer-off-changes.layer-off-comparison #drawing-mode-toolbar { display:none; }
.drawing-view-group-title {
  margin:0; color:var(--muted); font-size:11px; font-weight:700; letter-spacing:.06em;
  text-transform:uppercase; white-space:nowrap;
}
.drawing-viewer-dlg .drawing-toolbars .drawing-view-group:not([hidden]) {
  display:flex; flex-wrap:wrap; align-items:center; gap:4px 10px; width:100%; min-width:0;
  margin:0; padding:6px 0; box-sizing:border-box;
}
.drawing-viewer-dlg .drawing-toolbars .drawing-view-group:not([data-view-first]) { border-top:1px solid var(--line); }
.drawing-viewer-dlg .drawing-toolbars #drawing-target-toolbar:not([hidden]) {
  display:flex; flex-direction:column; flex-wrap:nowrap; align-items:stretch; gap:0;
  width:100%; margin:0; padding:0;
}
.drawing-viewer-dlg .drawing-toolbars .drawing-view-group > .marker-visibility-control { margin-block:0; }
/* The Markers filter: a row of its own, opened in place. */
.drawing-viewer-dlg .drawing-toolbars #drawing-marker-types fieldset {
  position:static; z-index:auto; width:100%; max-height:none; overflow:visible;
  margin:6px 0 0; box-shadow:none; background:var(--card2);
  grid-template-columns:repeat(auto-fill, minmax(190px, 1fr));
}
.drawing-viewer-dlg .drawing-toolbars #drawing-marker-types[open] { flex:1 1 100%; }
@media (min-width:1000px) {
  .drawing-viewer-dlg > .drawing-toolbars {
    left:18px; right:18px; width:auto; max-height:none; overflow:visible; padding:4px 14px;
  }
  .drawing-viewer-dlg .drawing-toolbars .drawing-view-group-title { flex:0 0 88px; }
}
@media (max-width:999.98px) {
  .drawing-viewer-dlg > .drawing-toolbars { width:min(560px, calc(100% - 12px)); right:6px; padding:4px 12px; }
  .drawing-viewer-dlg .drawing-toolbars .drawing-view-group:not([hidden]) {
    display:grid; grid-template-columns:minmax(0,1fr); align-items:stretch; gap:4px;
  }
  .drawing-viewer-dlg .drawing-toolbars .drawing-view-group > :is(.marker-visibility-control, .drawing-overlay-strength) {
    justify-content:flex-start; white-space:normal;
  }
  .drawing-viewer-dlg .drawing-toolbars .drawing-view-group > :is(button, select, .drawing-marker-types) {
    justify-self:stretch; width:100%; max-width:none; box-sizing:border-box;
  }
  .drawing-viewer-dlg .drawing-toolbars .drawing-view-group > .drawing-marker-types > summary { width:100%; box-sizing:border-box; }
  .drawing-viewer-dlg .drawing-toolbars #drawing-marker-types fieldset { grid-template-columns:minmax(0,1fr); }
}

/* The contractor's key (052): new work, the snag colours, the area colours. */
.drawing-legend-dlg .drawing-area-legend { display:none; }
.drawing-legend-dlg.status-legend .drawing-marker-legend dl > div:not(.teal) { display:none; }
.drawing-legend-dlg.status-legend :is(.drawing-snag-legend, .drawing-area-legend) {
  display:block; margin-top:12px; padding-top:10px; border-top:1px solid var(--line);
}
.drawing-legend-dlg.areas-key :is(.drawing-marker-legend, .drawing-snag-legend) { display:none; }
.drawing-legend-dlg.areas-key .drawing-area-legend { display:block; margin-top:10px; }
.drawing-legend-dlg.areas-key .drawing-area-legend h3 { display:none; }
.drawing-area-legend h3 { margin:0 0 8px; font-size:14px; }
.drawing-area-legend dl { display:grid; grid-template-columns:repeat(auto-fill, minmax(150px, 1fr)); gap:8px 14px; margin:0; }
.drawing-area-legend dt { display:flex; align-items:center; gap:9px; font-weight:650; }
.drawing-area-legend .area-swatch { width:22px; height:16px; }

/* The area panel shows one area's details in place of the list (052). The
   details scroll inside the panel; the back link, the arrows and Close
   details stay at its top. Outside the area drawing, the change list gives
   way to it, as it does to snag details. */
.drawing-viewer-dlg.has-area-selection > .drawing-change-panel:not(.drawing-area-panel) { display:none; }
.drawing-area-panel[data-area-panel="details"] > .drawing-area-selected:not([hidden]) {
  display:flex; flex-direction:column; flex:1 1 auto; min-height:0; padding:0; border-bottom:0;
}
.drawing-area-panel .drawing-change-panel-head[hidden] { display:none; }
.drawing-area-panel .drawing-area-summary[hidden],
.drawing-area-panel .drawing-area-list[hidden] { display:none; }
.drawing-viewer-dlg .drawing-panel-back {
  align-self:flex-start; min-height:44px; padding:0 8px 0 0; border-color:transparent; background:transparent;
  color:var(--accent-ink); font-size:13px; font-weight:650; box-shadow:none;
}
@media (hover:hover) { .drawing-viewer-dlg .drawing-panel-back:hover { text-decoration:underline; } }
.drawing-area-selected .drawing-area-nav { margin:0 0 6px; }
.drawing-change-details-nav:not([hidden]) { display:flex; flex-direction:column; align-items:stretch; gap:2px; margin:0 0 8px; }
.drawing-change-details-nav .drawing-panel-back { align-self:flex-start; }
.drawing-area-selected .drawing-area-selected-actions[hidden] { display:none; }
.drawing-area-details { flex:1 1 auto; min-height:0; overflow:auto; margin-top:6px; }
.drawing-area-details > .area-dlg-body { max-height:none; overflow:visible; padding:0 2px 12px; }
.drawing-area-details .area-dlg-section { padding:12px 0; }
.drawing-area-details .area-dlg-section:first-child { padding-top:4px; }
