:root{
  /* Surfaces climb in four steps — page, rail, card, raised — so depth is
     read from lightness rather than from borders everywhere. */
  --bg:#0b0d14; --bg-2:#11141e; --card:#171b28; --card-2:#1e2333;
  --line:#262c3e; --line-2:#333a51;
  --txt:#eef1f8; --muted:#939bb4; --faint:#646c88;
  --accent:#6366f1; --accent-2:#8b95ff; --accent-soft:rgba(99,102,241,.15);
  --accent-grad:linear-gradient(135deg,#6366f1,#8b5cf6);
  --green:#22c55e; --amber:#f59e0b; --red:#ef4444; --cyan:#06b6d4; --violet:#a855f7;
  --radius:16px; --radius-sm:10px;

  /* One elevation ramp, used everywhere something lifts off the page. */
  --shadow-sm:0 1px 2px rgba(0,0,0,.4);
  --shadow:0 18px 44px -20px rgba(0,0,0,.75), 0 2px 8px -3px rgba(0,0,0,.5);
  --shadow-lg:0 32px 70px -28px rgba(0,0,0,.85);
  --ring:0 0 0 3px var(--accent-soft);

  --font:'Inter',-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,sans-serif;
  /* The option list of a <select> is drawn by the browser, not by us. Without
     a declared colour-scheme it is painted light while our fields are dark,
     which left the options unreadable — dark text on a dark sheet. */
  color-scheme:dark;
}
[data-theme="light"]{
  --bg:#f6f7fb; --bg-2:#ffffff; --card:#ffffff; --card-2:#f4f6fc;
  --line:#e6eaf3; --line-2:#d6dcec;
  --txt:#101528; --muted:#5c6580; --faint:#8b93ad;
  /* The dark theme's accent-2 is a pale lavender chosen to glow on near-black.
     On white it all but disappears, so light gets a darker one — the same hue,
     read the other way round. Every status colour below follows the same rule. */
  --accent-2:#4f46e5;
  --accent-soft:rgba(99,102,241,.1);
  --shadow-sm:0 1px 2px rgba(16,21,40,.06);
  --shadow:0 16px 40px -22px rgba(16,21,40,.28), 0 2px 6px -3px rgba(16,21,40,.08);
  --shadow-lg:0 30px 64px -30px rgba(16,21,40,.34);
  color-scheme:light;
}

*{box-sizing:border-box;margin:0;padding:0}
html,body{height:100%}
body{
  font-family:var(--font); background:var(--bg); color:var(--txt);
  font-size:14px; line-height:1.5; -webkit-font-smoothing:antialiased;
}
a{color:var(--accent-2);text-decoration:none}
button,input,select,textarea{font-family:inherit;font-size:14px;color:inherit}
::-webkit-scrollbar{width:9px;height:9px}
::-webkit-scrollbar-thumb{background:var(--line-2);border-radius:99px}
::-webkit-scrollbar-track{background:transparent}

/* ── Login ─────────────────────────────────────────────────────────
   A split screen: the product on the left, the form on the right. The
   left half is decoration and collapses away below 900px, where it is
   replaced by a one-line brand lockup above the card — a phone has no
   room to be sold to, and the person signing in already knows what this
   is. Nothing on the left panel is a number: the tiles name the modules
   the workspace actually contains, so there is no invented statistic
   sitting on the front door of a live portal. */
.login-wrap{
  min-height:100vh;min-height:100dvh;
  display:grid;grid-template-columns:minmax(0,1.05fr) minmax(0,.95fr);
  background:var(--bg);
}

/* ── Left: the product ── */
.auth-brand{
  position:relative;overflow:hidden;display:flex;flex-direction:column;
  justify-content:center;gap:26px;padding:56px clamp(40px,5vw,72px);
  color:#fff;isolation:isolate;
  background:linear-gradient(150deg,#312e81 0%,#4c1d95 45%,#1e1b4b 100%);
}
/* Two soft lights over the gradient — the whole "premium" effect, at the
   cost of no images and no extra requests. */
.auth-brand::before{
  content:'';position:absolute;inset:0;z-index:-1;
  background:radial-gradient(760px 460px at 18% 8%,rgba(129,140,248,.45),transparent 62%),
             radial-gradient(620px 420px at 92% 88%,rgba(6,182,212,.28),transparent 60%);
}
.auth-lockup{display:flex;align-items:center;gap:13px}
.auth-lockup .mark{
  width:46px;height:46px;flex:none;border-radius:14px;display:grid;place-items:center;
  background:rgba(255,255,255,.14);border:1px solid rgba(255,255,255,.22);
  backdrop-filter:blur(6px);font-weight:800;font-size:18px;color:#fff;
}
.auth-lockup img.mark{background:#fff;object-fit:contain;padding:7px}
.auth-lockup b{display:block;font-size:19px;font-weight:700;letter-spacing:-.02em}
.auth-lockup small{display:block;font-size:11.5px;color:rgba(255,255,255,.62);
  letter-spacing:.04em;margin-top:2px}

.auth-brand h2{
  font-size:clamp(28px,3vw,40px);line-height:1.15;font-weight:750;
  letter-spacing:-.035em;max-width:15ch;
}
.auth-brand .lede{
  font-size:14.5px;line-height:1.65;color:rgba(255,255,255,.74);max-width:46ch;
}
.auth-tiles{
  display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:10px;max-width:520px;
}
.auth-tile{
  display:flex;align-items:center;gap:9px;padding:12px 13px;border-radius:13px;
  background:rgba(255,255,255,.08);border:1px solid rgba(255,255,255,.13);
  font-size:12.5px;font-weight:550;color:rgba(255,255,255,.9);
  backdrop-filter:blur(4px);
}
.auth-tile svg{width:16px;height:16px;flex:none;opacity:.85}
.auth-foot{
  font-size:11.5px;color:rgba(255,255,255,.5);letter-spacing:.05em;
  text-transform:uppercase;font-weight:600;
}

/* ── Right: the form ── */
.auth-panel{
  display:grid;place-items:center;padding:40px 24px;background:var(--bg-2);
  overflow-y:auto;
}
.login-card{
  width:100%;max-width:392px;
  animation:riseIn .45s cubic-bezier(.2,.8,.25,1);
}
@keyframes riseIn{from{opacity:0;transform:translateY(14px) scale(.985)}to{opacity:1;transform:none}}
/* The lockup repeated inside the card, for the phone layout where the left
   panel is gone. Hidden on desktop so the brand is not stated twice. */
.login-card .auth-lockup{display:none;margin-bottom:26px;color:var(--txt)}
.login-card .auth-lockup .mark{
  background:var(--accent-grad);border:0;
  box-shadow:0 10px 24px -10px rgba(99,102,241,.8);
}
.login-card .auth-lockup img.mark{background:#fff;box-shadow:none}
.login-card .auth-lockup small{color:var(--accent-2);font-weight:600}
.login-card h1{font-size:25px;font-weight:700;letter-spacing:-.03em}
.login-card p.sub{color:var(--muted);font-size:13.5px;margin:7px 0 26px}
#loginErr:not(:empty){margin-bottom:16px}
.login-card .field{margin-bottom:14px}
.login-card .field label{
  display:block;font-size:12px;font-weight:600;color:var(--muted);margin-bottom:6px;
}
.login-card .input{width:100%}
/* Row under the fields: the checkbox on the left, the reset note on the right.
   There is no self-service reset in this app, so it says who to ask rather
   than offering a link that goes nowhere. */
.login-opts{
  display:flex;align-items:center;justify-content:space-between;gap:12px;
  margin:2px 0 20px;font-size:12.5px;flex-wrap:wrap;
}
.login-opts label{display:flex;align-items:center;gap:8px;cursor:pointer;color:var(--muted)}
.login-opts input[type=checkbox]{
  width:15px;height:15px;accent-color:var(--accent);cursor:pointer;flex:none;
}
.login-opts .hint{color:var(--faint);font-size:12px}
.login-card .btn.primary{width:100%;justify-content:center;padding:12px;font-size:14px}
.login-legal{
  margin-top:22px;padding-top:18px;border-top:1px solid var(--line);
  font-size:11.5px;color:var(--faint);line-height:1.6;
}

/* Below 900px the left panel goes and the card takes the screen. */
@media (max-width:900px){
  .login-wrap{grid-template-columns:1fr}
  .auth-brand{display:none}
  .auth-panel{background:var(--bg);align-content:center;
    padding:32px 20px calc(32px + env(safe-area-inset-bottom))}
  .login-card .auth-lockup{display:flex}
}

/* ── Layout ────────────────────────────────────────────────────────
   The page itself never scrolls. The sidebar and the main area are two
   independent scroll regions, so a long menu can never push the content
   away — and scrolling a long table never moves the menu. */
.app{display:grid;grid-template-columns:252px 1fr;height:100vh;overflow:hidden}
.sidebar{
  background:var(--bg-2);border-right:1px solid var(--line);
  display:flex;flex-direction:column;padding:18px 14px;gap:4px;
  height:100vh;overflow-y:auto;overflow-x:hidden;
  scrollbar-width:thin;scrollbar-color:var(--line-2) transparent;
}
/* ── Why every direct child is flex:none ────────────────────────────────
   A column flex container gives its children flex-shrink:1. When the menu
   grows taller than the 100vh box — which is exactly what unfolding a group
   does at 100% zoom on a laptop — the browser's first move is to compress
   the children, not to scroll. Items lose their padding, labels clip, and
   rows visually run into one another; the scrollbar never appears because
   after the squashing nothing overflows any more.

   Pinning every child to its natural height means the overflow is real, so
   overflow-y:auto does its job and the menu scrolls. This is the fix for
   "opening one dropdown hides the other menu items". */
.sidebar > *{flex:0 0 auto;min-height:0}
[data-theme="light"] .sidebar{background:#fbfcfe}
/* Logo stays put at the top and the account block at the bottom while the
   menu itself scrolls between them. */
.sb-brand{
  display:flex;align-items:center;gap:10px;padding:4px 8px 14px;
  position:sticky;top:-18px;z-index:2;background:var(--bg-2);
  margin:-18px -14px 0;padding-left:22px;padding-right:22px;padding-top:22px;
}
.sb-brand .mk{width:34px;height:34px;border-radius:11px;display:grid;place-items:center;
  background:var(--accent-grad);color:#fff;font-weight:800;font-size:14px;
  box-shadow:0 6px 16px -6px rgba(99,102,241,.7)}
.sb-brand .mk-img{width:36px;height:36px;flex:none;object-fit:contain;
  background:#fff;border-radius:10px;padding:3px}
.sb-brand b{font-size:14.5px;font-weight:650;letter-spacing:-.01em;display:block;
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.sb-brand .sb-tag{display:block;font-size:9.5px;color:var(--faint);margin-top:1px;
  letter-spacing:.02em;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
/* Section heading. It doubles as the toggle for the group under it — the
   chevron and the pointer only appear once JS has wrapped the items, so a
   heading still reads as a plain label if the script never runs.

   It is laid out as a flex row unconditionally, not only once .sb-toggle is
   added: the coloured chip lives in the markup, so a heading has to sit its
   icon and its text on one line even in the half-second before the script
   groups the menu — otherwise the sidebar visibly reflows on every load. */
.sb-label{
  display:flex;align-items:center;gap:10px;
  font-size:11.5px;text-transform:uppercase;letter-spacing:.07em;color:var(--muted);
  padding:12px 9px 8px;font-weight:800;
}
/* Each section owns a hue, declared once per heading below. Twelve grey
   uppercase words in a column are read one at a time; twelve coloured chips
   are found at a glance, which is the only way a menu this long stays
   navigable without hunting. */
.sb-ic{
  width:27px;height:27px;flex:0 0 27px;border-radius:9px;
  display:grid;place-items:center;color:#fff;
  background:linear-gradient(140deg,var(--ic1),var(--ic2));
  box-shadow:0 4px 10px -4px rgba(0,0,0,.55),inset 0 1px 0 rgba(255,255,255,.3);
  transition:transform .16s ease,box-shadow .16s ease;
}
[data-theme="light"] .sb-ic{box-shadow:0 4px 10px -4px rgba(16,21,40,.35),inset 0 1px 0 rgba(255,255,255,.45)}
/* stroke-width is set here rather than on each <svg> so one number controls
   the weight of all thirteen. */
.sb-ic svg{width:15.5px;height:15.5px;flex:none;stroke-width:2.3}
.sb-label .sb-t{white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.sb-label.sb-toggle{
  cursor:pointer;user-select:none;
  border-radius:var(--radius-sm);transition:color .15s,background .15s;
}
.sb-label.sb-toggle:hover{color:var(--txt);background:var(--card)}
.sb-label.sb-toggle:hover .sb-ic{transform:translateY(-1px) scale(1.06)}
.sb-label.sb-toggle:focus-visible{outline:none;box-shadow:var(--ring)}
/* The chevron sits in its own chip so it reads as the control it is — a bare
   12px stroke on a heading was being missed entirely. */
.sb-label .sb-caret{
  width:20px;height:20px;flex:0 0 20px;padding:3px;border-radius:7px;
  color:var(--muted);background:var(--card-2);
  transition:transform .2s ease,background .15s,color .15s;
}
.sb-label.sb-toggle:hover .sb-caret{background:var(--accent-soft);color:var(--accent-2)}
.sb-label.collapsed .sb-caret{transform:rotate(-90deg)}
/* The count stays on whether the group is open or shut: how many screens are
   under a heading is worth knowing *before* you open it, not only after. */
.sb-label .sb-n{
  margin-left:auto;
  font-size:10px;font-weight:800;letter-spacing:0;line-height:1.6;color:var(--muted);
  background:var(--card-2);border:1px solid var(--line);
  border-radius:99px;padding:0 7px;display:inline-block;
}
/* .sb-n already claimed the free space with margin-left:auto; the caret only
   needs to sit next to it. */
.sb-label .sb-n + .sb-caret{margin-left:5px}
.nav-group{display:flex;flex-direction:column;gap:4px;overflow:hidden}
/* Opening a group slides its items in, so the eye follows what just appeared
   instead of the menu jumping. Purely opacity/transform — no height maths,
   which is what would break the scrolling fix described above. */
.nav-group:not(.collapsed){animation:navReveal .18s ease}
@keyframes navReveal{from{opacity:0;transform:translateY(-5px)}to{opacity:1;transform:none}}
/* Same reasoning as `.sidebar > *`: the group is a column flex box too, so
   its rows must not be allowed to compress into each other either. */
.nav-group > *{flex:0 0 auto}
.nav-group.collapsed{display:none}
.nav-item{
  display:flex;align-items:center;gap:11px;padding:9px 11px;border-radius:var(--radius-sm);
  color:var(--muted);cursor:pointer;font-weight:500;font-size:13.5px;
  border:1px solid transparent;transition:.15s;position:relative;
}
.nav-item:hover{background:var(--card);color:var(--txt)}
/* The open screen gets a filled pill and a rail down its left edge — one
   glance tells you where you are without reading the label. */
.nav-item.active{
  background:var(--accent-soft);color:var(--accent-2);
  border-color:rgba(99,102,241,.3);font-weight:600;
}
.nav-item.active::before{
  content:'';position:absolute;left:-14px;top:50%;transform:translateY(-50%);
  width:3px;height:20px;border-radius:0 3px 3px 0;background:var(--accent);
}
.nav-item svg{width:17px;height:17px;flex:0 0 17px}
.sb-foot{
  margin-top:auto;padding-top:14px;border-top:1px solid var(--line);
  position:sticky;bottom:-18px;
  /* Opaque, and above the menu it floats over: a translucent footer let the
     last two or three items show through it and look like live options. */
  background:var(--bg-2);z-index:3;
  margin-left:-14px;margin-right:-14px;padding-left:14px;padding-right:14px;
  padding-bottom:18px;
}
[data-theme="light"] .sb-foot{background:#fbfcfe}
/* Breathing room under the last menu item so the sticky footer settles
   below it rather than on top of it when the menu is exactly full. */
.sidebar > .nav-group:last-of-type{margin-bottom:6px}

/* One hue per section. Kept together so the palette can be read as a set —
   neighbouring groups must not land on the same colour.

   The pair is declared on the heading, not on .sb-ic, so the chip inherits
   it: a value set on .sb-ic itself would beat every [data-icon] rule below
   and flatten the whole palette to one colour. The bare .sb-label line is
   the fallback for a heading added later with no hue of its own — it loses
   to the attribute selectors on specificity, which is the point. */
.sb-label                       {--ic1:var(--accent);--ic2:var(--accent-2)}
.sb-label[data-icon="sales"]    {--ic1:#6366f1;--ic2:#8b5cf6}
.sb-label[data-icon="work"]     {--ic1:#0ea5e9;--ic2:#06b6d4}
.sb-label[data-icon="billing"]  {--ic1:#10b981;--ic2:#059669}
.sb-label[data-icon="finance"]  {--ic1:#f59e0b;--ic2:#f97316}
.sb-label[data-icon="schedule"] {--ic1:#3b82f6;--ic2:#4f46e5}
.sb-label[data-icon="tele"]     {--ic1:#ec4899;--ic2:#f43f5e}
.sb-label[data-icon="vendors"]  {--ic1:#fb923c;--ic2:#ea580c}
.sb-label[data-icon="campaigns"]{--ic1:#a855f7;--ic2:#d946ef}
.sb-label[data-icon="staff"]    {--ic1:#14b8a6;--ic2:#0d9488}
.sb-label[data-icon="partners"] {--ic1:#84cc16;--ic2:#16a34a}
.sb-label[data-icon="account"]  {--ic1:#8b5cf6;--ic2:#6366f1}
.sb-label[data-icon="partner"]  {--ic1:#06b6d4;--ic2:#3b82f6}
.sb-label[data-icon="admin"]    {--ic1:#f43f5e;--ic2:#be123c}


/* Thin, unobtrusive scrollbars on the two panes (WebKit; Firefox uses
   scrollbar-width above). */
.sidebar::-webkit-scrollbar,.main::-webkit-scrollbar{width:9px}
.sidebar::-webkit-scrollbar-track,.main::-webkit-scrollbar-track{background:transparent}
.sidebar::-webkit-scrollbar-thumb,.main::-webkit-scrollbar-thumb{
  background:var(--line-2);border-radius:99px;border:2px solid transparent;background-clip:content-box;
}
.sidebar::-webkit-scrollbar-thumb:hover,.main::-webkit-scrollbar-thumb:hover{background:var(--faint);background-clip:content-box}
.who{display:flex;align-items:center;gap:9px;padding:8px 6px}
.avatar{width:30px;height:30px;border-radius:50%;background:var(--accent);color:#fff;
  display:grid;place-items:center;font-size:12px;font-weight:700;flex:0 0 30px}
.who small{display:block;color:var(--faint);font-size:11px;text-transform:capitalize}

.main{padding:22px 26px 40px;min-width:0;height:100vh;overflow-y:auto;
  scrollbar-width:thin;scrollbar-color:var(--line-2) transparent}
.page-head{display:flex;align-items:flex-start;justify-content:space-between;gap:16px;flex-wrap:wrap;margin-bottom:20px}
.page-head h2{font-size:23px;font-weight:700;letter-spacing:-.035em}
.page-head .desc{color:var(--muted);font-size:13px;margin-top:4px;max-width:70ch}
.head-actions{display:flex;gap:8px;flex-wrap:wrap}
.view{display:none}
.view.active{display:block;animation:fade .22s ease}
@keyframes fade{from{opacity:0;transform:translateY(6px)}to{opacity:1;transform:none}}

/* ── Topbar: punch clock + notifications bell ─────────── */
.topbar{display:flex;align-items:center;gap:12px;margin-bottom:16px}

/* The Login / Logout control. It reads as a clock rather than a form field:
   the number is the thing being watched, the button next to it is the whole
   interaction. A green rail while the clock is running says "you are in"
   from across the room. */
.punch-mini{
  display:flex;align-items:center;gap:12px;padding:7px 8px 7px 14px;
  background:var(--card);border:1px solid var(--line);border-radius:99px;
  position:relative;overflow:hidden;
}
.punch-mini::before{
  content:'';position:absolute;left:0;top:0;bottom:0;width:3px;background:var(--line-2);
}
.punch-mini.live::before{background:var(--green)}
.punch-mini.done::before{background:var(--accent)}
.pm-read{display:flex;flex-direction:column;line-height:1.25;text-align:right}
.pm-read b{font-size:14.5px;font-weight:700;letter-spacing:-.02em;font-variant-numeric:tabular-nums}
.pm-read small{font-size:10.5px;color:var(--muted);white-space:nowrap}
.punch-mini.live .pm-read b{color:var(--green)}
.punch-mini .btn{flex:none;border-radius:99px}
.notif-wrap{position:relative}
.notif-bell{
  position:relative;display:grid;place-items:center;width:38px;height:38px;border-radius:99px;
  border:1px solid var(--line-2);background:var(--card);color:var(--muted);cursor:pointer;transition:.15s;
}
.notif-bell:hover{border-color:var(--accent);color:var(--accent-2)}
.notif-bell svg{width:18px;height:18px}
.notif-badge{
  position:absolute;top:-4px;right:-4px;min-width:17px;height:17px;padding:0 4px;border-radius:99px;
  background:#ef4444;color:#fff;font-size:10px;font-weight:700;display:grid;place-items:center;
  line-height:1;box-shadow:0 0 0 2px var(--bg-2);
}
.notif-panel{
  position:absolute;top:46px;right:0;width:330px;max-height:420px;overflow-y:auto;z-index:60;
  background:var(--card);border:1px solid var(--line);border-radius:14px;box-shadow:var(--shadow);
  display:none;flex-direction:column;
}
.notif-panel.open{display:flex}
.notif-head{padding:13px 16px;border-bottom:1px solid var(--line);font-weight:650;font-size:13px}
.notif-list{padding:6px}
.notif-item{padding:9px 10px;border-radius:9px;display:flex;gap:9px;align-items:flex-start}
.notif-item:hover{background:var(--card-2)}
.notif-item .ni-dot{
  flex:none;width:8px;height:8px;border-radius:99px;margin-top:5px;background:var(--accent);
}
.notif-item .ni-title{font-size:12.5px;font-weight:600}
.notif-item .ni-meta{font-size:11px;color:var(--faint);margin-top:2px}
.notif-foot{padding:10px 16px;border-top:1px solid var(--line);text-align:center}
.notif-foot a{font-size:12px;font-weight:600}
.notif-list .empty{padding:22px 10px;text-align:center;color:var(--faint);font-size:12.5px}

/* ── Controls ──────────────────────────────────────── */
.btn{
  display:inline-flex;align-items:center;gap:7px;padding:8px 15px;border-radius:var(--radius-sm);
  border:1px solid var(--line-2);background:var(--card);color:var(--txt);
  cursor:pointer;font-weight:550;transition:.15s;white-space:nowrap;
  box-shadow:var(--shadow-sm);
}
.btn:hover{border-color:var(--accent);color:var(--accent-2)}
/* A button that has been pressed says so — a 1px drop is enough and reads
   instantly on a touchscreen, where there is no hover to fall back on. */
.btn:active{transform:translateY(1px)}
.btn.primary{
  background:var(--accent-grad);border-color:transparent;color:#fff;
  box-shadow:0 6px 18px -8px rgba(99,102,241,.85);
}
.btn.primary:hover{filter:brightness(1.09);color:#fff;border-color:transparent}
.btn.danger{color:var(--red);border-color:rgba(239,68,68,.35)}
.btn.danger:hover{background:rgba(239,68,68,.12);border-color:var(--red);color:var(--red)}
.btn.warn{background:var(--amber);border-color:var(--amber);color:#1a1204}
.btn.warn:hover{filter:brightness(1.08);color:#1a1204}
.btn.sm{padding:5px 10px;font-size:12.5px}
.btn.ghost{background:transparent}
.btn:disabled{opacity:.55;cursor:not-allowed}
/* `.btn` sets display:inline-flex, which outranks the browser's own rule for
   the `hidden` attribute — without this, a hidden button still takes space. */
[hidden]{display:none !important}

.field{margin-bottom:14px}
.field label{display:block;font-size:12px;font-weight:600;color:var(--muted);margin-bottom:6px}
.input,select.input,textarea.input{
  width:100%;padding:10px 13px;border-radius:var(--radius-sm);
  border:1px solid var(--line-2);background:var(--bg);color:var(--txt);outline:none;transition:.15s;
}
.input:hover:not(:disabled){border-color:var(--faint)}
.input:focus{border-color:var(--accent);box-shadow:var(--ring)}
textarea.input{resize:vertical;min-height:72px}

/* ── Selects ───────────────────────────────────────────────────────
   The native arrow is dropped for one that follows the theme, and the
   right padding reserves its space so a long label never runs under it. */
select.input{
  appearance:none;-webkit-appearance:none;-moz-appearance:none;
  padding-right:34px;cursor:pointer;max-width:100%;
  text-overflow:ellipsis;
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%238b93ad' stroke-width='2.4' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='6 9 12 15 18 9'/%3E%3C/svg%3E");
  background-repeat:no-repeat;
  background-position:right 11px center;
  background-size:15px 15px;
}
[data-theme="light"] select.input{
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%235f6880' stroke-width='2.4' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='6 9 12 15 18 9'/%3E%3C/svg%3E");
}
select.input:hover{border-color:var(--line-2)}
select.input:disabled{opacity:.55;cursor:not-allowed}
/* Firefox keeps its own highlight on the closed field; this clears it. */
select.input:-moz-focusring{color:transparent;text-shadow:0 0 0 var(--txt)}
/* Windows Chrome/Edge and Firefox paint each row from the option's own
   colours, so they have to be stated — inheriting from the select is not
   enough and is what made the list look blank. */
select.input option,
select.input optgroup{
  background-color:var(--card);
  color:var(--txt);
}
select.input optgroup{font-weight:650;color:var(--muted)}
select.input option:disabled{color:var(--faint)}

/* Compact select used inside table rows. Replaces the inline padding that
   used to sit on these, which left no room for the arrow. */
select.input.sel-inline{padding:5px 30px 5px 9px;font-size:12.5px;background-position:right 8px center;background-size:13px 13px}
.grid-2{display:grid;grid-template-columns:1fr 1fr;gap:0 14px}
.hint{font-size:11.5px;color:var(--faint);margin-top:5px}

/* Country-code select beside a phone number input — the select keeps a
   fixed width for its dial code, the number field claims the rest. */
.phone-row{display:flex;gap:8px}
.phone-row select.input{flex:0 0 150px}
.phone-row input.input{flex:1;min-width:0}
@media (max-width:480px){
  .phone-row{flex-wrap:wrap}
  .phone-row select.input{flex:1 1 100%}
  .phone-row input.input{flex:1 1 100%}
}

.card{background:var(--card);border:1px solid var(--line);border-radius:var(--radius);padding:20px;
  box-shadow:var(--shadow-sm)}
.card h3{font-size:14.5px;font-weight:640;margin-bottom:14px;letter-spacing:-.01em}
.toolbar{display:flex;gap:8px;flex-wrap:wrap;align-items:center;margin-bottom:16px}
.toolbar .input{width:auto;min-width:150px}
.spacer{flex:1}

/* ── Stat cards ────────────────────────────────────── */
.stats{display:grid;grid-template-columns:repeat(auto-fit,minmax(172px,1fr));gap:12px;margin-bottom:18px}
.stat{background:var(--card);border:1px solid var(--line);border-radius:var(--radius);
  padding:16px 18px;position:relative;overflow:hidden;box-shadow:var(--shadow-sm);transition:.16s}
.stat:hover{border-color:var(--line-2);transform:translateY(-1px)}
.stat::after{content:'';position:absolute;inset:0 auto 0 0;width:3px;background:var(--accent-grad)}
/* A wash of the accent in the far corner, so a row of stat cards has some
   depth to it instead of reading as four grey boxes. */
.stat::before{content:'';position:absolute;right:-40px;top:-40px;width:120px;height:120px;
  border-radius:50%;background:var(--accent-soft);opacity:.55;pointer-events:none}
.stat .k{font-size:10.5px;text-transform:uppercase;letter-spacing:.08em;color:var(--faint);font-weight:650}
.stat .v{font-size:26px;font-weight:750;letter-spacing:-.035em;margin-top:6px;
  font-variant-numeric:tabular-nums;position:relative}
.stat .m{font-size:11.5px;color:var(--muted);margin-top:3px;position:relative}

/* ── Kanban ────────────────────────────────────────── */
.board{display:flex;gap:13px;overflow-x:auto;padding-bottom:14px;padding-right:4px;align-items:flex-start}
.col{
  flex:0 0 272px;background:var(--bg-2);border:1px solid var(--line);
  border-radius:var(--radius);display:flex;flex-direction:column;max-height:calc(100vh - 250px);
}
.col.drag-over{border-color:var(--accent);background:var(--accent-soft);box-shadow:0 0 0 3px var(--accent-soft)}
.col-head{padding:12px 13px;border-bottom:1px solid var(--line);display:flex;align-items:center;gap:8px}
.dot{width:8px;height:8px;border-radius:50%;flex:0 0 8px}
.col-head b{font-size:12.5px;font-weight:640;flex:1;letter-spacing:-.01em}
.pill{background:var(--card-2);color:var(--muted);border-radius:99px;padding:2px 8px;font-size:11px;font-weight:650}
.col-sum{padding:0 13px 9px;font-size:11.5px;color:var(--green);font-weight:600}
.col-body{padding:10px;display:flex;flex-direction:column;gap:9px;overflow-y:auto;min-height:80px}
.kcard{
  background:var(--card);border:1px solid var(--line);border-radius:11px;padding:11px 12px;
  cursor:grab;transition:.15s;border-left:3px solid var(--accent);
}
.kcard:hover{border-color:var(--line-2);transform:translateY(-1px);box-shadow:var(--shadow)}
.kcard.dragging{opacity:.4;cursor:grabbing}
.kcard .t{font-weight:620;font-size:13.5px;letter-spacing:-.01em;margin-bottom:5px;word-break:break-word}
.kcard .meta{display:flex;flex-direction:column;gap:3px;font-size:11.5px;color:var(--muted)}
.kcard .meta span{display:flex;align-items:center;gap:5px;word-break:break-all}
.kcard .amt{color:var(--green);font-weight:700;font-size:13px;margin-top:6px}
.kcard .who-tag{display:inline-block;margin-top:7px;font-size:10.5px;background:var(--accent-soft);
  color:var(--accent-2);padding:2px 7px;border-radius:99px;font-weight:600}
.kcard .owner-tag{margin-left:5px;background:rgba(100,116,139,.14);color:var(--muted)}
.kcard .assign-tag{margin-left:5px;background:rgba(34,197,94,.14);color:#4ade80}
.col-empty{color:var(--faint);font-size:12px;text-align:center;padding:18px 8px;border:1px dashed var(--line-2);border-radius:10px}

/* ── Table ─────────────────────────────────────────── */
.tbl-wrap{overflow-x:auto;border:1px solid var(--line);border-radius:var(--radius);
  background:var(--card);box-shadow:var(--shadow-sm)}
table{width:100%;border-collapse:collapse;font-size:13px}
th{
  text-align:left;padding:12px 14px;font-size:10.5px;text-transform:uppercase;letter-spacing:.08em;
  color:var(--faint);font-weight:700;border-bottom:1px solid var(--line);background:var(--card-2);white-space:nowrap;
}
td{padding:11px 14px;border-bottom:1px solid var(--line);vertical-align:middle}
tbody tr:last-child td{border-bottom:none}
tbody tr:hover{background:var(--card-2)}
.empty{padding:44px 20px;text-align:center;color:var(--faint)}

.badge{display:inline-block;padding:3px 9px;border-radius:99px;font-size:11px;font-weight:650;white-space:nowrap}
.b-new{background:rgba(139,147,173,.16);color:#a7aec6}
.b-interested{background:rgba(6,182,212,.16);color:#22d3ee}
.b-followup{background:rgba(245,158,11,.16);color:#fbbf24}
.b-demo_scheduled{background:rgba(99,102,241,.18);color:#a5b4fc}
.b-demo_done{background:rgba(168,85,247,.18);color:#c084fc}
.b-demo_reschedule{background:rgba(236,72,153,.18);color:#f472b6}
.b-converted{background:rgba(34,197,94,.18);color:#4ade80}
.b-junk{background:rgba(239,68,68,.16);color:#f87171}
.b-holiday{background:rgba(20,184,166,.16);color:#2dd4bf}
.b-event{background:rgba(99,102,241,.16);color:#a5b4fc}

/* Attendance day states + leave workflow */
.b-present{background:rgba(34,197,94,.18);color:#4ade80}
.b-half_day{background:rgba(245,158,11,.16);color:#fbbf24}
.b-leave{background:rgba(6,182,212,.16);color:#22d3ee}
.b-absent{background:rgba(239,68,68,.16);color:#f87171}
.b-week_off{background:rgba(139,147,173,.16);color:#a7aec6}
.b-pending{background:rgba(245,158,11,.16);color:#fbbf24}
.b-approved{background:rgba(34,197,94,.18);color:#4ade80}
.b-rejected{background:rgba(239,68,68,.16);color:#f87171}

/* ── Status colours on the light theme ─────────────────────────────
   Every badge, tag and chip above is coloured for a near-black page: pale
   inks that glow on dark and wash out on white. The light theme restates
   the ink at full strength against the same tint, so a badge is as easy to
   read on a laptop in an office as on a phone at night. */
[data-theme="light"]{
  --ink-grey:#4b5473; --ink-cyan:#0e7490; --ink-amber:#b45309; --ink-indigo:#4338ca;
  --ink-violet:#7e22ce; --ink-pink:#be185d; --ink-green:#15803d; --ink-red:#b91c1c;
  --ink-teal:#0f766e;
}
[data-theme="light"] .b-new,
[data-theme="light"] .b-week_off,
[data-theme="light"] .st-cancel,
[data-theme="light"] .p-low{color:var(--ink-grey)}
[data-theme="light"] .b-interested,
[data-theme="light"] .st-await,
[data-theme="light"] .b-leave{color:var(--ink-cyan)}
[data-theme="light"] .b-followup,
[data-theme="light"] .b-half_day,
[data-theme="light"] .b-pending,
[data-theme="light"] .st-late,
[data-theme="light"] .badge.d-rescheduled{color:var(--ink-amber)}
[data-theme="light"] .b-demo_scheduled,
[data-theme="light"] .b-event,
[data-theme="light"] .st-open,
[data-theme="light"] .p-normal{color:var(--ink-indigo)}
[data-theme="light"] .b-demo_done{color:var(--ink-violet)}
[data-theme="light"] .b-demo_reschedule{color:var(--ink-pink)}
[data-theme="light"] .b-converted,
[data-theme="light"] .b-present,
[data-theme="light"] .b-approved,
[data-theme="light"] .st-ontime,
[data-theme="light"] .badge.d-done{color:var(--ink-green)}
[data-theme="light"] .b-junk,
[data-theme="light"] .b-absent,
[data-theme="light"] .b-rejected,
[data-theme="light"] .st-reject,
[data-theme="light"] .st-overdue,
[data-theme="light"] .p-high,
[data-theme="light"] .badge.d-cancelled{color:var(--ink-red)}
[data-theme="light"] .b-holiday{color:var(--ink-teal)}

/* ── Punch card ────────────────────────────────────── */
.punch{display:flex;align-items:center;gap:18px;flex-wrap:wrap}
.punch-now{flex:1;min-width:190px}
.punch-now .t{font-size:27px;font-weight:700;letter-spacing:-.03em}
.punch-now .d{font-size:12.5px;color:var(--muted);margin-top:2px}
.punch-state{display:flex;gap:22px;flex-wrap:wrap}
.punch-state div{font-size:12px}
.punch-state b{display:block;font-size:15px;font-weight:680;margin-top:3px}
.punch .btn.lg{padding:12px 26px;font-size:14px;font-weight:650}
.geo-note{font-size:11.5px;color:var(--faint);margin-top:10px;width:100%}

/* ── Modal ─────────────────────────────────────────── */
.modal-bg{
  position:fixed;inset:0;background:rgba(4,6,11,.72);backdrop-filter:blur(6px);
  display:none;place-items:center;padding:20px;z-index:80;
}
.modal-bg.open{display:grid}
.modal{
  background:var(--card);border:1px solid var(--line);border-radius:20px;
  width:100%;max-width:500px;max-height:88vh;overflow-y:auto;box-shadow:var(--shadow-lg);
  animation:pop .22s cubic-bezier(.2,.8,.25,1);
}
.modal.wide{max-width:780px}
@keyframes pop{from{opacity:0;transform:scale(.96) translateY(10px)}to{opacity:1;transform:none}}
/* The title bar rides with the content when a tall dialog scrolls, so the
   close button is always in reach. */
.modal-head{padding:18px 22px;border-bottom:1px solid var(--line);display:flex;align-items:center;
  justify-content:space-between;position:sticky;top:0;background:var(--card);z-index:2;border-radius:20px 20px 0 0}
.modal-head h3{font-size:16.5px;font-weight:680;letter-spacing:-.02em}
.x{background:none;border:none;color:var(--faint);cursor:pointer;font-size:22px;line-height:1;padding:0 4px}
.x:hover{color:var(--txt)}
.modal-body{padding:20px 22px}
.modal-foot{padding:14px 22px;border-top:1px solid var(--line);display:flex;justify-content:flex-end;gap:8px}

/* ── Bars / misc ───────────────────────────────────── */
.bars{display:flex;flex-direction:column;gap:10px}
.bar-row{display:grid;grid-template-columns:130px 1fr auto;gap:11px;align-items:center;font-size:12.5px}
.bar-track{height:8px;background:var(--bg);border-radius:99px;overflow:hidden}
.bar-fill{height:100%;border-radius:99px;background:linear-gradient(90deg,var(--accent),var(--cyan));transition:width .5s ease}
.bar-row .val{font-weight:650;font-variant-numeric:tabular-nums;color:var(--muted)}
.two-col{display:grid;grid-template-columns:1fr 1fr;gap:14px}
/* Without this, a wide table in one column (e.g. Recently added) forces its
   grid track past its fair 1fr share and starves the other column — the
   table already scrolls internally via .tbl-wrap, it doesn't need to. */
.two-col>*{min-width:0}
.status-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(130px,1fr));gap:10px}
/* ── Daily tasks: derived state, priority, badges ──── */
.state-tag{display:inline-block;padding:3px 9px;border-radius:99px;font-size:11px;font-weight:650;white-space:nowrap}
.st-open{background:rgba(99,102,241,.16);color:#a5b4fc}
.st-overdue{background:rgba(239,68,68,.18);color:#f87171}
.st-ontime{background:rgba(34,197,94,.16);color:#4ade80}
.st-late{background:rgba(245,158,11,.18);color:#fbbf24}
.st-cancel{background:rgba(139,147,173,.14);color:#a7aec6}
/* Waiting on a reviewer — finished, but not yet counted. */
.st-await{background:rgba(56,189,248,.16);color:#7dd3fc}
.st-reject{background:rgba(239,68,68,.16);color:#f87171}

.prio{display:inline-block;padding:2px 8px;border-radius:6px;font-size:10.5px;font-weight:650;
  text-transform:uppercase;letter-spacing:.04em}
.p-high{background:rgba(239,68,68,.16);color:#f87171}
.p-normal{background:rgba(99,102,241,.14);color:#a5b4fc}
.p-low{background:rgba(139,147,173,.14);color:#a7aec6}

tr.row-overdue{background:rgba(239,68,68,.05)}
tr.row-overdue td:first-child{box-shadow:inset 3px 0 0 rgba(239,68,68,.6)}

.badge-chip{display:inline-flex;flex-direction:column;gap:1px;margin:0 6px 6px 0;padding:6px 11px;
  background:var(--accent-soft);color:var(--accent-2);border-radius:9px;font-size:12px;font-weight:650}
.badge-chip small{font-weight:500;font-size:10px;color:var(--faint)}
.badge-chip.sm{display:inline-block;padding:3px 8px;font-size:10.5px;margin:0 4px 4px 0;cursor:pointer}

/* ── Money in / out ────────────────────────────────────────────────
   One pair of tones used everywhere a figure has a direction, so the P&L,
   the expense sheet and the profit stat all read the same way. */
.m-in{color:var(--green);font-variant-numeric:tabular-nums}
.m-out{color:var(--red);font-variant-numeric:tabular-nums}
.cat-dot{display:inline-block;width:8px;height:8px;border-radius:50%;margin-right:7px;
  vertical-align:middle;flex:0 0 8px}
/* The accent stripe on .stat, recoloured to match what the number means. */
.stat.good::after{background:var(--green)}
.stat.bad::after{background:var(--red)}
.stat.warn::after{background:var(--amber)}

/* ── Targets & incentives ──────────────────────────────────────────── */
.tgt{background:var(--card);border:1px solid var(--line);border-radius:var(--radius);
  padding:16px 18px;margin-bottom:12px}
.tgt-head{display:flex;align-items:flex-start;gap:12px;flex-wrap:wrap}
.tgt-head h4{font-size:14.5px;font-weight:640}
.tgt-head .hint{margin-top:2px}
.tgt-figs{margin-left:auto;text-align:right;white-space:nowrap}
.tgt-figs b{font-size:18px;font-weight:700;letter-spacing:-.02em;font-variant-numeric:tabular-nums}
/* Taller than .bar-track: this is the headline of the card, not a row in a list. */
.prog{height:10px;background:var(--bg);border-radius:99px;overflow:hidden;margin:12px 0 8px}
.prog-fill{height:100%;border-radius:99px;transition:width .5s ease;
  background:linear-gradient(90deg,var(--accent),var(--cyan))}
.prog-fill.behind{background:linear-gradient(90deg,#ef4444,#f59e0b)}
.prog-fill.close{background:linear-gradient(90deg,#f59e0b,#facc15)}
.prog-fill.hit{background:linear-gradient(90deg,#16a34a,#4ade80)}
.inc-list{margin-top:12px;border-top:1px dashed var(--line);padding-top:10px;
  display:flex;flex-direction:column;gap:7px}
.inc-row{display:flex;align-items:center;gap:10px;font-size:12.5px;flex-wrap:wrap}
.inc-row .rule{color:var(--muted);min-width:0}
.inc-row .pay{margin-left:auto;font-weight:650;font-variant-numeric:tabular-nums;white-space:nowrap}
.inc-row.locked{opacity:.62}

/* ── Billing: client sheet, inventory, quotation builder ─────────── */
.ar{text-align:right}
.ac{text-align:center}
td.ar{text-align:right}
td.ac{text-align:center}

.api-no{font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-size:11.5px;
  background:var(--accent-soft);color:var(--accent-2);padding:2px 7px;border-radius:5px}

.doc-row{display:flex;gap:10px;align-items:center;padding:10px 0;border-bottom:1px solid var(--line)}
.doc-row:last-child{border-bottom:none}
.doc-row a{color:var(--accent-2);text-decoration:none}
.doc-row a:hover{text-decoration:underline}

/* ── Integrations ────────────────────────────────────────────────── */
.ig-tabs{display:flex;gap:6px;flex-wrap:wrap;margin-bottom:16px}
.ig-card{
  background:var(--card);border:1px solid var(--line);border-radius:12px;
  padding:15px;margin-bottom:12px;
}
.ig-card-head{display:flex;justify-content:space-between;align-items:flex-start;gap:12px;
  margin-bottom:11px}
.ig-card-head b{font-size:14px}
.ig-card .dot{width:9px;height:9px;border-radius:50%;flex:none}

/* ── Module permission toggles ───────────────────────────────────── */
.perm-row{
  display:flex;gap:11px;align-items:flex-start;padding:13px;margin-bottom:9px;cursor:pointer;
  border:1px solid var(--line);border-radius:10px;transition:.15s;
}
.perm-row:hover{border-color:var(--accent)}
.perm-row input{margin-top:2px;flex:none}
.perm-row b{display:block;font-size:13.5px;font-weight:650}
.perm-row small{display:block;font-size:11.5px;color:var(--muted);margin-top:2px}
/* Rights and modules are two different kinds of grant, so they get two
   labelled blocks rather than one undifferentiated column of checkboxes. */
.perm-sec + .perm-sec{margin-top:20px;padding-top:18px;border-top:1px solid var(--line)}
.perm-sec h4{margin:0 0 4px;font-size:12px;font-weight:700;letter-spacing:.07em;
  text-transform:uppercase;color:var(--muted)}
.perm-sec .hint{margin:0 0 12px}

/* ── Demo calendar ────────────────────────────────────────────────
   A month as a seven-column grid. Cells keep a minimum height so an empty
   week does not collapse and make the month a different shape each time. */
.cal{display:grid;grid-template-columns:repeat(7,minmax(0,1fr));gap:1px;background:var(--line);
  border-radius:var(--radius);overflow:hidden}
.cal-dow{background:var(--bg-2);padding:9px 10px;font-size:11px;font-weight:700;
  letter-spacing:.06em;text-transform:uppercase;color:var(--muted);text-align:center}
.cal-day{background:var(--card);min-height:104px;padding:7px 7px 9px;display:flex;
  flex-direction:column;gap:4px}
.cal-day.out{background:var(--bg-2);opacity:.5}
.cal-day.today{box-shadow:inset 0 0 0 2px var(--accent)}
.cal-n{font-size:11.5px;font-weight:700;color:var(--muted);margin-bottom:1px}
.cal-day.today .cal-n{color:var(--accent-2)}
.cal-chip{
  display:block;width:100%;text-align:left;border:none;border-left:3px solid currentColor;
  border-radius:6px;padding:4px 6px;font-size:11px;line-height:1.35;cursor:pointer;
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis;
  background:var(--card-2);color:var(--txt);transition:.13s;
}
.cal-chip:hover{background:var(--accent-soft)}
.cal-chip b{font-variant-numeric:tabular-nums;font-weight:700;margin-right:3px}
.cal-more{font-size:10.5px;color:var(--faint);padding-left:3px}

/* Status colours, shared by the calendar chips and the table badges. */
.cal-chip.d-scheduled{border-left-color:var(--accent)}
.cal-chip.d-rescheduled{border-left-color:var(--amber)}
.cal-chip.d-done{border-left-color:var(--green)}
.cal-chip.d-cancelled{border-left-color:var(--red);text-decoration:line-through;opacity:.65}
.cal-chip.d-noshow{border-left-color:var(--faint);opacity:.7}

.badge.d-scheduled{background:var(--accent-soft);color:var(--accent-2)}
.badge.d-rescheduled{background:rgba(245,158,11,.16);color:#fbbf24}
.badge.d-done{background:rgba(34,197,94,.16);color:#4ade80}
.badge.d-cancelled{background:rgba(239,68,68,.15);color:#f87171}
.badge.d-noshow{background:rgba(139,147,173,.16);color:var(--muted)}

/* One demo's history — what moved, when, and who said so. */
.dm-hist{display:flex;flex-direction:column;gap:1px;background:var(--line);
  border:1px solid var(--line);border-radius:var(--radius-sm);overflow:hidden}
.dm-h{display:grid;grid-template-columns:auto 1fr;gap:11px;padding:10px 12px;background:var(--card)}
.dm-h b{font-size:13px;font-weight:600}

/* ── Sheet column mapping ─────────────────────────────── */
.map-head{display:flex;align-items:center;justify-content:space-between;gap:10px;margin-bottom:6px}
.map-extra{margin-top:14px;padding-top:14px;border-top:1px solid var(--line)}
.map-extra-h{font-size:12px;font-weight:700;letter-spacing:.06em;text-transform:uppercase;
  color:var(--muted);margin-bottom:4px}
.map-col{display:flex;gap:10px;align-items:flex-start;padding:8px 10px;border-radius:9px;cursor:pointer}
.map-col:hover{background:var(--card-2)}
.map-col input{margin-top:3px;flex:none}
.map-col b{font-size:13px;font-weight:600;display:block}
.map-col small{display:block;font-size:11.5px;color:var(--faint);margin-top:1px}

/* ── One lead, in full ────────────────────────────────── */
.lead-view{display:flex;flex-direction:column;gap:1px;background:var(--line);
  border:1px solid var(--line);border-radius:var(--radius-sm);overflow:hidden}
.lv-row{display:grid;grid-template-columns:minmax(110px,34%) 1fr;gap:12px;
  padding:10px 13px;background:var(--card);align-items:baseline}
.lv-row > span{font-size:11.5px;color:var(--muted);font-weight:600;
  text-transform:uppercase;letter-spacing:.04em}
.lv-row > div{font-size:13.5px;word-break:break-word}

/* The lead's own name opens it, so View is reachable straight from the name
   as well as from the button at the end of the row. */
.lead-open{color:inherit;text-decoration:none;border-bottom:1px dotted var(--muted)}
.lead-open:hover{color:var(--accent);border-bottom-color:var(--accent)}

/* Range bar: Today / This week / This month / Last month / Custom */
.range-bar{gap:6px}
.range-bar .btn{flex:none}

/* ── Floating WhatsApp support button (partners) ─────────────────── */
.wa-fab{
  position:fixed;right:22px;bottom:22px;z-index:150;display:inline-flex;align-items:center;gap:9px;
  padding:12px 18px;border-radius:99px;background:#25d366;color:#fff;text-decoration:none;
  font-size:13.5px;font-weight:700;box-shadow:0 8px 24px rgba(37,211,102,.36);
  transition:.15s;
}
.wa-fab:hover{transform:translateY(-2px);box-shadow:0 12px 30px rgba(37,211,102,.46)}
.wa-fab svg{width:21px;height:21px;flex:none}
@media (max-width:640px){
  .wa-fab{right:14px;bottom:14px;padding:13px}
  .wa-fab span{display:none}
}

/* ── Client credentials ─────────────────────────────────────────── */
.cred-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(260px,1fr));gap:12px}
.cred-card{
  background:var(--card);border:1px solid var(--line);border-radius:12px;padding:14px;
  cursor:pointer;transition:.15s;display:flex;flex-direction:column;gap:10px;min-height:132px;
}
.cred-card:hover{border-color:var(--accent);transform:translateY(-1px)}
.cred-card.archived{opacity:.5}
.cc-head{display:flex;gap:8px;align-items:flex-start;justify-content:space-between}
.cc-head b{font-size:13.5px;display:block;overflow:hidden;text-overflow:ellipsis}
.cc-n{
  flex:none;min-width:24px;height:24px;border-radius:99px;background:var(--accent-soft);
  color:var(--accent-2);font-size:11.5px;font-weight:700;display:grid;place-items:center;padding:0 7px;
}
.cc-tags{display:flex;flex-wrap:wrap;gap:4px;flex:1;align-content:flex-start}
.cc-tag{
  font-size:10.5px;font-weight:600;padding:2px 7px;border-radius:5px;
  background:rgba(139,147,173,.14);color:var(--muted);white-space:nowrap;
}
.cc-foot{display:flex;justify-content:space-between;align-items:center;
  border-top:1px solid var(--line);padding-top:9px}
.cc-open{font-size:11.5px;font-weight:650;color:var(--accent-2)}

/* View dialog */
.cv-row{border:1px solid var(--line);border-radius:10px;padding:11px 13px;margin-bottom:9px}
.cv-head{display:flex;gap:7px;align-items:baseline;margin-bottom:7px;flex-wrap:wrap}
.cv-link{font-size:11px;color:var(--accent-2);text-decoration:none}
.cv-f{display:flex;gap:8px;align-items:center;margin-top:4px;flex-wrap:wrap}
.cv-k{font-size:10.5px;text-transform:uppercase;letter-spacing:.06em;color:var(--faint);min-width:66px}
.cv-v{
  font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-size:12px;
  background:rgba(139,147,173,.12);padding:3px 8px;border-radius:5px;
  word-break:break-all;flex:1;min-width:0;
}
.cv-v.masked{letter-spacing:2px;color:var(--faint)}

/* Edit dialog: one block per platform */
.cr-block{border:1px solid var(--line);border-radius:10px;padding:11px;margin-bottom:9px;
  background:rgba(139,147,173,.04)}
.cr-block-head{display:grid;grid-template-columns:26px 1fr 1fr 32px;gap:6px;align-items:center}
.cr-num{
  width:22px;height:22px;border-radius:99px;background:var(--accent-soft);color:var(--accent-2);
  font-size:11px;font-weight:700;display:grid;place-items:center;
}
.cr-block-body{display:grid;grid-template-columns:1fr 1fr;gap:6px;margin-top:7px}
.cr-block .input{padding:7px 9px;font-size:12.5px}
.cr-pw{display:flex;gap:5px}
.cr-pw .input{flex:1;min-width:0}
@media (max-width:760px){
  .cr-block-head{grid-template-columns:26px 1fr 32px}
  .cr-block-head .input:nth-of-type(2){grid-column:2/4}
  .cr-block-body{grid-template-columns:1fr}
}

/* The WhatsApp update box — monospace keeps the numbered list aligned. */
.summary-box{
  font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;
  font-size:12.5px;line-height:1.7;white-space:pre;overflow-wrap:normal;overflow-x:auto;
}

.qm-h{font-size:11px;text-transform:uppercase;letter-spacing:.08em;color:var(--muted);
  margin:18px 0 8px;padding-top:12px;border-top:1px solid var(--line)}

/* A sample payload shown inside a modal. Scrolls sideways rather than
   wrapping — a folded JSON key is harder to read than a scrollbar. */
.code-blk{
  font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;
  font-size:11.5px;line-height:1.55;color:var(--txt);
  background:var(--card-2);border:1px solid var(--line);border-radius:8px;
  padding:10px 12px;margin:0 0 4px;overflow-x:auto;white-space:pre;
}

/* Line-item grid: name | qty | rate | disc% | gst | amount | remove */
.qm-row{display:grid;grid-template-columns:1fr 72px 96px 68px 78px 96px 32px;gap:6px;
  align-items:center;margin-bottom:4px}
.qm-row .input{padding:7px 9px;font-size:12.5px}
.qm-amt{font-size:12.5px;font-weight:650;text-align:right;padding-right:2px;
  overflow:hidden;text-overflow:ellipsis}
.qm-sub{margin-bottom:10px;padding:6px 9px !important;font-size:11.5px !important;
  background:transparent;border-style:dashed}

.qm-totals{border:1px solid var(--line);border-radius:10px;padding:12px 14px;margin:14px 0 4px;
  background:var(--card)}
.qm-totals div{display:flex;justify-content:space-between;padding:4px 0;font-size:12.5px}
.qm-totals .grand{border-top:1px solid var(--line);margin-top:6px;padding-top:9px;
  font-size:15px;font-weight:750}

@media (max-width:820px){
  .qm-row{grid-template-columns:1fr 60px 78px;grid-auto-rows:auto}
  .qm-amt{grid-column:1/-1;text-align:left}
}

.sg-item{background:var(--card);border:1px solid var(--line);border-radius:11px;padding:12px 13px}
.sg-item .n{font-size:20px;font-weight:700;letter-spacing:-.02em}
.sg-item .l{font-size:11.5px;color:var(--muted);margin-top:2px}

.toast{
  position:fixed;bottom:22px;right:22px;z-index:200;display:flex;flex-direction:column;gap:9px;
}
.toast div{
  background:var(--card);border:1px solid var(--line-2);border-left:3px solid var(--accent);
  padding:11px 16px;border-radius:10px;box-shadow:var(--shadow);animation:slide .25s ease;max-width:330px;
  transition:opacity .3s ease;
}
.toast div.err{border-left-color:var(--red)}
.toast div.ok{border-left-color:var(--green)}
@keyframes slide{from{opacity:0;transform:translateX(24px)}to{opacity:1;transform:none}}

.alert{padding:10px 13px;border-radius:10px;font-size:12.5px;margin-bottom:14px}
.alert.err{background:rgba(239,68,68,.12);color:#f87171;border:1px solid rgba(239,68,68,.28)}
.alert.info{background:var(--accent-soft);color:var(--accent-2);border:1px solid rgba(99,102,241,.28)}
.alert.warn{background:rgba(245,158,11,.12);color:#fbbf24;border:1px solid rgba(245,158,11,.3)}
.alert:not(.err):not(.info):not(.warn){background:var(--card);border:1px solid var(--line);color:var(--muted)}
.drop{
  border:2px dashed var(--line-2);border-radius:12px;padding:26px;text-align:center;
  color:var(--muted);cursor:pointer;transition:.15s;
}
.drop:hover,.drop.over{border-color:var(--accent);background:var(--accent-soft);color:var(--accent-2)}

/* ── Mobile top bar and drawer ──────────────────────────────────────
   Both are desktop-invisible; the media query below turns them on. */
.mobile-bar{display:none;align-items:center;gap:10px;padding:10px 12px;
  padding-top:calc(10px + env(safe-area-inset-top));
  background:var(--bg-2);border-bottom:1px solid var(--line);
  position:sticky;top:0;z-index:70;
  /* Frosted, so content scrolling under the bar reads as behind it rather
     than colliding with it. */
  backdrop-filter:saturate(160%) blur(10px);box-shadow:var(--shadow-sm)}
.mb-icon{
  display:grid;place-items:center;width:40px;height:40px;flex:none;border-radius:11px;
  border:1px solid var(--line-2);background:var(--card);color:var(--txt);cursor:pointer;
}
.mb-icon svg{width:20px;height:20px}
.mb-title{display:flex;align-items:center;gap:9px;min-width:0;flex:1}
.mb-title img{width:26px;height:26px;flex:none;object-fit:contain;background:#fff;border-radius:7px;padding:2px}
.mb-title b{font-size:14.5px;font-weight:650;letter-spacing:-.01em;
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.nav-backdrop{
  display:none;position:fixed;inset:0;z-index:110;
  background:rgba(5,7,12,.6);backdrop-filter:blur(2px);
}
.install-float{
  position:fixed;left:16px;bottom:16px;bottom:calc(16px + env(safe-area-inset-bottom));z-index:150;
  box-shadow:0 10px 26px -8px rgba(99,102,241,.7);
}

@media(max-width:900px){
  /* The sidebar becomes an off-canvas drawer. It keeps its labels — a column
     of unlabelled icons is not something anyone can navigate on a phone.

     The explicit rows matter: the drawer is `position:fixed` and so is not a
     grid item, leaving the bar and the main area as the only two rows. Left
     to `auto`, both would stretch to share `min-height` on a short page and
     the top bar would balloon to twice its height. */
  .app{grid-template-columns:1fr;grid-template-rows:auto 1fr;
       height:auto;min-height:100dvh;overflow:visible}
  .mobile-bar{display:flex}
  .notif-panel{width:min(92vw,330px);right:-6px}

  .sidebar{
    position:fixed;top:0;left:0;bottom:0;width:min(84vw,300px);z-index:120;
    height:100dvh;transform:translateX(-102%);transition:transform .22s ease;
    box-shadow:0 0 44px rgba(0,0,0,.55);padding-bottom:calc(18px + env(safe-area-inset-bottom));
  }
  .app.nav-open .sidebar{transform:none}
  .app.nav-open .nav-backdrop{display:block}
  /* The page behind must not scroll while the drawer is open. */
  body.nav-locked{overflow:hidden}

  .main{padding:14px 13px 60px;height:auto;overflow:visible}
  .two-col{grid-template-columns:1fr}
  .page-head{margin-bottom:14px;gap:10px}
  .page-head h2{font-size:18px}
  .page-head .desc{font-size:12px}
  /* Action buttons share the width instead of overflowing off-screen. */
  .head-actions{width:100%}
  .head-actions .btn{flex:1 1 auto;justify-content:center}

  .toolbar{gap:7px}
  .toolbar .input{flex:1 1 150px;min-width:0;width:auto}
  /* A select has to stay wide enough to read its selected option; it wraps
     to the next row rather than shrinking down to a few letters. */
  .toolbar select.input{flex:1 1 165px;min-width:150px}
  .toolbar .btn{flex:0 0 auto}

  .stats{grid-template-columns:1fr 1fr;gap:9px;margin-bottom:14px}
  .stat{padding:13px 14px}
  .stat .v{font-size:20px}
  .status-grid,.sg-item{min-width:0}

  /* The punch clock is the whole reason a staff login opens the app, so on a
     phone it takes the width rather than squeezing into a corner. */
  .topbar{gap:9px}
  .punch-mini{flex:1;justify-content:space-between;padding:9px 10px 9px 15px}
  .pm-read{text-align:left}
  .pm-read b{font-size:16px}
  .punch-mini .btn{min-height:36px;padding:8px 16px}

  /* A seven-column month is unreadable at phone width, so the grid keeps the
     shape of the month but drops to coloured marks — the table underneath is
     where the detail is read. */
  .cal-day{min-height:62px;padding:5px 4px 6px}
  .cal-chip{font-size:0;padding:0;height:6px;border-radius:99px;border-left:none;
    background:currentColor;margin-bottom:3px}
  .cal-chip b{display:none}
  .cal-chip.d-scheduled{color:var(--accent)}
  .cal-chip.d-rescheduled{color:var(--amber)}
  .cal-chip.d-done{color:var(--green)}
  .cal-chip.d-cancelled{color:var(--red)}
  .cal-chip.d-noshow{color:var(--faint)}
  .cal-dow{padding:7px 2px;font-size:9.5px}
  .cal-more{font-size:9px}

  /* Tables keep their shape and scroll sideways, with momentum on iOS. */
  .tbl-wrap{-webkit-overflow-scrolling:touch}
  table{font-size:12.5px}
  th{padding:9px 11px}
  td{padding:9px 11px}

  .board .col{flex:0 0 84vw;max-height:none}
  .card{padding:14px}
  .cred-grid{grid-template-columns:1fr}

  /* Modals become bottom sheets, with the buttons always in reach. */
  .modal-bg{place-items:end center;padding:0}
  .modal{
    max-width:none;border-radius:18px 18px 0 0;max-height:92dvh;
    animation:sheet .22s ease;
  }
  .modal-head{padding:15px 17px;position:sticky;top:0;background:var(--card);z-index:2}
  .modal-body{padding:16px 17px}
  .modal-foot{
    padding:12px 17px;padding-bottom:calc(12px + env(safe-area-inset-bottom));
    position:sticky;bottom:0;background:var(--card);flex-wrap:wrap;
  }
  .modal-foot .btn{flex:1 1 auto;justify-content:center}
  .grid-2{grid-template-columns:1fr}

  .toast{left:12px;right:12px;bottom:12px;bottom:calc(12px + env(safe-area-inset-bottom))}
  .toast div{max-width:none}

  .wa-fab{bottom:calc(14px + env(safe-area-inset-bottom))}
  .install-float{left:12px;bottom:calc(12px + env(safe-area-inset-bottom))}
}
@keyframes sheet{from{opacity:0;transform:translateY(28px)}to{opacity:1;transform:none}}

@media(max-width:560px){
  /* 16px is the threshold below which iOS Safari zooms into a focused field
     and leaves the page scaled — every input has to clear it. */
  .input,select.input,textarea.input{font-size:16px;padding:10px 12px}
  button,input,select,textarea{font-size:16px}
  /* The shorthand above resets the room the arrow needs — restore it, and
     give the field a full touch target. */
  select.input{padding-right:36px;min-height:42px}
  select.input.sel-inline{padding:7px 32px 7px 10px;font-size:15px;min-height:36px}
  .btn{padding:9px 13px;min-height:38px}
  .btn.sm{padding:7px 11px;font-size:13px;min-height:34px}
  .stats{grid-template-columns:1fr 1fr}
  .bar-row{grid-template-columns:96px 1fr auto;font-size:12px}
  /* The card is no longer a raised surface — it sits directly on the panel —
     so it needs no padding of its own here, only a smaller heading. */
  .login-card h1{font-size:22px}
}

/* ══════════════════════════════════════════════════════════════════
   PAYMENTS, PROOF OF WORK, ADJUSTMENT & THE WEEKLY SCORECARD
   Everything below follows the tokens above — no new colours, only new
   arrangements of the ones the rest of the app already uses.
   ══════════════════════════════════════════════════════════════════ */

/* Three cards abreast for the weekly report's Attendance / Work / Sales.
   Collapses to two, then one, at the breakpoints .two-col already uses. */
.three-col{display:grid;grid-template-columns:repeat(3,1fr);gap:14px}
.three-col>*{min-width:0}
@media(max-width:1100px){.three-col{grid-template-columns:1fr 1fr}}
@media(max-width:900px){.three-col{grid-template-columns:1fr}}

/* ── Payment state on a quote ────────────────────────── */
.b-unpaid{background:rgba(139,147,173,.16);color:#a7aec6}
.b-advance{background:rgba(6,182,212,.16);color:#22d3ee}
.b-partial{background:rgba(245,158,11,.16);color:#fbbf24}
.b-paid{background:rgba(34,197,94,.18);color:#4ade80}
.b-correction{background:rgba(168,85,247,.18);color:#c084fc}
[data-theme="light"] .b-unpaid{color:var(--ink-grey)}
[data-theme="light"] .b-advance{color:var(--ink-cyan)}
[data-theme="light"] .b-partial{color:var(--ink-amber)}
[data-theme="light"] .b-paid{color:var(--ink-green)}
[data-theme="light"] .b-correction{color:var(--ink-violet)}

/* A quote's paid/outstanding split, drawn as one bar under the total. */
.pay-bar{height:5px;border-radius:99px;background:var(--line-2);overflow:hidden;margin-top:5px;min-width:64px}
.pay-bar i{display:block;height:100%;background:var(--green);border-radius:99px;transition:width .25s}
.pay-bar.part i{background:var(--amber)}

/* The payment history list inside the quote drawer. */
.pay-row{display:flex;align-items:flex-start;gap:12px;padding:11px 0;border-bottom:1px solid var(--line)}
.pay-row:last-child{border-bottom:0}
.pay-row .amt{font-weight:700;font-variant-numeric:tabular-nums;white-space:nowrap;color:var(--green)}
.pay-row .meta{flex:1;min-width:0;font-size:12px;color:var(--muted);line-height:1.5}
.pay-row .meta b{color:var(--txt);font-weight:600}

/* ── The attendance button in the top bar ────────────── */
/* It now carries up to two actions at once — Break and Logout — so the pill
   grows a second slot rather than the buttons stacking and shifting the bar. */
.pm-actions{display:flex;gap:6px}
.punch-mini.onbreak::before{background:var(--amber)}
.punch-mini.onbreak .pm-read b{color:var(--amber)}
/* The pulsing dot beside a live clock, so "still counting" reads at a glance. */
.pm-read b.tick::after{
  content:'';display:inline-block;width:5px;height:5px;border-radius:99px;
  background:currentColor;margin-left:6px;vertical-align:middle;animation:pmPulse 1.8s infinite;
}
@keyframes pmPulse{0%,100%{opacity:.25}50%{opacity:1}}
@media(max-width:640px){
  /* On a phone the readout is the first thing to go: the button is the point. */
  .punch-mini{padding-left:10px;gap:8px}
  .punch-mini .pm-read small{display:none}
}

/* The timeline of a day: login, breaks, resume, logout. */
.att-timeline{display:flex;flex-direction:column;margin:4px 0}
.att-ev{display:flex;gap:12px;align-items:flex-start;padding:9px 0;position:relative}
.att-ev::before{
  content:'';position:absolute;left:6px;top:22px;bottom:-9px;width:2px;background:var(--line-2);
}
.att-ev:last-child::before{display:none}
.att-ev .dot{
  width:14px;height:14px;border-radius:99px;flex:none;margin-top:3px;
  border:3px solid var(--card);box-shadow:0 0 0 1px var(--line-2);background:var(--muted);
}
.att-ev.k-login .dot{background:var(--green)}
.att-ev.k-logout .dot{background:var(--accent)}
.att-ev.k-break_start .dot{background:var(--amber)}
.att-ev.k-break_end .dot{background:var(--cyan)}
.att-ev .body{flex:1;min-width:0;font-size:12.5px;line-height:1.5}
.att-ev .body b{font-weight:650}
.att-ev .body .sub{font-size:11.5px;color:var(--muted)}
.att-ev img.shot{
  width:44px;height:44px;object-fit:cover;border-radius:9px;border:1px solid var(--line-2);flex:none;
}

/* The selfie preview inside the attendance dialog. */
.cam-wrap{
  position:relative;border-radius:12px;overflow:hidden;background:#000;aspect-ratio:4/3;
  display:grid;place-items:center;
}
.cam-wrap video,.cam-wrap canvas,.cam-wrap img{width:100%;height:100%;object-fit:cover;display:block}
.cam-hint{font-size:12px;color:var(--muted);text-align:center;padding:20px}

/* ── Attendance adjustment ───────────────────────────── */
/* A day changed by hand is marked, so the sheet says which rows are
   people's punches and which are somebody's judgement. */
tr.adjusted td:first-child{box-shadow:inset 3px 0 0 var(--amber)}
.adj-note{font-size:11px;color:var(--muted);margin-top:2px}
.audit-row{display:flex;gap:12px;padding:10px 0;border-bottom:1px solid var(--line);font-size:12.5px}
.audit-row:last-child{border-bottom:0}
.audit-row .when{color:var(--faint);white-space:nowrap;font-size:11.5px;min-width:104px}
.audit-row .what{flex:1;min-width:0;line-height:1.55}
.audit-old{color:var(--red);text-decoration:line-through;opacity:.8}
.audit-new{color:var(--green);font-weight:600}

/* The verb badge on an audit row. Colour carries the meaning at a glance —
   green added, red removed, amber changed — so a page of a few hundred lines
   can be scanned for the deletions without reading any of it. */
.badge.au-add{background:rgba(34,197,94,.16);color:#4ade80}
.badge.au-edit{background:rgba(245,158,11,.18);color:#fbbf24}
.badge.au-del{background:rgba(239,68,68,.18);color:#f87171}
.badge.au-deny{background:rgba(239,68,68,.28);color:#fca5a5}
.badge.au-quiet{background:var(--card-2);color:var(--muted)}

/* Sits under the table, hidden by the markup when everything fits on one
   page, so the frame stays quiet until there is genuinely more to see. */
.au-pager{display:flex;align-items:center;justify-content:space-between;gap:12px;
  padding:12px 16px;border-top:1px solid var(--line)}
.au-pager:empty{display:none}

/* ── Proof of work and the review queue ──────────────── */
.wa-card{
  background:var(--card);border:1px solid var(--line);border-radius:14px;
  padding:15px 17px;margin-bottom:12px;
}
.wa-card.pending{border-left:3px solid var(--amber)}
.wa-card.approved{border-left:3px solid var(--green)}
.wa-card.rejected{border-left:3px solid var(--red)}
.wa-card.correction{border-left:3px solid var(--violet)}
.wa-head{display:flex;align-items:flex-start;gap:12px;flex-wrap:wrap;margin-bottom:10px}
.wa-head .who{font-weight:650;font-size:14px}
.wa-head .spacer{flex:1}
.wa-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(150px,1fr));gap:12px;margin:10px 0}
.wa-grid .cell{background:var(--bg-2);border-radius:10px;padding:9px 11px}
.wa-grid .cell .k{font-size:10.5px;text-transform:uppercase;letter-spacing:.07em;color:var(--faint);font-weight:650}
.wa-grid .cell .v{font-size:13.5px;font-weight:600;margin-top:3px;word-break:break-word}
.wa-proofs{display:flex;gap:8px;flex-wrap:wrap;margin-top:8px}
.wa-proofs a{
  display:block;width:66px;height:66px;border-radius:10px;overflow:hidden;
  border:1px solid var(--line-2);position:relative;background:var(--bg-2);
}
.wa-proofs a img{width:100%;height:100%;object-fit:cover;display:block}
.wa-proofs a.file{display:grid;place-items:center;font-size:10.5px;color:var(--muted);text-align:center;padding:6px}
.wa-actions{display:flex;gap:8px;flex-wrap:wrap;margin-top:12px}

/* ── The weekly scorecard ────────────────────────────── */
.score-wrap{display:flex;align-items:center;gap:26px;flex-wrap:wrap}
.score-ring{
  --pc:0;
  width:118px;height:118px;border-radius:99px;flex:none;display:grid;place-items:center;position:relative;
  background:conic-gradient(var(--accent) calc(var(--pc)*1%),var(--line-2) 0);
}
.score-ring::after{content:'';position:absolute;inset:9px;border-radius:99px;background:var(--card)}
.score-ring .num{position:relative;z-index:1;text-align:center;line-height:1.1}
.score-ring .num b{font-size:29px;font-weight:750;letter-spacing:-.035em}
.score-ring .num small{
  display:block;font-size:10.5px;color:var(--faint);
  text-transform:uppercase;letter-spacing:.08em;font-weight:650;margin-top:2px;
}
.score-ring.good{background:conic-gradient(var(--green) calc(var(--pc)*1%),var(--line-2) 0)}
.score-ring.warn{background:conic-gradient(var(--amber) calc(var(--pc)*1%),var(--line-2) 0)}
.score-ring.poor{background:conic-gradient(var(--red) calc(var(--pc)*1%),var(--line-2) 0)}
.score-parts{flex:1;min-width:230px;display:flex;flex-direction:column;gap:11px}
.score-part .lbl{display:flex;justify-content:space-between;font-size:12.5px;margin-bottom:4px}
.score-part .lbl b{font-variant-numeric:tabular-nums}
.score-part .track{height:7px;border-radius:99px;background:var(--line-2);overflow:hidden}
.score-part .track i{display:block;height:100%;border-radius:99px;background:var(--accent);transition:width .3s}
.score-part.good .track i{background:var(--green)}
.score-part.warn .track i{background:var(--amber)}
.score-part.poor .track i{background:var(--red)}
.score-delta{font-size:12px;font-weight:600}
.score-delta.up{color:var(--green)}
.score-delta.down{color:var(--red)}

/* ── The permissions matrix ──────────────────────────── */
.perm-group{border:1px solid var(--line);border-radius:12px;margin-bottom:12px;overflow:hidden}
.perm-group>summary{
  padding:11px 14px;cursor:pointer;font-weight:650;font-size:13.5px;background:var(--bg-2);
  display:flex;align-items:center;gap:10px;list-style:none;
}
.perm-group>summary::-webkit-details-marker{display:none}
.perm-group>summary::before{content:'\25B8';color:var(--muted);transition:.15s;font-size:11px}
.perm-group[open]>summary::before{transform:rotate(90deg)}
.perm-group>summary .count{
  margin-left:auto;font-size:11px;font-weight:600;color:var(--muted);
  background:var(--card);border:1px solid var(--line-2);border-radius:99px;padding:2px 9px;
}
.perm-res{
  display:flex;gap:12px;flex-wrap:wrap;align-items:flex-start;
  padding:11px 14px;border-top:1px solid var(--line);
}
.perm-res .rname{width:190px;flex:none;font-size:12.5px;line-height:1.45}
.perm-res .rname b{font-weight:650;display:block}
.perm-res .rname small{color:var(--faint);font-size:11px}
.perm-acts{display:flex;gap:6px;flex-wrap:wrap;flex:1;min-width:200px}
.perm-chk{
  display:inline-flex;align-items:center;gap:5px;padding:4px 10px;border-radius:99px;
  border:1px solid var(--line-2);font-size:11.5px;cursor:pointer;user-select:none;
  background:var(--bg-2);transition:.12s;
}
.perm-chk:hover{border-color:var(--accent)}
.perm-chk input{margin:0;accent-color:var(--accent)}
.perm-chk.on{background:var(--accent-soft);border-color:var(--accent);color:var(--accent-2)}
/* A right the role already carries: shown ticked and locked, because
   unticking it would promise an access change that would not happen. */
.perm-chk.base{opacity:.62;cursor:not-allowed}
.perm-chk.base::after{content:'role';font-size:9px;letter-spacing:.05em;color:var(--faint)}
[data-theme="light"] .perm-chk.on{color:var(--ink-indigo)}
@media(max-width:640px){
  .perm-res{flex-direction:column;gap:8px}
  .perm-res .rname{width:auto}
}

/* ── Reminder alarm ─────────────────────────────────────
   Sits above the modal shell (z-index 80) on purpose: a reminder coming due
   while a dialog is open still has to be seen and closed. The backdrop is
   inert — no click handler, no Escape — because an alarm you dismiss by
   accident has not done its job. */
.rem-alarm{
  position:fixed;inset:0;z-index:120;display:none;place-items:center;padding:20px;
  background:rgba(4,6,11,.78);backdrop-filter:blur(7px);
}
.rem-alarm.open{display:grid}
.rem-box{
  width:100%;max-width:520px;max-height:88vh;overflow-y:auto;
  background:var(--card);border:1px solid var(--line);border-radius:20px;
  box-shadow:var(--shadow-lg);
  /* A ring that pulses with the sound, so the alarm reads as *ringing*
     rather than as one more dialog that happens to be open. */
  animation:pop .22s cubic-bezier(.2,.8,.25,1), rem-ring 1.15s ease-in-out .22s infinite;
}
@keyframes rem-ring{
  0%,100%{box-shadow:var(--shadow-lg),0 0 0 0 rgba(245,158,11,.44)}
  55%    {box-shadow:var(--shadow-lg),0 0 0 12px rgba(245,158,11,0)}
}
/* Somebody who has silenced the alarm should not still see it throbbing. */
.rem-alarm.muted .rem-box{animation:pop .22s cubic-bezier(.2,.8,.25,1)}

.rem-head{
  display:flex;align-items:center;gap:13px;padding:18px 22px;
  border-bottom:1px solid var(--line);
}
.rem-head h3{font-size:16.5px;font-weight:680;letter-spacing:-.02em}
.rem-bell{
  flex:none;display:grid;place-items:center;width:40px;height:40px;border-radius:12px;
  background:rgba(245,158,11,.15);color:var(--amber);
  animation:rem-swing 1.15s ease-in-out infinite;transform-origin:50% 15%;
}
@keyframes rem-swing{
  0%,100%{transform:rotate(-11deg)} 50%{transform:rotate(11deg)}
}
.rem-alarm.muted .rem-bell{animation:none;background:var(--card-2);color:var(--faint)}
.rem-bell svg{width:21px;height:21px}

.rem-list{padding:16px 22px;display:flex;flex-direction:column;gap:11px}
.rem-item{
  border:1px solid var(--line);border-left:3px solid var(--amber);
  border-radius:12px;padding:12px 14px;background:var(--card-2);
}
.rem-item h4{font-size:14.5px;font-weight:660;letter-spacing:-.01em}
.rem-item .rem-notes{font-size:12.5px;color:var(--muted);margin-top:5px;white-space:pre-wrap}
.rem-item .rem-when{font-size:11.5px;color:var(--faint);margin-top:6px}
.rem-item-btns{display:flex;gap:7px;flex-wrap:wrap;margin-top:11px}

.rem-foot{
  padding:14px 22px;border-top:1px solid var(--line);
  display:flex;align-items:center;justify-content:space-between;gap:12px;flex-wrap:wrap;
}
.rem-foot-btns{display:flex;gap:8px;flex-wrap:wrap;margin-left:auto}
.rem-foot .hint{max-width:34ch}

/* The reminders table: a due-but-unclosed row should be findable at a glance. */
tr.row-ringing{background:rgba(245,158,11,.08)}
.badge.r-pending{background:var(--accent-soft);color:var(--accent-2)}
.badge.r-due{background:rgba(245,158,11,.16);color:#fbbf24}
.badge.r-done{background:rgba(34,197,94,.16);color:#4ade80}
.badge.r-cancelled{background:rgba(139,147,173,.16);color:var(--muted)}

@media(max-width:560px){
  .rem-foot{align-items:stretch}
  .rem-foot-btns{margin-left:0;width:100%}
  .rem-foot-btns .btn{flex:1}
}

/* ── SOP library ───────────────────────────────────────────────────
   Three panes share the one view. Only the one carrying .on is drawn,
   which is what lets the editor keep an unsaved draft while somebody
   glances at another screen and comes back. */
.sop-pane{display:none}
.sop-pane.on{display:block}

.badge.s-pub{background:rgba(34,197,94,.16);color:#4ade80}
.badge.s-draft{background:rgba(245,158,11,.16);color:#fbbf24}
.badge.s-arch{background:rgba(139,147,173,.16);color:var(--muted)}
[data-theme="light"] .badge.s-pub{background:rgba(34,197,94,.14);color:#15803d}
[data-theme="light"] .badge.s-draft{background:rgba(245,158,11,.16);color:#b45309}

.hint.warn-text{color:var(--amber);font-weight:600}

/* ── The shelf ── */
.sop-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(268px,1fr));gap:12px}
.sop-card{
  background:var(--card);border:1px solid var(--line);border-radius:14px;padding:15px;
  cursor:pointer;transition:.15s;display:flex;flex-direction:column;gap:9px;min-height:158px;
}
.sop-card:hover{border-color:var(--accent);transform:translateY(-1px);box-shadow:var(--shadow-sm)}
.sc-top{display:flex;gap:8px;align-items:center;justify-content:space-between}
.sc-cat{
  font-size:10.5px;font-weight:700;text-transform:uppercase;letter-spacing:.06em;
  color:var(--accent-2);background:var(--accent-soft);padding:2px 8px;border-radius:5px;
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap;max-width:60%;
}
.sop-card h3{font-size:15px;font-weight:680;letter-spacing:-.015em;line-height:1.35}
.sc-ex{
  font-size:12.5px;color:var(--muted);line-height:1.55;flex:1;
  display:-webkit-box;-webkit-line-clamp:3;-webkit-box-orient:vertical;overflow:hidden;
}
.sc-foot{
  display:flex;gap:8px;align-items:center;justify-content:space-between;
  border-top:1px solid var(--line);padding-top:9px;font-size:11px;color:var(--faint);
}
.sc-foot > span:first-child{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.sc-marks{display:flex;gap:7px;align-items:center;flex:none}

/* ── The reader, and the editor's own canvas, share one type scale ──
   Both are scoped: an SOP body is authored HTML, and it must not be able to
   restyle the app around it. */
.sop-doc,.sop-canvas{
  background:var(--card);border:1px solid var(--line);border-radius:14px;
  padding:26px 30px;font-size:14.5px;line-height:1.75;overflow-wrap:break-word;
}
.sop-doc h1,.sop-canvas h1{font-size:22px;font-weight:780;margin:26px 0 10px;letter-spacing:-.02em}
.sop-doc h2,.sop-canvas h2{font-size:19px;font-weight:720;margin:24px 0 9px;letter-spacing:-.015em}
.sop-doc h3,.sop-canvas h3{font-size:16.5px;font-weight:680;margin:20px 0 8px}
.sop-doc h4,.sop-canvas h4,.sop-doc h5,.sop-canvas h5,.sop-doc h6,.sop-canvas h6{
  font-size:15px;font-weight:680;margin:18px 0 7px;
}
.sop-doc > :first-child,.sop-canvas > :first-child{margin-top:0}
.sop-doc p,.sop-canvas p{margin:0 0 12px}
.sop-doc ul,.sop-canvas ul,.sop-doc ol,.sop-canvas ol{margin:0 0 13px;padding-left:26px}
.sop-doc li,.sop-canvas li{margin:5px 0}
.sop-doc blockquote,.sop-canvas blockquote{
  margin:0 0 14px;padding:9px 16px;border-left:3px solid var(--accent);
  background:var(--card-2);color:var(--muted);
}
.sop-doc pre,.sop-canvas pre{
  margin:0 0 14px;padding:12px 14px;background:var(--bg-2);border:1px solid var(--line);
  border-radius:9px;white-space:pre-wrap;
  font:12.5px/1.6 ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;
}
.sop-doc code,.sop-canvas code{
  font:12.5px/1.5 ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;
  background:rgba(139,147,173,.14);padding:1px 5px;border-radius:4px;
}
.sop-doc pre code,.sop-canvas pre code{background:none;padding:0}
.sop-doc img,.sop-canvas img{max-width:100%;height:auto;border-radius:10px;margin:6px 0;display:block}
.sop-doc hr,.sop-canvas hr{border:0;border-top:1px solid var(--line);margin:20px 0}
.sop-doc table,.sop-canvas table{width:100%;border-collapse:collapse;margin:0 0 14px;font-size:13px}
.sop-doc th,.sop-canvas th,.sop-doc td,.sop-canvas td{
  border:1px solid var(--line-2);padding:7px 9px;text-align:left;vertical-align:top;
}
.sop-doc th,.sop-canvas th{background:var(--card-2);font-weight:680}
.sop-doc mark,.sop-canvas mark{background:rgba(245,158,11,.28);color:inherit;padding:0 2px}
.sop-doc figcaption,.sop-canvas figcaption{font-size:12px;color:var(--faint);margin-top:5px}

/* ── The editor ── */
.sop-meta{display:flex;gap:12px;flex-wrap:wrap;margin-bottom:14px}
.sop-meta .field{margin-bottom:0}

.sop-tools{
  display:flex;gap:6px;flex-wrap:wrap;align-items:center;
  background:var(--card);border:1px solid var(--line);border-radius:12px 12px 0 0;
  border-bottom:0;padding:8px 10px;position:sticky;top:0;z-index:5;
}
.sop-tgrp{display:flex;gap:3px;align-items:center;padding-right:7px;
  border-right:1px solid var(--line)}
.sop-tgrp:last-child{border-right:0;padding-right:0}
.sop-tb{
  min-width:30px;height:30px;padding:0 8px;border-radius:7px;border:1px solid transparent;
  background:transparent;color:var(--muted);cursor:pointer;font-size:12.5px;font-weight:600;
  display:inline-flex;align-items:center;justify-content:center;gap:4px;transition:.12s;
}
.sop-tb:hover{background:var(--card-2);color:var(--txt);border-color:var(--line)}
.sop-tb:active{background:var(--accent-soft);color:var(--accent-2)}
.sop-tools .input.sm{height:30px;padding:0 8px;font-size:12.5px;min-width:120px}

.sop-canvas{
  border-radius:0 0 12px 12px;min-height:52vh;outline:0;
}
.sop-canvas:focus{border-color:var(--line-2);box-shadow:var(--ring)}
.sop-canvas.drop{border-color:var(--accent);box-shadow:var(--ring)}
/* The placeholder is CSS-only, so nothing has to be typed into the document
   to hold the hint — an empty contenteditable is genuinely empty. */
.sop-canvas:empty::before{content:attr(data-placeholder);color:var(--faint)}
.sop-canvas img{cursor:default}

.sop-efoot{display:flex;align-items:center;gap:12px;margin-top:12px}
.sop-efoot .spacer{flex:1}

@media(max-width:700px){
  .sop-grid{grid-template-columns:1fr}
  .sop-doc,.sop-canvas{padding:18px 16px}
  .sop-meta .field{flex:1 1 100%!important;min-width:0!important}
  .sop-tools{position:static;overflow-x:auto}
}
