/* ===========================================================================
   ROC Polygraph System — Design System
   Professional, tablet + desktop friendly, print-ready.
   =========================================================================== */
:root{
  --navy-900:#0b1a2f; --navy-800:#12233d; --navy-700:#1b3157; --navy-600:#254170;
  --brand:#1f6feb; --brand-dark:#1657c4; --brand-soft:#e8f1ff;
  --teal:#0ea5a4; --amber:#d97706; --red:#dc2626; --green:#15803d;
  --ink:#0f172a; --muted:#5b6b82; --line:#e3e8f0; --line-2:#eef2f7;
  --bg:#f4f6fb; --card:#ffffff; --field:#ffffff;
  --shadow-sm:0 1px 2px rgba(15,23,42,.06),0 1px 3px rgba(15,23,42,.08);
  --shadow-md:0 4px 12px rgba(15,23,42,.08),0 2px 4px rgba(15,23,42,.04);
  --shadow-lg:0 20px 40px -12px rgba(15,23,42,.25);
  --radius:14px; --radius-sm:9px; --radius-lg:20px;
  --font:"Inter","Segoe UI",system-ui,-apple-system,Roboto,Arial,sans-serif;
}
*{box-sizing:border-box}
html,body{margin:0;padding:0;-webkit-text-size-adjust:100%;text-size-adjust:100%}
body{
  font-family:var(--font); color:var(--ink); background:var(--bg);
  font-size:15px; line-height:1.5; -webkit-font-smoothing:antialiased;
}
h1,h2,h3,h4{margin:0;font-weight:700;letter-spacing:-.01em;color:var(--ink)}
a{color:var(--brand);text-decoration:none}
button{font-family:inherit}
img,svg,canvas,video{max-width:100%}
/* nothing may force the page wider than the screen → no more sideways scrolling.
   min-width:0 lets grid/flex children shrink so their text wraps instead of
   pushing the layout wider than the viewport. */
.grid>*,.form-grid>*,.capture-grid>*,.rgrid>*,.wizard>*{min-width:0}
p,li,td,th,.consent-item p{overflow-wrap:break-word}
.hidden{display:none !important}
.mono{font-variant-numeric:tabular-nums;font-feature-settings:"tnum"}

