/* ============================================================================
   Blueprint — styles.css

   Design tokens are copied verbatim from vendor-portal/styles.css rather than
   re-derived, so Blueprint cannot drift from its siblings. Breakpoints and the
   responsive --maxw ladder match too.

   Only one genuinely new component exists here: the app tile. Everything else
   reuses the shared vocabulary (panel, kpi, table, chip, msg, btn).
   ========================================================================== */
:root{
  --navy:#0a2540; --blue:#0057b8; --blue-600:#0064d2; --blue-050:#eaf2fc;
  --ink:#1a2433; --muted:#5b6b7f; --line:#e3e8ef; --bg:#f5f7fa; --card:#fff;
  --good:#1a8f57; --warn:#c77700; --bad:#b3261e;
  --shadow:0 1px 3px rgba(10,37,64,.08),0 8px 24px rgba(10,37,64,.06);
  --radius:12px; --maxw:1440px;
}
*{box-sizing:border-box}
html,body{margin:0;padding:0}
body{font-family:"Segoe UI",system-ui,-apple-system,Roboto,Arial,sans-serif;
  color:var(--ink);background:var(--bg);line-height:1.45}
button{font-family:inherit;cursor:pointer}
a{color:var(--blue)}
.hidden{display:none!important}

/* ---------- Auth ---------- */
#auth{min-height:100vh;display:flex;align-items:center;justify-content:center;
  background:linear-gradient(135deg,#0a2540,#0057b8);padding:24px}
.auth-card{background:#fff;width:100%;max-width:420px;border-radius:16px;
  padding:40px 36px;box-shadow:0 20px 60px rgba(0,0,0,.25);color:#1a2433}
.brand{display:flex;align-items:center;gap:12px;margin-bottom:6px}
.brand img{height:38px;width:38px;display:block}
.brand h1{font-size:19px;margin:0;color:#0a2540}
.auth-sub{color:#5b6b7f;font-size:13.5px;margin:2px 0 26px}
.auth-card label.fld{color:#0a2540}
.auth-card input{border-color:#e3e8ef;background:#fff;color:#1a2433}
.demo-pill{display:inline-block;background:var(--warn);color:#fff;font-size:11px;
  font-weight:700;padding:3px 9px;border-radius:20px;margin-left:8px;vertical-align:middle}

label.fld{display:block;font-size:13px;font-weight:600;color:var(--navy);margin-bottom:6px}
input[type=email],input[type=text],input[type=password],input[type=url]{
  width:100%;padding:12px 14px;border:1.5px solid var(--line);border-radius:10px;
  font-size:15px;outline:none;transition:border .15s;background:var(--card);
  color:var(--ink);font-family:inherit}
input:focus{border-color:var(--blue)}
.btn{display:inline-flex;align-items:center;justify-content:center;gap:8px;width:100%;
  padding:12px 16px;border:none;border-radius:10px;background:var(--blue);color:#fff;
  font-size:15px;font-weight:600;margin-top:16px;transition:background .15s}
.btn:hover{background:var(--blue-600)}
.btn:disabled{opacity:.55;cursor:not-allowed}
.btn.ghost{background:var(--card);color:var(--blue);border:1.5px solid var(--line)}
.btn.ghost:hover{background:var(--blue-050)}
.btn.mini{padding:8px 13px;font-size:13px;width:auto;margin-top:0}
.btn.danger{background:var(--bad)}
.btn.danger:hover{background:#8f1e18}
.tiny{font-size:12px;color:var(--muted);margin-top:18px;text-align:center}
.hint{font-size:12px;color:var(--muted);margin:6px 0 0}
.msg{margin-top:14px;font-size:13.5px;padding:10px 12px;border-radius:9px;display:none}
.msg.err{display:block;background:#fdecec;color:var(--bad)}
.msg.ok{display:block;background:#e7f4ec;color:var(--good)}
.msg.info{display:block;background:var(--blue-050);color:var(--navy)}

/* ---------- Shell ---------- */
header.topbar{background:var(--card);border-bottom:1px solid var(--line);
  position:sticky;top:0;z-index:50}
.topbar-in{max-width:var(--maxw);margin:0 auto;padding:0 24px;height:60px;
  display:flex;align-items:center;gap:18px}
.home-logo{background:none;border:none;padding:0;display:flex;align-items:center;border-radius:6px}
.home-logo img{height:26px;width:26px;display:block}
.home-logo:hover{opacity:.75}
.topbar .title{font-weight:700;color:var(--navy);font-size:16px}
.spacer{flex:1}
.topbar-actions{display:flex;align-items:center;gap:8px}
.user-chip{font-size:13px;color:var(--muted)}
.role-tag{display:inline-block;background:var(--navy);color:#fff;border-radius:20px;
  padding:1px 8px;font-size:10.5px;font-weight:700;text-transform:uppercase;
  letter-spacing:.04em;margin-left:4px}
.linkbtn{background:none;border:none;color:var(--blue);font-weight:600;font-size:13.5px;
  padding:6px 8px;border-radius:7px}
.linkbtn:hover{background:var(--blue-050)}
.linkbtn.danger{color:#c0392b}
.linkbtn.danger:hover{background:#fdecea}
main{max-width:var(--maxw);margin:0 auto;padding:22px 24px 60px}
.tabs{display:flex;gap:4px;border-bottom:2px solid var(--line);margin-bottom:18px;flex-wrap:wrap}
.tab{padding:11px 18px;border:none;background:none;font-size:14.5px;font-weight:600;
  color:var(--muted);border-bottom:2px solid transparent;margin-bottom:-2px}
.tab.active{color:var(--blue);border-bottom-color:var(--blue)}
.tab:hover{color:var(--navy)}
#globalSearch{width:260px;padding:8px 12px;border:1.5px solid var(--line);
  border-radius:9px;font-size:13.5px}
.site-foot{display:flex;align-items:center;justify-content:center;gap:8px;
  padding:18px 24px 26px;font-size:12px;color:var(--muted);border-top:1px solid var(--line)}
.site-foot .sep{color:var(--line)}
.site-foot a{color:var(--blue);text-decoration:none;font-weight:600}

/* ---------- KPIs ---------- */
.kpis{display:grid;grid-template-columns:repeat(auto-fit,minmax(170px,1fr));gap:12px;margin-bottom:18px}
.kpi{display:flex;align-items:baseline;gap:10px;background:var(--card);border:1px solid var(--line);
  border-radius:var(--radius);padding:11px 15px;box-shadow:var(--shadow)}
.kpi .n{font-size:26px;font-weight:800;color:var(--navy);line-height:1;flex:0 0 auto}
.kpi .l{font-size:11.5px;color:var(--muted);text-transform:uppercase;letter-spacing:.03em;line-height:1.25}
.kpi.warn{border-color:#f2d9b0;background:#fffaf1}
.kpi.warn .n{color:var(--warn)}

/* ---------- Panels ---------- */
.panel{background:var(--card);border:1px solid var(--line);border-radius:var(--radius);
  box-shadow:var(--shadow);overflow:hidden;margin-bottom:18px}
.panel-h{padding:14px 18px;border-bottom:1px solid var(--line);font-weight:700;
  color:var(--navy);display:flex;align-items:center;gap:10px}
.panel-h .sp{flex:1}
.panel-b{padding:16px 18px}
.panel-inset{border:1px solid var(--line);border-radius:10px;padding:14px;margin:14px 0 0;background:var(--card)}
.empty{padding:40px;text-align:center;color:var(--muted)}

/* ---------- App tiles (the one new component) ---------- */
.tilegrid{display:grid;grid-template-columns:repeat(auto-fit,minmax(300px,1fr));gap:16px;margin-bottom:22px}
.apptile{position:relative;display:block;text-align:left;background:var(--card);
  border:1px solid var(--line);border-radius:var(--radius);box-shadow:var(--shadow);
  padding:18px;color:inherit;width:100%;
  transition:border-color .15s,transform .15s,box-shadow .15s}
.apptile:hover{border-color:var(--blue);transform:translateY(-2px);
  box-shadow:0 4px 10px rgba(10,37,64,.1),0 12px 32px rgba(10,37,64,.1)}
.apptile:focus-visible{outline:2px solid var(--blue);outline-offset:2px}
.apptile.inactive{opacity:.55}
.apptile-h{display:flex;align-items:center;gap:12px;margin-bottom:10px}
/* A flex child will not shrink below its content width by default, so without
   min-width:0 the text-overflow below never triggers and a long URL pushes the
   tile wider instead of clipping. */
.apptile-h>div{min-width:0}
.ic{width:40px;height:40px;border-radius:10px;flex:0 0 auto;display:block;object-fit:contain}
/* Generated placeholder for an app that publishes no logo.svg.
   The background is the literal brand blue, NOT var(--navy): --navy inverts in
   dark mode to the light text colour, which left white text on a near-white
   tile. Hardcoding #0057b8 matches the letter marks Takeoff Flow and Vendor
   Assignments actually ship, so a generated icon is readable in both themes and
   sits beside the real ones without looking out of place. */
.ic-ph{width:40px;height:40px;border-radius:10px;flex:0 0 auto;display:grid;place-items:center;
  background:#0057b8;color:#fff;font-weight:800;font-size:14px;position:relative}
/* Same problem as the initials: a "?" at 9px / weight 800 in a 14px circle was
   cramped and barely legible. Larger circle, lighter weight, and dark amber text
   instead of white — white on amber is roughly 2:1 contrast, which fails at any
   size, whereas the dark tone clears 7:1 on the dark fill and 4.4:1 on the light. */
.ic-ph::after{content:"?";position:absolute;top:-3px;right:-3px;width:16px;height:16px;
  border-radius:50%;background:var(--warn);color:#3d2a08;font-size:11px;display:grid;
  place-items:center;font-weight:600;line-height:1}
.apptile-h h3{margin:0;font-size:15.5px;color:var(--navy);
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
/* Tiles are fixed-width, so an unbroken 150-character URL would either overflow
   or wrap to five lines. Shortened text plus a hard clip keeps the header to one
   line; the full URL is on the title attribute. */
.apptile-h .sub{font-size:12px;color:var(--muted);margin-top:1px;
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap;max-width:100%}
.apptile p{margin:0 0 12px;font-size:13px;color:var(--muted);min-height:36px}
/* Names are never truncated. Sharing a row with the label left too little width
   for two full names, and clipping them to "Denis Cre…" made the tile less
   informative than showing nothing. The label moves to its own caption line, which
   gives the chips the tile's full width — enough for two full names even at the
   narrowest tile — and any overflow wraps to a second line intact. */
.apptile-auth{display:flex;flex-direction:column;align-items:flex-start;gap:6px;
  font-size:12px;color:var(--muted);padding:9px 0 0;
  border-top:1px dashed var(--line);margin-bottom:2px}
.apptile-auth .lbl{font-size:10px;font-weight:700;text-transform:uppercase;
  letter-spacing:.06em;opacity:.7;line-height:1}
.who-list{display:flex;flex-wrap:wrap;align-items:center;gap:6px;width:100%}
.who{display:inline-flex;align-items:center;gap:5px;background:var(--blue-050);
  border-radius:20px;padding:2px 9px 2px 2px;font-size:11.5px;font-weight:600;
  color:var(--navy);max-width:100%}
.who .nm{white-space:nowrap}
/* Initials at 8.5px / weight 800 were too small and too heavy for two caps: the
   letters ran together and read as a blob. Same typeface — the family was never
   the problem — just sized for legibility: a larger circle, a lighter weight and
   a touch of tracking so the pair separates. line-height:1 keeps them optically
   centred rather than sitting low on the baseline. */
.who .av{flex:0 0 auto;width:18px;height:18px;border-radius:50%;background:var(--navy);
  color:#fff;display:grid;place-items:center;font-size:10px;font-weight:600;
  letter-spacing:.03em;line-height:1}
.apptile-f{display:flex;align-items:center;gap:8px;flex-wrap:wrap;font-size:12px;
  color:var(--muted);border-top:1px solid var(--line);padding-top:10px;margin-top:9px}
.apptile .go{margin-left:auto;color:var(--blue);font-weight:700;font-size:13px}
.dot{width:8px;height:8px;border-radius:50%;flex:0 0 auto}
.dot.ok{background:var(--good)} .dot.warn{background:var(--warn)} .dot.bad{background:var(--bad)}

/* ---------- Chips / tags ---------- */
.chip{display:inline-block;background:var(--blue-050);color:var(--blue);border-radius:20px;
  padding:2px 10px;font-size:12px;font-weight:600;margin:2px 3px 2px 0}
.cat-tag{display:inline-block;background:#eef1f5;color:var(--muted);border-radius:6px;
  padding:2px 8px;font-size:11.5px;font-weight:600}
.pubtag{display:inline-block;background:#fff2df;color:var(--warn);border-radius:20px;
  padding:2px 9px;font-size:11px;font-weight:700}
.risk{font-size:11.5px;font-weight:700;padding:2px 9px;border-radius:20px}
.risk-ok{background:#e7f4ec;color:var(--good)}
.risk-warn{background:#fff2df;color:var(--warn)}
.risk-bad{background:#fdecec;color:var(--bad)}
.norole{color:var(--muted);font-size:12.5px;font-style:italic}

/* ---------- Tables ---------- */
.table-wrap{overflow:auto;max-height:70vh;border-radius:var(--radius)}
table{border-collapse:separate;border-spacing:0;width:100%;font-size:13.5px}
thead th{position:sticky;top:0;background:var(--navy);color:#fff;font-weight:600;
  text-align:left;padding:10px 12px;white-space:nowrap;z-index:2}
tbody td{padding:9px 12px;border-bottom:1px solid var(--line);white-space:nowrap}
tbody tr:hover{background:var(--blue-050)}
.num{text-align:right;font-variant-numeric:tabular-nums}
.rolesel{padding:5px 8px;border:1.5px solid var(--line);border-radius:7px;font-size:12.5px;
  font-weight:600;color:var(--navy);background:var(--card);font-family:inherit}
.ic-sm{width:24px;height:24px;border-radius:6px;display:block;object-fit:contain;flex:0 0 auto}
/* same reasoning as .ic-ph — theme-stable brand blue, not var(--navy) */
/* The 24px variant had the same 9px / weight 800 problem. Calibrated to match the
   initials avatar; line-height:1 stops the letters riding low in the circle. */
.ic-sm.ph{background:#0057b8;color:#fff;font-size:10px;font-weight:600;
  line-height:1;display:grid;place-items:center}
.ic.ph{width:40px;height:40px;border-radius:10px;flex:0 0 auto;display:grid;
  place-items:center;background:#0057b8;color:#fff;font-weight:800;font-size:14px}
/* Shortening handles readability; this cap is the structural guarantee. Even if a
   value arrives unshortened, the cell clips instead of widening the table and
   pushing the row actions off-screen behind a scrollbar. */
.urlc{color:var(--muted);font-size:12.5px;max-width:300px;overflow:hidden;
  text-overflow:ellipsis;white-space:nowrap}
@media (max-width:1100px){ .urlc{max-width:180px} }

/* ---------- Toolbar / forms ---------- */
.toolbar{display:flex;gap:10px;flex-wrap:wrap;align-items:center;margin-bottom:14px}
.toolbar input[type=text]{max-width:280px}
.toolbar select,select.std{padding:9px 12px;border:1.5px solid var(--line);border-radius:9px;
  font-size:14px;background:var(--card);color:var(--navy);font-family:inherit;font-weight:600}
.count{font-size:13px;color:var(--muted);margin-left:auto}
.field-row{display:flex;gap:12px;align-items:flex-start;flex-wrap:wrap;margin-bottom:14px}
.field-row>div{flex:1 1 220px}
.linkrow{display:flex;align-items:center;gap:8px}
.iconrow{display:flex;align-items:flex-start;gap:10px}
.iconrow-b{flex:1;min-width:0;display:flex;flex-direction:column;gap:6px}
.iconbtns{display:flex;gap:6px;flex-wrap:wrap}
.iconprev{flex:0 0 auto;width:40px;height:40px;display:grid;place-items:center}
.iconprev .ic,.iconprev .ic-ph{width:40px;height:40px}
.linkrow input{flex:1;min-width:0;font-size:13px;
  font-family:ui-monospace,SFMono-Regular,Menlo,monospace}
.grantgrid{display:grid;grid-template-columns:repeat(auto-fit,minmax(230px,1fr));gap:10px;margin:6px 0 4px}
.grantcard{border:1.5px solid var(--line);border-radius:10px;padding:12px}
.grantcard.on{border-color:var(--blue);background:var(--blue-050)}
.grantcard label.head{display:flex;align-items:center;gap:8px;font-size:13.5px;
  font-weight:700;color:var(--navy);cursor:pointer;margin:0}
.grantcard .r{margin-top:9px;display:flex;align-items:center;gap:8px;font-size:12.5px;color:var(--muted)}
.grantcard select{width:100%}
.divchks{display:flex;gap:10px;flex-wrap:wrap}
.divchk{font-size:12.5px;color:var(--navy);font-weight:600;display:inline-flex;align-items:center;gap:5px}
.radiorow{display:flex;gap:8px;flex-wrap:wrap;margin:4px 0 2px}
.radiochip{border:1.5px solid var(--line);border-radius:9px;padding:9px 13px;font-size:13px;
  font-weight:600;color:var(--navy);background:var(--card);display:flex;align-items:center;gap:7px;cursor:pointer}
.radiochip.on{border-color:var(--blue);background:var(--blue-050);color:var(--blue)}
.warnbox{background:#fffaf1;border:1px solid #f2d9b0;border-radius:10px;padding:10px 12px;
  margin:0 0 12px;font-size:13px;color:#7a4b00}
.warnbox ul{margin:6px 0 0;padding-left:18px}
.warnbox li{margin:3px 0}

/* Deleting a login sits below the Save row, fenced off. Same shape as .panel-inset
   so it reads as part of the modal rather than an alert, with a red edge so it is
   never mistaken for another way to save. */
.dangerzone{border:1px solid #f0c9c4;border-left:3px solid var(--bad);border-radius:10px;
  padding:12px 14px;margin:18px 0 0;background:#fdf7f6}
.dangerzone>b{color:#a02a20;font-size:13px}
.dangerzone .hint{margin:4px 0 10px}
.dangerzone .btn.mini{width:auto;margin:0}

/* ---------- Data Intake ----------
   The drop tile matches the ones in Vendor Assignments and Takeoff Flow, so the
   gesture is the one people already know — the only difference is that this one
   takes every workbook rather than a single named file. */
.uptile{border:2px dashed var(--line);border-radius:var(--radius);padding:26px 18px;
  text-align:center;cursor:pointer;background:var(--bg);transition:border-color .12s,background .12s}
.uptile:hover,.uptile:focus-visible{border-color:var(--blue);background:var(--blue-050);outline:none}
.uptile.drag{border-color:var(--blue);background:var(--blue-050)}
.uptile-ic{font-size:22px;color:var(--blue);line-height:1}
.uptile-t{font-weight:700;color:var(--navy);margin-top:6px}
.uptile-s{font-size:12px;color:var(--muted);margin-top:2px}

.pill{display:inline-block;font-size:11px;font-weight:700;padding:2px 8px;border-radius:999px;
  text-transform:uppercase;letter-spacing:.03em;vertical-align:middle}
.pill.ok{background:#e7f5ee;color:var(--good)}
.pill.warn{background:#fdf3e3;color:var(--warn)}
.pill.bad{background:#fdeceb;color:var(--bad)}

/* Progress is shown per file rather than for the batch: the RE2 export takes
   about fifteen seconds on its own, and a single bar for everything would sit
   apparently stalled while one large file worked. */
.prog{display:inline-block;width:120px;height:6px;border-radius:3px;background:var(--line);
  overflow:hidden;vertical-align:middle;margin-right:8px}
.prog-bar{height:100%;background:var(--blue);width:0;transition:width .2s}

.intake-card{border:1px solid var(--line);border-left:3px solid var(--blue);
  border-radius:10px;padding:14px 16px;background:var(--card)}
.intake-card h4{margin:0 0 10px;font-size:14px;color:var(--navy)}
.intake-card .kpis{margin-bottom:10px}
.intake-card p{margin:0 0 8px}
.intake-card.waiting{border-left-color:var(--line);background:var(--bg)}
.intake-card.ok{border-left-color:var(--good)}
.intake-card.bad{border-left-color:var(--bad)}

.intake-bar{display:flex;align-items:center;justify-content:space-between;gap:12px;
  flex-wrap:wrap;padding:10px 14px;border:1px solid var(--line);border-radius:10px;
  background:var(--blue-050)}
.intake-bar .btn{margin:0;width:auto}

.intake-cmd{background:var(--navy);color:#e7ecf4;border-radius:8px;padding:10px 12px;
  font-family:ui-monospace,SFMono-Regular,Consolas,monospace;font-size:11.5px;
  line-height:1.5;overflow-x:auto;margin:8px 0;white-space:pre}

.intake-notes{margin:8px 0;padding-left:18px;font-size:12.5px}
.intake-notes li{margin:3px 0}
.intake-notes li.note{color:var(--muted)}
.intake-notes li.warn{color:var(--warn)}
.intake-notes li.bad{color:var(--bad);font-weight:600}

/* ---------- Locating a community ----------
   Shared by Data Intake's map card and the Health panel's modal. One block,
   because they render the same rows through the same function and a second
   stylesheet is how the two would drift apart visually. */
.locate{margin-top:12px;border-top:1px solid var(--line);padding-top:12px}
.locate h4{margin:0 0 4px;font-size:13px;color:var(--warn)}
.locate-row{border:1px solid var(--line);border-radius:8px;padding:10px 12px;
  margin-top:10px;background:var(--bg)}
.locate-row h5{margin:0 0 6px;font-size:13px;color:var(--navy);
  display:flex;align-items:center;gap:8px;flex-wrap:wrap}
.locate-row p{margin:4px 0}
.locate-proposal{border-left:3px solid var(--warn);padding:6px 0 6px 10px;margin:8px 0}
.locate-proposal p{margin:0 0 4px;font-size:13px}
.locate-entry{display:flex;gap:8px;flex-wrap:wrap;align-items:center;margin-top:8px}
.locate-entry input[type=text]{width:auto;flex:1 1 190px;min-width:0;margin:0}
.locate-entry .btn.mini{flex:0 0 auto}
@media(max-width:640px){
  .locate-entry input[type=text]{flex:1 1 100%}
}

/* ---------- Health ---------- */
.healthgrid{display:grid;grid-template-columns:repeat(auto-fit,minmax(330px,1fr));gap:16px}
.healthgrid .panel{margin-bottom:0}
.hrow{display:flex;align-items:center;gap:10px;padding:9px 0;border-bottom:1px solid var(--line);font-size:13.5px}
.hrow:last-child{border-bottom:none}
.hrow .hl{color:var(--muted);flex:1}
.hrow .hv{font-weight:700;color:var(--navy);font-variant-numeric:tabular-nums}

/* ---------- Modal ---------- */
.modal-ov{position:fixed;inset:0;background:rgba(10,37,64,.45);display:flex;
  align-items:center;justify-content:center;z-index:200;padding:20px}
.modal-card{background:var(--card);border-radius:14px;box-shadow:0 20px 60px rgba(0,0,0,.3);
  max-width:620px;width:100%;max-height:82vh;display:flex;flex-direction:column;overflow:hidden}
.modal-h{display:flex;align-items:center;justify-content:space-between;padding:14px 18px;
  border-bottom:1px solid var(--line);font-weight:700;color:var(--navy)}
.modal-body{padding:16px 18px;overflow:auto}
.modal-actions{display:flex;gap:8px;justify-content:flex-end;margin-top:16px}
.modal-actions .btn{width:auto;margin-top:0}

/* toast */
#toast{position:fixed;left:50%;bottom:26px;transform:translateX(-50%);z-index:400;
  background:var(--navy);color:#fff;padding:11px 18px;border-radius:10px;font-size:13.5px;
  font-weight:600;box-shadow:var(--shadow);opacity:0;pointer-events:none;transition:opacity .2s}
#toast.show{opacity:1}
#toast.err{background:var(--bad)}
#toast.ok{background:var(--good)}

/* ---------- Dark mode ---------- */
[data-theme="dark"]{
  --navy:#e7ecf4; --ink:#e7ecf4; --muted:#9aa7ba; --line:#2a3547;
  --bg:#0e141d; --card:#19212e; --blue:#5aa0f0; --blue-600:#79b3f6; --blue-050:#18293f;
  --good:#3ecb86; --warn:#e0a44a; --bad:#f28b8b;
  --shadow:0 1px 3px rgba(0,0,0,.5),0 8px 24px rgba(0,0,0,.4);
  color-scheme:dark;
}
[data-theme="dark"] header.topbar,
[data-theme="dark"] select.std,
[data-theme="dark"] .toolbar select,
[data-theme="dark"] .rolesel,
[data-theme="dark"] .modal-card,
[data-theme="dark"] input[type=email],
[data-theme="dark"] input[type=text],
[data-theme="dark"] input[type=password],
[data-theme="dark"] #globalSearch{background:var(--card);color:var(--ink)}
[data-theme="dark"] thead th{background:#0c1929;color:#e7ecf4}
[data-theme="dark"] .role-tag{background:#33415a;color:#fff}
[data-theme="dark"] .cat-tag{background:#222d3d;color:var(--muted)}
[data-theme="dark"] .chip,[data-theme="dark"] .msg.info{background:#18293f;color:#8fbdf2}
[data-theme="dark"] .who{background:#18293f;color:#cfe0f5}
[data-theme="dark"] .who .av{background:#33415a}
[data-theme="dark"] .msg.ok,[data-theme="dark"] .risk-ok{background:#173a2b;color:#5ed6a0}
[data-theme="dark"] .msg.err,[data-theme="dark"] .risk-bad{background:#3a1c1c;color:#f28b8b}
[data-theme="dark"] .dangerzone{background:#2b1a19;border-color:#5a2a26}
[data-theme="dark"] .dangerzone>b{color:#f28b8b}
[data-theme="dark"] .kpi.warn,[data-theme="dark"] .warnbox,
[data-theme="dark"] .risk-warn,[data-theme="dark"] .pubtag{
  background:#33280f;color:#e9b866;border-color:#5a4420}

/* ---------- Responsive: same ladder as the sibling apps ---------- */
@media (min-width:1200px){ main{padding-left:32px;padding-right:32px} }
@media (min-width:1700px){ :root{ --maxw:1660px } }
@media (min-width:2100px){ :root{ --maxw:1960px } }
@media (max-width:820px){
  .topbar-in{height:auto;flex-wrap:wrap;padding:10px 14px;gap:10px}
  .topbar .title{display:none}
  .spacer{display:none}
  #globalSearch{width:100%}
  main{padding:16px 14px 50px}
  .kpis{grid-template-columns:repeat(2,1fr)}
  .toolbar input[type=text],.toolbar select{max-width:100%;flex:1 1 100%}
  .count{margin-left:0}
}
@media (max-width:640px){
  main{padding:12px 10px 36px}
  .kpis{grid-template-columns:1fr 1fr;gap:8px}
  .kpi{padding:10px 12px}
  .kpi .n{font-size:20px}
  .tilegrid{grid-template-columns:1fr}
  .field-row>div{flex:1 1 100%}
}
@media (max-width:480px){ .auth-card{padding:28px 22px} }

/* ---------- Print ---------- */
@media print{
  header.topbar,.tabs,.toolbar,.topbar-actions,#toast{display:none!important}
  #auth{display:none!important}
  body{background:#fff}
  main{max-width:100%;padding:0}
  .panel,.kpi,.apptile{box-shadow:none;border:1px solid #ccc}
  .table-wrap{max-height:none;overflow:visible}
  thead th{position:static;background:#0a2540!important;
    -webkit-print-color-adjust:exact;print-color-adjust:exact}
}
