/* ============================================================
   HR SUITE 24 — Design System
   Single source of truth for colour, type, spacing, components.
   Do not write page-specific CSS inside HTML files.
   ============================================================ */

/* ---------- 1. Tokens ---------------------------------------- */
:root {
  /* Brand — tenant-overridable at runtime via hrsuite24.js */
  --brand-primary: #2563eb;
  --brand-secondary: #7c3aed;
  --brand-primary-rgb: 37, 99, 235;
  --brand-secondary-rgb: 124, 58, 237;
  --brand-gradient: linear-gradient(135deg, var(--brand-primary), var(--brand-secondary));

  /* Ink */
  --ink-900: #0f172a;
  --ink-700: #1a2332;
  --ink-500: #1e293b;
  --ink-400: #334155;

  /* Surface */
  --surface: #ffffff;
  --surface-sunken: #f8fafc;
  --surface-rail: #ffffff;
  --page-bg: linear-gradient(135deg, #f8fbff, #eef6ff, #faf5ff);

  /* Line */
  --line: #e2e8f0;
  --line-brand: #dbeafe;

  /* Status — bg / fg / border triplets */
  --ok-bg: #f0fdf4;      --ok-fg: #15803d;   --ok-line: #86efac;
  --warn-bg: #fff7ed;    --warn-fg: #c2410c; --warn-line: #fed7aa;
  --danger-bg: #fef2f2;  --danger-fg: #dc2626; --danger-line: #fecaca;
  --info-bg: #faf5ff;    --info-fg: #7c3aed; --info-line: #d8b4fe;

  /* Type */
  --font-ui: "Inter", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
  --font-data: "JetBrains Mono", ui-monospace, "SF Mono", Menlo, monospace;

  --text-xs: 11px;
  --text-sm: 13px;
  --text-base: 14px;
  --text-md: 15px;
  --text-lg: 18px;
  --text-xl: 22px;
  --text-2xl: 28px;

  /* Space — 4px base */
  --sp-1: 4px;  --sp-2: 8px;  --sp-3: 12px; --sp-4: 16px;
  --sp-5: 20px; --sp-6: 24px; --sp-8: 32px; --sp-10: 40px;

  /* Radius */
  --r-sm: 8px;
  --r-md: 12px;
  --r-lg: 18px;
  --r-xl: 24px;
  --r-pill: 999px;

  /* Elevation */
  --shadow-sm: 0 1px 2px rgba(15, 23, 42, .06);
  --shadow-md: 0 4px 16px rgba(15, 23, 42, .06);
  --shadow-lg: 0 18px 44px rgba(15, 23, 42, .08);

  --rail-w: 253px;
  --rail-w-collapsed: 72px;
  --header-h: 64px;
}


/* ---------- Module tones ------------------------------------
   Each module carries its own colour so it stays recognisable
   across the sidebar, tiles and page headers. */
.tone-indigo  { --tone: #4f46e5; --tone-soft: #eef2ff; }
.tone-violet  { --tone: #7c3aed; --tone-soft: #f5f3ff; }
.tone-sky     { --tone: #0284c7; --tone-soft: #e0f2fe; }
.tone-teal    { --tone: #0d9488; --tone-soft: #ccfbf1; }
.tone-emerald { --tone: #059669; --tone-soft: #d1fae5; }
.tone-amber   { --tone: #d97706; --tone-soft: #fef3c7; }
.tone-rose    { --tone: #e11d48; --tone-soft: #ffe4e6; }
.tone-slate   { --tone: #475569; --tone-soft: #f1f5f9; }

/* ---------- 2. Reset ----------------------------------------- */
*, *::before, *::after { box-sizing: border-box; }

body {
  margin: 0;
  font-family: var(--font-ui);
  font-size: var(--text-base);
  line-height: 1.5;
  color: var(--ink-900);
  background: var(--page-bg);
  background-attachment: fixed;
  -webkit-font-smoothing: antialiased;
}

h1, h2, h3, h4, p { margin: 0; }

h1 { font-size: var(--text-xl); font-weight: 700; letter-spacing: -.02em; }
h2 { font-size: var(--text-md); font-weight: 650; letter-spacing: -.01em; }
h3 { font-size: var(--text-base); font-weight: 650; }

a { color: var(--brand-primary); text-decoration: none; }
a:hover { text-decoration: underline; }

:focus-visible {
  outline: 2px solid var(--brand-primary);
  outline-offset: 2px;
  border-radius: var(--r-sm);
}

/* Numbers, codes, amounts — always tabular so columns line up */
.num, td.num, .stat-value {
  font-family: var(--font-data);
  font-variant-numeric: tabular-nums;
  letter-spacing: -.02em;
}

/* ---------- 3. App shell ------------------------------------- */
.app { display: flex; min-height: 100vh; }

/* --- Left rail ---------------------------------------------- */
.rail {
  width: var(--rail-w);
  flex: 0 0 var(--rail-w);
  background: var(--surface-rail);
  border-right: 1px solid var(--line-brand);
  display: flex;
  flex-direction: column;
  position: sticky;
  top: 0;
  height: 100vh;
  transition: width .18s ease, flex-basis .18s ease;
}

.rail-brand {
  /* The wordmark sits on its own line with the company beneath it, rather
     than in a row, because the lockup is six times wider than it is tall and
     a row would either squash it or push the company name off the edge. */
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  justify-content: center;
  /* Air above the logo, between logo and company, and below: all the same
     9px, so the block reads as one piece rather than three stacked things. */
  gap: 9px;
  padding: 9px var(--sp-4);
  height: var(--header-h);
  border-bottom: 1px solid var(--line-brand);
  overflow: hidden;
}
.rail-brand > div { min-width: 0; max-width: 100%; }

.rail-logo { display: block; line-height: 0; max-width: 100%; }
.rail-logo-wide {
  display: block;
  width: 150px; max-width: 100%; height: auto;
}
/* Kept for a narrow rail; nothing shows it yet. */
.rail-logo-mark { display: none; width: 30px; height: 30px; }

.rail-mark {
  width: 34px; height: 34px;
  flex: 0 0 34px;
  border-radius: var(--r-md);
  background: transparent;
  display: grid;
  place-items: center;
  color: #fff;
}
.rail-mark svg { width: 20px; height: 20px; }
.rail-mark .ic-fill { opacity: .35; }

.rail-name { font-size: var(--text-md); font-weight: 700; color: var(--ink-900); letter-spacing: -.02em; }
.rail-tag  {
  font-size: var(--text-xs);
  color: var(--ink-700, #475569);
  font-weight: 700;
  letter-spacing: .01em;
  /* A long company name shortens with an ellipsis rather than pushing the
     rail wider or wrapping onto a second line. */
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis; max-width: 100%;
}

.rail-nav { flex: 1; overflow-y: auto; padding: var(--sp-4) var(--sp-3); }

.rail-group {
  font-size: 13px;
  line-height: 1.5;
  letter-spacing: .01em;
  color: var(--ink-500);
  font-weight: 700;
  padding: var(--sp-4) var(--sp-3) var(--sp-2);
}
.rail-group:first-child { padding-top: 0; }

.rail-link {
  display: flex;
  align-items: center;
  gap: var(--sp-3);
  padding: 9px var(--sp-3);
  margin-bottom: 2px;
  border-radius: var(--r-md);
  color: var(--ink-700);
  font-size: var(--text-base);
  font-weight: 500;
  white-space: nowrap;
  transition: background .12s ease, color .12s ease;
}
.rail-link:hover { background: var(--surface-sunken); color: var(--ink-900); text-decoration: none; }
.rail-ic {
  width: 26px; height: 26px;
  flex: 0 0 26px;
  border-radius: 7px;
  display: grid;
  place-items: center;
  background: var(--tone-soft, var(--surface-sunken));
  color: var(--tone, var(--ink-400));
  transition: transform .12s ease;
}
.rail-ic svg { width: 16px; height: 16px; }
.rail-ic .ic-fill { opacity: .28; }
.rail-link:hover .rail-ic { transform: scale(1.06); }

.rail-link.is-active {
  background: rgba(var(--brand-primary-rgb), .08);
  color: var(--brand-primary);
  font-weight: 600;
}
.rail-link.is-active .rail-ic { box-shadow: 0 0 0 1px var(--tone, var(--brand-primary)) inset; }

.rail-count {
  margin-left: auto;
  font-family: var(--font-data);
  font-size: var(--text-sm);
  font-weight: 650;
  background: var(--danger-bg);
  color: var(--danger-fg);
  border: 1px solid var(--danger-line);
  padding: 0 6px;
  border-radius: var(--r-pill);
}

.rail-foot {
  padding: var(--sp-3) var(--sp-4);
  border-top: 1px solid var(--line-brand);
  font-size: var(--text-xs);
  color: var(--ink-400);
}

/* --- Main column -------------------------------------------- */
.main { flex: 1; min-width: 0; display: flex; flex-direction: column; }

.topbar {
  height: var(--header-h);
  display: flex;
  align-items: center;
  gap: var(--sp-4);
  padding: 0 var(--sp-5);
  background: rgba(255, 255, 255, .82);
  backdrop-filter: blur(8px);
  border-bottom: 1px solid var(--line-brand);
  position: sticky;
  top: 0;
  z-index: 20;
}

.topbar-title { font-size: var(--text-md); font-weight: 650; }
.topbar-sub { font-size: var(--text-xs); color: var(--ink-500); margin-top: 1px; }
.topbar-actions { margin-left: auto; display: flex; align-items: center; gap: var(--sp-2); }

.icon-btn {
  width: 34px; height: 34px;
  display: grid; place-items: center;
  border: 1px solid var(--line);
  background: var(--surface);
  border-radius: var(--r-sm);
  color: var(--ink-500);
  cursor: pointer;
  transition: color .12s ease, border-color .12s ease;
}
.icon-btn:hover { color: var(--brand-primary); border-color: var(--line-brand); }
.icon-btn svg { width: 18px; height: 18px; }
.icon-btn .ic-fill { opacity: .18; }

.avatar {
  width: 34px; height: 34px;
  border-radius: var(--r-pill);
  background: var(--brand-gradient);
  color: #fff;
  display: grid; place-items: center;
  font-size: var(--text-sm);
  font-weight: 600;
}

.content { padding: var(--sp-4) var(--sp-5) var(--sp-5); width: 100%; }

/* ---------- 4. Cards ----------------------------------------- */
.card {
  background: var(--surface);
  border: 1px solid var(--line-brand);
  border-radius: var(--r-xl);
  box-shadow: var(--shadow-lg);
  padding: var(--sp-4) var(--sp-5);
  margin-bottom: var(--sp-3);
}

.card-head {
  display: flex;
  align-items: center;
  gap: var(--sp-3);
  margin-bottom: var(--sp-3);
}
.card-head .card-actions { margin-left: auto; display: flex; gap: var(--sp-2); }
.card-desc { font-size: var(--text-sm); color: var(--ink-500); margin-top: 2px; }

/* ---------- 5. Stats ----------------------------------------- */
.stat-row {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(170px, 1fr));
  gap: var(--sp-2);
}

.stat {
  padding: var(--sp-4);
  border-radius: var(--r-lg);
  background: var(--surface-sunken);
  border: 1px solid var(--line);
}
.stat-label {
  font-size: var(--text-xs);
  color: var(--ink-500);
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: .05em;
}
.stat-value { font-size: var(--text-2xl); font-weight: 600; margin-top: var(--sp-2); display: block; }
.stat-note { font-size: var(--text-xs); color: var(--ink-400); margin-top: var(--sp-1); }

/* Accent variants */
.stat.is-ok     { background: var(--ok-bg);     border-color: var(--ok-line); }
.stat.is-ok .stat-value { color: var(--ok-fg); }
.stat.is-warn   { background: var(--warn-bg);   border-color: var(--warn-line); }
.stat.is-warn .stat-value { color: var(--warn-fg); }
.stat.is-danger { background: var(--danger-bg); border-color: var(--danger-line); }
.stat.is-danger .stat-value { color: var(--danger-fg); }
.stat.is-brand  { background: rgba(var(--brand-primary-rgb), .06); border-color: rgba(var(--brand-primary-rgb), .22); }
.stat.is-brand .stat-value { color: var(--brand-primary); }

/* ---------- 6. Module tiles ---------------------------------- */
.tile-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(210px, 1fr));
  gap: var(--sp-2);
}

.tile {
  display: block;
  padding: var(--sp-4);
  border-radius: var(--r-lg);
  background: var(--surface);
  border: 1px solid var(--line);
  color: inherit;
  transition: border-color .15s ease, box-shadow .15s ease, transform .15s ease;
}
.tile:hover {
  text-decoration: none;
  border-color: var(--tone, var(--brand-primary));
  box-shadow: var(--shadow-md);
  transform: translateY(-1px);
}

.tile-icon {
  width: 38px; height: 38px;
  border-radius: var(--r-md);
  background: var(--tone-soft, rgba(var(--brand-primary-rgb), .08));
  color: var(--tone, var(--brand-primary));
  display: grid; place-items: center;
  margin-bottom: var(--sp-3);
}
.tile-icon svg { width: 21px; height: 21px; }
.tile-icon .ic-fill { opacity: .3; }
.tile-title { font-size: var(--text-base); font-weight: 650; }
.tile-desc { font-size: var(--text-sm); color: var(--ink-500); margin-top: var(--sp-1); line-height: 1.5; }

.tile.is-locked { opacity: .55; pointer-events: none; }

/* ---------- 7. Buttons --------------------------------------- */
.btn {
  height: 36px;
  padding: 0 var(--sp-4);
  border-radius: var(--r-sm);
  border: 1px solid var(--line);
  background: var(--surface);
  color: var(--ink-700);
  font-family: inherit;
  font-size: var(--text-base);
  font-weight: 550;
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  gap: var(--sp-2);
  transition: border-color .12s ease, background .12s ease, color .12s ease;
}
.btn:hover { border-color: var(--ink-400); color: var(--ink-900); }
.btn svg { width: 16px; height: 16px; }

.btn-primary {
  background: var(--brand-gradient);
  border-color: transparent;
  color: #fff;
}
.btn-primary:hover { color: #fff; filter: brightness(1.06); }

.btn-quiet { border-color: transparent; background: transparent; color: var(--ink-500); }
.btn-quiet:hover { background: var(--surface-sunken); }

.btn-danger { color: var(--danger-fg); border-color: var(--danger-line); background: var(--danger-bg); }

.btn:disabled { opacity: .5; cursor: not-allowed; }
.btn-sm { height: 30px; padding: 0 var(--sp-3); font-size: var(--text-sm); }

/* ---------- 8. Badges ---------------------------------------- */
.badge {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  padding: 3px 9px;
  border-radius: var(--r-pill);
  font-size: var(--text-xs);
  font-weight: 600;
  background: rgba(var(--brand-primary-rgb), .08);
  color: var(--brand-primary);
  border: 1px solid rgba(var(--brand-primary-rgb), .25);
}
.badge.is-ok     { background: var(--ok-bg);     color: var(--ok-fg);     border-color: var(--ok-line); }
.badge.is-warn   { background: var(--warn-bg);   color: var(--warn-fg);   border-color: var(--warn-line); }
.badge.is-danger { background: var(--danger-bg); color: var(--danger-fg); border-color: var(--danger-line); }
.badge.is-info   { background: var(--info-bg);   color: var(--info-fg);   border-color: var(--info-line); }
.badge.is-muted  { background: var(--surface-sunken); color: var(--ink-500); border-color: var(--line); }

.dot { width: 6px; height: 6px; border-radius: 50%; background: currentColor; }

/* ---------- 9. Tables ---------------------------------------- */
.table-wrap {
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  overflow: auto;
}

table { width: 100%; border-collapse: collapse; font-size: var(--text-base); }

thead th {
  text-align: left;
  padding: 11px var(--sp-4);
  line-height: 1.6;
  background: var(--surface-sunken);
  border-bottom: 1px solid var(--line);
  font-size: 12px;
  font-weight: 600;
  color: var(--ink-500);
  letter-spacing: .01em;
  white-space: nowrap;
  position: sticky;
  top: 0;
}

tbody td {
  padding: 14px var(--sp-4);
  border-bottom: 1px solid var(--line);
  color: var(--ink-900);
  line-height: 1.5;
}
tbody tr:last-child td { border-bottom: 0; }
tbody tr:hover { background: rgba(var(--brand-primary-rgb), .055); }

th.right, td.right { text-align: right; }

.cell-primary { font-weight: 600; }
.cell-sub { font-size: var(--text-xs); color: var(--ink-500); margin-top: 1px; }

/* ---------- 10. Forms ---------------------------------------- */
.field { margin-bottom: var(--sp-4); }
.field label {
  display: block;
  font-size: var(--text-sm);
  font-weight: 600;
  color: var(--ink-700);
  margin-bottom: var(--sp-2);
}

.input, select.input, textarea.input {
  width: 100%;
  height: 36px;
  padding: 0 var(--sp-3);
  border: 1px solid var(--line);
  border-radius: var(--r-sm);
  background: var(--surface);
  font-family: inherit;
  font-size: var(--text-base);
  color: var(--ink-900);
}
textarea.input { height: auto; padding: var(--sp-3); min-height: 84px; resize: vertical; }
.input::placeholder { color: var(--ink-400); }
.input:focus { border-color: var(--brand-primary); outline: none; box-shadow: 0 0 0 3px rgba(var(--brand-primary-rgb), .12); }
.input:disabled { background: var(--surface-sunken); color: var(--ink-400); }

.field-hint { font-size: var(--text-xs); color: var(--ink-500); margin-top: var(--sp-1); }
.field-error { font-size: var(--text-xs); color: var(--danger-fg); margin-top: var(--sp-1); }
.field.has-error .input { border-color: var(--danger-line); }

.form-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
  gap: 0 var(--sp-4);
}

.search {
  position: relative;
  display: flex;
  align-items: center;
}
.search svg {
  position: absolute;
  left: 11px;
  width: 15px; height: 15px;
  color: var(--ink-400);
  pointer-events: none;
}
.search .input { padding-left: 34px; }

/* ---------- 11. Messages ------------------------------------- */
.notice {
  display: flex;
  gap: var(--sp-3);
  padding: var(--sp-3) var(--sp-4);
  border-radius: var(--r-md);
  font-size: var(--text-base);
  border: 1px solid;
  margin-bottom: var(--sp-4);
}
.notice svg { width: 17px; height: 17px; flex: 0 0 17px; margin-top: 1px; }
.notice.is-ok     { background: var(--ok-bg);     color: var(--ok-fg);     border-color: var(--ok-line); }
.notice.is-warn   { background: var(--warn-bg);   color: var(--warn-fg);   border-color: var(--warn-line); }
.notice.is-danger { background: var(--danger-bg); color: var(--danger-fg); border-color: var(--danger-line); }
.notice.is-info   { background: var(--info-bg);   color: var(--info-fg);   border-color: var(--info-line); }
.notice[hidden] { display: none; }

/* Empty state — an invitation to act, not a shrug */
.empty { text-align: center; padding: var(--sp-10) var(--sp-4); }
.empty-icon {
  width: 44px; height: 44px;
  margin: 0 auto var(--sp-3);
  border-radius: var(--r-md);
  background: var(--surface-sunken);
  color: var(--ink-400);
  display: grid; place-items: center;
}
.empty-icon svg { width: 22px; height: 22px; }
.empty-title { font-weight: 650; }
.empty-text { font-size: var(--text-sm); color: var(--ink-500); margin: var(--sp-2) 0 var(--sp-4); }

/* Toast */
.toast-stack {
  position: fixed;
  right: var(--sp-5);
  bottom: var(--sp-5);
  display: flex;
  flex-direction: column;
  gap: var(--sp-2);
  z-index: 100;
}
.toast {
  background: var(--ink-900);
  color: #fff;
  padding: var(--sp-3) var(--sp-4);
  border-radius: var(--r-md);
  font-size: var(--text-base);
  box-shadow: var(--shadow-lg);
  animation: toast-in .2s ease;
}
.toast.is-ok { background: var(--ok-fg); }
.toast.is-danger { background: var(--danger-fg); }
@keyframes toast-in { from { opacity: 0; transform: translateY(6px); } }

/* Skeleton loading */
.skeleton {
  background: linear-gradient(90deg, var(--surface-sunken), #eef2f7, var(--surface-sunken));
  background-size: 200% 100%;
  animation: shimmer 1.2s linear infinite;
  border-radius: var(--r-sm);
  height: 14px;
}
@keyframes shimmer { to { background-position: -200% 0; } }

/* ---------- 12. Utilities ------------------------------------ */
.row { display: flex; align-items: center; gap: var(--sp-2); }
.row-wrap { flex-wrap: wrap; }
.push { margin-left: auto; }
.muted { color: var(--ink-500); }
.small { font-size: var(--text-sm); }
.mt-4 { margin-top: var(--sp-4); }
.mb-0 { margin-bottom: 0; }
.divider { height: 1px; background: var(--line); margin: var(--sp-4) 0; }
[hidden] { display: none !important; }


/* ---------- 14. Auth pages -----------------------------------
   Login, forgot password, reset. No sidebar, no topbar. */
.auth {
  min-height: 100vh;
  display: grid;
  grid-template-columns: 1fr 1fr;
}

.auth-brand {
  background: var(--brand-gradient);
  color: #fff;
  padding: var(--sp-10);
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  position: relative;
  overflow: hidden;
}
.auth-brand::after {
  content: "";
  position: absolute;
  width: 420px; height: 420px;
  border-radius: 50%;
  right: -160px; bottom: -160px;
  background: rgba(255, 255, 255, .08);
}

.auth-mark {
  display: flex;
  align-items: center;
  gap: var(--sp-3);
  position: relative;
}
.auth-mark-box {
  width: 40px; height: 40px;
  border-radius: var(--r-md);
  background: rgba(255, 255, 255, .18);
  display: grid; place-items: center;
}
.auth-mark-box svg { width: 22px; height: 22px; }
.auth-mark-name { font-size: var(--text-lg); font-weight: 700; letter-spacing: -.02em; }

.auth-pitch { position: relative; max-width: 380px; }
.auth-pitch h2 {
  font-size: var(--text-2xl);
  font-weight: 700;
  line-height: 1.25;
  letter-spacing: -.02em;
  color: #fff;
}
.auth-pitch p {
  margin-top: var(--sp-3);
  font-size: var(--text-md);
  line-height: 1.6;
  color: rgba(255, 255, 255, .82);
}

.auth-points { position: relative; display: grid; gap: var(--sp-3); }
.auth-point {
  display: flex;
  align-items: center;
  gap: var(--sp-3);
  font-size: var(--text-base);
  color: rgba(255, 255, 255, .9);
}
.auth-point svg { width: 16px; height: 16px; flex: 0 0 16px; }

.auth-form {
  display: flex;
  align-items: center;
  justify-content: center;
  padding: var(--sp-8) var(--sp-6);
}
.auth-box { width: 100%; max-width: 360px; }
.auth-box h1 { font-size: var(--text-xl); margin-bottom: var(--sp-2); }
.auth-box .lede { color: var(--ink-500); font-size: var(--text-base); margin-bottom: var(--sp-6); }

.auth-actions {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin: calc(var(--sp-2) * -1) 0 var(--sp-5);
  font-size: var(--text-sm);
}
.check { display: flex; align-items: center; gap: 7px; color: var(--ink-700); cursor: pointer; }
.check input { width: 15px; height: 15px; accent-color: var(--brand-primary); }

.btn-block { width: 100%; justify-content: center; height: 40px; }

.auth-foot {
  margin-top: var(--sp-6);
  padding-top: var(--sp-4);
  border-top: 1px solid var(--line);
  font-size: var(--text-sm);
  color: var(--ink-500);
  text-align: center;
}

@media (max-width: 860px) {
  .auth { grid-template-columns: 1fr; }
  .auth-brand { padding: var(--sp-6); gap: var(--sp-6); }
  .auth-pitch h2 { font-size: var(--text-xl); }
  .auth-points { display: none; }
}


/* ---------- 15. Filter bar ----------------------------------- */
.filters {
  display: flex;
  align-items: center;
  gap: var(--sp-2);
  flex-wrap: wrap;
  margin-bottom: var(--sp-4);
}
.filters .search { flex: 1 1 240px; min-width: 200px; }
.filters .input { height: 36px; }
select.input.compact { width: auto; min-width: 140px; padding-right: var(--sp-5); }

.chip-row { display: flex; gap: 6px; flex-wrap: wrap; }
.chip {
  padding: 5px 12px;
  border-radius: var(--r-pill);
  border: 1px solid var(--line);
  background: var(--surface);
  font-size: var(--text-sm);
  font-weight: 500;
  color: var(--ink-500);
  cursor: pointer;
}
.chip:hover { border-color: var(--ink-400); color: var(--ink-900); }
.chip.is-on {
  background: rgba(var(--brand-primary-rgb), .08);
  border-color: rgba(var(--brand-primary-rgb), .3);
  color: var(--brand-primary);
}

/* ---------- 16. Pagination ----------------------------------- */
.pager {
  display: flex;
  align-items: center;
  gap: var(--sp-3);
  margin-top: var(--sp-4);
  font-size: var(--text-sm);
  color: var(--ink-500);
}
.pager .push { margin-left: auto; display: flex; gap: var(--sp-2); }

/* ---------- 17. Modal ----------------------------------------
   Uses <dialog> so Esc, focus trapping and the backdrop are free. */
dialog.modal {
  border: 0;
  padding: 0;
  border-radius: var(--r-xl);
  box-shadow: var(--shadow-lg);
  width: min(560px, 94vw);
  background: var(--surface);
  color: var(--ink-900);
}
dialog.modal::backdrop { background: rgba(15, 23, 42, .45); }
dialog.modal.wide { width: min(760px, 94vw); }

.modal-head {
  display: flex;
  align-items: flex-start;
  gap: var(--sp-3);
  padding: var(--sp-5) var(--sp-5) var(--sp-3);
}
.modal-head h2 { font-size: var(--text-lg); }
.modal-head .card-desc { margin-top: 2px; }
.modal-close {
  margin-left: auto;
  width: 30px; height: 30px;
  border: 0;
  background: transparent;
  border-radius: var(--r-sm);
  color: var(--ink-400);
  font-size: 20px;
  line-height: 1;
  cursor: pointer;
}
.modal-close:hover { background: var(--surface-sunken); color: var(--ink-900); }

.modal-body { padding: 0 var(--sp-5); max-height: 62vh; overflow-y: auto; }
.modal-foot {
  display: flex;
  justify-content: flex-end;
  gap: var(--sp-2);
  padding: var(--sp-4) var(--sp-5) var(--sp-5);
  border-top: 1px solid var(--line);
  margin-top: var(--sp-4);
}

/* ---------- 18. Misc list bits ------------------------------- */
.avatar-sm {
  width: 32px; height: 32px;
  flex: 0 0 32px;
  border-radius: var(--r-pill);
  background: var(--tone-soft, var(--surface-sunken));
  color: var(--tone, var(--ink-500));
  display: grid; place-items: center;
  font-size: var(--text-sm);
  font-weight: 600;
}
.cell-person { display: flex; align-items: center; gap: var(--sp-3); }

.table-wrap.scroll { max-height: 62vh; }


/* ---------- 19. Segmented control ----------------------------
   Attendance marking — one tap per employee, no dropdown. */
.seg { display: inline-flex; border: 1px solid var(--line); border-radius: var(--r-sm); overflow: hidden; }
.seg button {
  border: 0;
  background: var(--surface);
  padding: 0 10px;
  height: 30px;
  font-family: inherit;
  font-size: var(--text-sm);
  font-weight: 500;
  color: var(--ink-500);
  cursor: pointer;
  border-right: 1px solid var(--line);
  white-space: nowrap;
}
.seg button:last-child { border-right: 0; }
.seg button:hover { background: var(--surface-sunken); color: var(--ink-900); }
.seg button.is-on { color: #fff; font-weight: 600; }
.seg button.is-on[data-v="P"]  { background: var(--ok-fg); }
.seg button.is-on[data-v="H"]  { background: var(--warn-fg); }
.seg button.is-on[data-v="A"]  { background: var(--danger-fg); }
.seg button.is-on[data-v="L"]  { background: var(--info-fg); }
.seg button.is-on[data-v="W"]  { background: var(--ink-500); }

/* ---------- 20. Date stepper --------------------------------- */
.datebar {
  display: flex;
  align-items: center;
  gap: var(--sp-2);
  flex-wrap: wrap;
  margin-bottom: var(--sp-4);
}
.datebar .day {
  font-size: var(--text-md);
  font-weight: 650;
  min-width: 190px;
}
.datebar .day small { display: block; font-size: var(--text-xs); color: var(--ink-500); font-weight: 500; }

/* Sticky save bar so it stays reachable on a long list */
.savebar {
  position: sticky;
  bottom: 0;
  display: flex;
  align-items: center;
  gap: var(--sp-3);
  padding: var(--sp-3) var(--sp-4);
  margin: var(--sp-4) calc(var(--sp-5) * -1) calc(var(--sp-5) * -1);
  border-top: 1px solid var(--line);
  background: rgba(255, 255, 255, .92);
  backdrop-filter: blur(6px);
  border-radius: 0 0 var(--r-xl) var(--r-xl);
  font-size: var(--text-sm);
  color: var(--ink-500);
}
.savebar .push { margin-left: auto; display: flex; gap: var(--sp-2); }

td.time-cell { width: 108px; }
td.time-cell .input { height: 30px; padding: 0 8px; font-size: var(--text-sm); }

/* ---------- 21. Tabs ----------------------------------------- */
.tabs {
  display: flex;
  gap: 2px;
  border-bottom: 1px solid var(--line);
  margin-bottom: var(--sp-4);
  overflow-x: auto;
}
.tab {
  border: 0;
  background: transparent;
  padding: 10px var(--sp-4);
  font-family: inherit;
  font-size: var(--text-base);
  font-weight: 550;
  color: var(--ink-500);
  cursor: pointer;
  border-bottom: 2px solid transparent;
  margin-bottom: -1px;
  white-space: nowrap;
}
.tab:hover { color: var(--ink-900); }
.tab.is-on { color: var(--brand-primary); border-bottom-color: var(--brand-primary); }
.tab .count {
  margin-left: 6px;
  font-family: var(--font-data);
  font-size: var(--text-xs);
  background: var(--surface-sunken);
  border: 1px solid var(--line);
  padding: 0 6px;
  border-radius: var(--r-pill);
}
.tab.is-on .count {
  background: rgba(var(--brand-primary-rgb), .1);
  border-color: rgba(var(--brand-primary-rgb), .25);
  color: var(--brand-primary);
}

/* Leave balance meter */
.meter {
  height: 5px;
  border-radius: 99px;
  background: var(--line);
  overflow: hidden;
  margin-top: 5px;
  min-width: 90px;
}
.meter span { display: block; height: 100%; background: var(--tone, var(--brand-primary)); border-radius: 99px; }

/* ---------- 22. Punch screen ---------------------------------
   Phone first. One thumb, one button, no hunting. */
.punch-wrap { max-width: 460px; margin: 0 auto; }

.punch-clock {
  text-align: center;
  padding: var(--sp-4) 0 var(--sp-5);
}
.punch-time {
  font-family: var(--font-data);
  font-size: 44px;
  font-weight: 500;
  letter-spacing: -.03em;
  line-height: 1;
}
.punch-date { font-size: var(--text-base); color: var(--ink-500); margin-top: var(--sp-2); }

/* Camera preview, square so the crop is predictable on every phone */
.cam {
  position: relative;
  aspect-ratio: 1;
  border-radius: var(--r-xl);
  overflow: hidden;
  background: var(--ink-900);
  margin-bottom: var(--sp-4);
}
.cam video, .cam canvas, .cam img {
  width: 100%; height: 100%;
  object-fit: cover;
  display: block;
  /* Mirror the preview so it behaves like a mirror, not a photograph */
  transform: scaleX(-1);
}
.cam-idle {
  position: absolute; inset: 0;
  display: grid; place-items: center;
  color: #64748b;
  text-align: center;
  padding: var(--sp-5);
  font-size: var(--text-base);
}
.cam-idle svg { width: 34px; height: 34px; margin-bottom: var(--sp-3); }

.cam-badge {
  position: absolute;
  left: var(--sp-3); bottom: var(--sp-3);
  display: flex; align-items: center; gap: 6px;
  padding: 5px 10px;
  border-radius: var(--r-pill);
  background: rgba(15, 23, 42, .72);
  color: #fff;
  font-size: var(--text-xs);
  font-weight: 600;
  backdrop-filter: blur(4px);
}
.cam-badge svg { width: 13px; height: 13px; }

.punch-btn {
  width: 100%;
  height: 56px;
  border: 0;
  border-radius: var(--r-lg);
  font-family: inherit;
  font-size: var(--text-md);
  font-weight: 650;
  color: #fff;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: var(--sp-2);
  background: var(--brand-gradient);
  box-shadow: 0 10px 26px rgba(var(--brand-primary-rgb), .3);
  transition: filter .12s ease, transform .08s ease;
}
.punch-btn:active { transform: translateY(1px); }
.punch-btn:hover { filter: brightness(1.05); }
.punch-btn:disabled { opacity: .5; cursor: not-allowed; box-shadow: none; }
.punch-btn svg { width: 20px; height: 20px; }
.punch-btn.is-out {
  background: linear-gradient(135deg, #e11d48, #be123c);
  box-shadow: 0 10px 26px rgba(225, 29, 72, .28);
}

.punch-meta {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--sp-2);
  margin-top: var(--sp-4);
}
.punch-meta .stat { padding: var(--sp-3); }
.punch-meta .stat-value { font-size: var(--text-lg); }

@media (max-width: 520px) {
  .punch-time { font-size: 38px; }
}

/* ---------- 22. Punch screen ---------------------------------
   Built for a phone held one-handed at the office gate. Big target,
   high contrast, no small text that matters. */
.punch {
  max-width: 460px;
  margin: 0 auto;
}

.punch-cam {
  position: relative;
  aspect-ratio: 3 / 4;
  border-radius: var(--r-xl);
  overflow: hidden;
  background: var(--ink-900);
  margin-bottom: var(--sp-4);
}
.punch-cam video,
.punch-cam canvas,
.punch-cam img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}
/* Front camera is mirrored, so people see themselves the right way. */
.punch-cam video { transform: scaleX(-1); }

.punch-cam-msg {
  position: absolute;
  inset: 0;
  display: grid;
  place-items: center;
  padding: var(--sp-6);
  text-align: center;
  color: #fff;
  font-size: var(--text-base);
  line-height: 1.6;
  background: var(--ink-900);
}

.punch-chip {
  position: absolute;
  left: var(--sp-3);
  bottom: var(--sp-3);
  right: var(--sp-3);
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 8px 12px;
  border-radius: var(--r-pill);
  background: rgba(15, 23, 42, .62);
  backdrop-filter: blur(6px);
  color: #fff;
  font-size: var(--text-sm);
  font-weight: 500;
}
.punch-chip svg { width: 15px; height: 15px; flex: 0 0 15px; }
.punch-chip.is-ok    { background: rgba(21, 128, 61, .82); }
.punch-chip.is-warn  { background: rgba(194, 65, 12, .82); }
.punch-chip.is-danger{ background: rgba(220, 38, 38, .82); }

.punch-btn {
  width: 100%;
  height: 60px;
  border: 0;
  border-radius: var(--r-lg);
  font-family: inherit;
  font-size: 17px;
  font-weight: 650;
  color: #fff;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: var(--sp-3);
  background: var(--brand-gradient);
  transition: filter .12s ease;
}
.punch-btn svg { width: 22px; height: 22px; }
.punch-btn:hover:not(:disabled) { filter: brightness(1.07); }
.punch-btn:disabled { opacity: .45; cursor: not-allowed; }
.punch-btn.is-out { background: linear-gradient(135deg, #e11d48, #be123c); }

.punch-today {
  display: grid;
  grid-template-columns: 1fr 1fr 1fr;
  gap: var(--sp-2);
  margin-top: var(--sp-4);
  text-align: center;
}
.punch-today > div {
  padding: var(--sp-3);
  border-radius: var(--r-md);
  background: var(--surface-sunken);
  border: 1px solid var(--line);
}
.punch-today .k { font-size: var(--text-xs); color: var(--ink-500); font-weight: 600; text-transform: uppercase; letter-spacing: .05em; }
.punch-today .v { font-family: var(--font-data); font-size: var(--text-lg); font-weight: 600; margin-top: 3px; }

.punch-clock {
  text-align: center;
  margin-bottom: var(--sp-4);
}
.punch-clock .t {
  font-family: var(--font-data);
  font-size: 40px;
  font-weight: 600;
  letter-spacing: -.03em;
  line-height: 1;
}
.punch-clock .d { font-size: var(--text-sm); color: var(--ink-500); margin-top: 5px; }


/* ---------- 13. Responsive ----------------------------------- */
@media (max-width: 900px) {
  .rail {
    position: fixed;
    left: 0; top: 0; bottom: 0;
    z-index: 60;
    transform: translateX(-100%);
    transition: transform .2s ease;
  }
  .app.is-open .rail { transform: translateX(0); }
  .app.is-open::after {
    content: "";
    position: fixed;
    inset: 0;
    background: rgba(15, 23, 42, .45);
    z-index: 50;
  }
  .content { padding: var(--sp-4); }
  .card { padding: var(--sp-4); border-radius: var(--r-lg); }
  .card-head { flex-wrap: wrap; }
  .card-head .card-actions { margin-left: 0; width: 100%; }
  .filters .search { flex-basis: 100%; }
}

@media (min-width: 901px) {
  .rail-toggle-mobile { display: none; }
}

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: .01ms !important;
    transition-duration: .01ms !important;
  }
}

@media print {
  .rail, .topbar-actions, .btn { display: none; }
  .card { box-shadow: none; border-color: #ccc; break-inside: avoid; }
}

/* ---------- 23. Table footer -------------------------------
   Totals were left unstyled, so they had no padding and drifted out of
   line with the columns above them. A total that does not sit under its
   column is worse than no total at all. */
tfoot td {
  padding: var(--sp-3) var(--sp-4);
  border-top: 2px solid var(--line);
  background: var(--surface-sunken);
  font-weight: 650;
}
tfoot tr:first-child td { border-top: 2px solid var(--line); }
tfoot td.right { text-align: right; }

/* ---------- 24. Week-off editor ------------------------------ */
.wo-days { display: flex; gap: 4px; flex-wrap: wrap; }
.wo-day { cursor: pointer; position: relative; }
.wo-day input { position: absolute; opacity: 0; }
.wo-day span {
  display: grid; place-items: center;
  width: 44px; height: 34px;
  border-radius: var(--r-sm);
  border: 1px solid var(--line);
  font-size: var(--text-sm); font-weight: 500;
  color: var(--ink-500);
}
.wo-day input:checked + span {
  background: rgba(var(--brand-primary-rgb), .1);
  border-color: rgba(var(--brand-primary-rgb), .35);
  color: var(--brand-primary); font-weight: 650;
}
.wo-day input:focus-visible + span { outline: 2px solid var(--brand-primary); outline-offset: 2px; }

.wo-rules { margin-top: var(--sp-3); display: grid; gap: 6px; }
.wo-rule {
  display: flex; align-items: center; gap: var(--sp-3); flex-wrap: wrap;
  padding: 7px 10px;
  background: var(--surface-sunken);
  border: 1px solid var(--line);
  border-radius: var(--r-sm);
}
.wo-name { font-size: var(--text-sm); font-weight: 600; min-width: 78px; }
.wo-rule .input { height: 30px; width: auto; min-width: 140px; font-size: var(--text-sm); }

.wo-weeks { display: flex; gap: 3px; }
.wo-weeks label { cursor: pointer; position: relative; }
.wo-weeks input { position: absolute; opacity: 0; }
.wo-weeks span {
  display: grid; place-items: center;
  width: 28px; height: 28px;
  border-radius: var(--r-sm);
  border: 1px solid var(--line);
  background: var(--surface);
  font-size: var(--text-xs); font-weight: 600;
  color: var(--ink-500);
}
.wo-weeks input:checked + span {
  background: var(--brand-primary); border-color: var(--brand-primary); color: #fff;
}

/* ---------- 25. Menu icons ----------------------------------
   3D emoji in the sidebar. Rendered as images rather than inline
   SVG, so the browser caches them once and the markup stays small. */
.rail-ic img {
  width: 22px;
  height: 22px;
  object-fit: contain;
  display: block;
}
.rail-ic.is-img {
  background: transparent;
  box-shadow: none !important;
  width: 26px;
  height: 26px;
}
.rail-link:hover .rail-ic.is-img { transform: scale(1.08); }

/* ---------- 26. Stat card with icon --------------------------
   Icon left, label and number stacked to its right. The number is the
   thing being scanned, so it gets the weight; the icon is there to make
   the card findable at a glance, not to be read. */
.stat.has-ic {
  display: flex;
  align-items: center;
  gap: var(--sp-3);
  padding: var(--sp-3) var(--sp-4);
}
.stat-ic {
  width: 44px; height: 44px;
  flex: 0 0 44px;
  border-radius: var(--r-md);
  background: rgba(255, 255, 255, .7);
  display: grid; place-items: center;
}
.stat-ic img { width: 30px; height: 30px; object-fit: contain; display: block; }
.stat.has-ic .stat-body { min-width: 0; }
.stat.has-ic .stat-label {
  font-size: var(--text-xs);
  letter-spacing: .05em;
  color: var(--ink-500);
}
.stat.has-ic .stat-value {
  font-size: var(--text-xl);
  line-height: 1.15;
  margin-top: 1px;
  color: var(--ink-900);
}
.stat.has-ic.is-ok .stat-value     { color: #14532d; }
.stat.has-ic.is-warn .stat-value   { color: #7c2d12; }
.stat.has-ic.is-danger .stat-value { color: #7f1d1d; }
.stat.has-ic.is-brand .stat-value  { color: #1e3a8a; }


/* ---------- 27. Trailing space -------------------------------
   The last card's margin sat on top of the content padding, so every
   page ended with a band of nothing that was enough to trigger a
   scrollbar on a screen that otherwise fit. */
.content > :last-child { margin-bottom: 0; }
.content > .grid2:last-child > .card,
.content > .grid3:last-child > .card,
#view > .grid2:last-child > .card,
#view > .grid3:last-child > .card { margin-bottom: 0; }

/* ---------- 28. Full-height dashboard ------------------------
   Width already follows the window. Height did not, so every zoom level
   left either a gap below the fold or a scrollbar.
   A page marked .fill divides the available height between its rows
   instead of stacking fixed pixel heights.

   The mistake to avoid here is min-height:0 on the card itself — that
   lets a flex child collapse to nothing, which is what emptied the
   cards the first time. Only the scrolling body gets it. */
@media (min-height: 600px) and (min-width: 1000px) {
  html:has(.content.fill), body:has(.content.fill) { overflow: hidden; }

  .content.fill {
    height: calc(100vh - var(--header-h));
    padding-bottom: var(--sp-4);
    overflow: hidden;
    display: flex;
    flex-direction: column;
  }

  /* Everything the dashboard draws lives in #view, so that is the
     element that has to divide the height — not .content, whose only
     child is the wrapper itself. */
  .content.fill > #view {
    flex: 1 1 auto;
    min-height: 0;
    display: flex;
    flex-direction: column;
    gap: var(--sp-3);
  }

  .content.fill #view > * { margin-bottom: 0; }

  /* The stat strip keeps its natural height; the rest shares the rest. */
  .content.fill #view > .fixed-row { flex: 0 0 auto; }

  /* On a shorter window the stat strip is what pushes everything past
     the fold, so it trims first — the numbers stay readable, the
     decoration around them does not. */
  @media (max-height: 820px) {
    .content.fill .stat.has-ic { padding: 9px var(--sp-3); gap: var(--sp-2); }
    .content.fill .stat-ic { width: 36px; height: 36px; flex: 0 0 36px; }
    .content.fill .stat-ic img { width: 26px; height: 26px; }
    .content.fill .stat.has-ic .stat-value { font-size: var(--text-lg); }
    .content.fill .card { padding: var(--sp-3) var(--sp-4); }
    .content.fill .card-head { margin-bottom: var(--sp-2); }
  }
  .content.fill #view > .grow-row { flex: 1 1 0; min-height: 170px; }

  /* Charts get the larger share: their whole job is the height of the
     bars. Lists read fine when they are tighter. */
  .content.fill #view > .grid2.grow-row { flex: 1.15 1 0; }
  .content.fill #view > .grid3.grow-row { flex: 1 1 0; }

  .content.fill .grow-row > .card {
    height: 100%;
    display: flex;
    flex-direction: column;
    margin-bottom: 0;
  }

  .content.fill .grow-row .card-head { flex: 0 0 auto; }

  /* Chart fills whatever the card has left. */
  .content.fill .grow-row .chart { flex: 1 1 auto; min-height: 120px; }
  .content.fill .grow-row .chart { display: flex; }
  .content.fill .grow-row .chart .yaxis { height: auto; flex: 0 0 auto; }
  .content.fill .grow-row .chart .bars { height: auto; flex: 1 1 auto; min-height: 0; width: 100%; }
  .content.fill .grow-row .chart .yaxis { padding-bottom: 30px; }
  .content.fill .grow-row .chart .plot {
    display: flex;
    flex-direction: column;
    flex: 1 1 auto;
    width: 100%;
    min-width: 0;
  }

  /* A slightly taller stat strip reads better and pulls the rows below
     it down, which is where the blank band under the charts was. */
  .content.fill .stat.has-ic { padding: 14px var(--sp-4); }
  .content.fill .stat-ic { width: 46px; height: 46px; flex: 0 0 46px; }
  .content.fill .stat-ic img { width: 32px; height: 32px; }
  /* The chart sat above a band of empty card. Pushing the legend to
     the bottom uses that space instead of leaving it blank, and at this
     size the labels are worth reading rather than squinting at. */
  .content.fill .grow-row .legend {
    flex: 0 0 auto;
    margin-top: auto;
    padding-top: var(--sp-3);
    font-size: var(--text-sm);
    gap: var(--sp-5);
  }
  .content.fill .grow-row .legend i { width: 11px; height: 11px; margin-right: 7px; }

  /* Lists scroll inside their own card rather than growing the page. */
  .content.fill .grow-row .card > .feed:first-of-type { margin-top: 0; }
  .content.fill .grow-row .card .panel-list {
    flex: 1 1 auto;
    min-height: 0;
    height: 0;
    overflow-y: auto;
  }
  .content.fill .grow-row .card .empty { margin: auto 0; }

  /* The card was stretching but its contents were not, which left the
     space at the bottom instead of distributing it. Whatever sits last
     in the card absorbs the slack. */
  .content.fill .grow-row .card > *:last-child { flex: 1 1 auto; min-height: 0; }
  .content.fill .grow-row .card > .legend:last-child { flex: 0 0 auto; min-height: auto; }
  .content.fill .grow-row .card > .card-head:last-child { flex: 0 0 auto; }

  /* Rows of numbers and meters spread out rather than bunching at the
     top of a tall card. */
  .content.fill .grow-row .card .stat-row { flex: 0 0 auto; }
  .content.fill .grow-row .card .punch-now { flex: 1 1 auto; align-items: center; }
  .content.fill .grow-row .card .panel-list { display: flex; flex-direction: column; }
  .content.fill .grow-row .card .panel-list > .feed { flex: 0 0 auto; }
}

/* ---------- 29. Card heading icons ---------------------------
   A small mark beside the title, so the three panels in a row are
   findable by shape before the words are read. */
.card-head h2 .h-ic,
.card-head h1 .h-ic {
  width: 22px;
  height: 22px;
  object-fit: contain;
  vertical-align: -4px;
  margin-right: 8px;
}

/* The password gate stands in for the whole app, so it owns the
   viewport rather than sitting inside a shell that is not there. */
.pw-gate { min-height: 100vh; display: flex; align-items: center;
           justify-content: center; padding: var(--sp-4);
           background: var(--surface-sunken); }
.pw-card { width: 100%; max-width: 420px; background: var(--surface);
           border: 1px solid var(--line); border-radius: var(--r-lg);
           padding: var(--sp-6); box-shadow: var(--shadow-lg); }
.pw-card h1 { margin: 0 0 6px; font-size: 20px; }
.pw-card p { margin: 0 0 18px; color: var(--ink-500); line-height: 1.5; }

.mode-grid { display:grid; grid-template-columns:repeat(auto-fit, minmax(220px, 1fr));
             gap:var(--sp-3) }
.mode-card { border:1px solid var(--line); border-radius:var(--r-md); padding:var(--sp-4) }
.mode-card.is-on { border-color:rgb(var(--brand-primary-rgb));
                   background:rgba(var(--brand-primary-rgb), .04) }
.mode-name { font-weight:650; margin-bottom:4px }
.mode-card .btn { margin-top:10px }

/* The week picker is the whole question on that row, so the boxes are
   sized to be hit rather than squinted at. */
#wof-dlg { max-width: 900px; width: 92vw; }
#wof-dlg .modal-body { max-height: none; overflow: visible; }
.week-picks { display: flex; gap: 14px; align-items: center; flex-wrap: nowrap }
.week-picks label { display: flex; align-items: center; gap: 5px;
                    font-size: 13px; cursor: pointer; white-space: nowrap }
.week-picks input { width: 16px; height: 16px; margin: 0; cursor: pointer }
#wof-dlg table td { padding: 8px 12px }

/* A leave type that is not offered stays visible but quiet. */
tr.is-off td { opacity: .45 }
tr.is-off .badge { opacity: .6 }

/* A switch that reads the same on and off, only quieter when off: the
   knob moves and the mark inside it changes. */
.sw2 { width:44px; height:24px; border-radius:12px; border:0; padding:0;
       background:var(--ok-fg); position:relative; cursor:pointer;
       transition:background .18s ease }
.sw2-knob { width:18px; height:18px; border-radius:50%; background:#fff;
            position:absolute; top:3px; left:23px; display:grid;
            place-items:center; font-size:11px; line-height:1;
            color:var(--ok-fg); transition:left .18s ease, color .18s ease }
/* Off is the same switch in a paler green, not a greyed-out one: the
   row is still readable at a glance. */
.sw2:not(.is-on) { background:rgba(16, 185, 129, .28) }
.sw2:not(.is-on) .sw2-knob { left:3px; color:rgba(16, 185, 129, .8) }
.sw2:focus-visible { outline:2px solid rgb(var(--brand-primary-rgb));
                     outline-offset:2px }

/* Impossible to miss, because forgetting you are inside somebody
   else's account is the whole risk. */
#support-bar { position:sticky; top:0; z-index:900; display:flex;
               align-items:center; justify-content:space-between; gap:16px;
               padding:10px 20px; background:var(--warn-bg);
               color:var(--warn-fg); border-bottom:1px solid var(--warn-fg);
               font-size:13px }
#support-bar strong { font-weight:650 }

/* The plan running out, said once in the middle rather than as a strip
   that moves the whole page down. */
.plan-dlg { max-width:420px }
.plan-dlg-icon { font-size:42px; line-height:1 }
.plan-dlg.is-warn .plan-dlg-icon { color:var(--warn-fg) }
.plan-dlg.is-danger .plan-dlg-icon { color:var(--danger-fg) }

/* Searching the menu. Above it rather than inside, so it does not move
   when the list filters. */
.rail-find { padding:0 14px 10px }
.rail-find .input { width:100%; height:32px; font-size:13px; padding:0 10px }
.rail-link.is-hidden, .rail-group.is-hidden { display:none }

/* A menu item that opens rather than going anywhere. */
.rail-parent { width:100%; background:transparent; border:0; text-align:left;
               font:inherit; cursor:pointer;
               color:var(--ink-700); font-weight:500 }
.rail-chev { margin-left:auto; font-size:15px; color:var(--ink-600);
             transition:transform .15s; line-height:1 }
.rail-parent.is-open .rail-chev { transform:rotate(90deg) }
.rail-kids { display:none; margin:1px 0 4px 34px; padding-left:10px;
             border-left:1px solid var(--line) }
.rail-kids.is-open { display:block }
.rail-kid { display:block; padding:6px 8px; border-radius:6px;
            font-size:inherit; color:inherit; text-decoration:none }
.rail-kid:hover { background:var(--surface-2); color:var(--ink-900) }
.rail-kid.is-active { color:rgb(var(--brand-primary-rgb)); font-weight:600 }
.rail-kid.is-hidden { display:none }

/* A menu item with nothing behind it yet. Visible so the shape is
   clear, quiet so nobody keeps clicking it. */
.rail-soon { opacity:.55; cursor:default }
.rail-soon-tag { margin-left:auto; font-size:9px; letter-spacing:.4px;
                 padding:1px 5px; border-radius:4px;
                 background:var(--surface-2); color:var(--ink-500);
                 text-transform:uppercase; font-weight:600 }
.rail-kid.rail-soon { display:flex; align-items:center }

/* Attendance policy. Each way of punching carries its own rules inside
   its own card, so a setting is never read against the wrong mode. */
.ap-sub { font-size:11px; text-transform:uppercase; letter-spacing:.5px;
          color:var(--ink-500); font-weight:600; margin:0 0 10px }
.ap-common { border:1px solid var(--line); border-radius:var(--r-md);
             padding:16px 18px; margin-bottom:22px;
             background:var(--surface-1) }
/* Three abreast on a wide screen, stacked on a narrow one. Each mode
   has its own colour so it is recognised before it is read. */
.ap-grid { display:grid; grid-template-columns:repeat(auto-fit,minmax(300px,1fr));
           gap:14px; align-items:start }
.ap-card { border:1px solid var(--line); border-radius:var(--r-md);
           overflow:hidden; display:flex; flex-direction:column }
.ap-card.is-on { border-width:2px }

.ap-head { display:flex; align-items:flex-start; gap:12px; padding:16px 18px;
           flex-wrap:wrap }
.ap-head img { margin-top:1px }

/* Punching from a phone: the blue of the app itself. */
.ap-selfie { border-color:#93c5fd }
.ap-selfie .ap-head { background:linear-gradient(135deg,#dbeafe,#e0e7ff) }
.ap-selfie.is-on { border-color:#3b82f6 }

/* A fingerprint reader: warmer, and unmistakably not the phone. */
.ap-fingerprint { border-color:#fcd34d }
.ap-fingerprint .ap-head { background:linear-gradient(135deg,#fef3c7,#fde68a) }
.ap-fingerprint.is-on { border-color:#f59e0b }

/* A face reader: green, the third of three. */
.ap-face { border-color:#86efac }
.ap-face .ap-head { background:linear-gradient(135deg,#dcfce7,#bbf7d0) }
.ap-face.is-on { border-color:#22c55e }
.ap-name { font-size:15px; font-weight:600 }
.ap-desc { font-size:12px; color:var(--ink-500); margin-top:2px }
.ap-body { padding:4px 18px 14px; border-top:1px solid var(--line) }
.ap-body { flex:1 }
.ap-set { display:flex; align-items:center; justify-content:space-between;
          gap:14px; padding:11px 0; border-bottom:1px solid var(--line) }
.ap-set .input { width:66px }
.ap-set.is-last { border-bottom:0 }
.ap-set-name { font-size:13px }
.ap-set-help { font-size:11px; color:var(--ink-500); margin-top:1px }
.ap-reader { display:flex; align-items:center; justify-content:space-between;
             gap:12px; padding:9px 12px; border-radius:8px;
             background:var(--surface-2); margin-bottom:6px }
.ap-reader-sub { font-size:11px; color:var(--ink-500); margin-top:1px }

/* The payslip register. */
.ps-bar { display:flex; align-items:center; gap:14px; flex-wrap:wrap;
          padding:14px 18px; border:1px solid var(--line);
          border-radius:var(--r-md); margin-bottom:18px;
          background:linear-gradient(135deg,rgba(99,102,241,.08),rgba(59,130,246,.08)) }
.ps-facts { display:flex; gap:22px }
.ps-n { font-size:16px; font-weight:600; line-height:1.2 }
.ps-l { font-size:11px; color:var(--ink-500) }

.ps-table { width:100%; border-collapse:collapse; font-size:13px }
.ps-table th { text-align:left; padding:10px 14px; font-weight:600;
               font-size:11px; text-transform:uppercase; letter-spacing:.4px;
               color:var(--ink-500); background:var(--surface-2) }
.ps-table td { padding:11px 14px; border-top:1px solid var(--line);
               vertical-align:middle }
.ps-table .right { text-align:right }

.ps-who { display:flex; align-items:center; gap:10px }
.ps-av { width:30px; height:30px; border-radius:50%; display:grid;
         place-items:center; font-size:11px; font-weight:600; flex:0 0 auto }
.ps-sub { font-size:11px; color:var(--ink-500); margin-top:1px }

.chip-tag { font-size:11px; padding:2px 9px; border-radius:var(--r-sm);
            display:inline-block }

/* A payslip read without leaving the list. */
.sl-top { display:grid; grid-template-columns:repeat(auto-fit,minmax(130px,1fr));
          gap:12px; padding:14px 16px; border:1px solid var(--line);
          border-radius:var(--r-md); margin-bottom:16px;
          background:var(--surface-2) }
.sl-l { font-size:11px; color:var(--ink-500) }
.sl-v { font-size:13px; font-weight:600; margin-top:1px }

.sl-cols { display:grid; grid-template-columns:1fr 1fr; gap:16px }
@media (max-width:640px) { .sl-cols { grid-template-columns:1fr } }
.sl-col { border:1px solid var(--line); border-radius:var(--r-md);
          padding:12px 14px }
.sl-h { font-size:11px; text-transform:uppercase; letter-spacing:.5px;
        color:var(--ink-500); font-weight:600; margin-bottom:8px }
.sl-line { display:flex; justify-content:space-between; gap:12px;
           font-size:13px; padding:4px 0 }
.sl-line.is-sum { border-top:1px solid var(--line); margin-top:6px;
                  padding-top:8px; font-weight:650 }

.sl-net { display:flex; justify-content:space-between; align-items:center;
          margin-top:16px; padding:14px 18px; border-radius:var(--r-md);
          background:linear-gradient(135deg,rgba(16,185,129,.12),rgba(59,130,246,.12));
          font-size:18px; font-weight:650 }
.sl-words { font-size:11px; color:var(--ink-500); margin-top:8px;
            text-align:right }

/* A face beside the name; a grey circle where there is none. */
.ps-dp { width:32px; height:32px; border-radius:50%; object-fit:cover;
         flex:0 0 auto; background:var(--surface-3) }
.ps-dp.is-blank { background:var(--ink-200) }


/* A labelled setting with its control on the right. Shared, because
   more than one page lays settings out this way now. */
.setting { display:flex; gap:var(--sp-4); padding:var(--sp-4) 0;
           border-bottom:1px solid var(--line) }
.setting:last-child { border-bottom:0 }
.setting-text { flex:1; min-width:0 }
.setting-text .t { font-weight:600; font-size:var(--text-base) }
.setting-text .d { font-size:var(--text-sm); color:var(--ink-500);
                   margin-top:3px; line-height:1.55 }
.setting-ctrl { flex:0 0 auto; display:flex; align-items:center;
                gap:var(--sp-2) }
.setting-ctrl .input { width:120px }
.setting-ctrl .input.wide { width:190px }

/* The switch those settings rows use. Shared for the same reason. */
.sw { position:relative; width:42px; height:24px; flex:0 0 42px }
.sw input { opacity:0; width:0; height:0 }
.sw span { position:absolute; inset:0; background:var(--line);
           border-radius:99px; cursor:pointer;
           transition:background .15s ease }
.sw span::before { content:""; position:absolute; width:18px; height:18px;
                   left:3px; top:3px; background:#fff; border-radius:50%;
                   transition:transform .15s ease; box-shadow:var(--shadow-sm) }
.sw input:checked + span { background:var(--brand-primary) }
.sw input:checked + span::before { transform:translateX(18px) }
.sw input:focus-visible + span { outline:2px solid var(--brand-primary);
                                 outline-offset:2px }

/* Lists across the engagements pages: tabs that carry their own count,
   and actions as icons rather than a row of words. */
.ce-tabs { display:flex; gap:2px; border-bottom:1px solid var(--line);
           margin:0 0 var(--sp-4) }
.ce-tab { background:transparent; border:0; border-bottom:2px solid transparent;
          padding:9px 16px; font:inherit; font-size:var(--text-sm);
          color:var(--ink-500); cursor:pointer; display:flex;
          align-items:center; gap:7px }
.ce-tab:hover { color:var(--ink-900) }
.ce-tab.is-on { color:rgb(var(--brand-primary-rgb)); font-weight:600;
                border-bottom-color:rgb(var(--brand-primary-rgb)) }
.ce-n { background:var(--surface-sunken); border-radius:99px;
        padding:1px 8px; font-size:var(--text-xs); font-weight:600 }
.ce-tab.is-on .ce-n { background:rgba(99,102,241,.14) }

.ce-name { font-weight:600; color:var(--ink-900) }

.ce-acts { display:flex; gap:4px }
.ce-act { width:32px; height:32px; border-radius:9px; border:0;
          display:grid; place-items:center; cursor:pointer;
          color:#fff; padding:0; transition:filter .12s }
.ce-act:hover { filter:brightness(1.08) }
.ce-act:active { filter:brightness(.94) }
.ce-act svg { width:17px; height:17px }
.ce-act.is-view   { background:#3b82f6 }
.ce-act.is-edit   { background:#7c3aed }
.ce-act.is-toggle { background:#f59e0b }
.ce-act.is-danger { background:#dc2626 }
.ce-act:disabled  { opacity:.45; cursor:default; filter:none }

.v-row { display:flex; justify-content:space-between; gap:16px;
         padding:9px 0; border-bottom:1px solid var(--line);
         font-size:var(--text-sm) }
.v-row:last-child { border-bottom:0 }
.v-l { color:var(--ink-500) }
.v-v { text-align:right }


/* A thinner scrollbar. The default on Windows is wide enough to read
   as a design element, which it is not. */
/* Chrome and Edge honour scrollbar-width over the -webkit rules below,
   so the exact size we want never took effect while it was set for every
   browser. Firefox has only scrollbar-width, so it keeps it; the others
   take the width from the -webkit rule. */
@supports (-moz-appearance: none) {
  * { scrollbar-width: thin; scrollbar-color: #b6bdcc transparent }
}
*::-webkit-scrollbar { width: 3.5px; height: 3.5px }
*::-webkit-scrollbar-track { background: transparent }
*::-webkit-scrollbar-thumb { background: #b6bdcc; border-radius: 99px }
*::-webkit-scrollbar-thumb:hover { background: #8b94a7 }

/* Picking particular people out of a list that could be long. */


.pick-row:last-child { border-bottom:0 }
.pick-row:hover { background:var(--surface-sunken) }
.ce-tag.is-person { background:rgba(124,58,237,.12); color:#6d28d9 }

/* A dropdown that holds tick boxes and reports how many are ticked. */




.pick-pop .pick-row:last-child { border-bottom:0 }
.pick-pop .pick-row:hover { background:var(--surface-sunken) }
.pick-pop .pick-row.is-all { border-bottom:2px solid var(--line);
                             background:var(--surface-sunken) }

/* The three-part audience picker. */

.aud .field { position:relative }






/* A dropdown that floats over the page rather than pushing it, with a
   search box once the list is long enough to need one. */
.pick { position:relative }
.pick-btn { display:flex; align-items:center; justify-content:space-between;
            gap:8px; width:100%; text-align:left; cursor:pointer;
            background:var(--surface) }
.pick-btn.is-open { border-color:var(--brand-primary) }
.pick-text { overflow:hidden; text-overflow:ellipsis; white-space:nowrap }
.pick-chev { color:var(--ink-500); transform:rotate(-90deg);
             transition:transform .15s; flex:0 0 auto }
.pick-btn.is-open .pick-chev { transform:rotate(90deg) }

.pick-pop { position:absolute; top:calc(100% + 4px); left:0; right:0;
            z-index:60; background:var(--surface);
            border:1px solid var(--line); border-radius:var(--r-md);
            box-shadow:var(--shadow-lg); overflow:hidden }
.pick-search { padding:8px; border-bottom:1px solid var(--line) }
.pick-search .input { width:100%; height:32px }
.pick-list { max-height:260px; overflow-y:auto; padding:4px }

.pick-row { display:flex; align-items:center; gap:10px; width:100%;
            padding:8px 10px; border:0; border-radius:var(--r-sm);
            background:transparent; font:inherit;
            font-size:var(--text-base); color:var(--ink-900);
            text-align:left; cursor:pointer }
.pick-row:hover { background:var(--surface-sunken) }
.pick-row.is-on { background:var(--surface-sunken) }
.pick-tick { width:16px; height:16px; flex:0 0 16px;
             color:var(--brand-primary) }
.pick-sub { color:var(--ink-500); font-size:var(--text-sm) }
.pick-none { padding:18px; text-align:center; color:var(--ink-500);
             font-size:var(--text-sm) }

.aud { display:grid; grid-template-columns:repeat(auto-fit,minmax(210px,1fr));
       gap:var(--sp-4) }
.pick-foot { display:flex; align-items:center; justify-content:space-between;
             gap:10px; padding:8px 10px; border-top:1px solid var(--line);
             background:var(--surface-sunken) }
.pick-count { font-size:var(--text-sm); color:var(--ink-600) }

/* The meeting and event form: four along the top, then the
   description beside where it is held. */
.ef-top { display:grid; grid-template-columns:1fr 2fr;
          gap:var(--sp-4); margin-bottom:var(--sp-4);
          align-items:start }
.ef-when { display:grid; grid-template-columns:repeat(3,1fr);
           gap:var(--sp-4); border-top:1px solid var(--line);
           padding-top:var(--sp-4) }
.ef-mid { display:grid; grid-template-columns:2fr 1fr 1.4fr 1fr;
          gap:var(--sp-4); align-items:start; margin-bottom:var(--sp-5) }
.ef-mid.is-narrow { grid-template-columns:2fr 1fr 1.6fr }
.ef-mid textarea { resize:vertical; min-height:86px }
@media (max-width:1000px) {
  .ef-top, .ef-mid, .ef-mid.is-narrow, .ef-when { grid-template-columns:1fr 1fr }
}
@media (max-width:620px) {
  .ef-top, .ef-mid, .ef-mid.is-narrow, .ef-when { grid-template-columns:1fr }
}
.ef-who { border-top:1px solid var(--line); padding-top:var(--sp-4) }
.ef-who-head { font-size:var(--text-base); font-weight:650;
               margin-bottom:var(--sp-3) }

/* What is on for one date. */
.day-ev { display:flex; align-items:center; gap:12px; padding:12px 14px;
          border:1px solid var(--line); border-radius:var(--r-md);
          margin-bottom:8px; background:var(--surface) }
.day-ev-ic { width:34px; height:34px; object-fit:contain; flex:0 0 auto }
.day-ev-t { font-weight:600 }
.day-ev-s { font-size:var(--text-sm); color:var(--ink-500); margin-top:1px }
.ft-tabs { display:flex; gap:2px; margin-bottom:var(--sp-4) }

/* The bell, and what is behind it. */
.bell-wrap { position:relative }
.bell-dot { position:absolute; top:2px; right:2px; min-width:16px;
            height:16px; padding:0 4px; border-radius:99px;
            background:#ef4444; color:#fff; font-size:10px;
            font-weight:700; display:grid; place-items:center;
            line-height:1; border:2px solid var(--surface) }
.bell-pop { position:absolute; top:calc(100% + 8px); right:0; z-index:80;
            width:330px; max-width:calc(100vw - 24px);
            background:var(--surface); border:1px solid var(--line);
            border-radius:14px; box-shadow:var(--shadow-lg);
            overflow:hidden }
.bell-head { display:flex; align-items:center; justify-content:space-between;
             padding:12px 14px; border-bottom:1px solid var(--line);
             font-size:13px; font-weight:650 }
.bell-clear { border:0; background:transparent; font:inherit;
              font-size:12px; color:var(--brand-primary); cursor:pointer;
              font-weight:500 }
.bell-list { max-height:380px; overflow-y:auto }
.bell-item { display:block; padding:12px 14px;
             border-bottom:1px solid var(--line); text-decoration:none;
             color:inherit }
.bell-item:last-child { border-bottom:0 }
.bell-item:hover { background:var(--surface-sunken) }
.bell-item.is-new { background:rgba(99,102,241,.05);
                    border-left:3px solid var(--brand-primary);
                    padding-left:11px }
.bell-t { font-size:13px; font-weight:600; line-height:1.35 }
.bell-b { font-size:12px; color:var(--ink-600); margin-top:2px;
          line-height:1.4; display:-webkit-box; -webkit-line-clamp:2;
          -webkit-box-orient:vertical; overflow:hidden }
.bell-ago { font-size:11px; color:var(--ink-500); margin-top:4px }
.bell-none { padding:34px 14px; text-align:center; color:var(--ink-500);
             font-size:13px }
.icon-btn.is-3d { padding:0; display:grid; place-items:center }
.icon-btn.is-3d img { width:22px; height:22px; object-fit:contain }

.bell-all { display:block; padding:11px; text-align:center;
            border-top:1px solid var(--line); font-size:12.5px;
            color:var(--brand-primary); text-decoration:none;
            font-weight:500 }
.bell-all:hover { background:var(--surface-sunken) }
.ann-right { display:flex; align-items:center; gap:10px; flex:0 0 auto }
.ann-del { width:28px; height:28px; border:0; border-radius:8px;
           background:#fee2e2; color:#b91c1c; display:grid;
           place-items:center; cursor:pointer; padding:0 }
.ann-del:hover { background:#fecaca }
.ann-del svg { width:14px; height:14px }
.view-mode { font-size:12px; font-weight:700; letter-spacing:.05em;
             text-transform:uppercase; color:var(--ink-600);
             padding:6px 12px; border-radius:99px;
             background:var(--surface-sunken);
             border:1px solid var(--line); white-space:nowrap }

/* --- The frame, before JavaScript draws it ------------------------
   The whole shell — rail, topbar, content — is built in JavaScript and
   dropped into an empty <body>. So for a beat the page is blank, and
   then an entire layout appears at once. That jump is what reads as a
   flicker.

   Painting the rail's stripe and its edge here means the frame is
   already on screen when the real markup lands on top of it, in exactly
   the same place. Nothing flashes, nothing shifts; the menu simply
   fills in.

   Below 901px the rail is a drawer parked off-screen, so a stripe there
   would be a lie. It is drawn only where the rail actually sits. */
@media (min-width: 901px) {
  body {
    background-image:
      linear-gradient(to right,
        var(--surface-rail) 0,
        var(--surface-rail) var(--rail-w),
        var(--line-brand)   var(--rail-w),
        var(--line-brand)   calc(var(--rail-w) + 1px),
        transparent         calc(var(--rail-w) + 1px)),
      var(--page-bg);
    background-repeat: no-repeat;
    background-attachment: fixed;
  }
}

/* Shell JavaScript banata he, isliye cold load par browser pehle kachcha
   HTML paint kar deta tha -- form poori chaudai me, bina rail ke, aadhe
   second ke liye. Shell bante hi ye rok apne aap hat jati he.
   4 second ka jaal: agar JS kabhi na aaye to content phir bhi dikhe. */
body.shell:not(:has(.app)) > * {
    visibility: hidden;
    animation: hr-reveal 0s 4s forwards;
}
@keyframes hr-reveal { to { visibility: visible } }