/* ---------- Buttons ---------- */
.btn{display:inline-flex;align-items:center;gap:.5rem;justify-content:center;
  border:1px solid transparent;border-radius:var(--radius-sm);padding:.62rem 1.05rem;
  font-weight:600;font-size:.92rem;cursor:pointer;transition:.15s;white-space:nowrap;
  background:var(--brand);color:#fff}
.btn:hover{background:var(--brand-dark)}
.btn:active{transform:translateY(1px)}
.btn.secondary{background:#fff;color:var(--ink);border-color:var(--line)}
.btn.secondary:hover{background:#f7f9fc;border-color:#cfd8e6}
.btn.ghost{background:transparent;color:var(--muted)}
.btn.ghost:hover{background:#eef2f7;color:var(--ink)}
.btn.danger{background:var(--red)}
.btn.danger:hover{background:#b91c1c}
.btn.success{background:var(--green)}
.btn.lg{padding:.85rem 1.4rem;font-size:1rem}
.btn.sm{padding:.4rem .75rem;font-size:.82rem}
.btn:disabled{opacity:.5;cursor:not-allowed}
.btn-row{display:flex;gap:.6rem;flex-wrap:wrap}

/* ---------- Badges / pills ---------- */
.badge{display:inline-flex;align-items:center;gap:.35rem;font-size:.74rem;font-weight:700;
  padding:.22rem .6rem;border-radius:999px;letter-spacing:.02em;text-transform:uppercase}
.badge.di{background:#fdecec;color:var(--red)}
.badge.ndi{background:#e7f6ec;color:var(--green)}
.badge.inc{background:#fff4e5;color:var(--amber)}
.badge.uco{background:#eef2f7;color:var(--muted)}
.badge.ref{background:#f3e8ff;color:#7c3aed}
.badge.draft{background:#eef2f7;color:var(--muted)}
.badge.in_progress{background:var(--brand-soft);color:var(--brand-dark)}
.badge.scored{background:#fff4e5;color:var(--amber)}
.badge.completed{background:#e7f6ec;color:var(--green)}
.badge.no_show{background:#fdecec;color:var(--red)}

/* ---------- App shell ---------- */
.app{display:grid;grid-template-columns:250px 1fr;min-height:100vh}
.sidebar{background:linear-gradient(180deg,var(--navy-900),var(--navy-800));
  color:#cdd7e6;display:flex;flex-direction:column;position:sticky;top:0;height:100vh}
.brand{display:flex;align-items:center;gap:.7rem;padding:1.15rem 1.25rem;border-bottom:1px solid rgba(255,255,255,.07)}
.brand .logo{width:38px;height:38px;border-radius:10px;background:linear-gradient(135deg,var(--brand),var(--teal));
  display:grid;place-items:center;font-weight:800;color:#fff;font-size:1.05rem;flex:none}
.brand b{color:#fff;font-size:.98rem;display:block;line-height:1.15}
.brand span{font-size:.72rem;color:#8ea3c0}
/* Customer logo (logo3) used as the brand mark across the app */
.brand .logo-img{height:40px;width:auto;max-width:150px;object-fit:contain;background:#fff;border-radius:9px;padding:5px 7px;flex:none;box-shadow:var(--shadow-sm)}
.topbar-logo{display:none;height:30px;width:auto;max-width:130px;object-fit:contain;flex:none}
.login-logo{height:56px;width:auto;max-width:230px;object-fit:contain;display:block}
.page-logo{height:44px;width:auto;max-width:170px;object-fit:contain;flex:none}
@media(max-width:1024px){.topbar-logo{display:block}}
.nav{padding:.75rem .6rem;flex:1;overflow-y:auto}
.nav a{display:flex;align-items:center;gap:.75rem;color:#aebbd0;padding:.62rem .8rem;
  border-radius:10px;font-weight:600;font-size:.9rem;margin-bottom:2px;cursor:pointer}
.nav a svg{width:18px;height:18px;flex:none;opacity:.85}
.nav a:hover{background:rgba(255,255,255,.06);color:#fff}
.nav a.active{background:var(--brand);color:#fff}
.nav .section{font-size:.68rem;text-transform:uppercase;letter-spacing:.08em;color:#6f83a3;
  padding:.9rem .9rem .4rem}
.sidebar .foot{padding:.9rem 1rem;border-top:1px solid rgba(255,255,255,.07);font-size:.78rem}
.sidebar .foot .who{color:#fff;font-weight:600}
.sidebar .foot .env{display:inline-block;margin-top:.3rem;font-size:.66rem;padding:.15rem .5rem;border-radius:6px}
.env.demo{background:#3a2a00;color:#fbbf24}
.env.live{background:#052e1c;color:#34d399}

/* ---------- Account block (sidebar footer) ---------- */
.acct{display:flex;align-items:center;gap:.6rem;margin-bottom:.7rem;min-width:0}
.acct .av{width:34px;height:34px;flex:none;border-radius:50%;display:grid;place-items:center;
  background:linear-gradient(135deg,var(--brand),var(--teal));color:#fff;
  font-weight:700;font-size:.78rem;letter-spacing:.02em;box-shadow:0 2px 8px rgba(0,0,0,.28)}
.acct .id{min-width:0}
.acct .id b{display:block;color:#fff;font-weight:600;font-size:.8rem;line-height:1.25;
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.acct .id span{display:block;color:#8ea3c0;font-size:.68rem;
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis}

.signout{display:flex;align-items:center;justify-content:center;gap:.5rem;width:100%;
  margin-top:.7rem;padding:.55rem .7rem;border-radius:9px;cursor:pointer;
  font:inherit;font-size:.78rem;font-weight:600;
  background:rgba(255,255,255,.05);color:#c8d4e6;
  border:1px solid rgba(255,255,255,.12);transition:.16s}
.signout:hover{background:rgba(220,38,38,.16);border-color:rgba(248,113,113,.5);color:#fecaca}
.signout:active{transform:translateY(1px)}
.signout:focus-visible{outline:2px solid var(--brand);outline-offset:2px}
.signout svg{flex:none}

.install-link{display:none;align-items:center;justify-content:center;gap:.5rem;width:100%;
  margin-top:.7rem;padding:.5rem .7rem;border-radius:9px;cursor:pointer;
  font-size:.78rem;font-weight:600;color:#7fd1a8;
  background:rgba(52,211,153,.1);border:1px solid rgba(52,211,153,.28);transition:.16s}
.install-link:hover{background:rgba(52,211,153,.18)}

/* Topbar account button — the sidebar is a drawer on tablets, so sign-out
   stays reachable without opening it. */
.topbar .avatar-btn{width:36px;height:36px;flex:none;border-radius:50%;border:1px solid var(--line);
  background:linear-gradient(135deg,var(--brand),var(--teal));color:#fff;
  font-weight:700;font-size:.76rem;cursor:pointer;display:grid;place-items:center;
  box-shadow:var(--shadow-sm);transition:.16s}
.topbar .avatar-btn:hover{filter:brightness(1.08)}
.topbar .avatar-btn:focus-visible{outline:2px solid var(--brand);outline-offset:2px}
.acct-menu{position:absolute;right:0;top:calc(100% + .5rem);z-index:130;min-width:212px;
  background:#fff;border:1px solid var(--line);border-radius:12px;box-shadow:var(--shadow-lg);
  padding:.5rem;animation:fade .12s}
.acct-menu .hd{padding:.5rem .6rem .6rem;border-bottom:1px solid var(--line-2);margin-bottom:.4rem}
.acct-menu .hd b{display:block;font-size:.84rem;color:var(--ink);
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.acct-menu .hd span{display:block;font-size:.72rem;color:var(--muted);
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.acct-menu button{display:flex;align-items:center;gap:.55rem;width:100%;padding:.5rem .6rem;
  border:none;background:none;border-radius:8px;cursor:pointer;
  font:inherit;font-size:.82rem;color:var(--ink);text-align:left}
.acct-menu button:hover{background:var(--line-2)}
.acct-menu button.danger{color:var(--red)}
.acct-menu button.danger:hover{background:#fdecec}

.main{min-width:0;display:flex;flex-direction:column}
.topbar{position:sticky;top:0;z-index:20;background:rgba(255,255,255,.9);backdrop-filter:blur(8px);
  border-bottom:1px solid var(--line);padding:.85rem 1.6rem;display:flex;align-items:center;gap:1rem}
.topbar h1{font-size:1.15rem}
.topbar .sub{color:var(--muted);font-size:.83rem;margin-top:1px}
.topbar .spacer{flex:1}
.hamburger{display:none;background:none;border:none;cursor:pointer;padding:.3rem}
/* The working width of every screen in the app.

   This was 1240px, set when the app was mostly forms. It is now mostly TABLES —
   the examinations register alone carries a dozen columns — and on a 1900px
   monitor that cap left roughly 200px of dead margin down each side while the
   table it was constraining had to scroll sideways to show its own columns.
   Squeezing data into a column and then making the reader scroll it is the
   worst of both.

   No cap at all now: the screen is the working area, and on a wide monitor the
   register, the analytics cards and the schedule all have real use for it.

   Reading measure is protected where it actually matters rather than by
   starving every screen of width — the report sheet keeps its own 850px below,
   because that one is a document, and the prose blocks that follow are held to
   a sensible line length of their own. */
.content{padding:1.6rem;max-width:none;width:100%;min-width:0;margin:0}
/* Long-form text is the one thing that must not run the full width of a wide
   monitor: a 1900px line is genuinely hard to read back to the start of. Cards
   and tables are unaffected — this only holds loose paragraphs and the lead
   lines that introduce a screen. */
.content > p,
.content > .lead,
.content > .an-hint{max-width:110ch}

/* ---------- Cards & grids ---------- */
.card{background:var(--card);border:1px solid var(--line);border-radius:var(--radius);
  box-shadow:var(--shadow-sm)}
.card.pad{padding:1.4rem}
.card-head{display:flex;align-items:center;gap:.8rem;flex-wrap:wrap;padding:1.1rem 1.4rem;border-bottom:1px solid var(--line-2)}
.card h3{font-size:1.2rem;font-weight:800;color:#000}
.card-head h3{font-size:1.25rem;font-weight:800;color:#000}
.card-head .spacer{flex:1}
.card-body{padding:1.4rem}
.grid{display:grid;gap:1.2rem}
.grid.cols-2{grid-template-columns:repeat(2,1fr)}
.grid.cols-3{grid-template-columns:repeat(3,1fr)}
.grid.cols-4{grid-template-columns:repeat(4,1fr)}

/* ---------- Stat tiles ---------- */
.stat{background:var(--card);border:1px solid var(--line);border-radius:var(--radius);
  padding:1.15rem 1.25rem;box-shadow:var(--shadow-sm);position:relative;overflow:hidden;text-align:center}
.stat .k{font-size:.78rem;color:var(--muted);font-weight:600;text-transform:uppercase;letter-spacing:.03em}
.stat .v{font-size:2rem;font-weight:800;margin-top:.25rem;line-height:1}
.stat .d{font-size:.8rem;color:var(--muted);margin-top:.35rem}
.stat .ic{width:34px;height:34px;border-radius:10px;margin:0 auto .55rem;
  display:grid;place-items:center;background:var(--brand-soft);color:var(--brand)}
.stat.green .v{color:var(--green)} .stat.red .v{color:var(--red)} .stat.amber .v{color:var(--amber)}
.stat.clickable{cursor:pointer;transition:.13s}
.stat.clickable:hover{border-color:var(--brand);box-shadow:0 0 0 2px rgba(31,111,235,.14);transform:translateY(-2px)}

/* ---------- Dashboard summary tiles ----------
   Four tinted backgrounds, one per tile, so the headline numbers are told
   apart at a glance. Same soft-tint convention the status badges already use
   (.badge.di / .badge.ndi / .badge.in_progress above) rather than a new
   palette — muted enough to stay business-professional, not a poster. Only
   the four dashboard tiles get this (the .dash-summary marker on their
   container); every other .stat elsewhere in the app is unaffected. */
.dash-summary .stat:nth-child(1){background:var(--brand-soft);border-color:#cfe1fb}
.dash-summary .stat:nth-child(1) .ic{background:#fff;color:var(--brand-dark)}
.dash-summary .stat:nth-child(2){background:#e6f7f6;border-color:#c8ece9}
.dash-summary .stat:nth-child(2) .ic{background:#fff;color:var(--teal)}
.dash-summary .stat:nth-child(3){background:#fdecec;border-color:#f7cdcd}
.dash-summary .stat:nth-child(3) .ic{background:#fff;color:var(--red)}
.dash-summary .stat:nth-child(4){background:#e7f6ec;border-color:#c9e9d3}
.dash-summary .stat:nth-child(4) .ic{background:#fff;color:var(--green)}
.dash-summary .stat:nth-child(4).red{background:#fdecec;border-color:#f7cdcd}
.dash-summary .stat:nth-child(4).red .ic{color:var(--red)}

/* ---------- Analytics page KPI tiles ----------
   Same idea as the dashboard summary row above, applied to the Analytics
   page's own headline row (Total tests / Deception Indicated / First-timer DI
   / No service data). Tiles 2 and 4 already carry a live .red/.green/.amber
   modifier from stat()'s own good/bad logic — the background follows that
   same signal rather than a second, disagreeing one. */
.an-kpi .stat:nth-child(1){background:var(--brand-soft);border-color:#cfe1fb}
.an-kpi .stat:nth-child(1) .ic{background:#fff;color:var(--brand-dark)}
.an-kpi .stat:nth-child(2).red{background:#fdecec;border-color:#f7cdcd}
.an-kpi .stat:nth-child(2).red .ic{background:#fff;color:var(--red)}
.an-kpi .stat:nth-child(2).green{background:#e7f6ec;border-color:#c9e9d3}
.an-kpi .stat:nth-child(2).green .ic{background:#fff;color:var(--green)}
.an-kpi .stat:nth-child(3){background:#fdf3e3;border-color:#f5e0af}
.an-kpi .stat:nth-child(3) .ic{background:#fff;color:var(--amber)}
.an-kpi .stat:nth-child(4).amber{background:#fdf3e3;border-color:#f5e0af}
.an-kpi .stat:nth-child(4).amber .ic{background:#fff;color:var(--amber)}
.an-kpi .stat:nth-child(4).green{background:#eef2f7;border-color:#dbe2ec}
.an-kpi .stat:nth-child(4).green .ic{background:#fff;color:var(--muted)}

.barrow{border-radius:8px;padding:.35rem;margin:-.35rem -.35rem .35rem !important;transition:.12s}
.barrow:hover{background:#f4f7fe}

/* ---------- Forms ---------- */
.field{margin-bottom:1rem}
.field > label{display:block;font-weight:600;font-size:.83rem;margin-bottom:.35rem;color:#2a3a52}
.field .hint{font-size:.76rem;color:var(--muted);margin-top:.3rem}
input,select,textarea{width:100%;min-width:0;max-width:100%;padding:.6rem .75rem;border:1px solid var(--line);
  border-radius:var(--radius-sm);font-size:.92rem;font-family:inherit;background:var(--field);color:var(--ink);
  transition:.15s}
input:focus,select:focus,textarea:focus{outline:none;border-color:var(--brand);
  box-shadow:0 0 0 3px rgba(31,111,235,.13)}
textarea{resize:vertical;min-height:90px}
/* A field the APP fills, not the examiner — the examination End time, stamped
   when the examinee signs the post-test release form. Blacked out so it reads
   as "not yours to type" rather than "we forgot to ask you". -webkit-text-fill
   and opacity are needed because a disabled input is otherwise washed out to
   the point the stamped time cannot be read. */
input.locked-fld{background:#0e2038;border-color:#0e2038;color:#e9eef7;cursor:not-allowed}
input.locked-fld:disabled{-webkit-text-fill-color:#e9eef7;opacity:1}
input.locked-fld:focus{outline:none;border-color:#0e2038;box-shadow:none}
input.locked-fld::-webkit-calendar-picker-indicator{filter:invert(1);opacity:.55;cursor:not-allowed}
/* Tick boxes must not inherit the full-width text-field styling above. */
input[type=checkbox],input[type=radio]{width:auto;min-width:0;max-width:none;padding:0;border:none;
  background:none;box-shadow:none;flex:0 0 auto;accent-color:var(--brand);
  width:1.05rem;height:1.05rem;cursor:pointer}
input[type=checkbox]:focus,input[type=radio]:focus{box-shadow:0 0 0 3px rgba(31,111,235,.2)}
/* A row picked for a bulk action (e.g. the Email tab's report selection). */
table.data tbody tr.picked td{background:var(--brand-soft)}
table.data tbody tr.picked:hover td{background:#dbe9ff}
.form-grid{display:grid;grid-template-columns:repeat(2,1fr);gap:0 1.2rem}
.form-grid .full{grid-column:1/-1}
.form-grid.cols-3{grid-template-columns:repeat(3,1fr)}
.req::after{content:" *";color:var(--red)}

/* segmented / choice chips */
.chips{display:flex;flex-wrap:wrap;gap:.45rem}
.chip{border:1px solid var(--line);background:#fff;border-radius:999px;padding:.42rem .9rem;
  font-size:.85rem;font-weight:600;cursor:pointer;color:#33465e;transition:.12s;user-select:none}
.chip:hover{border-color:#c4d0e2}
.chip.on{background:var(--brand);border-color:var(--brand);color:#fff}
.chip.on.yes{background:var(--green);border-color:var(--green)}
.chip.on.no{background:#64748b;border-color:#64748b}
.chip.on.di{background:var(--red);border-color:var(--red)}
.chip.on.ndi{background:var(--green);border-color:var(--green)}
.chip.on.inc{background:var(--amber);border-color:var(--amber)}
.chip.on.uco{background:#64748b;border-color:#64748b}
.chip.on.ref{background:#7c3aed;border-color:#7c3aed}

/* consent checklist */
.consent-item{display:flex;gap:.8rem;padding:.85rem 1rem;border:1px solid var(--line);
  border-radius:var(--radius-sm);margin-bottom:.6rem;cursor:pointer;transition:.12s;background:#fff}
.consent-item:hover{border-color:#c4d0e2}
.consent-item.checked{border-color:var(--green);background:#f4fbf6}
.consent-item .box{width:22px;height:22px;border:2px solid #c4d0e2;border-radius:6px;flex:none;
  display:grid;place-items:center;margin-top:1px;transition:.12s}
.consent-item.checked .box{background:var(--green);border-color:var(--green);color:#fff}
.consent-item p{margin:0;font-size:.88rem;color:#334155}
.consent-item .box svg{opacity:0}
.consent-item.checked .box svg{opacity:1}

/* ---------- Tables ---------- */
.table-wrap{overflow-x:auto;-webkit-overflow-scrolling:touch;overscroll-behavior-x:contain;border:1px solid var(--line);border-radius:var(--radius);background:#fff}
table.data{width:100%;border-collapse:collapse;font-size:.86rem;min-width:640px}
table.data th{text-align:left;font-size:.72rem;text-transform:uppercase;letter-spacing:.04em;
  color:var(--muted);padding:.7rem .9rem;border-bottom:1px solid var(--line);background:#fafbfe;white-space:nowrap}
table.data td{padding:.7rem .9rem;border-bottom:1px solid var(--line-2)}
table.data tr:last-child td{border-bottom:none}
table.data tbody tr{cursor:pointer;transition:.1s}
table.data tbody tr:hover{background:#f7f9fe}
.cell-name{font-weight:600}
.cell-sub{color:var(--muted);font-size:.78rem}

/* ---------- Wizard ---------- */
.wizard{display:grid;grid-template-columns:270px 1fr;gap:1.4rem;align-items:start}
.steps{position:sticky;top:80px}
.steps ol{list-style:none;margin:0;padding:0}
.steps li{display:flex;gap:.75rem;padding:.55rem .6rem;border-radius:10px;cursor:pointer;color:#52627a;
  font-size:.86rem;font-weight:600;align-items:flex-start}
.steps li:hover{background:#eef2f7}
.steps li.active{background:var(--brand-soft);color:var(--brand-dark)}
.steps li .n{width:26px;height:26px;border-radius:50%;border:2px solid #cdd8e8;display:grid;
  place-items:center;font-size:.78rem;flex:none;background:#fff;color:#6b7d97;transition:.15s}
.steps li.active .n{border-color:var(--brand);color:var(--brand)}
.steps li.done .n{background:var(--green);border-color:var(--green);color:#fff}
.steps li small{display:block;font-weight:500;color:#93a2b8;font-size:.72rem}
.wizard-panel{min-width:0}
.step-head{margin-bottom:1.2rem}
.step-head h2{font-size:1.25rem}
.step-head p{color:var(--muted);margin:.3rem 0 0}
.wizard-foot{display:flex;flex-wrap:wrap;gap:.6rem;margin-top:1.5rem;padding-top:1.2rem;border-top:1px solid var(--line-2)}
.wizard-foot .spacer{flex:1}
.progressbar{height:6px;background:var(--line-2);border-radius:99px;overflow:hidden;margin-bottom:1.2rem}
.progressbar > span{display:block;height:100%;background:linear-gradient(90deg,var(--brand),var(--teal));transition:.3s}

/* ---------- Signature & camera ---------- */
.capture-grid{display:grid;grid-template-columns:1fr 1fr;gap:1.2rem}
.sig-pad,.cam-box{border:2px dashed #cdd8e8;border-radius:var(--radius);background:#fff;
  position:relative;overflow:hidden}
.sig-pad canvas{display:block;width:100%;height:200px;touch-action:none;cursor:crosshair}
.cam-box{aspect-ratio:4/3;display:grid;place-items:center;background:#0b1a2f}
/* `contain`, not `cover`: a live 16:9 webcam feed forced to `cover` inside
   this 4:3 box was cropping the sides out of view before the shot was even
   taken — "zoomed in" with no way to see, let alone frame, the part being
   cut off. `contain` shows the whole camera frame, letterboxed, which is
   also what the CAPTURED photo below does — so the preview now shows
   exactly what capture is about to keep. */
.cam-box video{width:100%;height:100%;object-fit:contain}
/* A CAPTURED photograph must be shown WHOLE. `cover` cropped it to the 4:3 box,
   so a portrait photo from a phone lost its top and bottom and looked zoomed
   in — and on an ID document that is not cosmetic: the corners are exactly what
   has to be visible, and the examiner was checking a picture the record does
   not actually contain. `contain` shows the real image, letterboxed. */
.cam-box img{width:100%;height:100%;object-fit:contain;background:#0b1a2f}
.cap-label{font-size:.8rem;font-weight:600;color:#33465e;margin-bottom:.5rem;display:flex;align-items:center;gap:.4rem}
.cap-actions{display:flex;gap:.5rem;margin-top:.6rem;flex-wrap:wrap;align-items:center}

/* ---------- Signing on a pad ----------
   ADDITIVE ONLY. Every rule here is either on the new button or behind
   .is-signing, which exists only while Sign Now holds the pointer — so a
   signature block that nobody presses Sign now on looks and behaves exactly as
   it did before. */

/* Sign now is the primary action on this block. */
.sig-signbtn{font-weight:700}

/* While pad mode is on, the box owns the screen's attention. */
.sig-pad.is-signing{border-style:solid;border-color:#1657c4;
  box-shadow:0 0 0 4px rgba(22,87,196,.14), 0 10px 30px rgba(15,23,42,.16)}

/* ---------- FULL-SCREEN SIGNING SURFACE ----------
   The signing block fills the display while the pad is live. A browser cannot
   fence a system cursor without Pointer Lock, and Pointer Lock is unusable with
   an absolute digitiser — so instead of confining the pointer, there is simply
   nowhere else for it to go. The whole pad maps onto the whole block. */
.sig-fullscreen{position:fixed;inset:0;z-index:99998;
  display:flex;flex-direction:column;align-items:center;justify-content:center;
  gap:1.1rem;padding:3vh 3vw;margin:0;
  background:radial-gradient(120% 100% at 50% 0%,#16304f 0%,#0b1a2f 70%)}
.sig-fullscreen .cap-label{color:#e8eef7;font-size:1.05rem;font-weight:700;margin:0}
.sig-fullscreen .cap-label span{color:inherit}
/* The surface fills the screen area, taking the SCREEN's shape. The tablet's
   active area is mapped onto the whole screen, so a screen-shaped surface is
   what lets the pad reach it corner to corner with nothing letterboxed off and
   nothing stretched. The signature is cropped to its own ink on the way out, so
   the stored image is the writing, not this rectangle. */
.sig-fullscreen .sig-pad{flex:1;width:100%;height:auto;min-height:0;background:#fff;
  border-width:3px;border-style:solid;border-color:#1657c4;
  box-shadow:0 24px 70px rgba(0,0,0,.5)}
.sig-fullscreen .sig-pad canvas{height:100%}
.sig-fullscreen .sig-lockhint{font-size:.82rem;padding:.45rem .8rem}
.sig-fullscreen .cap-actions{margin:0}
.sig-fullscreen .cap-actions .btn{font-size:.95rem;padding:.6rem 1.2rem}
/* The audit line under the pad is noise on a signing screen. */
.sig-fullscreen > div:last-child:not(.cap-actions){display:none}
@media (max-width:640px){
  .sig-fullscreen{padding:2vh 2vw;gap:.8rem}
  .sig-fullscreen .cap-label{font-size:.92rem}
}

/* The page behind is covered by the full-screen signing surface, so it needs no
   dimming of its own.

   It must NOT be dimmed with `filter`, either: a filter on an ancestor makes it
   the containing block for any position:fixed descendant, which would stop the
   signing surface covering the screen and leave it trapped inside the form. The
   earlier version of this rule did exactly that. Scrolling is frozen instead. */
body.sig-padlive{overflow:hidden}
/* The cursor stays VISIBLE. On an absolute digitiser the system cursor is
   already in the right place — it is where the pen is on the pad — so hiding it
   would remove the one accurate piece of feedback the signer has. */
.sig-pad.is-signing canvas{cursor:crosshair}

.sig-lockhint{position:absolute;left:0;right:0;top:0;display:none;z-index:2;
  padding:.32rem .6rem;text-align:center;pointer-events:none;
  background:#1657c4;color:#fff;font-size:.72rem;font-weight:700;letter-spacing:.01em}
.sig-pad.is-signing .sig-lockhint{display:block}

@media (prefers-reduced-motion:reduce){ .sig-pad{transition:none} }

/* ---------- Modal / drawer ---------- */
.overlay{position:fixed;inset:0;background:rgba(11,26,47,.5);backdrop-filter:blur(2px);z-index:100;
  display:grid;place-items:center;padding:1.5rem;animation:fade .15s}
@keyframes fade{from{opacity:0}to{opacity:1}}
/* display:flex + overflow:hidden here, overflow-y:auto on .modal-body alone —
   the header and footer used to scroll away WITH the body (.modal had the
   overflow:auto), so a modal whose body content ran tall (e.g. the personnel
   photo editor, once its preview image plus the camera row plus the footer
   buttons together outgrew 90vh) could scroll its own action buttons —
   Cancel/Crop/Save — out of view with nothing on screen hinting they were
   still there below. Now only .modal-body scrolls; the footer stays put. */
.modal{background:#fff;border-radius:var(--radius-lg);box-shadow:var(--shadow-lg);width:100%;
  max-width:560px;max-height:90vh;overflow:hidden;animation:pop .18s;
  display:flex;flex-direction:column}
@keyframes pop{from{transform:scale(.96);opacity:0}to{transform:scale(1);opacity:1}}
.modal.wide{max-width:900px}
.modal-head{display:flex;align-items:center;padding:1.1rem 1.4rem;border-bottom:1px solid var(--line-2);flex:none}
.modal-head h3{font-size:1.05rem}
.modal-head .x{margin-left:auto;background:none;border:none;cursor:pointer;font-size:1.4rem;color:var(--muted);line-height:1}
.modal-body{padding:1.4rem;overflow-y:auto;min-height:0}
/* wrap, never clip — three buttons must stay reachable on a narrow window */
.modal-foot{padding:1rem 1.4rem;border-top:1px solid var(--line-2);display:flex;gap:.6rem;
  justify-content:flex-end;flex-wrap:wrap;flex:none}

/* ---------- Toast ---------- */
#toasts{position:fixed;bottom:1.2rem;right:1.2rem;z-index:200;display:flex;flex-direction:column;gap:.6rem}
.toast{background:var(--navy-800);color:#fff;padding:.8rem 1.1rem;border-radius:10px;box-shadow:var(--shadow-lg);
  font-size:.88rem;display:flex;gap:.6rem;align-items:center;animation:slide .2s;max-width:340px}
@keyframes slide{from{transform:translateX(20px);opacity:0}to{transform:translateX(0);opacity:1}}
.toast.ok{background:#0f4c2f}.toast.err{background:#7f1d1d}

/* ---------- Login ---------- */
.login-wrap{min-height:100vh;display:grid;place-items:center;padding:1.5rem;
  background:radial-gradient(1200px 600px at 20% -10%,#1b3157 0,transparent 60%),
             radial-gradient(900px 500px at 100% 100%,#0ea5a4 0,transparent 55%),var(--navy-900)}
.login-card{background:#fff;border-radius:var(--radius-lg);box-shadow:var(--shadow-lg);
  width:100%;max-width:420px;padding:2.2rem;animation:pop .2s}
/* The brand block on the login card is the SIDEBAR .brand re-used on a WHITE
   background, so two things must be overridden here, not inline in auth.js:
     • layout — stack it and centre the logo above the wordmark;
     • colour — .brand b is white for the navy sidebar and would be invisible. */
.login-card .brand{border:none;padding:0;margin:0 0 1.5rem;
  flex-direction:column;align-items:center;justify-content:center;text-align:center;gap:.55rem}
.login-card .brand .login-logo{margin-left:auto;margin-right:auto}
.login-card .brand b{color:var(--ink);font-size:1.02rem}
.login-card .brand span{color:var(--muted);font-size:.78rem}
.login-card h2{font-size:1.3rem;margin-bottom:.3rem}
.login-card .lead{color:var(--muted);font-size:.9rem;margin-bottom:1.5rem}
.demo-note{margin-top:1.2rem;font-size:.8rem;color:var(--muted);background:#f7f9fc;padding:.8rem;
  border-radius:10px;border:1px solid var(--line)}

/* ---------- Empty / loading ---------- */
.empty{text-align:center;padding:3rem 1.5rem;color:var(--muted)}
.empty svg{width:46px;height:46px;opacity:.35;margin-bottom:.7rem}
.spinner{width:34px;height:34px;border:3px solid var(--line);border-top-color:var(--brand);
  border-radius:50%;animation:spin .7s linear infinite;margin:2rem auto}
@keyframes spin{to{transform:rotate(360deg)}}
.section-title{font-size:.78rem;text-transform:uppercase;letter-spacing:.05em;color:var(--muted);
  font-weight:700;margin:1.6rem 0 .8rem}

/* ---------- Filters bar ---------- */
.toolbar{display:flex;gap:.6rem;flex-wrap:wrap;align-items:center;margin-bottom:1.2rem}
.toolbar .search{flex:1;min-width:180px}
.toolbar select,.toolbar input{max-width:220px}

/* ---------- Report (screen + print), boxed & neat ---------- */
.report-sheet{background:#fff;max-width:850px;margin:0 auto;padding:0 0 1.6rem;
  border:1px solid var(--line);border-radius:12px;box-shadow:var(--shadow-md);
  font-size:13px;color:#1a2438;overflow:hidden}
.report-band{background:linear-gradient(120deg,var(--navy-900),var(--navy-700));color:#fff;
  padding:1.5rem 2rem;display:flex;justify-content:space-between;align-items:flex-start;gap:1.4rem;
  -webkit-print-color-adjust:exact;print-color-adjust:exact}
.report-band .brandline{font-size:.7rem;letter-spacing:.15em;text-transform:uppercase;color:#9db4d6;font-weight:700}
.report-band h1{font-size:1.65rem;margin:.2rem 0 .6rem;color:#fff}
.report-band .meta{display:flex;gap:1.5rem;flex-wrap:wrap;font-size:.82rem}
.report-band .meta .l{color:#9db4d6;text-transform:uppercase;font-size:.6rem;letter-spacing:.08em;display:block}
.report-band .meta b{color:#fff;font-variant-numeric:tabular-nums;letter-spacing:.02em}
/* `contain`, not `cover` — same reasoning as .cam-box img above: this photo is
   captured on a phone/tablet at whatever aspect that device's camera gives,
   almost never this box's own 104:126, and `cover` silently cropped the top
   or sides off. A letterboxed WHOLE photo is correct here; a zoomed-in,
   half-cropped one is not, on an identity document. */
.report-band .photo{width:104px;height:126px;border-radius:8px;object-fit:contain;background:#1b3157;
  border:2px solid rgba(255,255,255,.25);flex:none}
.report-body{padding:1.5rem 2rem}
.rgrid{display:grid;grid-template-columns:1fr 1fr;gap:1rem;margin-bottom:1rem}
.rbox{border:1px solid var(--line);border-radius:10px;overflow:hidden;background:#fff;margin-bottom:1rem}
.rbox-h{background:#f4f7fc;border-bottom:1px solid var(--line);padding:.5rem .85rem;
  font-size:.68rem;font-weight:800;letter-spacing:.06em;text-transform:uppercase;color:var(--brand-dark)}
.rbox-b{padding:.75rem .85rem}
.rbox-b p:first-child{margin-top:0}.rbox-b p:last-child{margin-bottom:0}
.rgrid .rbox{margin-bottom:0}
table.rkv{width:100%;border-collapse:collapse;font-size:12.5px}
table.rkv td{padding:.26rem .1rem;vertical-align:top;border-bottom:1px solid #f1f4f9}
table.rkv tr:last-child td{border-bottom:none}
table.rkv td.k{color:var(--muted);font-weight:600;width:48%;white-space:nowrap}
.report-body p{margin:.45rem 0;line-height:1.5}
.report-sheet table.rq{width:100%;border-collapse:collapse;margin:.3rem 0;font-size:12.5px}
.report-sheet table.rq th,.report-sheet table.rq td{border:1px solid #d6deea;padding:.5rem .6rem;text-align:left}
.report-sheet table.rq th{background:#eef4fc;font-size:.7rem;text-transform:uppercase;letter-spacing:.03em;color:#33465e}
/* The relevant question that produced the significant response. Printed, not
   just shown — print-color-adjust keeps the fill when the sheet goes to paper,
   where a highlight that drops out would change what the document says. */
.report-sheet table.rq tr.rq-most td{background:#fde2e2;color:#991b1b;font-weight:700;
  -webkit-print-color-adjust:exact;print-color-adjust:exact}
.report-sheet table.rq td.di{color:#b91c1c;font-weight:700;text-align:center;
  -webkit-print-color-adjust:exact;print-color-adjust:exact}
.report-sheet table.rq tr.rq-most td.di{color:#991b1b}
.report-result{display:flex;gap:1rem;align-items:center;border:1px solid var(--line);
  border-radius:10px;padding:.9rem 1.2rem;margin:.2rem 0 0;background:#f7f9fc;
  -webkit-print-color-adjust:exact;print-color-adjust:exact}
.report-result.di{background:#fdecec;border-color:#f3c9c9}
.report-result.ndi{background:#eef8f1;border-color:#c7e6d2}
.report-result.inc{background:#fff6e8;border-color:#f2ddb4}
/* Invoice / quotation line items + totals */
table.inv-items{width:100%;border-collapse:collapse;margin:.2rem 0;font-size:.86rem}
table.inv-items th{background:var(--navy-900,#12233d);color:#fff;text-align:left;padding:.55rem .7rem;font-size:.68rem;text-transform:uppercase;letter-spacing:.04em;font-weight:700}
table.inv-items th.r,table.inv-items td.r{text-align:right}
table.inv-items td{padding:.55rem .7rem;border-bottom:1px solid var(--line-2);vertical-align:top}
table.inv-items tbody tr:last-child td{border-bottom:1px solid var(--line)}
table.inv-items input{padding:.4rem .5rem;border:1px solid var(--line);border-radius:7px;font-size:.85rem;font-family:inherit}
.inv-totals{width:320px;max-width:100%;font-size:.9rem}
.inv-totals .row{display:flex;justify-content:space-between;gap:1.5rem;padding:.32rem 0}
.inv-totals .row span{color:var(--muted)}
.inv-totals .row.grand{border-top:2px solid var(--navy-900,#12233d);margin-top:.35rem;padding-top:.55rem;font-size:1.12rem}
.inv-totals .row.grand span{color:var(--ink);font-weight:800}
.inv-totals .row.bal b{color:var(--red)}
.inv-totals .row.bal span{color:var(--red);font-weight:700}
table.rkv{width:100%;border-collapse:collapse;font-size:12.5px}
table.rkv td{padding:2px 4px;border-bottom:1px solid #f1f4f9;vertical-align:top}
table.rkv td.k{color:var(--muted);font-weight:700;width:42%}

.report-logos{display:flex;align-items:center;justify-content:space-between;gap:1rem;padding:.85rem 1.2rem;background:#fff;border-bottom:1px solid var(--line);flex-wrap:wrap}
.report-logos .rl-cust{max-height:60px;max-width:220px;object-fit:contain}
.report-logos .rl-bodies{display:flex;flex-direction:column;align-items:flex-end;gap:.3rem;margin-left:auto}
.report-logos .rl-lbl{font-size:.62rem;text-transform:uppercase;letter-spacing:.06em;color:var(--muted);font-weight:800}
.report-logos .rl-imgs{display:flex;align-items:center;gap:.9rem}
.report-logos .rl-imgs img{max-height:46px;max-width:150px;object-fit:contain}
.report-result.uco{background:#f1f5f9;border-color:#d7deea}
.report-result.ref{background:#faf5ff;border-color:#e5d4fb}
.report-result .big{font-size:1.6rem;font-weight:800;line-height:1.1}
.report-result .mostsig-di{background:#fde2e2;border:1px solid #f3b4b4;border-radius:8px;padding:.4rem .7rem}
.mflag{display:inline-block;background:#fdecec;color:#b91c1c;border:1px solid #f3c9c9;border-radius:6px;
  padding:2px 9px;margin:2px;font-size:12px}
.sig-line{display:grid;grid-template-columns:1fr 1fr;gap:2rem;margin-top:.4rem}
.sig-line .s{font-size:11.5px;color:var(--muted)}
.sig-line .s .line{border-top:1px solid #334155;padding-top:.3rem;font-size:12px;color:#1a2438}
.sig-line img{max-height:56px;margin-bottom:.15rem;display:block}

/* ---------- Personnel / search front page ---------- */
.pf-hero{position:relative;overflow:hidden;border-radius:var(--radius-lg);color:#fff;
  padding:2.3rem 2.3rem 2.5rem;margin-bottom:1.5rem;box-shadow:var(--shadow-md);
  background:radial-gradient(1100px 480px at 10% -35%,#1b3157 0,transparent 60%),
            radial-gradient(820px 460px at 112% 135%,#0ea5a4 0,transparent 55%),
            linear-gradient(120deg,var(--navy-900),var(--navy-700))}
.pf-hero .eyebrow{font-size:.72rem;letter-spacing:.18em;text-transform:uppercase;color:#8fd8d6;font-weight:800}
.pf-hero h2{font-size:2rem;color:#fff;margin:.35rem 0 .35rem;letter-spacing:-.02em}
.pf-hero .lead{color:#b9c8de;margin:0 0 1.4rem;max-width:600px;font-size:.94rem;line-height:1.55}
.pf-searchbar{position:relative;max-width:640px}
.pf-searchbar svg{position:absolute;left:1.05rem;top:50%;transform:translateY(-50%);color:#7f93b3}
.pf-searchbar input{padding:1rem 1.1rem 1rem 3rem;border-radius:999px;border:1px solid rgba(255,255,255,.2);
  background:rgba(255,255,255,.98);font-size:1.02rem;box-shadow:var(--shadow-md);color:var(--ink)}
.pf-searchbar input:focus{border-color:transparent;box-shadow:0 0 0 4px rgba(14,165,164,.4)}
.pf-hero .hint{display:flex;gap:1.6rem;flex-wrap:wrap;margin-top:1.25rem}
.pf-hero .hint .i{display:flex;align-items:center;gap:.5rem;font-size:.84rem;color:#c6d4e8}
.pf-hero .hint .i svg{opacity:.8}
.pf-hero .hint b{color:#fff;font-size:1.1rem;font-weight:800;font-variant-numeric:tabular-nums}

.pf-sec{display:flex;align-items:baseline;gap:.7rem;margin:.2rem 0 1rem}
.pf-sec h3{font-size:1.08rem}
.pf-sec .count{color:var(--muted);font-size:.82rem;font-weight:600}
.pf-sec .spacer{flex:1}

/* The rarely-edited half of the client form, behind a fold. */
.cl-more{margin-top:1.2rem;border:1px solid var(--line);border-radius:var(--radius-sm);
  padding:.7rem .9rem;background:#fbfcfe}
.cl-more>summary{cursor:pointer;font-weight:700;font-size:.86rem;color:var(--brand-dark);
  list-style:none;display:flex;align-items:baseline;flex-wrap:wrap}
.cl-more>summary::-webkit-details-marker{display:none}
.cl-more>summary::before{content:"▸";margin-right:.45rem;transition:transform .15s;display:inline-block}
.cl-more[open]>summary::before{transform:rotate(90deg)}
.cl-more>summary:hover{color:var(--brand)}

/* Someone no longer employed. Faded rather than hidden — the record is intact
   and still searchable; it simply is not who you are working on today. */
.pf-card.inactive{opacity:.62;background:#fbfcfd}
.pf-card.inactive:hover{opacity:1}
.pf-card.inactive .pf-avatar{filter:grayscale(1)}
.pf-inactive{display:flex;gap:.7rem;align-items:flex-start;margin-top:1rem;
  padding:.75rem .9rem;border-radius:var(--radius-sm);background:#fdecec;
  border:1px solid #f3b4b4;color:#7f1d1d}
.pf-inactive svg{width:16px;height:16px;flex:none;margin-top:.15rem}
.pf-inactive b{display:block;font-size:.9rem}
.pf-inactive .cell-sub{color:#9b3b3b}

/* Personnel photograph on the personnel file, with its own change button.
   `contain`, not `cover` — see .report-band .photo above: a phone/tablet
   photo's own aspect almost never matches this box's 120:145, and `cover`
   cropped straight through a face rather than showing the whole photo. */
.pf-photo{display:flex;flex-direction:column;gap:.5rem;flex:none;width:120px}
.pf-photo img{width:120px;height:145px;object-fit:contain;border-radius:10px;
  border:1px solid var(--line);display:block;background:#eef2f7}
.pf-photo .ph{width:120px;height:145px;border-radius:10px;background:#eef2f7;
  display:grid;place-items:center;color:#94a3b8}
.pf-photo-btn{width:100%;justify-content:center;white-space:nowrap}
@media print{ .pf-photo-btn{display:none!important} }

/* The three standing report paragraphs, shown on a client card. Clamped so one
   long paragraph cannot push the question sets off the bottom of the card;
   hovering releases it, because the point of showing them is proof-reading. */
.cl-blocks{display:flex;flex-direction:column;gap:.55rem}
.cl-block{border-left:3px solid var(--brand);background:#f7f9fe;border-radius:0 8px 8px 0;
  padding:.5rem .7rem}
.cl-block .k{font-size:.68rem;font-weight:800;text-transform:uppercase;letter-spacing:.05em;
  color:var(--brand-dark);margin-bottom:.15rem}
.cl-block .v{font-size:.82rem;line-height:1.45;color:#33465e;white-space:pre-wrap;
  display:-webkit-box;-webkit-line-clamp:4;-webkit-box-orient:vertical;overflow:hidden}
.cl-block:hover .v{-webkit-line-clamp:unset;overflow:visible}
/* Not ".empty" — that is the app's full-page empty-state class, and reusing the
   name here inherited its centred text into a left-aligned paragraph block. */
.cl-block.unset{border-left-color:#c9d3e0;background:#fafbfd}
.cl-block.unset .k{color:var(--muted)}
.cl-block.unset .v{color:var(--muted);font-style:italic}

.pf-cards{display:grid;grid-template-columns:repeat(auto-fill,minmax(285px,1fr));gap:1rem}
.pf-card{background:var(--card);border:1px solid var(--line);border-radius:var(--radius);
  box-shadow:var(--shadow-sm);padding:1.15rem 1.25rem;cursor:pointer;transition:.16s;
  display:flex;flex-direction:column;gap:.85rem;position:relative}
.pf-card:hover{border-color:#c4d6f5;box-shadow:var(--shadow-md);transform:translateY(-2px)}
.pf-card .top{display:flex;align-items:center;gap:.85rem}
.pf-avatar{width:48px;height:48px;border-radius:13px;flex:none;display:grid;place-items:center;
  font-weight:800;color:#fff;font-size:1.02rem;letter-spacing:.02em;box-shadow:var(--shadow-sm);
  overflow:hidden;position:relative}
/* Face photograph in place of the initials. The gradient is dropped rather than
   left behind the image: a portrait is not always opaque to its own edges, and
   a coloured halo around someone's head reads as a rendering fault. */
.pf-avatar.has-photo{background:#eef2f7!important;
  box-shadow:var(--shadow-sm),inset 0 0 0 1px rgba(15,23,42,.08)}
.pf-avatar img{width:100%;height:100%;object-fit:cover;display:block;
  animation:pfPhotoIn .22s ease both}
@keyframes pfPhotoIn{from{opacity:0}to{opacity:1}}
.pf-card:hover .pf-avatar.has-photo{box-shadow:var(--shadow-sm),inset 0 0 0 1px rgba(31,111,235,.35)}
@media (prefers-reduced-motion:reduce){ .pf-avatar img{animation:none} }
.pf-card .nm{font-weight:700;font-size:1.02rem;line-height:1.15}
.pf-card .idn{font-size:.79rem;color:var(--muted);font-variant-numeric:tabular-nums;margin-top:2px}
.pf-card .chips-row{display:flex;gap:.4rem;flex-wrap:wrap;align-items:center}
.pf-card .meta{display:flex;justify-content:space-between;align-items:center;gap:.5rem;
  font-size:.79rem;color:var(--muted);border-top:1px solid var(--line-2);padding-top:.7rem;margin-top:auto}
.pf-card .meta .cl{font-weight:600;color:#33465e;text-align:right;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.pf-card .go{position:absolute;top:1.05rem;right:1.15rem;color:#c4d0e2;transition:.15s}
.pf-card:hover .go{color:var(--brand);transform:translateX(2px)}

/* ============ Responsive ============ */

/* ===== Tablets & below (≤1024): the drawer AND the two-column collapse happen
   together, so there is never a width where forms/cards spill off the edge. ===== */
@media (max-width:1024px){
  /* shell → slide-in drawer, content takes the full width */
  .app{grid-template-columns:1fr}
  .sidebar{position:fixed;left:0;top:0;bottom:0;width:min(288px,86vw);z-index:120;
    transform:translateX(-100%);transition:transform .25s ease;box-shadow:var(--shadow-lg)}
  .sidebar.open{transform:none}
  .hamburger{display:block}
  .scrim{position:fixed;inset:0;background:rgba(0,0,0,.45);z-index:110}
  .content{padding:1.15rem}

  /* KPI tiles & 3-up grids become 2-up. Two-column FORMS stay two-up on tablets
     so each field keeps a sensible width and fills the space (they only stack on
     phones). Fields can shrink (min-width:0 above), so two columns never overflow. */
  .grid.cols-4{grid-template-columns:repeat(2,1fr)}
  .grid.cols-3{grid-template-columns:repeat(2,1fr)}

  /* controls: 16px avoids iOS focus-zoom */
  input,select,textarea{font-size:16px}
  .toolbar .search{flex:1 1 100%;min-width:0}
  .toolbar select,.toolbar input{max-width:none;flex:1 1 auto}

  /* wizard: steps become a horizontal strip above the panel */
  .wizard{grid-template-columns:1fr}
  .steps{position:static}
  .steps ol{display:flex;overflow-x:auto;-webkit-overflow-scrolling:touch;gap:.4rem;padding-bottom:.5rem}
  .steps li{flex:none;flex-direction:column;align-items:center;text-align:center;min-width:82px}
  .steps li small{display:none}
}

/* Small tablets / large phones → documents become one readable column */
@media (max-width:768px){
  .report-sheet{border-radius:10px}
  .report-band{flex-direction:column;align-items:flex-start;padding:1.3rem 1.4rem;gap:1rem}
  .report-band h1{font-size:1.45rem}
  .report-band .photo{width:88px;height:106px}
  .report-body{padding:1.3rem 1.4rem}
  .rgrid,.sig-line{grid-template-columns:1fr;gap:1rem}
  .report-logos{padding:.75rem 1rem}
  .report-logos .rl-bodies{align-items:flex-start;margin-left:0}
  .report-result{flex-wrap:wrap}
  .report-result > div:last-child,.report-result .mostsig-di{margin-left:0 !important;text-align:left !important;max-width:100% !important}
  .pf-hero{padding:1.6rem 1.4rem 1.8rem}
  .pf-hero h2{font-size:1.5rem}
  .pf-searchbar input{font-size:1rem}
  .modal-body{padding:1.1rem}
  .modal-head,.modal-foot{padding:1rem 1.1rem}
}

/* Phones → single column everywhere so nothing is cramped */
@media (max-width:600px){
  .form-grid,.form-grid.cols-3,.capture-grid{grid-template-columns:1fr}
  .grid.cols-2,.grid.cols-3,.grid.cols-4{grid-template-columns:1fr}
  .content{padding:.85rem}
  .topbar{padding:.7rem 1rem;gap:.6rem}
  .topbar h1{font-size:1.05rem}
  .topbar .sub{display:none}
  .topbar .btn.secondary{display:none}       /* Home lives in the menu on phones */
  .card.pad{padding:1.1rem}
  .card-head{padding:.9rem 1.1rem}
  .card-body{padding:1.1rem}
  .card h3,.card-head h3{font-size:1.08rem}
  .grid{gap:1rem}
  .stat{padding:1rem}
  .stat .v{font-size:1.7rem}
  table.data{font-size:.82rem;min-width:520px}
  table.data th,table.data td{padding:.6rem .7rem}
  /* modals go near-fullscreen for easy thumb use */
  .overlay{padding:0;place-items:stretch}
  .modal,.modal.wide{max-width:none;max-height:100vh;height:100%;border-radius:0}
  .modal-foot{flex-direction:column-reverse;gap:.5rem}
  .modal-foot .btn{width:100%}
  .btn-row .btn{flex:1 1 auto}
  /* report / invoice */
  .report-sheet{font-size:12.5px}
  .report-band .meta{gap:.7rem 1.1rem}
  .inv-totals{width:100%}
  .pf-cards{grid-template-columns:1fr}
  .login-card{padding:1.6rem}
}

/* Touch devices: bigger, thumb-friendly hit areas everywhere */
@media (pointer:coarse){
  .btn{min-height:44px;padding:.72rem 1.15rem}
  .btn.sm{min-height:38px;padding:.5rem .9rem}
  .btn.lg{min-height:52px}
  .nav a{padding:.8rem .85rem}
  .chip{padding:.55rem 1rem;font-size:.9rem}
  .consent-item{padding:1rem 1.05rem}
  .consent-item .box{width:26px;height:26px}
  input,select,textarea{padding:.72rem .8rem}
  table.data tbody td{padding:.85rem .9rem}
  .modal-head .x{padding:.3rem .5rem;font-size:1.7rem}
  .pf-card{padding:1.25rem}
}

/* ============ Print ============ */
@media print{
  @page{size:A4;margin:14mm}
  body{background:#fff}
  .sidebar,.topbar,.wizard-foot,.no-print,#toasts,.steps{display:none !important}
  .app{display:block}
  .content{padding:0;max-width:none}
  *{-webkit-print-color-adjust:exact;print-color-adjust:exact}
  .report-sheet{box-shadow:none;border:none;max-width:none;margin:0;border-radius:0}
  .report-band{border-radius:0}
  .rbox,.report-result,table.rq,.sig-line,.rgrid{break-inside:avoid}
  .rbox-h{break-after:avoid}
}

/* ===========================================================================
   Periodic Screening Schedule — month calendar + totals rail
   =========================================================================== */
.btn.icon{padding:.42rem .7rem;font-size:1.15rem;line-height:1}

.sch-toolbar{display:flex;align-items:center;justify-content:space-between;gap:1rem;
  flex-wrap:wrap;margin-bottom:1rem}
.sch-nav{display:flex;align-items:center;gap:.5rem}
.sch-month{margin:0;min-width:11rem;text-align:center;font-size:1.1rem;font-weight:700;color:var(--ink)}
.sch-tools{display:flex;align-items:center;gap:.6rem;flex-wrap:wrap}
.sch-tools select{min-width:12rem}

.sch-layout{display:grid;grid-template-columns:minmax(0,1fr) 258px;gap:1.1rem;align-items:start}

/* --- calendar grid --- */
.sch-grid{display:grid;grid-template-columns:repeat(7,minmax(0,1fr));gap:1px;
  background:var(--line);border:1px solid var(--line);border-radius:var(--radius);overflow:hidden}
.sch-head{background:#f7f9fc;padding:.5rem .6rem;font-size:.7rem;font-weight:800;
  text-transform:uppercase;letter-spacing:.06em;color:var(--muted);text-align:center}
.sch-day{background:var(--card);min-height:118px;padding:.45rem .5rem;display:flex;
  flex-direction:column;gap:.28rem;cursor:pointer;transition:background .15s}
.sch-day:hover{background:#f7f9fc}
.sch-day:focus-visible{outline:2px solid var(--brand);outline-offset:-2px}
.sch-day.blank{background:#fbfcfe;cursor:default}
.sch-day.blank:hover{background:#fbfcfe}
.sch-day.weekend{background:#fafbfe}
.sch-day.weekend:hover{background:#f4f7fc}
/* Holiday / leave / event — subtle diagonal hatch so it reads as "no testing". */
.sch-day.nonworking{background-image:repeating-linear-gradient(45deg,
  rgba(217,119,6,.07) 0 6px, transparent 6px 12px)}
.sch-day.today{box-shadow:inset 0 0 0 2px var(--brand)}

.sch-daynum{display:flex;align-items:baseline;justify-content:space-between;gap:.4rem}
.sch-daynum span{font-weight:800;font-size:.95rem;color:var(--ink);font-variant-numeric:tabular-nums}
.sch-daynum em{font-style:normal;font-size:.63rem;font-weight:700;text-transform:uppercase;
  letter-spacing:.05em;color:#a3b0c2}

.sch-booking{border-radius:var(--radius-sm);padding:.28rem .42rem;font-size:.71rem;line-height:1.25;
  background:var(--brand-soft);border-left:3px solid var(--brand);display:flex;flex-direction:column}
.sch-booking b{font-weight:700;color:var(--ink);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.sch-booking span{color:var(--muted);font-variant-numeric:tabular-nums}
.sch-booking.done{background:#e7f6ec;border-left-color:var(--green)}
.sch-booking.partial{background:#fff4e5;border-left-color:var(--amber)}
.sch-booking.missed{background:#fdecec;border-left-color:var(--red)}
.sch-booking.unplanned{background:#f3e8ff;border-left-color:#7c3aed}

.sch-note{font-size:.68rem;line-height:1.3;color:var(--muted);padding-left:.4rem;
  border-left:2px solid var(--line);overflow:hidden;text-overflow:ellipsis}
.sch-note.sub{color:#94a3b8;font-style:italic}

/* --- totals rail --- */
.sch-rail{display:flex;flex-direction:column;gap:.9rem}
.sch-rail .card{padding:.9rem 1rem}
.sch-rail h4{margin:0 0 .35rem;font-size:.7rem;font-weight:800;text-transform:uppercase;
  letter-spacing:.06em;color:var(--muted)}
.sch-big{font-size:1.9rem;font-weight:800;color:var(--ink);line-height:1.1;font-variant-numeric:tabular-nums}
.sch-big.ok{color:var(--green)}
.sch-big.warn{color:var(--amber)}
.sch-sub{font-size:.74rem;color:var(--muted)}
.sch-divider{height:1px;background:var(--line-2);margin:.7rem 0 .5rem}
.sch-total-row{display:flex;align-items:center;justify-content:space-between;gap:.6rem;
  padding:.3rem 0;font-size:.8rem;border-bottom:1px solid var(--line-2)}
.sch-total-row:last-child{border-bottom:none}
.sch-total-row span{color:var(--muted);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.sch-total-row b{color:var(--ink);font-variant-numeric:tabular-nums}

/* --- day editor --- */
.sch-edit-list{display:flex;flex-direction:column;gap:.8rem;margin-bottom:.9rem}
.sch-edit-row{border:1px solid var(--line);border-radius:var(--radius-sm);padding:.8rem;background:#fbfcfe}
.sch-edit-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(150px,1fr));gap:.7rem}
.sch-edit-grid .field.full{grid-column:1/-1}
.sch-edit-actions{display:flex;gap:.5rem;margin-top:.7rem}
.sch-check{display:flex;align-items:center;gap:.45rem;font-size:.82rem;color:var(--ink)}
.sch-check input{width:auto;margin:0}

@media (max-width:1024px){
  .sch-layout{grid-template-columns:minmax(0,1fr)}
  .sch-rail{flex-direction:row;flex-wrap:wrap}
  .sch-rail>.card{flex:1 1 210px}
}
@media (max-width:600px){
  .sch-day{min-height:82px;padding:.35rem .3rem}
  .sch-booking{font-size:.62rem;padding:.2rem .3rem}
  .sch-booking b{white-space:normal}
  .sch-note{font-size:.6rem}
  .sch-head{font-size:.6rem;padding:.4rem .2rem}
  .sch-month{min-width:8rem;font-size:.95rem}
  .sch-tools select{min-width:9rem}
}

@media print{
  /* Schedule prints as a clean month planner: drop the toolbar, let the rail
     sit under the calendar, and keep the colour coding. */
  .sch-toolbar{display:none !important}
  .sch-layout{display:block}
  .sch-grid{border-radius:0;break-inside:avoid}
  .sch-day{min-height:92px}
  .sch-day:hover{background:var(--card)}
  .sch-rail{flex-direction:row;flex-wrap:wrap;gap:.6rem;margin-top:1rem;break-inside:avoid}
  .sch-rail>.card{flex:1 1 30%;box-shadow:none;border:1px solid var(--line)}
}

/* Completed-vs-planned ratio in the schedule rail */
.sch-ratio{font-variant-numeric:tabular-nums;padding:.1rem .4rem;border-radius:999px;font-size:.74rem}
.sch-ratio.ok{background:#e7f6ec;color:var(--green)}
.sch-ratio.part{background:#fff4e5;color:var(--amber)}
.sch-ratio.none{background:#fdecec;color:var(--red)}
.sch-ratio.extra{background:#f3e8ff;color:#7c3aed}
/* Sortable table headings */
table.data th.sortable{cursor:pointer;user-select:none;white-space:nowrap;transition:color .15s}
table.data th.sortable:hover{color:var(--brand)}
table.data th.sortable.sorted{color:var(--brand)}
table.data th .sort-arrow{display:inline-block;width:.9em;margin-left:.25rem;font-size:.72em;opacity:.85}
table.data th.sortable:hover .sort-arrow:empty::after{content:"\2195";opacity:.35}
.card-head input.search,.card-head select.search{padding:.4rem .7rem;font-size:.82rem}
@media (max-width:600px){
  .card-head input.search,.card-head select.search{max-width:100%!important;width:100%}
}
/* Refusal tick on the consent step — visually distinct from a consent clause */
.consent-item.refusal{border-color:#e9d5ff;background:#faf7ff}
.consent-item.refusal:hover{border-color:#c4b5fd}
.consent-item.refusal.checked{border-color:#7c3aed;background:#f3e8ff}
.consent-item.refusal.checked .box{background:#7c3aed;border-color:#7c3aed}
/* Bulk selection on examination tables */
.bulk-bar{display:flex;align-items:center;gap:.6rem;flex-wrap:wrap;margin:0 0 .7rem;
  padding:.55rem .8rem;border:1px solid var(--brand);border-radius:var(--radius-sm);
  background:var(--brand-soft);color:var(--ink);font-size:.85rem}
.bulk-bar b{font-variant-numeric:tabular-nums}
table.data th.pick-col,table.data td.pick-col{width:2.2rem;text-align:center;padding-left:.6rem;padding-right:.2rem}
table.data td.pick-col input,table.data th.pick-col input{width:auto;margin:0;cursor:pointer;vertical-align:middle}
/* Running row number. Sits between the tick box and the reference, quiet enough
   that it reads as a position rather than as another identifier. */
table.data th.num-col,table.data td.num-col{width:2.6rem;text-align:right;
  padding-left:.2rem;padding-right:.55rem;color:var(--muted);
  font-variant-numeric:tabular-nums;font-size:.8rem;white-space:nowrap}
table.data tr.picked td.num-col{color:var(--brand-dark);font-weight:700}
table.data tr.picked{background:var(--brand-soft)}
table.data tr.picked:hover{background:#dbe9ff}
@media print{.bulk-bar,th.pick-col,td.pick-col{display:none !important}}

/* ===========================================================================
   ANALYTICS — charts, drill-through and the popup behind every figure

   One rule runs through this block: anything you can click says so before you
   click it, and says it the same way everywhere — a lift, a tint, a pointer.
   Nothing here changes what a figure MEANS; the affordances sit around the
   number, never on top of it, so a table of counts still reads as a table.
   =========================================================================== */

/* ---- ranking bars ---- */
.bars{display:flex;flex-direction:column;gap:.15rem}
.barrow{border-radius:10px;padding:.45rem .55rem;margin:0;transition:background .13s,box-shadow .13s,transform .13s}
.barrow-top{display:flex;justify-content:space-between;align-items:baseline;
  gap:.8rem;font-size:.82rem;margin-bottom:.3rem}
.barrow-label{font-weight:600;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.barrow-fig{display:flex;align-items:baseline;gap:.55rem;flex:none}
.barrow-note{color:var(--muted);font-size:.76rem;font-weight:500;white-space:nowrap}
.barrow-val{font-weight:700;font-variant-numeric:tabular-nums}
.bartrack{height:9px;background:#eef2f7;border-radius:99px;overflow:hidden}
.barfill{height:100%;border-radius:99px;transform-origin:left center;
  animation:barGrow .55s cubic-bezier(.2,.8,.2,1) both}
@keyframes barGrow{from{transform:scaleX(0)}to{transform:scaleX(1)}}

.barrow.drillable{cursor:pointer}
.barrow.drillable:hover{background:#f4f7fe;transform:translateX(2px)}
.barrow.drillable:hover .barrow-label{color:var(--brand-dark)}
.barrow.drillable:hover .bartrack{background:#e4ebf6}
.barrow.drillable:focus-visible{outline:none;background:#f4f7fe;
  box-shadow:0 0 0 2px rgba(31,111,235,.35)}
/* The affordance itself — a chevron that only occupies space on hover. */
.barrow.drillable .barrow-val::after{content:"›";margin-left:.35rem;color:var(--brand);
  opacity:0;transition:opacity .13s;font-weight:800}
.barrow.drillable:hover .barrow-val::after,
.barrow.drillable:focus-visible .barrow-val::after{opacity:1}

/* ---- SVG charts ---- */
.chart{position:relative}
.chart svg{overflow:visible}
.gc-bar{transform-box:fill-box;transform-origin:50% 100%;
  animation:colGrow .5s cubic-bezier(.2,.8,.2,1) both;transition:opacity .13s,filter .13s}
.gc-bar.dim{opacity:.24}
.gc-bar:hover{filter:brightness(1.06)}
@keyframes colGrow{from{transform:scaleY(0)}to{transform:scaleY(1)}}
.lc-area,.lc-line{animation:fadeUp .5s ease both}
@keyframes fadeUp{from{opacity:0}to{opacity:1}}
.lc-pt{transition:r .12s}
.lc-guide{transition:opacity .12s}
.gc-xlab{transition:fill .13s}
.gc-xlab.hot{cursor:pointer}
.gc-xlab.hot:hover{fill:var(--brand-dark);font-weight:700}

/* Legend — hovering an entry isolates its series, clicking opens it */
.gc-legend{display:flex;gap:.5rem;flex-wrap:wrap;margin-top:.7rem;justify-content:center}
.lg-item{display:flex;align-items:center;gap:.4rem;padding:.25rem .55rem;border-radius:999px;
  transition:background .13s}
.lg-dot{width:11px;height:11px;border-radius:3px;flex:none}
.lg-item.hot{cursor:pointer}
.lg-item.hot:hover{background:#f4f7fe}
.lg-item.hot:focus-visible{outline:none;box-shadow:0 0 0 2px rgba(31,111,235,.35)}

/* Hover card shared by every chart */
.chart-tip{position:absolute;pointer-events:none;z-index:6;
  opacity:0;transition:opacity .12s;transform:translate(-50%,calc(-100% - 12px));
  background:rgba(15,23,42,.96);color:#fff;border-radius:9px;
  padding:.45rem .65rem;box-shadow:0 8px 22px -6px rgba(15,23,42,.5);
  display:flex;flex-direction:column;gap:.1rem;max-width:260px}
.chart-tip.on{opacity:1}
.chart-tip b{font-size:.74rem;font-weight:700;letter-spacing:.02em;opacity:.75;
  text-transform:uppercase}
.chart-tip .t-v{font-size:.92rem;font-weight:700;font-variant-numeric:tabular-nums}
.chart-tip .t-s{font-size:.75rem;opacity:.8}
.chart-tip .t-go{font-size:.68rem;font-weight:700;text-transform:uppercase;letter-spacing:.05em;
  color:#8ab6ff;margin-top:.15rem}

/* ---- table cells that drill ---- */
table.data td.drill{cursor:pointer;position:relative;transition:background .12s,color .12s}
table.data td.drill:hover{background:var(--brand-soft);color:var(--brand-dark);font-weight:700;
  box-shadow:inset 0 0 0 1px rgba(31,111,235,.35)}
table.data td.drill:focus-visible{outline:none;background:var(--brand-soft);
  box-shadow:inset 0 0 0 2px var(--brand)}
table.data td.tot{font-weight:700}
table.data td.hot{color:var(--red);font-weight:700}
table.data td.hot:hover{color:var(--red)}
table.data td.zero{color:#c9d3e0}
/* An analytics table is a grid of figures, not a list of records: the ROW does
   not open anything, so it must not claim to. The cell does, and says so. */
table.data.an-tbl tbody tr{cursor:default}
table.data.an-tbl tbody tr:hover{background:#fafbfe}

/* ---- download buttons on every card ----
   Paired and quiet: they sit at the end of the card head, after the note, and
   must never out-shout the figures they belong to. */
.xp-group{display:flex;gap:.4rem;flex:none;flex-wrap:wrap}
.card-head .xp-group{margin-left:.55rem}
.xp-btn{white-space:nowrap}
.btn.sm.xp-btn{padding:.32rem .6rem;font-size:.76rem}
.xp-btn svg{opacity:.75}
.xp-btn:hover svg{opacity:1}
.xp-btn:disabled{opacity:.6;cursor:progress}
@media (max-width:600px){
  .xp-group{width:100%;margin-left:0!important}
  .xp-group>*{flex:1 1 auto;justify-content:center}
}
@media print{.xp-group{display:none!important}}

/* ---- the "everything is clickable" hint above the page ---- */
.an-hint{display:flex;gap:.6rem;align-items:flex-start;margin-top:1rem;padding:.7rem .85rem;
  border-radius:var(--radius-sm);background:var(--brand-soft);
  border:1px solid rgba(31,111,235,.18);color:#1b3157;font-size:.82rem;line-height:1.45}
.an-hint svg{width:15px;height:15px;flex:none;margin-top:.15rem;color:var(--brand)}
.an-hint b{color:var(--brand-dark)}

/* ---- drill-through popup ---- */
.dd-facts{display:grid;grid-template-columns:repeat(auto-fit,minmax(128px,1fr));gap:.6rem;
  margin:0 0 .9rem}
.dd-fact{background:var(--bg);border:1px solid var(--line-2);border-radius:var(--radius-sm);
  padding:.55rem .7rem;display:flex;flex-direction:column;gap:.15rem;min-width:0}
.dd-fact .k{font-size:.68rem;font-weight:700;text-transform:uppercase;letter-spacing:.05em;
  color:var(--muted)}
.dd-fact .v{font-size:.95rem;font-weight:700;font-variant-numeric:tabular-nums;
  overflow:hidden;text-overflow:ellipsis}
.dd-chips{display:flex;flex-wrap:wrap;gap:.4rem;margin-bottom:.7rem}
.dd-chip{--c:var(--brand);display:inline-flex;align-items:center;gap:.4rem;cursor:pointer;
  border:1px solid var(--line);background:#fff;border-radius:999px;padding:.32rem .75rem;
  font:inherit;font-size:.79rem;font-weight:600;color:var(--ink);transition:.13s}
.dd-chip .dot{width:8px;height:8px;border-radius:99px;background:var(--c);flex:none}
.dd-chip b{font-variant-numeric:tabular-nums;color:var(--muted)}
.dd-chip:hover{border-color:var(--c);background:#f7f9fe}
.dd-chip.on{border-color:var(--c);background:var(--c);color:#fff;
  box-shadow:0 0 0 2px color-mix(in srgb,var(--c) 22%,transparent)}
.dd-chip.on b{color:#fff;opacity:.85}
.dd-chip.on .dot{background:#fff}
@media (max-width:600px){
  .dd-facts{grid-template-columns:repeat(2,1fr)}
  .barrow-note{display:none}
}
@media (prefers-reduced-motion:reduce){
  .barfill,.gc-bar,.lc-area,.lc-line{animation:none}
  .barrow.drillable:hover{transform:none}
}

/* ---------------------------------------------------------------------------
   ANALYTICS — SECTION INDEX AND FOLDED SECTIONS
   The page carries eight sections. Presented open, all at once, it reads as a
   wall and gets scrolled past. The index is the contents page: each badge names
   a section and carries its headline figure, so the numbers are legible without
   opening anything, and one click opens the section that matters.
   --------------------------------------------------------------------------- */
/* ---- toolbar ----
   Replaces a strip of fourteen badges that wrapped over four ragged rows,
   repeated every heading listed directly beneath it, and truncated the long
   ones mid-word. One quiet line: how many sections, a filter, one control. */
.an-bar{display:flex;align-items:center;gap:.6rem;margin:0 0 .85rem;
  padding-bottom:.7rem;border-bottom:1px solid #e6ebf3}
.an-bar-gap{flex:1}
.an-bar-count{font-size:.78rem;font-weight:700;color:#8794a8;
  letter-spacing:.04em;text-transform:uppercase;font-variant-numeric:tabular-nums}
.an-bar-filter{width:210px;max-width:44vw;padding:.42rem .7rem;
  border:1px solid #dde4ee;border-radius:9px;background:#fff;color:#0f172a;
  font:500 .82rem/1.3 inherit}
.an-bar-filter::placeholder{color:#9fadc0}
.an-bar-filter:focus{outline:none;border-color:#1657c4;
  box-shadow:0 0 0 3px rgba(22,87,196,.13)}
.an-bar-btn{cursor:pointer;flex:none;padding:.42rem .8rem;border-radius:9px;
  border:1px solid #dde4ee;background:#fff;color:#33465e;font:700 .78rem/1.3 inherit}
.an-bar-btn:hover{border-color:#1657c4;color:#1657c4}
.an-bar-btn:focus-visible{outline:2px solid #1657c4;outline-offset:2px}

/* ---- the grid ----
   Two or three columns of compact cards instead of fourteen full-width strips.
   An open section spans every column, so it still gets the whole page to draw
   its chart on. */
.an-grid{display:grid;gap:.7rem;grid-template-columns:repeat(auto-fill,minmax(340px,1fr));
  align-items:start;margin-bottom:1.2rem}
.an-grid > .an-sect{margin:0!important}
.an-grid > .an-sect.is-open{grid-column:1/-1}
.an-grid.is-empty::after{content:"No section matches that.";grid-column:1/-1;
  padding:1.4rem;text-align:center;color:#8794a8;font-size:.86rem}

/* ---- the folded sections: drill-through cards ----
   Closed, each card has one job: say what it holds and how much, and invite the
   click. So the figure is the largest thing on the row, the icon gives it a
   shape to be recognised by, the instruction drops to a caption, and the two
   download buttons — repeated eight times down the page — recede until the row
   is actually being used. */
.an-sect .card-body[hidden]{display:none!important}

.an-head{display:flex;align-items:center;gap:.7rem;cursor:pointer;user-select:none;
  padding:.72rem .85rem;border-radius:11px;position:relative;
  transition:background-color .14s ease}
.an-head::before{content:"";position:absolute;left:0;top:14%;bottom:14%;width:3px;
  border-radius:0 3px 3px 0;background:#1657c4;opacity:0;transition:opacity .14s ease}
.an-head:hover{background:#f8fafd}
.an-head:hover::before,.an-sect.is-open .an-head::before{opacity:1}
.an-head:focus-visible{outline:2px solid #1657c4;outline-offset:-2px}

/* Icon tile — the shape a reader navigates by. */
.an-ico{flex:none;display:grid;place-items:center;width:32px;height:32px;border-radius:9px;
  background:#eef3fb;color:#1657c4}
.an-ico.tone-blue{background:#eaf1fd;color:#1657c4}
.an-ico.tone-violet{background:#f1ecfd;color:#6d3ff0}
.an-ico.tone-teal{background:#e6f6f4;color:#0d8a7d}
.an-ico.tone-amber{background:#fdf3e3;color:#a76a08}
.an-ico.tone-red{background:#fdecec;color:#c0392f}
.an-ico.tone-slate{background:#eef1f6;color:#51607a}

.an-titlewrap{flex:1;min-width:0;display:flex;flex-direction:column;gap:.1rem}
.an-titlewrap h3{margin:0;font-size:.875rem;font-weight:650;line-height:1.3;
  letter-spacing:-.005em;color:#16283f}
.an-hintline{font-size:.715rem;line-height:1.3;color:#93a1b5;
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap}

/* The figure. Tabular, so the numbers line up down each column. */
.an-figure{flex:none;display:flex;flex-direction:column;align-items:flex-end;
  gap:0;text-align:right;margin-left:.3rem}
.an-fig-n{font-size:1.16rem;font-weight:750;line-height:1.1;color:#0f172a;
  font-variant-numeric:tabular-nums;letter-spacing:-.02em}
.an-fig-u{font-size:.665rem;font-weight:600;color:#93a1b5;white-space:nowrap;
  max-width:14ch;overflow:hidden;text-overflow:ellipsis;letter-spacing:.01em}
/* A card with no number still needs its label to sit where numbers sit. */
.an-figure:not(:has(.an-fig-n)) .an-fig-u{font-size:.79rem;color:#51607a}

/* Downloads belong to a section being read, so they appear when it opens.
   Closed, twenty-eight faded buttons read as broken rather than subtle. */
.an-acts{flex:none;display:none;gap:.35rem}
.an-sect.is-open .an-acts{display:flex}

.an-chev{display:inline-flex;align-items:center;flex:none;
  color:#c2ccda;transition:transform .18s ease,color .14s ease}
.an-sect.is-open .an-chev{transform:rotate(90deg);color:#1657c4}
.an-head:hover .an-chev{color:#1657c4}

/* Closed: a quiet card. Open: it lifts and takes the page. */
.an-sect{transition:box-shadow .16s ease,border-color .16s ease;
  border-radius:12px}
.an-sect:not(.is-open){box-shadow:0 1px 2px rgba(15,23,42,.035)}
.an-sect:not(.is-open):hover{box-shadow:0 4px 14px rgba(15,23,42,.08);
  border-color:#cddaea}
.an-sect.is-open{box-shadow:0 8px 26px rgba(15,23,42,.09);border-color:#cddaea}

@media (max-width:560px){
  .an-bar{flex-wrap:wrap}
  .an-bar-gap{display:none}
  .an-bar-filter{width:100%;max-width:none;order:3}
  .an-hintline{white-space:normal}
}

@media (prefers-reduced-motion:reduce){
  .an-chev,.an-sect,.an-head{transition:none}
}
/* Printing and PDF capture must show every section, folded or not, in one
   column — a two-column grid of half-drawn charts is not a document. */
@media print{
  .an-bar{display:none!important}
  .an-grid{display:block!important}
  .an-sect .card-body[hidden]{display:block!important}
  .an-acts{display:none!important}
}

/* ---------------------------------------------------------------------------
   OFFLINE READINESS STRIP
   One line, directly under the topbar, in plain language. It is the only part
   of the offline system anyone is expected to read: this computer can work
   without internet, or it cannot. Colour carries the same message as the words
   for anyone scanning rather than reading, and never carries it alone.
   --------------------------------------------------------------------------- */
.offline-ready{display:flex;align-items:center;gap:.55rem;
  padding:.5rem .9rem;font-size:.82rem;line-height:1.4;font-weight:600;
  border-bottom:1px solid transparent}
.offline-ready:empty{display:none}
/* Ready, and there is a line: quiet confirmation, not a celebration. */
.offline-ready.ok{background:#f0fdf4;color:#166534;border-bottom-color:#bbf7d0}
/* Ready, and running on the device right now. */
.offline-ready.working{background:#eff6ff;color:#1e3a8a;border-bottom-color:#bfdbfe}
/* Not ready — the one state that needs someone to do something. */
.offline-ready.not{background:#fffbeb;color:#78350f;border-bottom-color:#fde68a}
.offline-ready .ready-install{margin-left:auto;flex:none;cursor:pointer;
  border:1px solid currentColor;border-radius:8px;background:transparent;
  color:inherit;font:700 .78rem/1 inherit;padding:.4rem .7rem}
.offline-ready .ready-install:hover{background:rgba(0,0,0,.06)}
@media (max-width:640px){
  .offline-ready{align-items:flex-start;font-size:.78rem}
  .offline-ready .ready-install{margin-left:0;margin-top:.4rem}
  .offline-ready{flex-wrap:wrap}
}
@media print{.offline-ready{display:none!important}}