/* ============================================================================
   Digital Work Space — design system

   Direction: an HR system people keep open for eight hours, not a landing page.
   That means solid surfaces rather than glass, one accent rather than seven,
   crisp hairline borders, and type that holds up in a dense table of payroll
   figures. Every token name here predates this file's current values — the
   names are a contract with ~1,000 lines of component CSS and 49 pages, so
   values changed and names did not.

   Light is the primary experience (OS preference decides), because that is
   where payroll and attendance data is actually read. Dark is a full peer,
   not an afterthought.
   ============================================================================ */
:root {
  color-scheme: dark;

  /* ---------- Foundation (dark) ---------- */
  --bg-primary: #0B0F19;
  --bg-secondary: #111827;
  --bg-elevated: #1A2236;
  /* Kept translucent: these are overlay fills (row hover, pressed states), not surfaces. */
  --surface-glass: rgba(255, 255, 255, .025);
  --surface-glass-strong: rgba(255, 255, 255, .06);
  --border-subtle: rgba(255, 255, 255, .09);
  --border-strong: rgba(255, 255, 255, .17);
  --border: var(--border-subtle);
  --scrim: rgba(2, 6, 16, .70);

  /* ---------- Text ---------- */
  --text-primary: #F9FAFB;
  --text-secondary: #98A2B3;
  --text-tertiary: #667085;
  --text-muted: var(--text-secondary);
  --text-on-accent: #FFFFFF;

  /* ---------- Brand ----------
     Violet is pulled toward indigo so the two read as one family. The old pair
     (#6366F1 + #8B5CF6) fought each other across the sidebar, topbar and every
     primary button. */
  --indigo: #6172F3;
  --indigo-dark: #4E5BC6;
  --violet: #7A85F5;
  --brand-gradient: linear-gradient(135deg, #4E5BC6, #7A85F5);
  --accent: var(--indigo);
  --accent-dark: var(--indigo-dark);
  --accent-soft: rgba(97, 114, 243, .16);
  --purple: var(--violet);

  /* ---------- Data / supporting colours ----------
     For charts and category marks only. Chrome does not use these. */
  --cyan: #67E3F9;
  --emerald: #47CD89;
  --pink: #F670C7;
  --orange: #FDB022;
  --blue: #84CAFF;

  /* ---------- Semantic ---------- */
  --success: #47CD89;
  --success-bg: rgba(71, 205, 137, .14);
  --danger: #F97066;
  --danger-bg: rgba(249, 112, 102, .14);
  --warning: #FDB022;
  --warning-bg: rgba(253, 176, 34, .14);
  --info: #84CAFF;
  --info-bg: rgba(132, 202, 255, .14);
  --gray: #98A2B3;
  --gray-bg: rgba(152, 162, 179, .14);
  --cyan-bg: rgba(103, 227, 249, .14);
  --pink-bg: rgba(246, 112, 199, .14);
  --purple-bg: rgba(122, 133, 245, .14);
  --danger-soft: var(--danger-bg);
  --warning-soft: var(--warning-bg);
  --info-soft: var(--info-bg);

  /* ---------- Chrome ----------
     The topbar used to be solid violet. An eight-hour tool should not shout. */
  --sidebar-bg: var(--bg-secondary);
  --sidebar-bg-2: var(--bg-elevated);
  --sidebar-active: var(--indigo);
  --topbar-bg: var(--bg-secondary);

  /* ---------- Shape ----------
     Tightened. Large radii read consumer; enterprise density wants restraint. */
  --radius-sm: 6px;
  --radius: 8px;
  --radius-lg: 10px;
  --radius-xl: 14px;

  /* ---------- Elevation / motion ----------
     glow-indigo is retained as a name but is no longer a glow: a coloured halo
     under every brand element was the single biggest "not a real product" tell. */
  --shadow-sm: 0 1px 2px rgba(0, 0, 0, .32);
  --shadow-md: 0 4px 14px rgba(0, 0, 0, .38);
  --shadow-lg: 0 16px 40px rgba(0, 0, 0, .50);
  --glow-indigo: var(--shadow-sm);
  --transition: 140ms ease;
}

/* ---------- Light: the primary experience ---------- */
@media (prefers-color-scheme: light) {
  :root:not([data-theme="dark"]) {
    color-scheme: light;

    --bg-primary: #F7F8FA;
    --bg-secondary: #FFFFFF;
    --bg-elevated: #FFFFFF;
    --surface-glass: rgba(16, 24, 40, .022);
    --surface-glass-strong: rgba(16, 24, 40, .05);
    --border-subtle: rgba(16, 24, 40, .09);
    --border-strong: rgba(16, 24, 40, .15);
    --scrim: rgba(16, 24, 40, .45);

    --text-primary: #101828;
    --text-secondary: #475467;
    --text-tertiary: #98A2B3;

    --indigo: #4F46E5;
    --indigo-dark: #4338CA;
    --violet: #6366F1;
    --brand-gradient: linear-gradient(135deg, #4F46E5, #6366F1);
    --accent-soft: rgba(79, 70, 229, .10);

    --cyan: #0E7090;
    --emerald: #067647;
    --pink: #C11574;
    --orange: #B54708;
    --blue: #175CD3;

    --success: #067647;
    --success-bg: rgba(6, 118, 71, .10);
    --danger: #B42318;
    --danger-bg: rgba(180, 35, 24, .10);
    --warning: #B54708;
    --warning-bg: rgba(181, 71, 8, .10);
    --info: #175CD3;
    --info-bg: rgba(23, 92, 211, .10);
    --gray: #475467;
    --gray-bg: rgba(71, 84, 103, .09);
    --cyan-bg: rgba(14, 112, 144, .10);
    --pink-bg: rgba(193, 21, 116, .10);
    --purple-bg: rgba(99, 102, 241, .10);

    --shadow-sm: 0 1px 2px rgba(16, 24, 40, .06);
    --shadow-md: 0 4px 12px rgba(16, 24, 40, .08);
    --shadow-lg: 0 12px 32px rgba(16, 24, 40, .14);
  }
}

/* Explicit toggle always wins over the system preference. Same values as above. */
:root[data-theme="light"] {
  color-scheme: light;

  --bg-primary: #F7F8FA;
  --bg-secondary: #FFFFFF;
  --bg-elevated: #FFFFFF;
  --surface-glass: rgba(16, 24, 40, .022);
  --surface-glass-strong: rgba(16, 24, 40, .05);
  --border-subtle: rgba(16, 24, 40, .09);
  --border-strong: rgba(16, 24, 40, .15);
  --scrim: rgba(16, 24, 40, .45);

  --text-primary: #101828;
  --text-secondary: #475467;
  --text-tertiary: #98A2B3;

  --indigo: #4F46E5;
  --indigo-dark: #4338CA;
  --violet: #6366F1;
  --brand-gradient: linear-gradient(135deg, #4F46E5, #6366F1);
  --accent-soft: rgba(79, 70, 229, .10);

  --cyan: #0E7090;
  --emerald: #067647;
  --pink: #C11574;
  --orange: #B54708;
  --blue: #175CD3;

  --success: #067647;
  --success-bg: rgba(6, 118, 71, .10);
  --danger: #B42318;
  --danger-bg: rgba(180, 35, 24, .10);
  --warning: #B54708;
  --warning-bg: rgba(181, 71, 8, .10);
  --info: #175CD3;
  --info-bg: rgba(23, 92, 211, .10);
  --gray: #475467;
  --gray-bg: rgba(71, 84, 103, .09);
  --cyan-bg: rgba(14, 112, 144, .10);
  --pink-bg: rgba(193, 21, 116, .10);
  --purple-bg: rgba(99, 102, 241, .10);

  --shadow-sm: 0 1px 2px rgba(16, 24, 40, .06);
  --shadow-md: 0 4px 12px rgba(16, 24, 40, .08);
  --shadow-lg: 0 12px 32px rgba(16, 24, 40, .14);
}
:root[data-theme="dark"] { color-scheme: dark; }
* { box-sizing: border-box; }
html { scroll-behavior: smooth; }
body {
  margin: 0;
  /* No webfont: these deploy on office LANs with no internet, where a Google
     Fonts link is a blocked request and a flash of nothing. The system UI stack
     is what every OS already renders best. */
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI Variable Text", "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
  background: var(--bg-primary);
  color: var(--text-primary);
  font-size: 14px;
  -webkit-font-smoothing: antialiased;
}
a { color: inherit; text-decoration: none; }
:focus-visible { outline: 2px solid var(--indigo); outline-offset: 2px; border-radius: 4px; }
::-webkit-scrollbar { width: 9px; height: 9px; }
::-webkit-scrollbar-track { background: transparent; }
::-webkit-scrollbar-thumb { background: var(--border-strong); border-radius: 8px; }
::-webkit-scrollbar-thumb:hover { background: var(--text-tertiary); }

.ui-icon { display: inline-block; vertical-align: -3px; flex: none; }

/* AJAX top progress bar */
#ajax-progress {
  position: fixed; top: 0; left: 0; height: 3px; width: 0%; z-index: 999;
  background: var(--accent);
  transition: opacity 200ms ease;
}

.app-shell { display: flex; min-height: 100vh; }

/* ================= Sidebar ================= */
/* Standard expandable ERP-style sidebar by default (icon + visible label, click-to-expand
   accordion for groups) — a hover-triggered flyout read as unfamiliar/broken rather than
   premium, so that behavior is now opt-in via the collapse toggle (.sidebar.collapsed), where
   it correctly signals "this is a compact rail, hover for more" instead of being the default
   first impression. */
.sidebar {
  width: 252px;
  flex: none;
  background: var(--bg-secondary);
  border-right: 1px solid var(--border-subtle);
  color: var(--text-secondary);
  display: flex;
  flex-direction: column;
  padding: 18px 12px;
  position: relative;
  z-index: 40;
  transition: width 200ms ease;
}
.sidebar .brand { display: flex; align-items: center; gap: 10px; padding: 2px 6px 16px; margin-bottom: 8px; border-bottom: 1px solid var(--border-subtle); }
.sidebar .brand-mark {
  width: 36px; height: 36px; border-radius: var(--radius-sm); flex: none;
  background: var(--brand-gradient); color: #fff;
  display: flex; align-items: center; justify-content: center;
  font-weight: 800; font-size: 12px; letter-spacing: .02em;
  box-shadow: var(--glow-indigo);
}
/* A tenant logo sits in its own tile: no gradient or glow behind it, because those are the
   product's brand and would tint somebody else's mark. `contain` so a wide wordmark is letterboxed
   rather than cropped — logos are rarely square and cropping one is worse than showing it small. */
.sidebar .brand-mark.has-logo {
  background: var(--surface-glass-strong);
  box-shadow: none;
  overflow: hidden;
  padding: 3px;
}
.sidebar .brand-mark.has-logo img { width: 100%; height: 100%; object-fit: contain; display: block; }
.sidebar .brand-name { font-weight: 800; font-size: 15px; color: var(--text-primary); letter-spacing: .01em; white-space: nowrap; overflow: hidden; }

.sidebar-collapse-btn {
  position: absolute; top: 66px; right: -12px; width: 24px; height: 24px; border-radius: 50%;
  background: var(--bg-elevated); border: 1px solid var(--border-strong); color: var(--text-secondary);
  display: flex; align-items: center; justify-content: center; cursor: pointer; z-index: 45; padding: 0;
  transition: background var(--transition), color var(--transition); box-shadow: var(--shadow-sm);
}
.sidebar-collapse-btn:hover { color: var(--text-primary); background: var(--surface-glass-strong); }
.sidebar-collapse-btn svg { transition: transform 200ms ease; }
.sidebar.collapsed .sidebar-collapse-btn svg { transform: rotate(180deg); }

.sidebar .user-box {
  display: flex; align-items: center; gap: 10px;
  padding: 4px 6px 14px; margin-bottom: 6px; border-bottom: 1px solid var(--border-subtle); width: 100%;
}
.sidebar .user-box .avatar {
  width: 34px; height: 34px; border-radius: 50%; flex: none;
  background: var(--surface-glass-strong); border: 1px solid var(--border-strong);
  display: flex; align-items: center; justify-content: center;
  font-weight: 700; font-size: 12px; color: var(--text-primary);
}
.sidebar .user-box .name { font-weight: 600; color: var(--text-primary); font-size: 13px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.sidebar .user-box .role { font-size: 11px; color: var(--text-tertiary); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }

.sidebar nav { flex: 1; overflow-y: auto; overflow-x: hidden; padding: 4px 0; display: flex; flex-direction: column; gap: 2px; width: 100%; }
.sidebar nav::-webkit-scrollbar { width: 5px; }

.nav-group { position: relative; width: 100%; }
.nav-group > .nav-label {
  display: flex; align-items: center; gap: 12px; width: 100%; height: 42px; padding: 0 11px;
  border-radius: var(--radius-sm); cursor: pointer;
  font-size: 13.5px; font-weight: 600; color: var(--text-secondary);
  transition: background var(--transition), color var(--transition);
}
.nav-group > .nav-label .nav-ico { flex: none; width: 18px; display: flex; align-items: center; justify-content: center; }

/* ---- Per-section icon colour ----------------------------------------------------------------
   Colour lands on the ICON ONLY; label text stays --text-secondary. Colouring the text too would
   put twelve competing hues in a single column and make the one that matters — the active item —
   harder to find, which is the opposite of the point. The icon carries the hue, the text stays
   readable, and the active row's indigo tint still wins because it is the only filled background.

   Keyed off data-nav (set in js/shell.js), which reuses the icon name. A section with no rule
   here just inherits the neutral colour, so adding a nav item can never break the sidebar.

   Hues are set per theme: the dark palette needs light, desaturated tones to stay legible on a
   near-black panel, while light mode needs deeper ones for contrast against near-white. */
:root {
  --nav-dashboard:  #818CF8;  /* indigo  */
  --nav-settings:   #A78BFA;  /* violet  */
  --nav-users:      #2DD4BF;  /* teal    */
  --nav-attendance: #FBBF24;  /* amber   */
  --nav-monitor:    #38BDF8;  /* sky     */
  --nav-calendar:   #FB7185;  /* rose    */
  --nav-barChart:   #22D3EE;  /* cyan    */
  --nav-wallet:     #34D399;  /* emerald */
  --nav-mapPin:     #FB923C;  /* orange  */
  --nav-trash:      #94A3B8;  /* slate   */
  --nav-building:   #C084FC;  /* purple  */
  --nav-creditCard: #4ADE80;  /* green   */
  --nav-bell:       #F472B6;  /* pink    */
}
@media (prefers-color-scheme: light) {
  :root:not([data-theme="dark"]) {
    --nav-dashboard:  #4F46E5;
    --nav-settings:   #7C3AED;
    --nav-users:      #0D9488;
    --nav-attendance: #B45309;
    --nav-monitor:    #0284C7;
    --nav-calendar:   #E11D48;
    --nav-barChart:   #0891B2;
    --nav-wallet:     #059669;
    --nav-mapPin:     #EA580C;
    --nav-trash:      #64748B;
    --nav-building:   #9333EA;
    --nav-creditCard: #16A34A;
  --nav-bell:       #DB2777;
  }
}
:root[data-theme="light"] {
  --nav-dashboard:  #4F46E5;
  --nav-settings:   #7C3AED;
  --nav-users:      #0D9488;
  --nav-attendance: #B45309;
  --nav-monitor:    #0284C7;
  --nav-calendar:   #E11D48;
  --nav-barChart:   #0891B2;
  --nav-wallet:     #059669;
  --nav-mapPin:     #EA580C;
  --nav-trash:      #64748B;
  --nav-building:   #9333EA;
  --nav-creditCard: #16A34A;
  --nav-bell:       #DB2777;
}

.nav-group[data-nav="dashboard"]  > .nav-label .nav-ico { color: var(--nav-dashboard); }
.nav-group[data-nav="settings"]   > .nav-label .nav-ico { color: var(--nav-settings); }
.nav-group[data-nav="users"]      > .nav-label .nav-ico { color: var(--nav-users); }
.nav-group[data-nav="attendance"] > .nav-label .nav-ico { color: var(--nav-attendance); }
.nav-group[data-nav="monitor"]    > .nav-label .nav-ico { color: var(--nav-monitor); }
.nav-group[data-nav="calendar"]   > .nav-label .nav-ico { color: var(--nav-calendar); }
.nav-group[data-nav="barChart"]   > .nav-label .nav-ico { color: var(--nav-barChart); }
.nav-group[data-nav="wallet"]     > .nav-label .nav-ico { color: var(--nav-wallet); }
.nav-group[data-nav="mapPin"]     > .nav-label .nav-ico { color: var(--nav-mapPin); }
.nav-group[data-nav="trash"]      > .nav-label .nav-ico { color: var(--nav-trash); }
.nav-group[data-nav="building"]   > .nav-label .nav-ico { color: var(--nav-building); }
.nav-group[data-nav="creditCard"] > .nav-label .nav-ico { color: var(--nav-creditCard); }
.nav-group[data-nav="bell"]       > .nav-label .nav-ico { color: var(--nav-bell); }

/* Dimmed at rest so the column reads as one list rather than twelve badges; full strength on
   hover, on the open group, and on the active row. */
.nav-group > .nav-label .nav-ico { opacity: .82; transition: opacity var(--transition); }
.nav-group > .nav-label:hover .nav-ico,
.nav-group.open > .nav-label .nav-ico,
.nav-group.has-active > .nav-label .nav-ico,
.nav-group > .nav-label.active .nav-ico { opacity: 1; }
.nav-group > .nav-label .chev { flex: none; margin-left: auto; opacity: .55; transition: transform 200ms ease; }
.nav-group.open > .nav-label .chev { transform: rotate(180deg); }
.nav-group > .nav-label:hover { background: var(--surface-glass-strong); color: var(--text-primary); }
.nav-group.open > .nav-label { color: var(--text-primary); }
/* Active text is --text-primary, not a hardcoded #fff: the background here is a 16%-alpha indigo
   tint, which sits over a near-white sidebar in light mode and left white text barely legible. */
.nav-group > .nav-label.active { background: rgba(99, 102, 241, .16); color: var(--text-primary); box-shadow: inset 0 0 0 1px rgba(99, 102, 241, .35); }
.nav-group.has-active > .nav-label { background: var(--surface-glass); color: var(--text-primary); }

/* Always-visible label text (was a hover tooltip in an earlier iteration) */
.nav-group > .nav-label .rail-tip {
  font-size: 13.5px; font-weight: 600; color: inherit; white-space: nowrap; overflow: hidden;
  text-overflow: ellipsis; flex: 1;
}

/* In-place accordion for grouped nav items */
.nav-children {
  overflow: hidden; max-height: 0; padding: 0 0 0 38px;
  transition: max-height 220ms ease;
}
.nav-group.open .nav-children { max-height: 480px; }
.nav-children .flyout-title { display: none; }
.nav-children a {
  display: block; padding: 8px 10px; margin: 1px 0; font-size: 13px; color: var(--text-secondary); border-radius: 8px;
  transition: background var(--transition), color var(--transition);
}
.nav-children a:hover { background: var(--surface-glass-strong); color: var(--text-primary); }
.nav-children a.active {
  background: rgba(99, 102, 241, .16); color: var(--text-primary); font-weight: 700;
  box-shadow: inset 0 0 0 1px rgba(99, 102, 241, .35);
}

.sidebar .rail-bottom { margin-top: auto; padding-top: 10px; border-top: 1px solid var(--border-subtle); }

/* ---------- Collapsed mode: compact icon rail with hover tooltip / flyout ---------- */
.sidebar.collapsed { width: 76px; padding: 18px 0; align-items: center; }
.sidebar.collapsed .brand { flex-direction: column; padding: 0 0 16px; }
.sidebar.collapsed .brand-name { display: none; }
.sidebar.collapsed .user-box { flex-direction: column; padding: 4px 0 14px; }
.sidebar.collapsed .user-box .name, .sidebar.collapsed .user-box .role { display: none; }
.sidebar.collapsed nav { align-items: center; overflow: visible; }
.sidebar.collapsed .nav-group { width: 52px; }
.sidebar.collapsed .nav-group > .nav-label { width: 52px; justify-content: center; padding: 0; position: relative; }
.sidebar.collapsed .nav-group > .nav-label .chev { display: none; }
.sidebar.collapsed .nav-group > .nav-label.active::before {
  content: ''; position: absolute; left: -13px; top: 50%; transform: translateY(-50%);
  width: 3px; height: 20px; border-radius: 3px; background: var(--brand-gradient);
}
.sidebar.collapsed .nav-group > .nav-label .rail-tip {
  position: absolute; left: calc(100% + 12px); top: 50%; transform: translateY(-50%) translateX(-4px);
  background: var(--bg-elevated); border: 1px solid var(--border-strong);
  padding: 6px 10px; border-radius: 8px; white-space: nowrap;
  box-shadow: var(--shadow-md); opacity: 0; pointer-events: none; transition: opacity 150ms ease, transform 150ms ease;
  z-index: 60; flex: none;
}
.sidebar.collapsed .nav-group:not(.has-children):hover > .nav-label .rail-tip { opacity: 1; transform: translateY(-50%) translateX(0); }
.sidebar.collapsed .nav-children {
  position: absolute; left: calc(100% + 12px); top: 50%; transform: translateY(-50%) translateX(-6px) scale(.98);
  min-width: 200px; max-height: none; background: var(--bg-elevated); border: 1px solid var(--border-strong);
  border-radius: var(--radius); box-shadow: var(--shadow-lg); padding: 8px; z-index: 60; margin: 0;
  opacity: 0; visibility: hidden; transition: opacity 160ms ease, transform 160ms ease, visibility 160ms;
}
.sidebar.collapsed .nav-group.has-children:hover .nav-children,
.sidebar.collapsed .nav-group.has-children.open .nav-children {
  opacity: 1; visibility: visible; transform: translateY(-50%) translateX(0) scale(1);
}
.sidebar.collapsed .nav-children::before {
  content: ''; position: absolute; right: 100%; top: 50%; transform: translateY(-50%);
  border: 6px solid transparent; border-right-color: var(--bg-elevated);
}
.sidebar.collapsed .nav-children .flyout-title {
  display: block; font-size: 10.5px; font-weight: 700; text-transform: uppercase; letter-spacing: .06em;
  color: var(--text-tertiary); padding: 6px 10px 4px;
}
.sidebar.collapsed .nav-children a { padding: 8px 10px; }

/* ================= Topbar (floating) ================= */
.main { flex: 1; display: flex; flex-direction: column; min-width: 0; }
/* A real app bar: flush to the top, edge to edge, one hairline separating it
   from the content. The floating rounded card that used to sit here wasted
   vertical space on every page and never aligned with the sidebar. */
.topbar {
  margin: 0; padding: 10px 20px;
  background: var(--bg-secondary);
  border: 0; border-bottom: 1px solid var(--border-subtle); border-radius: 0;
  display: flex; align-items: center; justify-content: space-between; gap: 14px;
  position: sticky; top: 0; z-index: 20;
}
.topbar-search {
  flex: 1; max-width: 420px; display: flex; align-items: center; gap: 8px;
  background: var(--surface-glass-strong); border: 1px solid var(--border-subtle);
  border-radius: 999px; padding: 8px 12px; color: var(--text-tertiary);
  transition: border-color var(--transition), background var(--transition);
}
.topbar-search:focus-within { border-color: rgba(99, 102, 241, .55); background: var(--surface-glass); }
.topbar-search input {
  border: none; background: none; outline: none; color: var(--text-primary); font-size: 13px; flex: 1;
  padding: 0; min-width: 0;
}
.topbar-search input::placeholder { color: var(--text-tertiary); }
.topbar-search .kbd {
  font-size: 10.5px; font-weight: 700; color: var(--text-tertiary); border: 1px solid var(--border-strong);
  border-radius: 5px; padding: 2px 6px; flex: none; font-family: inherit;
}
.topbar-actions { display: flex; align-items: center; gap: 4px; }
.topbar-icon-btn {
  width: 36px; height: 36px; border-radius: 10px; display: flex; align-items: center; justify-content: center;
  color: var(--text-secondary); cursor: pointer; position: relative; transition: background var(--transition), color var(--transition);
  border: none; background: none;
}
.topbar-icon-btn:hover { background: var(--surface-glass-strong); color: var(--text-primary); }
.topbar-icon-btn .dot {
  position: absolute; top: 6px; right: 6px; width: 8px; height: 8px; border-radius: 50%;
  background: var(--danger); border: 2px solid var(--bg-secondary);
}
.topbar-date {
  display: flex; flex-direction: column; align-items: flex-end; margin-right: 4px;
}
.topbar-date .d1 { font-size: 12.5px; font-weight: 700; color: var(--text-primary); }
.topbar-date .d2 { font-size: 10.5px; color: var(--text-tertiary); }

.mobile-menu-btn { display: none; }
.topbar .user-menu { display: flex; align-items: center; gap: 8px; cursor: pointer; padding: 5px 8px 5px 5px; border-radius: 999px; transition: background var(--transition); margin-left: 6px; }
.topbar .user-menu:hover { background: var(--surface-glass-strong); }
.topbar .user-menu .avatar {
  width: 30px; height: 30px; border-radius: 50%; background: var(--brand-gradient);
  color: #fff; display: flex; align-items: center; justify-content: center; font-weight: 700; font-size: 12px;
}
.impersonate-bar {
  display: flex; align-items: center; gap: 8px; color: var(--warning); background: var(--warning-bg);
  border: 1px solid rgba(251, 191, 36, .3); border-radius: 999px; padding: 6px 14px 6px 16px; font-size: 12.5px; flex: none;
}
.impersonate-bar .btn { margin-left: 6px; }

/* Dropdown panel (profile / notifications) */
.dropdown-panel {
  position: absolute; top: calc(100% + 10px); right: 0; min-width: 240px; max-width: 320px;
  background: var(--bg-elevated); border: 1px solid var(--border-strong); border-radius: var(--radius);
  box-shadow: var(--shadow-lg); padding: 8px; z-index: 70; opacity: 0; visibility: hidden;
  transform: translateY(-6px); transition: opacity 150ms ease, transform 150ms ease, visibility 150ms;
}
.dropdown-panel.open { opacity: 1; visibility: visible; transform: none; }
.dropdown-panel .dd-header { padding: 8px 10px 6px; font-size: 12px; font-weight: 700; color: var(--text-tertiary); text-transform: uppercase; letter-spacing: .04em; }
.dropdown-panel .dd-item {
  display: flex; align-items: center; gap: 10px; padding: 9px 10px; border-radius: 8px; font-size: 13px;
  color: var(--text-secondary); cursor: pointer; transition: background var(--transition), color var(--transition);
}
.dropdown-panel .dd-item:hover { background: var(--surface-glass-strong); color: var(--text-primary); }
.dropdown-panel .dd-sep { height: 1px; background: var(--border-subtle); margin: 6px 4px; }
.dropdown-panel .dd-empty { padding: 20px 10px; text-align: center; color: var(--text-tertiary); font-size: 12.5px; }
.dropdown-wrap { position: relative; }
.dropdown-panel.search-results { left: 0; right: auto; top: calc(100% + 8px); width: max(100%, 260px); }
.dropdown-panel .dd-item mark { background: rgba(99, 102, 241, .35); color: inherit; border-radius: 3px; }
.dropdown-panel .dd-item.active-hl { background: var(--surface-glass-strong); color: var(--text-primary); }
.dd-note { padding: 10px 10px 4px; font-size: 12px; color: var(--text-tertiary); line-height: 1.5; }

@media (max-width: 700px) {
  .topbar { flex-wrap: wrap; row-gap: 8px; }
  .topbar-search { order: 3; flex-basis: 100%; max-width: none; }
  .impersonate-bar span, .impersonate-bar b { white-space: nowrap; }
}

.content { padding: 22px 20px 32px; animation: fadeIn 180ms ease; }
@keyframes fadeIn { from { opacity: 0; transform: translateY(4px); } to { opacity: 1; transform: none; } }
.breadcrumb { color: var(--text-muted); font-size: 12px; margin-bottom: 6px; }
.page-title { font-size: 21px; font-weight: 650; margin: 0 0 16px; color: var(--text-primary); letter-spacing: -.01em; }

/* ================= Cards ================= */
/* A card is a solid panel, not a pane of frosted glass. The blur was costing a
   repaint on every scroll and, over a busy page, made nothing look grouped —
   everything was equally translucent, so nothing read as separate. */
.card {
  background: var(--bg-secondary); border: 1px solid var(--border-subtle); border-radius: var(--radius-lg);
  padding: 18px; margin-bottom: 16px;
  box-shadow: var(--shadow-sm); transition: box-shadow var(--transition), border-color var(--transition);
}
.card-header {
  font-size: 13px; font-weight: 650; letter-spacing: 0; text-transform: none; color: var(--text-primary);
  border-bottom: 1px solid var(--border-subtle); padding-bottom: 12px; margin-bottom: 14px;
  display: flex; justify-content: space-between; align-items: center; flex-wrap: wrap; gap: 8px;
}

/* ================= Buttons ================= */
.btn {
  display: inline-flex; align-items: center; gap: 6px; border: none; border-radius: var(--radius);
  padding: 9px 16px; font-size: 13px; cursor: pointer; font-weight: 600;
  transition: background var(--transition), box-shadow var(--transition), transform 80ms ease, border-color var(--transition);
}
.btn:active:not(:disabled) { transform: translateY(1px); }
/* Solid, not a gradient with a coloured halo. A primary button appears many
   times on a page; a glow on each one turns a form into a light show. */
.btn-primary { background: var(--accent); color: #fff; box-shadow: var(--shadow-sm); }
.btn-primary:hover { background: var(--accent-dark); }
.btn-outline { background: var(--bg-secondary); border: 1px solid var(--border-strong); color: var(--text-primary); }
.btn-outline:hover { background: var(--surface-glass-strong); border-color: var(--text-tertiary); }
.btn-danger { background: var(--danger); color: #fff; }
.btn-danger:hover { background: #ef5350; }
.btn-warning { background: var(--warning); color: #1a1200; }
.btn-warning:hover { filter: brightness(1.08); }
.btn-sm { padding: 6px 11px; font-size: 12px; }

/* Row actions inside a data table are tonal, not solid. Every row carries an Edit and a Delete,
   so two saturated blocks per row turned a quiet list into a wall of orange and red and gave the
   destructive action the same visual weight as the routine one. The tint keeps the colour coding
   (and the semantic tokens, so both themes follow automatically) while letting the data read
   first; hover fills the button in, so the affordance is still obvious.

   Deliberately scoped to .data-table: `.btn-danger` is also the confirm button in showConfirm()
   (js/ui.js), where a destructive choice SHOULD be solid and unmissable. That one is untouched. */
.data-table .btn-sm.btn-danger,
.data-table .btn-sm.btn-warning {
  font-weight: 500;
  box-shadow: none;
  border: 1px solid transparent;
}
/* Edit is the routine action, so it borrows the app's own accent rather than a warning colour —
   nothing about editing a department is a caution. Delete keeps the danger tokens. */
.data-table .btn-sm.btn-warning {
  background: var(--accent-soft);
  color: var(--accent);
}
.data-table .btn-sm.btn-warning:hover {
  background: var(--accent);
  color: var(--text-on-accent);
  filter: none;
}
.data-table .btn-sm.btn-danger {
  background: var(--danger-bg);
  color: var(--danger);
}
.data-table .btn-sm.btn-danger:hover {
  background: var(--danger);
  color: #fff;
}
.data-table .btn-sm.btn-warning:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }
.data-table .btn-sm.btn-danger:focus-visible  { outline: 2px solid var(--danger);  outline-offset: 1px; }
.btn:disabled { opacity: 0.5; cursor: not-allowed; }
.btn.is-loading { cursor: wait; }

/* ================= Forms ================= */
.form-row { display: flex; flex-wrap: wrap; gap: 16px; margin-bottom: 14px; }
.form-group { flex: 1; min-width: 200px; }
.form-group label { display: block; font-size: 12.5px; font-weight: 600; color: var(--text-secondary); margin-bottom: 5px; }
.form-group .hint { font-size: 11.5px; color: var(--text-tertiary); margin-top: 3px; }
input[type="text"], input[type="number"], input[type="date"], input[type="time"],
input[type="email"], input[type="password"], input[type="tel"], select, textarea {
  width: 100%; padding: 9px 11px; border: 1px solid var(--border-strong); border-radius: var(--radius); font-size: 13px;
  font-family: inherit; transition: border-color var(--transition), box-shadow var(--transition), background var(--transition);
  /* Solid, not a grey wash. A filled field on a card on a page reads as three
     shades of nothing; a white field with a real border reads as a field. */
  background: var(--bg-secondary); color: var(--text-primary);
}
input::placeholder, textarea::placeholder { color: var(--text-tertiary); }
input:hover, select:hover, textarea:hover { border-color: var(--text-tertiary); }
input:focus, select:focus, textarea:focus {
  outline: none; border-color: var(--indigo); box-shadow: 0 0 0 3px var(--accent-soft);
}
input[readonly] { background: transparent; color: var(--text-secondary); }
textarea { resize: vertical; }
select option { background: var(--bg-elevated); color: var(--text-primary); }
.section-title {
  font-weight: 700; font-size: 13px; margin: 18px 0 10px; padding: 9px 12px; border-radius: 8px;
  color: var(--text-primary); border: 1px solid var(--border-subtle);
}
.section-title.rules { background: var(--success-bg); }
.section-title.hours { background: var(--info-bg); }
.section-title.ot { background: var(--warning-bg); }
.section-title.breaks { background: var(--purple-bg); }
.section-title.weekoff { background: var(--info-bg); }
.section-title.missed { background: var(--danger-bg); }
.section-title.latelogin { background: var(--warning-bg); }
.section-title.missedbreak { background: var(--gray-bg); }

/* ================= Split form layout (add / edit pages) ================= */
.form-card { padding: 0; }
.form-card-head {
  display: flex; align-items: center; justify-content: space-between; gap: 10px; flex-wrap: wrap;
  padding: 15px 20px; border-bottom: 2px solid var(--indigo);
  font-size: 15px; font-weight: 700; text-transform: uppercase; letter-spacing: .06em; color: var(--text-secondary);
}
.form-split { display: flex; flex-wrap: wrap; }
.form-split > .form-col { flex: 1 1 340px; min-width: 0; padding: 20px; }
.form-split > .form-col + .form-col { border-left: 1px solid var(--border-subtle); }
.form-legend {
  display: flex; align-items: center; gap: 8px;
  font-size: 12px; font-weight: 700; text-transform: uppercase; letter-spacing: .06em;
  padding-bottom: 10px; margin-bottom: 18px; border-bottom: 1px solid var(--border-subtle);
}
.form-legend.is-required { color: var(--indigo); border-bottom-color: var(--indigo); }
.form-legend.is-optional { color: var(--text-secondary); }
.form-col .form-group { margin-bottom: 16px; }
.form-col .form-group:last-child { margin-bottom: 0; }
.form-group label .req { color: var(--danger); font-weight: 700; margin-left: 2px; }
.form-actions {
  display: flex; align-items: center; justify-content: flex-end; gap: 10px; flex-wrap: wrap;
  padding: 16px 20px; border-top: 1px solid var(--border-subtle);
}
.form-actions .spacer { margin-right: auto; }
.form-alert-slot:not(:empty) { padding: 16px 20px 2px; }

/* Stacked sections of a long form, each a fixed 4-up grid. Fields that only apply when a switch
   above them is on are hidden rather than greyed, so a section shrinks to what is actually in use. */
/* Divider on the top edge of every section but the first, rather than the bottom edge of every
   section but the last — the actions bar carries its own top border, so a bottom rule here would
   draw a second line right against it. */
.form-section { padding: 18px 20px; }
.form-section + .form-section { border-top: 1px solid var(--border-subtle); }
.form-grid { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 14px 16px; }
.form-grid + .form-grid { margin-top: 14px; }
.form-grid > .form-group { min-width: 0; margin-bottom: 0; }
.form-grid > .form-group.span-2 { grid-column: span 2; }
@media (max-width: 1180px) {
  .form-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .form-grid > .form-group.span-2 { grid-column: span 2; }
}
@media (max-width: 620px) {
  .form-section { padding: 16px; }
  .form-grid, .form-grid > .form-group.span-2 { grid-template-columns: minmax(0, 1fr); grid-column: auto; }
}

/* Inline radio / checkbox rows inside a form group */
.form-group .radio-inline { display: flex; align-items: center; gap: 20px; flex-wrap: wrap; padding-top: 5px; }
.form-group .radio-inline label,
.form-group .check-inline {
  display: inline-flex; align-items: center; gap: 7px; margin: 0;
  font-size: 13px; font-weight: 500; color: var(--text-primary); cursor: pointer;
}
.form-group .radio-inline input, .form-group .check-inline input { accent-color: var(--indigo); margin: 0; }

/* Toggle chips (week off days, and similar multi-selects) */
.chip-group { display: flex; flex-wrap: wrap; gap: 8px; padding-top: 2px; }
.chip-group .chip {
  display: inline-flex; align-items: center; justify-content: center; position: relative;
  min-width: 54px; padding: 7px 12px; margin: 0; border: 1px solid var(--border-strong); border-radius: 9px;
  background: var(--surface-glass-strong); color: var(--text-secondary);
  font-size: 12.5px; font-weight: 600; cursor: pointer; user-select: none;
  transition: background var(--transition), border-color var(--transition), color var(--transition);
}
.chip-group .chip input { position: absolute; opacity: 0; width: 0; height: 0; pointer-events: none; }
.chip-group .chip:hover { border-color: var(--indigo); color: var(--text-primary); }
.chip-group .chip.is-on {
  background: var(--brand-gradient); border-color: transparent; color: #fff;
  box-shadow: 0 4px 14px rgba(99, 102, 241, .3);
}
.chip-group .chip:focus-within { outline: 2px solid var(--indigo); outline-offset: 2px; }

/* File input, styled like the other controls */
input[type="file"] {
  width: 100%; padding: 7px 11px; border: 1px solid var(--border-strong); border-radius: 9px;
  background: var(--surface-glass-strong); color: var(--text-secondary); font-size: 13px; font-family: inherit;
}
input[type="file"]::file-selector-button {
  margin: 0 10px 0 0; padding: 6px 12px; border: 1px solid var(--border-strong); border-radius: 7px;
  background: var(--surface-glass-strong); color: var(--text-primary);
  font-family: inherit; font-size: 12.5px; font-weight: 600; cursor: pointer;
}
input[type="file"]::file-selector-button:hover { border-color: var(--indigo); }

@media (max-width: 900px) {
  .form-split > .form-col + .form-col { border-left: none; border-top: 1px solid var(--border-subtle); }
}
@media (max-width: 560px) {
  .form-split > .form-col { padding: 16px; }
  .form-actions { padding: 14px 16px; }
  .form-actions .btn { flex: 1 1 auto; justify-content: center; }
}

/* ================= Tables ================= */
.table-wrap { overflow-x: auto; border-radius: var(--radius); }
/* The table is the workhorse of an HR system — employees, attendance, payroll,
   leave are all tables. Figures get tabular numerals so columns of hours and
   amounts line up digit for digit; a proportional font makes a salary column
   ragged and genuinely harder to scan. */
table.data-table {
  width: 100%; border-collapse: separate; border-spacing: 0; font-size: 13px;
  font-variant-numeric: tabular-nums;
}
table.data-table th {
  text-align: left; background: var(--bg-secondary); padding: 10px 12px;
  border-bottom: 1px solid var(--border-strong);
  font-size: 11px; font-weight: 650; color: var(--text-secondary);
  text-transform: uppercase; letter-spacing: .04em;
  white-space: nowrap; position: sticky; top: 0; z-index: 1;
}
table.data-table td {
  padding: 11px 12px; border-bottom: 1px solid var(--border-subtle);
  vertical-align: middle; color: var(--text-primary);
}
/* Numeric columns are opted in per page with .num — right-aligned so the units
   place stacks, which is the whole point of a money or hours column. */
table.data-table th.num, table.data-table td.num { text-align: right; }
table.data-table tbody tr { transition: background var(--transition); }
table.data-table tbody tr:hover td { background: var(--surface-glass); }
table.data-table tbody tr:last-child td { border-bottom: none; }
.table-toolbar { display: flex; justify-content: space-between; align-items: center; margin-bottom: 14px; gap: 10px; flex-wrap: wrap; }
.table-toolbar .filters { display: flex; gap: 8px; flex-wrap: wrap; align-items: center; }
.table-toolbar .filters select, .table-toolbar .filters input { width: auto; min-width: 140px; }
.search-input-wrap { position: relative; display: inline-flex; align-items: center; }
.search-input-wrap .ui-icon { position: absolute; left: 9px; color: var(--text-tertiary); pointer-events: none; }
.search-input-wrap input { padding-left: 30px; min-width: 220px; }

.badge { display: inline-flex; align-items: center; gap: 4px; padding: 3px 10px; border-radius: 999px; font-size: 11.5px; font-weight: 700; white-space: nowrap; }
.badge::before { content: ''; width: 6px; height: 6px; border-radius: 50%; background: currentColor; }
.badge-present, .badge-active { background: var(--success-bg); color: var(--success); }
/* Late Present is a full present day, so it stays in the success family — tinted amber to read as
   "present, with a caveat" rather than as a separate outcome. */
.badge-late_present { background: var(--warning-bg); color: var(--warning); }
/* Early Present is likewise a full present day — tinted cyan so it reads as a variation on
   present rather than a problem. */
.badge-early_present { background: var(--cyan-bg); color: var(--cyan); }
.badge-absent { background: var(--danger-bg); color: var(--danger); }
.badge-half_day { background: var(--warning-bg); color: var(--warning); }
.badge-leave { background: var(--info-bg); color: var(--info); }
.badge-week_off, .badge-inactive { background: var(--gray-bg); color: var(--gray); }
.badge-holiday { background: var(--purple-bg); color: var(--violet); }
.badge-pending { background: var(--warning-bg); color: var(--warning); }
.badge-approved { background: var(--success-bg); color: var(--success); }
.badge-rejected { background: var(--danger-bg); color: var(--danger); }
.badge-fingerprint { background: var(--info-bg); color: var(--info); }
.badge-face { background: var(--purple-bg); color: var(--violet); }
.badge-card { background: var(--success-bg); color: var(--success); }
.badge-password { background: var(--warning-bg); color: var(--warning); }
.badge-manual { background: var(--gray-bg); color: var(--gray); }
.badge-unknown { background: var(--danger-bg); color: var(--danger); }

.pagination-info { color: var(--text-muted); font-size: 12.5px; }
.empty-state { text-align: center; padding: 46px 10px; color: var(--text-tertiary); }
.empty-state .ui-icon { opacity: .45; margin-bottom: 8px; }
.empty-state .empty-title { font-size: 13px; }
.empty-state .empty-sub { font-size: 12px; margin-top: 5px; opacity: .75; }
.alert { display: flex; align-items: flex-start; gap: 9px; padding: 10px 14px; border-radius: 10px; font-size: 13px; margin-bottom: 14px; }
.alert .ui-icon { margin-top: 1px; flex: none; }
.alert-danger { background: var(--danger-bg); color: var(--danger); }
.alert-success { background: var(--success-bg); color: var(--success); }
.alert-warning { background: var(--warning-bg); color: var(--warning); }
.alert-info { background: var(--info-bg); color: var(--info); }

.stat-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(160px, 1fr)); gap: 12px; margin-bottom: 18px; }
.stat-card {
  background: var(--surface-glass); border: 1px solid var(--border-subtle); border-radius: var(--radius); padding: 14px;
  box-shadow: var(--shadow-sm); transition: transform var(--transition), box-shadow var(--transition), border-color var(--transition);
  border-top: 2px solid var(--indigo);
}
.stat-card:hover { transform: translateY(-2px); box-shadow: var(--shadow-md); border-color: var(--border-strong); }
.stat-card .value { font-size: 24px; font-weight: 700; line-height: 1.2; color: var(--text-primary); font-variant-numeric: tabular-nums; }
.stat-card .label { font-size: 11.5px; color: var(--text-tertiary); text-transform: uppercase; letter-spacing: .03em; margin-top: 2px; }
.stat-card.has-icon { display: flex; align-items: center; gap: 12px; }
.stat-card .stat-icon {
  width: 40px; height: 40px; border-radius: 10px; flex: none;
  display: flex; align-items: center; justify-content: center; font-size: 18px;
  background: var(--accent-soft); color: var(--indigo);
}
.stat-card.c-teal { border-top-color: var(--emerald); }
.stat-card.c-teal .stat-icon { background: var(--success-bg); color: var(--success); }
.stat-card.c-red { border-top-color: var(--danger); }
.stat-card.c-red .stat-icon { background: var(--danger-bg); color: var(--danger); }
.stat-card.c-blue { border-top-color: var(--blue); }
.stat-card.c-blue .stat-icon { background: var(--info-bg); color: var(--info); }
.stat-card.c-orange { border-top-color: var(--orange); }
.stat-card.c-orange .stat-icon { background: var(--warning-bg); color: var(--warning); }
.stat-card.c-purple { border-top-color: var(--violet); }
.stat-card.c-purple .stat-icon { background: var(--purple-bg); color: var(--violet); }
.stat-card.c-gray { border-top-color: var(--gray); }
.stat-card.c-gray .stat-icon { background: var(--gray-bg); color: var(--gray); }

.quick-actions { display: grid; grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); gap: 12px; }
.quick-action {
  background: var(--surface-glass); border: 1px solid var(--border-subtle); border-radius: var(--radius); padding: 14px;
  display: flex; gap: 12px; align-items: center; box-shadow: var(--shadow-sm);
  transition: transform var(--transition), box-shadow var(--transition), border-color var(--transition);
}
.quick-action:hover { transform: translateY(-2px); box-shadow: var(--shadow-md); border-color: var(--border-strong); }
.quick-action .icon {
  width: 40px; height: 40px; border-radius: 10px; background: var(--brand-gradient);
  color: #fff; display: flex; align-items: center; justify-content: center; font-weight: 700; font-size: 17px; flex: none;
}
.quick-action .title { font-weight: 700; font-size: 13.5px; color: var(--text-primary); }
.quick-action .sub { font-size: 11.5px; color: var(--text-tertiary); }
.quick-action.c-teal .icon { background: linear-gradient(135deg, #34d399, #059669); }
.quick-action.c-red .icon { background: linear-gradient(135deg, #f87171, #dc2626); }
.quick-action.c-blue .icon { background: linear-gradient(135deg, #60a5fa, #2563eb); }
.quick-action.c-orange .icon { background: linear-gradient(135deg, #fbbf24, #d97706); }
.quick-action.c-purple .icon { background: linear-gradient(135deg, #a78bfa, var(--violet)); }
.quick-action.c-gray .icon { background: linear-gradient(135deg, #94a3b8, #64748b); }

/* ================= Modal ================= */
.modal-overlay {
  position: fixed; inset: 0; background: var(--scrim); display: none; align-items: center; justify-content: center; z-index: 200;
  backdrop-filter: blur(3px);
}
.modal-overlay.open { display: flex; animation: overlayIn 150ms ease; }
@keyframes overlayIn { from { opacity: 0; } to { opacity: 1; } }
.modal-box {
  background: var(--bg-elevated); border: 1px solid var(--border-strong); border-radius: var(--radius-lg); width: 520px; max-width: 92vw; max-height: 88vh; overflow-y: auto;
  box-shadow: var(--shadow-lg); animation: modalIn 180ms cubic-bezier(.2,.9,.3,1.2);
}
@keyframes modalIn { from { opacity: 0; transform: translateY(10px) scale(.98); } to { opacity: 1; transform: none; } }
.modal-box .modal-header { padding: 15px 18px; border-bottom: 1px solid var(--border-subtle); font-weight: 700; color: var(--text-primary); display: flex; justify-content: space-between; align-items: center; }
.modal-x { cursor: pointer; color: var(--text-tertiary); display: flex; padding: 4px; border-radius: 6px; transition: background var(--transition), color var(--transition); }
.modal-x:hover { background: var(--surface-glass-strong); color: var(--text-primary); }
.modal-box .modal-body { padding: 18px; }
.modal-box .modal-footer { padding: 12px 18px; border-top: 1px solid var(--border-subtle); display: flex; justify-content: flex-end; gap: 8px; }
.confirm-icon { width: 36px; height: 36px; border-radius: 50%; background: var(--info-bg); color: var(--info); display: flex; align-items: center; justify-content: center; flex: none; }
.confirm-icon.danger { background: var(--danger-bg); color: var(--danger); }

/* ================= Toasts ================= */
#toast-host { position: fixed; top: 16px; right: 16px; z-index: 999; display: flex; flex-direction: column; gap: 8px; }
.toast {
  display: flex; align-items: center; gap: 10px; background: var(--bg-elevated); border: 1px solid var(--border-strong);
  border-radius: 10px; padding: 11px 14px; box-shadow: var(--shadow-lg); font-size: 13px; min-width: 260px; max-width: 360px;
  opacity: 0; transform: translateX(20px); transition: opacity 200ms ease, transform 200ms ease; border-left: 3px solid var(--info); color: var(--text-primary);
}
.toast.show { opacity: 1; transform: none; }
.toast span:not(.toast-close) { flex: 1; }
.toast-close { cursor: pointer; color: var(--text-tertiary); flex: none; display: flex; }
.toast-close:hover { color: var(--text-primary); }
.toast-success { border-left-color: var(--success); } .toast-success .ui-icon { color: var(--success); }
.toast-danger { border-left-color: var(--danger); } .toast-danger .ui-icon { color: var(--danger); }
.toast-warning { border-left-color: var(--warning); } .toast-warning .ui-icon { color: var(--warning); }
.toast-info .ui-icon { color: var(--info); }

/* ================= Spinner / loading ================= */
.spinner {
  display: inline-block; width: 15px; height: 15px; border: 2px solid rgba(255,255,255,.15);
  border-top-color: currentColor; border-radius: 50%; animation: spin 700ms linear infinite; vertical-align: -3px;
}
.btn .spinner { border-color: rgba(255,255,255,.35); border-top-color: #fff; }
.btn-outline .spinner, .btn-warning .spinner { border-color: rgba(0,0,0,.15); border-top-color: currentColor; }
.spinner-sm { width: 12px; height: 12px; border-width: 2px; }
.spinner-lg { width: 26px; height: 26px; border-width: 3px; }
@keyframes spin { to { transform: rotate(360deg); } }
.table-loading { display: flex; align-items: center; justify-content: center; gap: 8px; padding: 30px 0; color: var(--text-tertiary); }
.page-loading { display: flex; align-items: center; justify-content: center; gap: 10px; padding: 60px 0; color: var(--text-tertiary); font-size: 13.5px; }

/* ================= Skeleton loaders ================= */
.skeleton { position: relative; overflow: hidden; background: var(--surface-glass-strong); border-radius: 8px; }
.skeleton::after {
  content: ''; position: absolute; inset: 0; transform: translateX(-100%);
  background: linear-gradient(90deg, transparent, rgba(255,255,255,.08), transparent);
  animation: shimmer 1.3s infinite;
}
@keyframes shimmer { 100% { transform: translateX(100%); } }
.skeleton-stat { height: 66px; border-radius: var(--radius); border: 1px solid var(--border-subtle); }
.skeleton-line { height: 12px; margin: 6px 0; }

/* ================= Login ================= */
/* A calm neutral ground. The two lavender radial washes that used to sit here
   were the first thing anyone saw and made the product read as a consumer app
   before a single field was filled in. */
.login-page { display: flex; align-items: center; justify-content: center; min-height: 100vh; padding: 24px; background: var(--bg-primary); }
.login-box { background: var(--bg-secondary); border: 1px solid var(--border-subtle); padding: 32px; border-radius: var(--radius-xl); width: 380px; max-width: 100%; box-shadow: var(--shadow-lg); animation: modalIn 180ms ease; }
.login-box .brand-badge {
  width: 46px; height: 46px; border-radius: 14px; background: var(--brand-gradient);
  color: #fff; display: flex; align-items: center; justify-content: center; font-weight: 800; font-size: 18px; margin-bottom: 14px;
  box-shadow: var(--glow-indigo);
}
.login-box h1 { font-size: 19px; font-weight: 650; margin: 0 0 4px; color: var(--text-primary); letter-spacing: -.01em; }
.login-box .sub { color: var(--text-tertiary); font-size: 12.5px; margin-bottom: 20px; }

.avatar-fallback {
  display: inline-flex; align-items: center; justify-content: center; width: 32px; height: 32px;
  border-radius: 50%; background: var(--accent-soft); color: var(--indigo); font-weight: 700; font-size: 12.5px;
}
.grid-day-cell { text-align: center; min-width: 62px; }
.legend-dot { display: inline-block; width: 9px; height: 9px; border-radius: 50%; margin-right: 5px; }

@media (max-width: 860px) {
  /* Mobile is always the off-canvas drawer, always in its full labeled form — the desktop
     collapse toggle (icon-only rail) doesn't apply here, so its narrower width is overridden. */
  .sidebar, .sidebar.collapsed {
    position: fixed; z-index: 50; height: 100vh; width: 260px; transform: translateX(-100%);
    transition: transform 220ms ease; padding: 18px 12px; box-shadow: var(--shadow-lg); align-items: stretch;
  }
  .sidebar.open { transform: none; }
  .sidebar.collapsed .brand, .sidebar.collapsed .user-box { flex-direction: row; }
  .sidebar.collapsed .brand-name,
  .sidebar.collapsed .user-box .name, .sidebar.collapsed .user-box .role { display: block; }
  .sidebar.collapsed nav { align-items: stretch; }
  .sidebar.collapsed .nav-group { width: 100%; }
  .sidebar.collapsed .nav-group > .nav-label { width: 100%; justify-content: flex-start; padding: 0 11px; }
  .sidebar.collapsed .nav-group > .nav-label .chev { display: block; }
  .sidebar.collapsed .nav-group > .nav-label .rail-tip { position: static; opacity: 1; visibility: visible; transform: none; background: none; border: none; box-shadow: none; padding: 0; }
  /* Reset the desktop rail's absolute/hover-gated flyout back to a normal accordion — show/hide
     is driven by max-height + .open here, not opacity/visibility, so only the clicked group
     expands instead of every group rendering open at once. */
  .sidebar.collapsed .nav-children {
    position: static; max-height: 0; opacity: 1; visibility: visible; transform: none;
    box-shadow: none; border: none; background: none; padding: 0 0 0 38px; overflow: hidden;
    transition: max-height 220ms ease;
  }
  .sidebar.collapsed .nav-group.open .nav-children { max-height: 480px; }
  .sidebar.collapsed .nav-children::before { display: none; }
  .sidebar.collapsed .nav-children .flyout-title { display: none; }
  .sidebar-collapse-btn { display: none; }
  .sidebar-backdrop { position: fixed; inset: 0; background: var(--scrim); z-index: 45; display: none; }
  .sidebar-backdrop.open { display: block; }
  .topbar { margin: 10px 12px 0; }
  .topbar-search { max-width: none; }
  .topbar-date { display: none; }
  .mobile-menu-btn { display: flex; }
  .content { padding: 14px; }
}
@media (max-width: 560px) {
  .topbar-search .kbd { display: none; }
}

/* ---------- Charts (hand-built SVG donut + CSS bar charts, no library) ---------- */
.charts-row { display: grid; grid-template-columns: minmax(280px, 1fr) minmax(320px, 1.4fr); gap: 16px; align-items: stretch; }
@media (max-width: 900px) { .charts-row { grid-template-columns: 1fr; } }

.donut-chart-row { display: flex; align-items: center; gap: 22px; flex-wrap: wrap; justify-content: center; padding: 6px 0; }
.donut-chart-row svg circle { transition: stroke-dasharray 600ms ease; }
.donut-legend { display: flex; flex-direction: column; gap: 8px; min-width: 140px; }
.donut-legend-item { display: flex; align-items: center; gap: 8px; font-size: 12.5px; color: var(--text-primary); }
.donut-legend-item b { margin-left: auto; font-variant-numeric: tabular-nums; }
.donut-legend-item .legend-dot { width: 10px; height: 10px; }

.dept-chart { display: flex; flex-direction: column; gap: 16px; }
.dept-block .dept-name { font-size: 12.5px; font-weight: 700; color: var(--text-primary); margin-bottom: 6px; }
.dept-series { display: flex; flex-direction: column; gap: 5px; }
.series-row { display: grid; grid-template-columns: 56px 1fr 26px; align-items: center; gap: 8px; }
.series-row .series-label { font-size: 11px; color: var(--text-tertiary); text-transform: uppercase; letter-spacing: .02em; }
.series-track { background: var(--surface-glass-strong); border-radius: 5px; height: 14px; overflow: hidden; }
.series-fill { height: 100%; border-radius: 5px; transition: width 600ms cubic-bezier(.2,.8,.2,1); min-width: 2px; }
.series-fill.present { background: linear-gradient(90deg, var(--emerald), #059669); }
.series-fill.absent { background: linear-gradient(90deg, #f2777a, var(--danger)); }
.series-row .series-count { font-size: 12px; font-weight: 700; text-align: right; font-variant-numeric: tabular-nums; color: var(--text-primary); }
.chart-empty { color: var(--text-tertiary); font-size: 12.5px; text-align: center; padding: 30px 0; }

/* Payslip document */
.payslip-sheet { background: var(--bg-elevated); border: 1px solid var(--border-subtle); border-radius: var(--radius-lg); box-shadow: var(--shadow-sm); padding: 28px 32px; max-width: 780px; margin: 0 auto; color: var(--text-primary); }
.payslip-header { text-align: center; border-bottom: 2px solid var(--border-strong); padding-bottom: 14px; margin-bottom: 18px; }
.payslip-company { font-size: 20px; font-weight: 800; letter-spacing: .02em; }
.payslip-title { font-size: 13px; font-weight: 700; letter-spacing: .12em; color: var(--text-tertiary); margin-top: 4px; }
.payslip-period { font-size: 12.5px; color: var(--text-tertiary); margin-top: 2px; }
.payslip-meta { display: grid; grid-template-columns: repeat(3, 1fr); gap: 12px 20px; margin-bottom: 16px; }
.payslip-meta div { display: flex; flex-direction: column; gap: 2px; }
.payslip-meta span { font-size: 10.5px; text-transform: uppercase; letter-spacing: .04em; color: var(--text-tertiary); }
.payslip-meta b { font-size: 13.5px; }
.payslip-note { background: var(--warning-bg); color: var(--warning); border-radius: 8px; padding: 8px 12px; font-size: 12.5px; margin-bottom: 16px; }
.payslip-section-label { font-size: 11.5px; font-weight: 700; text-transform: uppercase; letter-spacing: .06em; color: var(--text-tertiary); margin-bottom: 8px; }
.payslip-attendance { display: grid; grid-template-columns: repeat(auto-fit, minmax(92px, 1fr)); gap: 8px; margin-bottom: 18px; }
.payslip-att-cell { border-radius: 10px; padding: 8px 6px; text-align: center; }
.payslip-att-cell b { display: block; font-size: 17px; }
.payslip-att-cell span { display: block; font-size: 10px; text-transform: uppercase; letter-spacing: .03em; opacity: .85; margin-top: 2px; }
.payslip-att-cell.present { background: var(--success-bg); color: var(--success); }
.payslip-att-cell.absent { background: var(--danger-bg); color: var(--danger); }
.payslip-att-cell.half-day { background: var(--warning-bg); color: var(--warning); }
.payslip-att-cell.week-off { background: var(--gray-bg); color: var(--gray); }
.payslip-att-cell.holiday { background: var(--purple-bg); color: var(--violet); }
.payslip-att-cell.paid-leave { background: var(--info-bg); color: var(--info); }
.payslip-att-cell.unpaid-leave { background: var(--gray-bg); color: var(--gray); }
.payslip-cols { display: grid; grid-template-columns: 1fr 1fr; gap: 20px; border-top: 1px solid var(--border-subtle); border-bottom: 1px solid var(--border-subtle); padding: 16px 0; margin-bottom: 16px; }
.payslip-col-title { font-size: 11.5px; font-weight: 700; text-transform: uppercase; letter-spacing: .06em; color: var(--text-tertiary); margin-bottom: 8px; }
.payslip-col table { width: 100%; border-collapse: collapse; font-size: 13px; }
.payslip-col td { padding: 5px 0; border-bottom: 1px dashed var(--border-subtle); }
.payslip-col td:last-child { text-align: right; font-variant-numeric: tabular-nums; }
.payslip-col tr.total td { border-bottom: none; border-top: 2px solid var(--border-strong); font-weight: 700; padding-top: 8px; }
.payslip-col td.muted { color: var(--text-tertiary); border-bottom: none; font-style: italic; }
.payslip-net { display: flex; align-items: center; justify-content: space-between; background: var(--brand-gradient); color: #fff; border-radius: 10px; padding: 14px 20px; }
.payslip-net span { font-size: 13px; letter-spacing: .04em; text-transform: uppercase; opacity: .85; }
.payslip-net b { font-size: 22px; font-variant-numeric: tabular-nums; }
.payslip-footer { text-align: center; margin-top: 18px; }
/* Per-employee monthly attendance sheet — built on demand, one A4 page per employee, and
   handed to html2pdf.js (public/js/reports-monthly.js) for a real one-click .pdf download.
   html2canvas (which html2pdf uses internally) can't measure/rasterize a display:none element,
   so this sits off-screen instead of hidden — visually absent from the page without being
   display:none. Always plain black-on-white regardless of the app's theme since it's never
   meant to be seen directly. */
#print-sheet { position: absolute; left: -10000px; top: 0; width: 820px; }
/* html2canvas's document-cloning step doesn't reliably capture position:fixed/absolute content
   (a known limitation — the clone can mis-measure it as zero-height) — so for the brief moment
   generation actually runs (public/js/reports-monthly.js), this drops back into plain static
   flow instead, which it renders correctly, then goes back to hidden once the PDF is done. */
#print-sheet.generating { position: static; width: 820px; background: #fff; }

@media print {
  .sidebar, .topbar, .no-print { display: none !important; }
  .app-shell, .main, .content { display: block !important; margin: 0 !important; padding: 0 !important; }
  body { background: #fff !important; color: #000 !important; }
  .payslip-sheet { box-shadow: none; border: none; max-width: none; padding: 0; background: #fff; color: #000; }
  #print-sheet { display: none !important; }
  @page { size: A4; margin: 12mm; }
}

/* =========================================================================
   Customer App additions — pagination, the company profile page, the payroll
   dashboard and the employee 360 profile. Appended rather than woven into the
   sections above so the diff against the previous stylesheet stays readable.
   ========================================================================= */

/* Password field with a reveal toggle. The button sits inside the field's padding rather than
   beside it, so the input keeps the same width as every other control in the form. */
.password-field { position: relative; display: block; }
.password-field input { width: 100%; padding-right: 38px; }
.password-toggle {
  position: absolute; top: 50%; right: 6px; transform: translateY(-50%);
  display: flex; align-items: center; justify-content: center;
  width: 28px; height: 28px; padding: 0;
  background: none; border: none; border-radius: 6px; cursor: pointer;
  color: var(--text-tertiary); transition: color var(--transition), background var(--transition);
}
.password-toggle:hover { color: var(--text-primary); background: var(--surface-glass-strong); }
.password-toggle:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }

/* Company logo picker — Master Admin company modal (js/master-companies.js) */
.logo-picker { display: flex; align-items: flex-start; gap: 14px; }
.logo-preview {
  flex: none; width: 76px; height: 76px; border-radius: var(--radius-sm);
  border: 1px dashed var(--border-strong); background: var(--surface-glass);
  display: flex; align-items: center; justify-content: center; overflow: hidden; padding: 5px;
  font-size: 11px; color: var(--text-tertiary); text-align: center;
}
/* `contain`, never `cover`: a logo is rarely square and cropping somebody's brand mark is worse
   than showing it letterboxed. */
.logo-preview img { width: 100%; height: 100%; object-fit: contain; display: block; }
.logo-picker-actions { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; }
.logo-picker-actions .hint { flex-basis: 100%; margin: 0; }

/* Notification list — Customer App (js/notifications.js). Deliberately not the .data-table
   treatment: these are things to read and act on, not records to scan in columns. */
.note-legend {
  font-size: 12.5px; color: var(--text-tertiary);
  padding: 0 2px 12px; border-bottom: 1px solid var(--border-subtle); margin-bottom: 4px;
}
.note-row {
  display: flex; align-items: flex-start; gap: 12px;
  padding: 13px 10px; border-radius: var(--radius-sm);
  border-bottom: 1px solid var(--border-subtle);
  color: inherit; transition: background var(--transition);
}
.note-row:last-child { border-bottom: none; }
.note-row:hover { background: var(--surface-glass-strong); }
/* Unread is carried by a left bar and weight, not a wash of colour across the row — with a feed
   that is mostly unread, a tinted background on every row stops distinguishing anything. */
.note-row.unread { box-shadow: inset 2px 0 0 var(--accent); }
.note-row.unread .note-title { font-weight: 700; color: var(--text-primary); }
.note-ico {
  flex: none; width: 30px; height: 30px; border-radius: 8px;
  display: flex; align-items: center; justify-content: center;
  background: var(--surface-glass-strong); color: var(--text-secondary);
}
.note-ico.info    { background: var(--accent-soft);  color: var(--accent); }
.note-ico.success { background: var(--success-bg);   color: var(--success); }
.note-ico.warning { background: var(--warning-bg);   color: var(--warning); }
.note-ico.danger  { background: var(--danger-bg);    color: var(--danger); }
.note-body { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 3px; }
.note-title { font-size: 13.5px; font-weight: 600; color: var(--text-primary); }
.note-sub { font-size: 12.5px; color: var(--text-secondary); line-height: 1.45; }
.note-meta {
  flex: none; display: flex; align-items: center; gap: 8px;
  font-size: 11.5px; color: var(--text-tertiary); white-space: nowrap;
}
@media (max-width: 640px) {
  .note-meta { display: none; }
}

/* Pagination (see createPager / pagerHtml in js/ui.js) */
.pager {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  flex-wrap: wrap;
  padding: 12px 2px 2px;
  margin-top: 8px;
  border-top: 1px solid var(--border-subtle);
}
.pager-info { font-size: 12.5px; color: var(--text-tertiary); display: flex; align-items: center; gap: 12px; }
.pager-controls { display: flex; align-items: center; gap: 8px; }
.pager-page { font-size: 12.5px; color: var(--text-secondary); font-variant-numeric: tabular-nums; }
.pager-size { display: flex; align-items: center; gap: 6px; font-size: 12.5px; color: var(--text-tertiary); }
.pager-size select {
  padding: 4px 6px;
  font-size: 12.5px;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm, 6px);
  background: var(--surface);
  color: var(--text-primary);
}

/* Sortable column headers (see sortableHeader in js/ui.js). The neutral double-chevron is dimmed
   until the column is the active sort, so a busy header row does not read as seven active states. */
.data-table th.sortable { cursor: pointer; user-select: none; white-space: nowrap; }
.data-table th.sortable .ui-icon { margin-left: 5px; vertical-align: -2px; opacity: .35; transition: opacity .12s ease; }
.data-table th.sortable:hover .ui-icon { opacity: .7; }
.data-table th.sortable.sorted { color: var(--text-primary); }
.data-table th.sortable.sorted .ui-icon { opacity: 1; }

/* A labelled progress meter — leave balances, plan usage */
.meter { height: 8px; border-radius: 999px; background: var(--surface-glass-strong); overflow: hidden; }
.meter > span { display: block; height: 100%; border-radius: 999px; background: var(--indigo); transition: width 240ms ease; }
.meter > span.warn { background: var(--warning); }
.meter > span.over { background: var(--danger); }
.meter-row { display: flex; justify-content: space-between; align-items: baseline; font-size: 12.5px; margin-bottom: 5px; }
.meter-row b { font-variant-numeric: tabular-nums; }

/* Definition list used by the company and employee profile pages */
.detail-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(210px, 1fr));
  gap: 14px 22px;
}
.detail-item .k {
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: .04em;
  color: var(--text-tertiary);
  margin-bottom: 3px;
}
.detail-item .v { font-size: 13.5px; font-weight: 600; color: var(--text-primary); word-break: break-word; }

/* Employee 360 header */
.profile-head { display: flex; align-items: center; gap: 16px; flex-wrap: wrap; }
.profile-avatar {
  width: 68px;
  height: 68px;
  border-radius: 20px;
  object-fit: cover;
  background: var(--brand-gradient);
  color: #fff;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 24px;
  font-weight: 800;
  flex: none;
  overflow: hidden;
}
.profile-avatar img { width: 100%; height: 100%; object-fit: cover; }
.profile-name { font-size: 19px; font-weight: 700; color: var(--text-primary); }
.profile-meta { font-size: 12.5px; color: var(--text-tertiary); margin-top: 2px; }
.profile-head-actions { margin-left: auto; display: flex; gap: 8px; flex-wrap: wrap; }

/* Payroll dashboard KPI strip */
.kpi-row {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
  gap: 12px;
  margin-bottom: 16px;
}
.kpi {
  background: var(--bg-elevated);
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius);
  padding: 15px 16px;
  box-shadow: var(--shadow-sm);
}
.kpi .k { font-size: 11.5px; text-transform: uppercase; letter-spacing: .04em; color: var(--text-tertiary); }
.kpi .v {
  font-size: 23px;
  font-weight: 700;
  color: var(--text-primary);
  margin-top: 4px;
  font-variant-numeric: tabular-nums;
}
.kpi .sub { font-size: 11.5px; color: var(--text-tertiary); margin-top: 3px; }
.kpi.accent { border-left: 3px solid var(--indigo); }
.kpi.good .v { color: var(--success); }
.kpi.bad .v { color: var(--danger); }

/* Right-aligned numeric table columns — money and day counts read wrong when ragged */
.data-table td.num, .data-table th.num { text-align: right; font-variant-numeric: tabular-nums; }

@media (max-width: 700px) {
  .profile-head-actions { margin-left: 0; width: 100%; }
  .pager { justify-content: center; }
}

/* ================= Printed salary documents (public/js/salary-slip.js) =================
   Ruled black-on-white tables rather than the app's own palette: these are meant to be printed
   and filed, and a screen-tinted sheet photocopies badly. They keep the same look on screen so
   what you see before pressing Print is what comes out. */
.slip-sheet {
  background: #fff; color: #000; max-width: 210mm; margin: 0 auto 18px;
  padding: 14mm 12mm; border: 1px solid var(--border-subtle); border-radius: var(--radius);
  box-shadow: var(--shadow-sm); font-size: 12.5px;
}
.slip-sheet-wide { max-width: 297mm; } /* the register is landscape A4 */
.slip-title { text-align: center; font-size: 17px; font-weight: 800; margin-bottom: 4px; }
.slip-subtitle { text-align: center; font-size: 12px; color: #444; margin-bottom: 12px; }
.slip-table { width: 100%; border-collapse: collapse; }
.slip-table td, .slip-table th { border: 1px solid #000; padding: 5px 7px; vertical-align: middle; }
.slip-table .slip-head th { text-align: center; font-weight: 700; background: #f1f1f1; }
.slip-table .slip-k { font-weight: 600; }
.slip-table .slip-v { text-align: right; }
.slip-table .slip-v-l { text-align: left; }
.slip-table .slip-total td { font-weight: 700; background: #f7f7f7; }
.slip-note { margin-top: 10px; font-size: 12px; font-style: italic; }

/* Register: many numeric columns, so centre them and keep the text ones left */
.slip-register { font-size: 11px; }
.slip-register td, .slip-register th { text-align: center; padding: 4px 5px; }
.slip-register td.l, .slip-register th.l { text-align: left; }
.slip-register .slip-sign-cell { min-width: 90px; height: 26px; }

/* Signed by hand on the printed sheet — nothing here stores a signature image */
.slip-signatures { display: flex; justify-content: space-between; gap: 24px; margin-top: 34px; }
.slip-sign { flex: 1; text-align: center; }
.slip-sign-line { border-top: 1px solid #000; margin-bottom: 5px; }
.slip-sign span { font-size: 11.5px; font-weight: 600; }

@media print {
  .slip-sheet { border: none; box-shadow: none; margin: 0; padding: 0; max-width: none; border-radius: 0; }
  .slip-sheet + .slip-sheet { page-break-before: always; }
  /* Orientation is not set here. A named page (page: landscapeSheet) needs Chrome 118+ and was
     being ignored, and @page cannot be scoped to a class — so salary-report.js injects a
     document-level @page while the register is open instead. */
}
/* ================= Printed Monthly Attendance sheet (public/js/reports-monthly.js) =============
   A4 portrait, exactly one page per employee, rendered into #print-sheet and rasterised by
   html2pdf. Deliberately plain: black rules on white, no fills, no status tints — this is a
   document to be printed, signed and filed, and colour only costs ink and photocopies badly.

   Sizing is in px, not mm, because html2pdf does not honour mm here — it rasterises #print-sheet
   at its 820px width and scales that to the printable width (A4 210mm less the 6mm margin each
   side = 198mm). One PDF page is therefore 285mm tall / (198mm / 820px) = 1180px of content.
   Pinning each page element to exactly that, with overflow hidden, is what stops a 31-day month
   dribbling a few rows onto a second sheet. A 31-day month uses about 970px of the 1180. */
.attendance-sheet-page { width: 820px; height: 1180px; overflow: hidden; padding: 6px 12px; background: #fff; }

.ar-report { width: 100%; height: 100%; display: flex; flex-direction: column; color: #000; background: #fff; font-family: Arial, Helvetica, sans-serif; }
.ar-title {
  border: 1.5px solid #000; height: 30px; display: flex; align-items: center; justify-content: center;
  font-size: 15px; font-weight: 700; letter-spacing: .02em; margin-bottom: 10px;
}
.ar-info, .ar-summary, .ar-days { width: 100%; border-collapse: collapse; table-layout: fixed; background: #fff; }
.ar-info { border: 1.5px solid #000; }
.ar-summary { border: 1.5px solid #000; margin-top: 12px; }
.ar-info td, .ar-summary td { border: 1px solid #000; height: 19px; padding: 1px 5px; font-size: 10.5px; vertical-align: middle; }
.ar-info td.label, .ar-summary td.label { width: 17%; font-weight: 700; }
.ar-info td.value, .ar-summary td.value { width: 16%; font-weight: 600; }

.ar-days { border: 1.5px solid #000; margin-top: 12px; flex: 1 1 auto; }
.ar-days tbody { height: 100%; }
.ar-days th, .ar-days td {
  border: 1px solid #000; padding: 1px 2px; text-align: center; vertical-align: middle;
  font-size: 9.5px; line-height: 1.05;
}
.ar-days th { height: 26px; font-weight: 700; }
.ar-days td { height: 20px; font-weight: 500; }
.ar-info, .ar-summary, .ar-title { flex: 0 0 auto; }
.ar-days td.day { font-weight: 700; text-align: left; padding-left: 4px; }
.ar-days td.status { font-weight: 700; }
.ar-info tr > *:last-child,
.ar-summary tr > *:last-child,
.ar-days tr > *:last-child { border-right: 1.5px solid #000; }
.ar-days th:nth-child(1), .ar-days td:nth-child(1) { width: 12%; }
.ar-days th:nth-child(n+2), .ar-days td:nth-child(n+2) { width: 11%; }
/* Weekends are marked by italicising the day label rather than by a fill — the one distinction
   worth keeping once the tints are gone, and it survives a photocopy. */
.ar-days tr.weekend td.day { font-style: italic; }
.ar-days .manual-mark { font-size: 8px; vertical-align: super; margin-left: 1px; }


/* The sign-in mode switch. It was a bare <a> inheriting body colour, so it read
   as a stray sentence rather than the control it is. */
.login-box #toggle-mode {
  display: inline-block; margin: 2px 0 18px;
  font-size: 12.5px; font-weight: 600; color: var(--accent);
  border-bottom: 1px solid transparent; transition: border-color var(--transition);
}
.login-box #toggle-mode:hover { border-bottom-color: currentColor; }
