/* ============================================================================
   WAGS EMPLOYEE PORTAL - public/styles.css
   ----------------------------------------------------------------------------
   The only stylesheet the Portal loads. It has two halves:

     1. SHARED CORE - the Wags design system (tokens, app shell, page header
        band, cards, tables, forms, buttons, auth, responsive rules). It is
        DUPLICATED VERBATIM from the shared design system and is byte-identical
        to the copy at the top of the CRM's client/src/styles.css. There is no
        build step and no @import here, so the copies ARE the sync mechanism:
        edit the shared core once, then re-paste it into BOTH apps. Never patch
        one copy in place, or the two apps silently drift apart.

     2. PORTAL-SPECIFIC - everything below the END SHARED CORE marker: legacy
        token aliases, the Portal's own components (employee directory, time
        off, admin tables, the <dialog> sheets) and the alias classes that keep
        pre-redesign markup rendering while it migrates.

   Plain CSS. No preprocessor, no nesting, no external dependencies.
   ============================================================================ */

/* ===== SHARED CORE - keep in sync with crm/client/src/styles.css ===== */

/* ============================================================================
   WAGS DESIGN SYSTEM — SHARED CORE
   ----------------------------------------------------------------------------
   The common half of the Wags look and feel: tokens, app shell, page header
   band, cards, tables, forms, buttons, auth and the responsive rules.
   App-agnostic — it knows nothing about CRM leads or Portal timesheets.

   !! THIS BLOCK IS DUPLICATED VERBATIM INTO EACH APP'S STYLESHEET !!
   It is pasted, byte-identical, at the top of:
     - Wags CRM             client/src/styles.css
     - Wags Employee Portal public/styles.css
   There is no build step and no @import, so the copies are the mechanism.
   Edit the shared core in ONE place and re-paste it into BOTH apps; never
   patch a single copy, or the two apps silently drift apart. App-specific
   rules (and the legacy token aliases) go BELOW this block, never inside it.

   Plain CSS, no preprocessor, no nesting, no external dependencies.
   ============================================================================ */

:root {
  /* Wags brand */
  --navy: #1f3a68;
  --navy-deep: #142847;
  --navy-soft: #2c4b80;
  --navy-wash: #e2eaf6;
  --lime: #b5d334;
  --lime-hover: #a3c521;
  --lime-text: #66860a;   /* lime dark enough for text on white */
  --lime-soft: #f4f9e2;

  /* Neutrals */
  --bg: #f3f5f8;
  --card: #ffffff;
  --ink: #1c2233;
  --ink-2: #4d5468;
  --muted: #6d7387;
  --border: #e3e6ee;
  --border-strong: #d4d9e4;
  --thead: #f8f9fc;

  /* Status (reserved for state, never decoration) */
  --good: #178217;
  --good-text: #106310;
  --good-soft: #ecf7e6;
  --critical: #c43535;
  --critical-text: #a92c2c;
  --critical-soft: #fdf0f0;
  --warning: #e8a413;
  --warning-text: #815500;
  --warning-soft: #fdf5e0;

  --radius: 12px;
  --radius-sm: 8px;
  --shadow-card: 0 1px 3px rgba(20, 40, 71, 0.05), 0 4px 14px rgba(20, 40, 71, 0.05);
  --shadow-pop: 0 12px 40px rgba(20, 40, 71, 0.28);

  --control-h: 40px;      /* input/button height; grows on touch screens */
  --font-input: 14.5px;
  --sidebar-w: 244px;

  /* Deterministic avatar tints, cycled by first letter */
  --av-1: #1f3a68; --av-2: #66860a; --av-3: #8a5a1b; --av-4: #7b3f8f;
  --av-5: #1d6a6a; --av-6: #a92c2c;
}

/* ---------- base ---------- */
* { box-sizing: border-box; }
html, body { margin: 0; padding: 0; }
/* min-height, never height: `height: 100%` on the wrapper clips the fixed
   sidebar and stops the content column growing past one viewport. */
html, body, #root { min-height: 100%; }
body {
  font-family: "Segoe UI", system-ui, -apple-system, Roboto, sans-serif;
  background: var(--bg);
  color: var(--ink);
  font-size: 15px;
  line-height: 1.5;
  -webkit-font-smoothing: antialiased;
}
::selection { background: var(--lime-soft); }

a { color: var(--navy); text-decoration: none; }
a:hover { text-decoration: underline; }
:focus-visible { outline: 2px solid var(--navy); outline-offset: 2px; border-radius: 4px; }

.skip {
  position: absolute; left: -9999px; top: 0; z-index: 100;
  background: var(--card); color: var(--navy); padding: 8px 14px; border-radius: 0 0 8px 0;
}
.skip:focus { left: 0; }

/* ---------- app shell: fixed sidebar + scrolling content ---------- */
/* visually hidden but focusable — the drawer must be keyboard-operable.
   Never `hidden` or `display: none`: that drops the checkbox out of the tab
   order and makes the drawer unreachable without a mouse. */
.navtoggle-input { position: absolute; width: 1px; height: 1px; opacity: 0; }
/* Above the drawer breakpoint there is no drawer: the sidebar is permanently
   visible and this checkbox controls nothing. Left focusable it is a tab stop
   with no visible focus indicator and no effect — a WCAG 2.4.7 failure on every
   desktop page. Taking it out of the tab order here is the accessible choice and
   does NOT break the invariant above: that invariant is about drawer mode
   (<= 860px), where the checkbox is the only keyboard way to open the sidebar
   and must stay focusable. Do not "fix" this back to always-focusable. */
@media (min-width: 861px) { .navtoggle-input { display: none; } }
/* surface focus on the label the user actually sees */
.navtoggle-input:focus-visible ~ .shell .mobilebar .btn-icon,
.navtoggle-input:focus-visible ~ .shell .nav-close {
  outline: 2px solid #fff; outline-offset: 2px;
}
.shell { min-height: 100vh; }
.shell-main { margin-left: var(--sidebar-w); min-width: 0; }
.content { max-width: 1180px; margin: 0 auto; padding: 20px 22px 64px; }

.sidebar {
  position: fixed; inset: 0 auto 0 0; width: var(--sidebar-w); z-index: 30;
  background: var(--navy-deep); color: #fff;
  display: flex; flex-direction: column;
  overflow-y: auto; overflow-x: hidden;   /* never scroll sideways */
}
.sidebar-top { display: flex; align-items: center; gap: 8px; padding: 16px 14px 12px; }
.sidebar-brand {
  display: flex; align-items: center; gap: 10px; color: #fff;
  font-size: 14px; line-height: 1.2; flex: 1; min-width: 0;
}
.sidebar-brand:hover { text-decoration: none; }
.sidebar-brand b { display: block; font-weight: 700; font-size: 15px; }
.sidebar-brand span { min-width: 0; opacity: 0.85; }
.sidebar-brand b, .sidebar-brand span b { opacity: 1; }
.sidebar-brand .brand-logo, .mobilebar-brand .brand-logo {
  width: 32px; height: 32px; border-radius: 9px; background: #fff; display: block; flex-shrink: 0;
}
.nav-close { display: none; }

/* the one primary action for the app, directly under the brand block */
/* The CTA carries `.btn-block`, whose `width: 100%` resolves against the
   sidebar's FULL width — so together with these side margins the button
   overhung the right edge by exactly one margin (14px) and `overflow-x: hidden`
   sliced it off, leaving it visibly off-centre. `.sidebar` is a column flex
   container, so `width: auto` hands sizing back to the default
   `align-items: stretch`, which fits the button to (sidebar − margins) and
   keeps both gutters equal. Scoped to `.sidebar` so it outranks `.btn-block`,
   which is defined later in this file at the same specificity. */
.sidebar .sidebar-cta { width: auto; margin: 0 14px 16px; gap: 8px; }
.sidebar-cta .ico { width: 17px; height: 17px; }

.sidenav { display: flex; flex-direction: column; gap: 1px; padding: 0 8px; flex: 1; }
.navgroup-label {
  font-size: 10.5px; text-transform: uppercase; letter-spacing: 0.09em; font-weight: 700;
  color: rgba(255, 255, 255, 0.55); padding: 16px 8px 6px;
}
.navlink {
  display: flex; align-items: center; gap: 10px;
  padding: 9px 10px; border-radius: 8px; border-left: 3px solid transparent;
  color: rgba(255, 255, 255, 0.82); font-size: 14px; font-weight: 600; line-height: 1.2;
}
.navlink:hover { background: rgba(255, 255, 255, 0.1); color: #fff; text-decoration: none; }
.navlink .ico { width: 18px; height: 18px; opacity: 0.85; flex-shrink: 0; }
.navlink.active {
  background: var(--lime-soft); border-left-color: var(--lime);
  color: var(--navy-deep); font-weight: 700;
}
.navlink.active .ico { opacity: 1; color: var(--lime-text); }

.sidebar-user {
  display: flex; align-items: center; gap: 9px; margin: 16px 0 0;
  padding: 12px 14px; border-top: 1px solid rgba(255, 255, 255, 0.12);
}
.sidebar-user-text { flex: 1; min-width: 0; line-height: 1.25; }
.sidebar-user-name {
  display: block; font-size: 13.5px; font-weight: 600; color: #fff;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.sidebar-user-role { display: block; font-size: 11.5px; color: rgba(255, 255, 255, 0.6); text-transform: capitalize; }
.sidebar-user .btn-icon { color: rgba(255, 255, 255, 0.75); border-color: rgba(255, 255, 255, 0.25); }
.sidebar-user .btn-icon:hover { color: #fff; background: rgba(255, 255, 255, 0.14); }

/* both appear only in drawer mode (see the 860px block) */
.mobilebar { display: none; }
.nav-backdrop { display: none; }

/* ---------- page header band ---------- */
.pagehead {
  background: linear-gradient(155deg, #eef3fa 0%, #e4ecf7 100%);
  border: 1px solid var(--border); border-radius: var(--radius);
  padding: 16px 18px; margin-bottom: 18px;
  display: grid; grid-template-columns: 1fr auto; gap: 10px 22px; align-items: start;
}
.pagehead-main { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; min-width: 0; }
.pagehead-titles { min-width: 0; }
.pagehead-eyebrow {
  font-size: 10.5px; font-weight: 700; text-transform: uppercase;
  letter-spacing: 0.09em; color: var(--ink-2);
}
.pagehead-title {
  font-size: 25px; font-weight: 700; letter-spacing: -0.025em;
  color: var(--navy-deep); margin: 0; line-height: 1.15;
}
.pagehead-today { margin-left: 6px; }
.pagehead-chips { grid-column: 1; display: flex; gap: 8px; flex-wrap: wrap; }

/* ---------- headings ---------- */
h1 {
  font-size: 22px; margin: 4px 0 12px; color: var(--navy-deep);
  letter-spacing: -0.02em; line-height: 1.25;
}
h2 {
  font-size: 12.5px; margin: 26px 0 10px; color: var(--muted);
  text-transform: uppercase; letter-spacing: 0.07em; font-weight: 700;
}
h2:first-of-type { margin-top: 20px; }

/* ---------- chips (context counts) ---------- */
.chip {
  display: inline-flex; align-items: center; gap: 6px;
  background: var(--card); border: 1px solid var(--border); border-radius: 999px;
  padding: 3px 11px; font-size: 12.5px; font-weight: 600; color: var(--ink-2);
  white-space: nowrap;
}
.chip strong { color: var(--navy-deep); font-weight: 700; }
.chip-warn { background: var(--warning-soft); border-color: #f0dcae; color: var(--warning-text); }

/* ---------- tabs (module nav) ---------- */
.tabs {
  display: flex; gap: 6px; margin: 0 0 18px;
  overflow-x: auto; -webkit-overflow-scrolling: touch;
  scrollbar-width: none; padding: 2px;
}
.tabs::-webkit-scrollbar { display: none; }
.tabs a {
  padding: 7px 14px; border-radius: 999px; background: var(--card);
  border: 1px solid var(--border); font-weight: 600; font-size: 13.5px;
  color: var(--ink-2); white-space: nowrap; flex-shrink: 0;
}
.tabs a.active { background: var(--navy-deep); border-color: var(--navy-deep); color: #fff; }
.tabs a:hover { text-decoration: none; border-color: var(--navy); color: var(--navy-deep); }
.tabs a.active:hover { color: #fff; }

/* ---------- underlined tab bar (in-page section switching) ---------- */
.tabbar { display: flex; gap: 4px; border-bottom: 1px solid var(--border); margin-bottom: 16px; }
.tabbar a {
  padding: 10px 16px; font-weight: 600; font-size: 14px; color: var(--ink-2);
  border-bottom: 3px solid transparent; margin-bottom: -1px;
}
.tabbar a:hover { text-decoration: none; color: var(--navy-deep); }
.tabbar a.active {
  color: var(--lime-text); border-bottom-color: var(--lime);
  background: var(--lime-soft); border-radius: 8px 8px 0 0;
}

/* ---------- segmented control ---------- */
.seg {
  display: inline-flex; background: var(--card); border: 1px solid var(--border);
  border-radius: 999px; padding: 3px; gap: 2px;
}
.seg a, .seg button {
  padding: 6px 13px; border-radius: 999px; border: 0; background: none;
  font: inherit; font-size: 13px; font-weight: 600; color: var(--ink-2); cursor: pointer;
}
.seg a:hover, .seg button:hover { background: var(--bg); text-decoration: none; }
.seg a.active, .seg button.active { background: var(--navy-deep); color: #fff; }

/* ---------- pager (prev / title / next navigation) ---------- */
.pager { display: flex; align-items: center; gap: 10px; margin: 4px 0 14px; }
.pager-title { font-size: 17px; font-weight: 700; color: var(--navy-deep); letter-spacing: -0.01em; }
.pager .btn { flex-shrink: 0; }
.pager-spacer { flex: 1; }

/* ---------- cards ---------- */
.cards { display: grid; grid-template-columns: repeat(auto-fill, minmax(260px, 1fr)); gap: 14px; }
.card {
  background: var(--card); border: 1px solid var(--border); border-radius: var(--radius);
  padding: 16px 18px; box-shadow: var(--shadow-card);
}
.card-link { display: block; color: inherit; }
.card-link:hover { text-decoration: none; border-color: var(--lime); box-shadow: 0 0 0 3px var(--lime-soft); }
.card-title { font-weight: 700; font-size: 16.5px; color: var(--navy-deep); }
.card-sub { color: var(--muted); font-size: 13.5px; margin-top: 2px; }

/* accent card (callouts that need a state rail) */
.card-accent { border-left: 4px solid var(--warning); }
.card-good { border-left: 4px solid var(--good); }

/* ---------- stat tiles (icon tile + number + label) ---------- */
.statcards, .statrow {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(152px, 1fr));
  gap: 12px; margin: 0 0 18px;
}
.stat {
  background: var(--card); border: 1px solid var(--border); border-radius: var(--radius);
  padding: 13px 15px; box-shadow: var(--shadow-card); min-width: 0;
  display: flex; align-items: flex-start; gap: 11px;
}
.stat-icon {
  width: 34px; height: 34px; border-radius: 10px; flex-shrink: 0;
  display: flex; align-items: center; justify-content: center;
  background: var(--navy-wash); color: var(--navy);
}
.stat-body { min-width: 0; }
.stat .label {
  font-size: 11px; color: var(--muted); font-weight: 700;
  text-transform: uppercase; letter-spacing: 0.05em;
}
.stat .value {
  font-size: 24px; font-weight: 700; letter-spacing: -0.02em; margin-top: 1px;
  font-variant-numeric: tabular-nums; color: var(--navy-deep); line-height: 1.2;
}
.stat .sub { font-size: 12.5px; color: var(--muted); margin-top: 2px; }
/* the highlighted tile (Goose marks the focused metric) — at most one per row */
.stat.is-active { border-color: var(--lime); background: var(--lime-soft); }
.stat.is-active .stat-icon { background: #fff; color: var(--lime-text); }

/* mini stat tiles inside cards stack icon-over-label */
.mini-stat { min-width: 0; }
.mini-stat .stat-icon { width: 28px; height: 28px; border-radius: 8px; margin-bottom: 6px; }
.mini-stat .label { font-size: 10.5px; color: var(--muted); font-weight: 700; text-transform: uppercase; letter-spacing: 0.05em; }
.mini-stat .value { font-size: 19px; font-weight: 700; font-variant-numeric: tabular-nums; color: var(--navy-deep); margin-top: 1px; }

/* ---------- avatars ---------- */
.avatar-sm, .avatar {
  display: inline-flex; align-items: center; justify-content: center;
  border-radius: 50%; background: var(--av-1); color: #fff;
  font-weight: 700; text-transform: uppercase; flex-shrink: 0; line-height: 1;
}
.avatar-sm { width: 30px; height: 30px; font-size: 12.5px; }
.avatar { width: 40px; height: 40px; font-size: 15px; }
/* `i` flag: names may be stored lower-case ("kai nguyen").
   A/G/M/S/Y intentionally have no rule — they fall through to --av-1 above,
   which is what makes six tints out of five overrides. */
[data-letter="B" i], [data-letter="H" i], [data-letter="N" i], [data-letter="T" i], [data-letter="Z" i] { background: var(--av-2); }
[data-letter="C" i], [data-letter="I" i], [data-letter="O" i], [data-letter="U" i] { background: var(--av-3); }
[data-letter="D" i], [data-letter="J" i], [data-letter="P" i], [data-letter="V" i] { background: var(--av-4); }
[data-letter="E" i], [data-letter="K" i], [data-letter="Q" i], [data-letter="W" i] { background: var(--av-5); }
[data-letter="F" i], [data-letter="L" i], [data-letter="R" i], [data-letter="X" i] { background: var(--av-6); }

/* identity cell: avatar + name + meta */
.idcell { display: flex; align-items: center; gap: 10px; text-align: left; }
.idcell-text { min-width: 0; line-height: 1.3; }
.rc-name { display: block; font-weight: 700; color: var(--navy-deep); }
.rc-meta { display: block; font-size: 12.5px; color: var(--muted); white-space: normal; }
.idcell-text .pill { margin-top: 3px; }

/* small round badge used beside a name (e.g. an outstanding count) */
.badge-dot {
  display: inline-flex; align-items: center; justify-content: center;
  width: 18px; height: 18px; border-radius: 50%; font-size: 11px; font-weight: 700;
  background: var(--critical-soft); color: var(--critical-text); border: 1px solid #f0cfcb;
}

/* inline checkbox rows (multi-select assignment) */
.checkline {
  display: inline-flex; flex-direction: row; align-items: center; gap: 5px;
  font-weight: 400; margin: 0 12px 4px 0; font-size: 13.5px; color: var(--ink);
}
.field-label { display: block; font-size: 12.5px; font-weight: 600; color: var(--ink-2); margin-bottom: 4px; }

/* ---------- section cards (icon badge + title + hint + body) ---------- */
.section-card {
  background: var(--card); border: 1px solid var(--border); border-radius: var(--radius);
  box-shadow: var(--shadow-card); padding: 16px 18px; margin-bottom: 16px;
  display: flex; gap: 14px; align-items: flex-start;
}
.section-icon {
  width: 38px; height: 38px; border-radius: 50%; flex-shrink: 0;
  display: flex; align-items: center; justify-content: center;
  background: var(--navy-wash); color: var(--navy);
}
.section-body { flex: 1; min-width: 0; }
/* h2.section-title must beat `h2:first-of-type { margin-top: 20px }` */
.section-body > .section-title, h2.section-title {
  font-size: 15.5px; font-weight: 700; color: var(--navy-deep); margin: 0;
  text-transform: none; letter-spacing: -0.01em;
}
.section-hint { font-size: 13px; color: var(--muted); margin: 2px 0 0; }
.section-body > .form-grid, .section-body > form, .section-body > .table-wrap { margin-top: 12px; }
.section-card.is-open { border-color: var(--lime); border-width: 1px; box-shadow: 0 0 0 3px var(--lime-soft); }

/* ---------- sticky action bar ---------- */
.actionbar {
  position: sticky; bottom: 0; z-index: 5;
  display: flex; align-items: center; gap: 14px; flex-wrap: wrap;
  background: var(--card); border: 1px solid var(--border); border-radius: var(--radius);
  box-shadow: 0 -2px 14px rgba(20, 40, 71, 0.08); padding: 12px 16px; margin-top: 16px;
}
.actionbar-summary { flex: 1; text-align: center; font-size: 14px; color: var(--ink-2); min-width: 140px; }
.actionbar-summary strong { color: var(--navy-deep); font-variant-numeric: tabular-nums; }
/* long explanatory copy rather than a short running total */
.actionbar-note { flex: 1; text-align: left; font-size: 12.5px; color: var(--muted); min-width: 180px; }

/* ---------- icon button ---------- */
.btn-icon {
  display: inline-flex; align-items: center; justify-content: center;
  width: var(--control-h); height: var(--control-h); flex-shrink: 0;
  border: 1px solid var(--border-strong); border-radius: var(--radius-sm);
  background: var(--card); color: var(--ink-2); cursor: pointer;
  /* shorthand first — it resets font-size, so the explicit size must follow */
  font: inherit; font-size: 16px; line-height: 1; padding: 0;
}
.btn-icon:hover { background: var(--bg); color: var(--navy-deep); text-decoration: none; }
.btn-icon-quiet { border-color: transparent; background: none; }

/* ---------- forms ---------- */
.stack { display: flex; flex-direction: column; gap: 12px; }
label {
  display: flex; flex-direction: column; gap: 5px;
  font-size: 12.5px; font-weight: 600; color: var(--ink-2);
}
input, select, textarea {
  font: inherit; font-size: var(--font-input); color: var(--ink);
  padding: 0 12px; height: var(--control-h);
  border: 1px solid var(--border-strong); border-radius: var(--radius-sm);
  background: var(--card); min-width: 0; width: 100%;
}
textarea { height: auto; padding: 10px 12px; }
input[type="checkbox"] { width: auto; height: auto; accent-color: var(--navy); }
input[type="file"] { padding: 6px 10px; height: auto; }
input:focus, select:focus, textarea:focus {
  outline: none; border-color: var(--navy); box-shadow: 0 0 0 3px var(--navy-wash);
}

/* form-grid: fields flow into columns on desktop, 2-up on phones */
.form-grid {
  display: grid; gap: 12px 14px; align-items: end;
  grid-template-columns: repeat(auto-fit, minmax(140px, 1fr));
}
.form-grid .f-wide { grid-column: span 2; }
.form-actions { display: flex; gap: 10px; align-items: center; }
.form-note { font-size: 13px; color: var(--muted); margin: 10px 0 0; }
.card .form-note + form { margin-top: 12px; }

/* section-level blocks stacked directly on the page get breathing room */
.content > .card, .content > .table-wrap, .content > details.disclosure,
.content > form > .table-wrap { margin-bottom: 16px; }
.statcards + .card, .statrow + .card { margin-top: 10px; }
/* a section-card nested in a disclosure already has the disclosure's margin */
details.disclosure > .section-card { margin-bottom: 0; }

/* legacy inline form (still used while views migrate) */
.inline-form { display: flex; gap: 10px; align-items: end; flex-wrap: wrap; }
.inline-form label { min-width: 110px; flex: 1; }
.field-sm { max-width: 130px; }

/* ---------- buttons ---------- */
.btn {
  font: inherit; font-size: 14px; font-weight: 600;
  height: var(--control-h); padding: 0 15px;
  display: inline-flex; align-items: center; justify-content: center;
  border-radius: var(--radius-sm);
  border: 1px solid var(--border-strong); background: var(--card); color: var(--ink);
  cursor: pointer; transition: background 0.12s, border-color 0.12s;
  white-space: nowrap;
}
.btn:hover { background: var(--bg); text-decoration: none; }
.btn:focus-visible { outline: 2px solid var(--navy); outline-offset: 2px; }
.btn-primary {
  background: var(--lime); border-color: var(--lime); color: var(--navy-deep); font-weight: 700;
}
.btn-primary:hover { background: var(--lime-hover); border-color: var(--lime-hover); }
.btn-ghost { background: transparent; border-color: var(--border-strong); color: var(--ink-2); }
.btn-ghost:hover { background: var(--card); color: var(--ink); }
.btn-danger { background: transparent; border-color: var(--border-strong); color: var(--critical-text); }
.btn-danger:hover { background: var(--critical-soft); border-color: #eccfcf; }
.btn-block { width: 100%; }
.btn-sm { height: 32px; padding: 0 11px; font-size: 12.5px; }
.btn:disabled, .btn[aria-disabled="true"], .btn-icon:disabled {
  opacity: 0.55; cursor: not-allowed;
}
.btn:disabled:hover, .btn[aria-disabled="true"]:hover, .btn-icon:disabled:hover {
  background: var(--card);
}
.btn-primary:disabled:hover, .btn-primary[aria-disabled="true"]:hover { background: var(--lime); }

/* ---------- alerts ---------- */
.alert {
  background: var(--critical-soft); color: var(--critical-text);
  border: 1px solid #f0cfcb; border-left: 4px solid var(--critical);
  border-radius: var(--radius-sm); padding: 10px 12px; font-size: 14px; margin-bottom: 12px;
}
.notice {
  background: var(--good-soft); color: var(--good-text);
  border: 1px solid #cfe6a8; border-left: 4px solid var(--lime);
  border-radius: var(--radius-sm); padding: 10px 12px; font-size: 14px; margin-bottom: 12px;
}

/* ---------- auth ---------- */
.auth-wrap {
  min-height: 100vh; display: flex; align-items: center; justify-content: center; padding: 16px;
  background: linear-gradient(160deg, var(--navy) 0%, var(--navy-deep) 100%);
}
.auth-card {
  width: 100%; max-width: 384px; background: var(--card);
  border-radius: 16px; padding: 36px 32px 32px; box-shadow: var(--shadow-pop);
  border-top: 4px solid var(--lime);
}
.auth-logo { width: 68px; height: 68px; display: block; margin: 0 auto 12px; }
.auth-brand {
  font-size: 21px; font-weight: 700; color: var(--navy-deep); text-align: center; letter-spacing: -0.01em;
}
.auth-brand span { font-weight: 400; }
.auth-tag { text-align: center; color: var(--muted); font-size: 13.5px; margin: 4px 0 20px; }

/* ---------- tables ---------- */
.table-tools {
  display: flex; align-items: center; justify-content: flex-end; gap: 10px;
  margin: 0 0 8px;
}
/* Rows render as separated white cards (Goose pattern), not flat ruled rows.
   The wrapper owns the horizontal scroll — the content column must never
   scroll sideways, so every wide table stays inside its own overflow box. */
.table-wrap { overflow-x: auto; padding: 1px; }
.table-narrow { max-width: 700px; }
table { border-collapse: separate; border-spacing: 0 8px; width: 100%; font-size: 13.5px; }
th, td {
  text-align: right; padding: 11px 11px; border: 0;
  white-space: nowrap; vertical-align: middle; font-variant-numeric: tabular-nums;
}
.table-wrap input[type="date"] { max-width: 150px; }
th:first-child, td:first-child { text-align: left; padding-left: 14px; }
td:last-child, th:last-child { padding-right: 14px; }
thead th {
  font-size: 10.5px; font-weight: 700; text-transform: uppercase; letter-spacing: 0.04em;
  color: var(--muted); padding: 0 11px 2px; white-space: normal; line-height: 1.25;
}
tbody tr { background: var(--card); box-shadow: var(--shadow-card); }
tbody td { border-top: 1px solid var(--border); border-bottom: 1px solid var(--border); }
tbody td:first-child { border-left: 1px solid var(--border); border-radius: var(--radius) 0 0 var(--radius); }
tbody td:last-child { border-right: 1px solid var(--border); border-radius: 0 var(--radius) var(--radius) 0; }
tbody tr:hover td { background: #fbfcfe; border-color: var(--navy-wash); }
tfoot td {
  font-weight: 700; background: var(--navy-wash); color: var(--navy-deep);
  border-top: 1px solid var(--border-strong); border-bottom: 1px solid var(--border-strong);
}
tfoot td:first-child { border-left: 1px solid var(--border-strong); border-radius: var(--radius) 0 0 var(--radius); }
tfoot td:last-child { border-right: 1px solid var(--border-strong); border-radius: 0 var(--radius) var(--radius) 0; }
.cell-text { text-align: left; max-width: 200px; white-space: normal; }
.cell-act { text-align: right; }
.row-dim { opacity: 0.6; }

/* space / room / department identifier pill */
.pill-space {
  display: inline-flex; align-items: center; gap: 6px;
  background: var(--navy-wash); color: var(--navy); border-radius: 999px;
  padding: 3px 11px; font-size: 12px; font-weight: 700;
}

/* Focused columns: .c-detail cells are hidden until the wrapper gets
   .show-detail (toggled by app.js, persisted per table). */
.table-wrap .c-detail { display: none; }
.table-wrap.show-detail th.c-detail,
.table-wrap.show-detail td.c-detail { display: table-cell; }

.pill {
  display: inline-block; padding: 2px 10px; border-radius: 999px;
  font-weight: 700; font-size: 12px; border: 1px solid transparent;
  font-variant-numeric: tabular-nums;
}
.pill-green { background: var(--good-soft); color: var(--good-text); border-color: #cbe4bb; }
.pill-red { background: var(--critical-soft); color: var(--critical-text); border-color: #f0cfcb; }
.pill-amber { background: var(--warning-soft); color: var(--warning-text); border-color: #f0dcae; }
.pill-muted { background: var(--bg); color: var(--ink-2); border-color: var(--border); }

/* ---------- empty states + text helpers ---------- */
.empty {
  background: var(--card); border: 1px dashed var(--border-strong); border-radius: var(--radius);
  padding: 30px 20px; text-align: center; color: var(--muted);
}
.muted { color: var(--muted); }
.small { font-size: 13px; }

/* ---------- toolbar (filter rows) ---------- */
.toolbar { display: flex; gap: 10px; align-items: end; flex-wrap: wrap; margin-bottom: 14px; }
.toolbar form { display: flex; gap: 10px; align-items: end; flex-wrap: wrap; }
.toolbar .note { font-size: 13px; color: var(--muted); padding-bottom: 10px; }

/* ---------- charts ---------- */
.chart-card { padding: 16px 18px 10px; }
.chart-title { font-size: 13px; font-weight: 600; color: var(--ink-2); margin-bottom: 8px; }
.chart svg { width: 100%; height: auto; display: block; }

/* ---------- disclosure ---------- */
details.disclosure { margin-bottom: 14px; }
details.disclosure > summary {
  cursor: pointer; font-size: 13.5px; font-weight: 600; color: var(--navy);
  padding: 4px 0;
}
details.disclosure[open] > summary { margin-bottom: 8px; }

/* ---------- responsive ---------- */
/* Tablet: narrower sidebar before it collapses entirely. */
@media (max-width: 1080px) {
  :root { --sidebar-w: 210px; }
  .content { padding: 18px 16px 56px; }
}

/* Phone/tablet: sidebar becomes an off-canvas drawer, toggled by a checkbox
   so it works with JavaScript disabled. */
@media (max-width: 860px) {
  .shell-main { margin-left: 0; }
  /* visibility is what removes the closed drawer from the tab order and the
     accessibility tree — transform alone only moves it off screen, leaving the
     brand link, the CTA, every nav link and logout focusable and read aloud.
     The 0s/0.2s delay when closed lets the slide-out finish before the sidebar
     disappears; open flips it to visible with no delay, so the drawer is never
     invisible while it is sliding in or open. */
  .sidebar {
    width: 270px; transform: translateX(-100%); visibility: hidden;
    transition: transform 0.2s ease, visibility 0s 0.2s; box-shadow: var(--shadow-pop);
  }
  .navtoggle-input:checked ~ .shell .sidebar {
    transform: translateX(0); visibility: visible;
    transition: transform 0.2s ease, visibility 0s 0s;
  }
  .navtoggle-input:checked ~ .shell .nav-backdrop {
    display: block; position: fixed; inset: 0; z-index: 25;
    background: rgba(20, 40, 71, 0.45);
  }
  .nav-close {
    display: flex; align-items: center; justify-content: center;
    width: 34px; height: 34px; border-radius: 8px; cursor: pointer;
    color: rgba(255, 255, 255, 0.85); font-size: 24px; line-height: 1;
  }
  .nav-close:hover { background: rgba(255, 255, 255, 0.14); }
  .mobilebar {
    display: flex; align-items: center; gap: 12px;
    background: var(--navy-deep); border-bottom: 3px solid var(--lime);
    padding: 9px 12px; position: sticky; top: 0; z-index: 20;
  }
  .mobilebar .btn-icon {
    background: rgba(255, 255, 255, 0.12); border-color: rgba(255, 255, 255, 0.28);
    color: #fff; width: 40px; height: 40px;
  }
  .mobilebar-brand {
    display: flex; align-items: center; gap: 9px;
    color: #fff; font-weight: 700; font-size: 15px;
  }
  .mobilebar-brand:hover { text-decoration: none; }
  .mobilebar .brand-logo { width: 28px; height: 28px; }
  .pagehead { grid-template-columns: 1fr; padding: 14px; }
  .pagehead-title { font-size: 21px; }
}

@media (max-width: 720px) {
  :root { --control-h: 44px; --font-input: 16px; } /* 16px stops iOS zoom-on-focus */
  .content { padding: 14px 12px 48px; }
  h1 { font-size: 20px; }
  .auth-card { padding: 28px 22px 24px; }
  .statcards, .statrow { grid-template-columns: repeat(2, 1fr); }
  .stat { padding: 11px 12px; gap: 9px; }
  .stat-icon { width: 30px; height: 30px; }
  .stat .value { font-size: 21px; }
  .section-card { padding: 14px; gap: 11px; }
  .section-icon { width: 32px; height: 32px; }
  .actionbar { flex-direction: column; align-items: stretch; }
  .actionbar .btn { width: 100%; }

  .form-grid { grid-template-columns: repeat(2, 1fr); }
  .form-grid .f-wide, .form-grid .form-actions { grid-column: 1 / -1; }
  .form-actions .btn-primary { flex: 1; }
  .inline-form label { min-width: 45%; }

  /* Card-collapse for responsive tables: each row becomes a labeled card.
     Every td needs data-th="<column label>" — it becomes the row label here.
     A td with no data-th right-aligns unlabeled (correct for actions cells). */
  .rtable table, .rtable tbody, .rtable tfoot, .rtable tr, .rtable td { display: block; }
  .rtable table { border-spacing: 0; }
  .rtable thead { display: none; }
  .rtable tr {
    padding: 12px 14px; border: 1px solid var(--border);
    border-radius: var(--radius); margin-bottom: 10px;
  }
  .rtable td {
    display: flex; justify-content: space-between; align-items: center; gap: 14px;
    border: 0; padding: 3px 0; text-align: right; white-space: normal;
  }
  .rtable td:first-child, .rtable td:last-child { border-radius: 0; border: 0; }
  .rtable .idcell { justify-content: flex-start; }
  .rtable td::before {
    content: attr(data-th); font-size: 12px; font-weight: 600; color: var(--muted);
    text-align: left; flex-shrink: 0;
  }
  .rtable td:not([data-th]) { justify-content: flex-end; }
  .rtable td:not([data-th])::before { content: none; }
  .rtable td:first-child { font-weight: 700; }
  .rtable td:empty { display: none; }
  .rtable tbody tr:hover td { background: transparent; border-color: transparent; }
  .rtable .cell-text { max-width: none; }
  .rtable tfoot td { background: transparent; border: 0; border-radius: 0; }
  .rtable tfoot tr { background: var(--navy-wash); border-color: var(--border-strong); }
  .rtable.show-detail td.c-detail { display: flex; }
  .rtable.show-detail td.c-detail:empty { display: none; }
  .rtable td .btn-sm { height: 36px; }
  /* inputs inside collapsed rows (editable grids) */
  .rtable td input, .rtable td select { max-width: 55%; }
}

@media (prefers-reduced-motion: reduce) {
  * { transition: none !important; }
}

/* ===== END SHARED CORE ===== */


/* ============================================================================
   PORTAL-SPECIFIC
   Everything below here belongs to the Employee Portal alone. Nothing in this
   section may be copied back into the shared core.
   ============================================================================ */

/* ---------- legacy token aliases ----------------------------------------- */
/* The pre-redesign stylesheet, and any markup the migration has not reached
   yet, still names colours with these variables. Aliasing them onto the new
   tokens means nothing ever resolves to an empty value mid-migration. */
:root {
  --brand: var(--navy);
  --brand-dark: var(--navy-deep);
  --accent: var(--lime);
  --accent-hover: var(--lime-hover);
  --accent-text: var(--lime-text);
  --text: var(--ink);
  --error: var(--critical);
}

/* ---------- retired: the old top bar -------------------------------------- */
/* .dash-header / .dash-brand / .dash-logo / .dash-nav / .dash-user /
   .dash-user-link and their 960px + 520px media queries were deleted here.
   The Portal now uses the shared sidebar shell (.shell / .sidebar / .sidenav /
   .mobilebar in the core above), so the horizontal top bar and all of its
   wrapping rules no longer have anything to lay out. Their old comments about
   the six-link nav overflowing at 960px and the wordmark dropping to a third
   row under 430px are recorded here for context only - the drawer removes both
   problems outright. .nav-link is likewise NOT redefined below: the sidebar
   link class now lives in the core as .navlink, and nav.js emits that name. */

/* ---------- status pills -------------------------------------------------- */
/* .badge is the Portal's historic name for the core's .pill. Both vocabularies
   are live: admin.js and timeoff.js still write `badge badge-active` /
   `badge badge-${status}`, and migrated markup can use .pill / .pill-green
   directly. Keep the aliases until every writer has moved over. */
.badge {
  display: inline-block; padding: 2px 10px; border-radius: 999px;
  font-weight: 700; font-size: 12px; border: 1px solid transparent;
  font-variant-numeric: tabular-nums;
}
/* -> .pill-green */
.badge-active, .badge-approved {
  background: var(--good-soft); color: var(--good-text); border-color: #cbe4bb;
}
/* -> .pill-muted */
.badge-inactive { background: var(--bg); color: var(--ink-2); border-color: var(--border); }
/* -> .pill-amber */
.badge-pending { background: var(--warning-soft); color: var(--warning-text); border-color: #f0dcae; }
/* -> .pill-red */
.badge-denied { background: var(--critical-soft); color: var(--critical-text); border-color: #f0cfcb; }

/* ---------- button aliases ------------------------------------------------ */
/* The old names mapped onto the core .btn variants:
     .btn-add         -> .btn.btn-primary.btn-sm
     .btn-small       -> .btn.btn-sm
     .btn-link        -> .btn.btn-sm on an <a>
     .btn-secondary   -> .btn.btn-ghost
     .btn-destructive -> .btn.btn-danger
   The old rules leaned on !important to beat `.detail-modal button`. That
   blanket rule is gone (see the modal section), so no alias needs !important -
   and none carries one. */
.btn-add, .btn-small, .btn-secondary, .btn-destructive, .btn-link {
  font: inherit; font-size: 14px; font-weight: 600;
  height: var(--control-h); padding: 0 15px;
  display: inline-flex; align-items: center; justify-content: center;
  border-radius: var(--radius-sm);
  border: 1px solid var(--border-strong); background: var(--card); color: var(--ink);
  cursor: pointer; transition: background 0.12s, border-color 0.12s;
  white-space: nowrap;
}
.btn-add:hover, .btn-small:hover, .btn-secondary:hover,
.btn-destructive:hover, .btn-link:hover { background: var(--bg); text-decoration: none; }
.btn-add:focus-visible, .btn-small:focus-visible, .btn-secondary:focus-visible,
.btn-destructive:focus-visible, .btn-link:focus-visible {
  outline: 2px solid var(--navy); outline-offset: 2px;
}

/* the small (32px) geometry */
.btn-add, .btn-small, .btn-link { height: 32px; padding: 0 11px; font-size: 12.5px; }

.btn-add { background: var(--lime); border-color: var(--lime); color: var(--navy-deep); font-weight: 700; }
.btn-add:hover { background: var(--lime-hover); border-color: var(--lime-hover); }

.btn-secondary { background: transparent; border-color: var(--border-strong); color: var(--ink-2); }
.btn-secondary:hover { background: var(--card); color: var(--ink); }

.btn-destructive { background: transparent; color: var(--critical-text); }
.btn-destructive:hover { background: var(--critical-soft); border-color: #eccfcf; }

/* `btn-small btn-danger` is the commonest pair in admin.js / documents.js /
   timeoff.js. The core's .btn-danger sits ABOVE this section, so the alias base
   would otherwise win on later-wins-at-equal-specificity; restate the danger
   colours here so the combination keeps working. */
.btn-small.btn-danger, .btn-link.btn-danger {
  background: transparent; border-color: var(--border-strong); color: var(--critical-text);
}
.btn-small.btn-danger:hover, .btn-link.btn-danger:hover {
  background: var(--critical-soft); border-color: #eccfcf;
}

.btn-add:disabled, .btn-small:disabled, .btn-secondary:disabled, .btn-destructive:disabled {
  opacity: 0.55; cursor: not-allowed;
}
.btn-add:disabled:hover { background: var(--lime); border-color: var(--lime); }
.btn-small:disabled:hover { background: var(--card); }
.btn-secondary:disabled:hover, .btn-destructive:disabled:hover { background: transparent; }

/* ---------- page scaffolding ---------------------------------------------- */
.dash-body { min-height: 100vh; }

/* .page-wrap is the pre-shell page container. It mirrors the core's .content
   exactly, so an unmigrated <main class="page-wrap"> still reads correctly;
   migration replaces it with <main class="content" id="main"> inside .shell,
   and this rule can be deleted once no page uses it. Never nest one inside the
   other - the padding would double. */
.page-wrap { max-width: 1180px; margin: 0 auto; padding: 20px 22px 64px; }

/* .page-head / .page-sub are the pre-pagehead title block. On migrated screens
   the .pagehead band in the core replaces them. .page-sub is also used as a
   quiet caption inside the <dialog> sheets, so it outlives .page-head. */
.page-head { margin-bottom: 16px; }
.page-head h1 { margin: 0; font-size: 22px; color: var(--navy-deep); letter-spacing: -0.02em; }
.page-sub { margin: 4px 0 0; color: var(--muted); font-size: 13.5px; }
/* Several migrated pages keep the subtitle copy inside the .pagehead band. The
   band is a light gradient, not white, and --muted (#6d7387) on its darkest
   stop (#e4ecf7) is only 3.95:1 - under the 4.5:1 AA needs at 13.5px. --ink-2
   (#4d5468) on that same stop is 6.34:1. Scoped to .pagehead so .page-sub stays
   --muted where it is a quiet caption on white inside the <dialog> sheets. */
.pagehead .page-sub { color: var(--ink-2); }

.placeholder {
  min-height: 100vh; display: flex; flex-direction: column;
  align-items: center; justify-content: center; gap: 8px;
  padding: 24px; text-align: center;
}
.placeholder h1 { color: var(--navy-deep); margin: 0; }
.placeholder p { color: var(--muted); margin: 0; }

/* A .card used as a titled block still leads with a plain <h2>. The core's h2
   is the small uppercase section label, which is wrong for a card title, so
   restore the title treatment. Migrated blocks should move to .section-card
   (icon + .section-title + .section-hint) or .card-title instead. */
.card > h2 {
  margin: 0 0 12px; font-size: 16.5px; font-weight: 700; color: var(--navy-deep);
  text-transform: none; letter-spacing: -0.01em;
}

/* ---------- form feedback -------------------------------------------------- */
/* .form-error is the core's .alert, .form-success is its .notice. Neither sets
   `display`, so the `hidden` attribute these elements toggle keeps working. */
.form-error {
  background: var(--critical-soft); color: var(--critical-text);
  border: 1px solid #f0cfcb; border-left: 4px solid var(--critical);
  border-radius: var(--radius-sm); padding: 10px 12px; font-size: 13.5px;
  margin: 12px 0 0;
}
.form-success {
  background: var(--good-soft); color: var(--good-text);
  border: 1px solid #cfe6a8; border-left: 4px solid var(--lime);
  border-radius: var(--radius-sm); padding: 10px 12px; font-size: 13.5px;
  font-weight: 600; margin: 12px 0 0;
}
.field-hint { color: var(--muted); font-size: 12.5px; margin: 4px 0 0; }
.muted-note { color: var(--muted); font-size: 12.5px; margin: 10px 0 0; }

/* ---------- auth screens --------------------------------------------------- */
/* .auth-wrap / .auth-card / .auth-logo come from the core. The Portal's login,
   sign-up and join screens wrap the logo + title + tagline in .auth-brand, so
   those bits live here. Field rhythm is deliberately NOT set here: those forms
   carry class="stack", and .stack's 12px gap plus the core label's own 5px gap
   already own every bit of the vertical spacing. The transitional
   `.auth-card label` margins that used to sit below compounded with both gaps
   and gave the auth forms an uneven rhythm, so they are gone. */
.auth-brand { text-align: center; margin-bottom: 20px; }
.auth-brand h1 {
  font-size: 21px; font-weight: 700; margin: 10px 0 0;
  color: var(--navy-deep); letter-spacing: -0.01em;
}
.auth-tagline { color: var(--muted); margin: 4px 0 0; font-size: 13.5px; }

.auth-card form { display: flex; flex-direction: column; }
/* Transitional: the auth submit buttons carry no class yet. Scoped to
   type="submit" so a future secondary button in the card is not painted lime.
   Delete once the markup says class="btn btn-primary". */
.auth-card form button[type="submit"] {
  margin-top: 20px; height: var(--control-h); padding: 0 15px;
  display: inline-flex; align-items: center; justify-content: center;
  font: inherit; font-size: 14px; font-weight: 700;
  border: 1px solid var(--lime); border-radius: var(--radius-sm);
  background: var(--lime); color: var(--navy-deep); cursor: pointer;
  transition: background 0.12s, border-color 0.12s;
}
.auth-card form button[type="submit"]:hover { background: var(--lime-hover); border-color: var(--lime-hover); }
.auth-card form button[type="submit"]:disabled { opacity: 0.55; cursor: not-allowed; }
.auth-card form button[type="submit"]:disabled:hover { background: var(--lime); }

.auth-alt { text-align: center; font-size: 13.5px; color: var(--muted); margin: 20px 0 0; }
.auth-alt a { color: var(--navy); font-weight: 600; }

/* ---------- dashboard ------------------------------------------------------ */
.dash-grid {
  display: grid;
  /* min() so the 320px floor can't exceed the space available - on a 320px
     phone the bare minmax made the card wider than the viewport. */
  grid-template-columns: repeat(auto-fit, minmax(min(320px, 100%), 1fr));
  gap: 14px;
}

.profile-list { margin: 0; }
.profile-list div {
  display: flex; gap: 12px; padding: 7px 0; border-bottom: 1px solid var(--border);
}
.profile-list div:last-child { border-bottom: none; }
/* 4rem (64px), down from 7.5rem (120px). The labels are a closed set - Name,
   Email, Job title, Location, Role - and the widest of them ("Location")
   measures 48.9px at this size, so 120px was reserving ~71px of dead space the
   value column needed. 64px keeps ~15px of headroom for a longer label and
   hands 56px back to the values.

   Why this exact figure: .section-body is ~279px wide at every desktop size
   (.dash-grid packs more columns as the viewport grows rather than widening
   the card), so the value column is 279 - 64 - 12(gap) = ~203px. A 26-character
   work address needs ~203px - which is to say this fits the addresses in use,
   not every address. A longer one still wraps, and that is what the dd's
   overflow-wrap is there for.

   A fixed width, not auto: auto sizes each dt to its own text, which leaves the
   values starting at a different x on every row. */
.profile-list dt { width: 4rem; flex-shrink: 0; color: var(--muted); font-size: 13px; }
/* min-width:0 lets the dd shrink inside the flex row; overflow-wrap then lets a
   long unbroken value (an email address is the usual one) break rather than
   run off the edge of the card. */
.profile-list dd {
  margin: 0; min-width: 0; overflow-wrap: anywhere;
  font-weight: 600; font-size: 14px; color: var(--ink);
}

.announcement-list { list-style: none; margin: 0; padding: 0; }
.announcement-list li { padding: 12px 0; border-bottom: 1px solid var(--border); }
.announcement-list li:last-child { border-bottom: none; padding-bottom: 0; }
.announcement-list h3 {
  margin: 0; font-size: 15px; font-weight: 700; color: var(--navy-deep); letter-spacing: -0.01em;
}
.announcement-meta { margin: 2px 0 6px; color: var(--muted); font-size: 12.5px; }
.announcement-body { margin: 0; font-size: 14px; line-height: 1.5; color: var(--ink-2); }

/* Quick links are icon tiles: a tinted badge over a short label, with the same
   lime hover ring as .card-link so they read as one family.

   Each destination gets its own badge tint, so the three are told apart by
   colour as well as by glyph and label. The colours come from the avatar ramp
   (--av-3/4/5), which is the system's DECORATIVE palette; the status tokens are
   reserved for state and would make a quick link read as a warning or an error.
   Each pairs a saturated stroke with a wash mixed from the same hue.

   Colour is never the only signal here - every tile keeps its icon and its text
   label - so this stays readable for a colourblind user and when the badge
   fails to paint at all.

   Icon strokes are non-text graphics, so the 3:1 bar applies (the same reading
   as the .employee-location note below). Measured against their own washes:
   navy 9.30:1, teal 5.35:1, purple 5.96:1, brown 5.05:1. */
.quick-links { display: grid; grid-template-columns: repeat(3, 1fr); gap: 10px; }
.quick-link {
  display: flex; flex-direction: column; align-items: center; gap: 7px;
  padding: 13px 8px; text-align: center;
  background: var(--card); border: 1px solid var(--border); border-radius: var(--radius);
  color: var(--ink); font-weight: 600; font-size: 12.5px;
  transition: border-color 0.12s, box-shadow 0.12s;
}
.quick-link span {
  display: flex; align-items: center; justify-content: center;
  width: 36px; height: 36px; border-radius: 10px;
  background: var(--navy-wash); color: var(--navy); font-size: 18px; line-height: 1;
}
/* Keyed off the destination rather than nth-child, so the tints stay attached
   to their pages if the tiles are reordered or a fourth is added. An unlisted
   href simply keeps the navy default above. */
.quick-link[href="/timeoff"] span { background: #e1efee; color: #1d6a6a; }
/* Payroll is purple, not the av-3 brown: that brown sits a few points off
   --warning-text (#815500), and money next to something amber invites the
   reading that a payment needs attention. Brown goes to Documents, where it
   reads as a manila folder and carries no such implication. */
.quick-link[href="/payroll"] span { background: #f1e8f4; color: #7b3f8f; }
.quick-link[href="/documents"] span { background: #f6ecdd; color: #8a5a1b; }
.quick-link .ico { width: 20px; height: 20px; }
.quick-link:hover {
  text-decoration: none; border-color: var(--lime); box-shadow: 0 0 0 3px var(--lime-soft);
}
.quick-link[aria-disabled="true"] { opacity: 0.6; cursor: not-allowed; }
.quick-link[aria-disabled="true"]:hover { border-color: var(--border); box-shadow: none; }

/* ---------- payroll -------------------------------------------------------- */
.payroll-grid .card p { font-size: 14px; line-height: 1.55; margin: 0 0 8px; }
.payroll-grid .card p:last-child { margin-bottom: 0; }
.payroll-grid .card a { color: var(--navy); font-weight: 600; }

/* ---------- employee directory --------------------------------------------- */
/* .dir-controls is the directory's filter row - the same treatment as .toolbar
   in the core, kept under its own name until the markup adopts .toolbar. */
.dir-controls { display: flex; gap: 10px; align-items: end; flex-wrap: wrap; margin: 0 0 14px; }
.dir-controls input { flex: 1; min-width: 220px; }
.dir-controls select { min-width: 180px; flex: 0 1 220px; }

.employee-grid {
  list-style: none; margin: 0; padding: 0;
  display: grid; grid-template-columns: repeat(auto-fill, minmax(min(230px, 100%), 1fr));
  gap: 12px;
}
/* A directory tile is a .card-link that happens to be a <button>: same white
   card, same lime hover ring. `font: inherit` is what stops the UA button font
   from leaking in. */
.employee-card {
  width: 100%; display: flex; flex-direction: column; gap: 2px; text-align: left;
  background: var(--card); border: 1px solid var(--border); border-radius: var(--radius);
  box-shadow: var(--shadow-card); padding: 13px 15px;
  font: inherit; color: var(--ink); cursor: pointer;
  transition: border-color 0.12s, box-shadow 0.12s;
}
.employee-card:hover {
  text-decoration: none; border-color: var(--lime); box-shadow: 0 0 0 3px var(--lime-soft);
}
.employee-card strong { font-size: 15px; font-weight: 700; color: var(--navy-deep); }
.employee-card span { color: var(--muted); font-size: 13px; }
/* Hard-coded #5c7a09 rather than var(--lime-text). The token (#66860a) on this
   card's white surface measures 4.22:1, under the 4.5:1 AA bar at 12px;
   #5c7a09 is 4.95:1. The token itself is deliberately NOT changed: its other
   uses here are icon strokes (.navlink.active .ico, .stat.is-active
   .stat-icon), where the 3:1 non-text bar applies and #66860a is fine - and it
   is a shared-core token, which is never patched in place from this file. */
.employee-card .employee-location { color: #5c7a09; font-weight: 700; font-size: 12px; }

.dir-count { margin: 0 0 8px; font-size: 14px; color: var(--ink-2); }
.dir-count strong {
  color: var(--navy-deep); font-size: 19px; font-weight: 700; font-variant-numeric: tabular-nums;
}
.dir-list { list-style: none; margin: 0; padding: 0; }
.dir-list li { padding: 6px 0; font-size: 13.5px; border-bottom: 1px solid var(--border); }
.dir-list li:last-child { border-bottom: none; }
.dir-list span { color: var(--muted); }

/* ---------- time off -------------------------------------------------------- */
.timeoff-layout {
  display: grid; grid-template-columns: minmax(280px, 380px) 1fr; gap: 14px;
}
@media (max-width: 760px) { .timeoff-layout { grid-template-columns: 1fr; } }

.timeoff-list { list-style: none; margin: 0; padding: 0; }
.timeoff-list li { padding: 12px 0; border-bottom: 1px solid var(--border); }
.timeoff-list li:last-child { border-bottom: none; padding-bottom: 0; }
.timeoff-top { display: flex; align-items: center; justify-content: space-between; gap: 10px; flex-wrap: wrap; }
.timeoff-list .btn-small { margin-top: 8px; }

/* ---------- admin ----------------------------------------------------------- */
.admin-section { margin-bottom: 16px; }

/* .table-scroll is the old name for the core's .table-wrap: the wrapper owns
   the horizontal scroll so the content column itself never scrolls sideways.
   Migrate to class="table-wrap rtable" to also get the phone card-collapse. */
.table-scroll { overflow-x: auto; padding: 1px; }

/* Section heading with an action button parked on the right; wraps on narrow
   screens rather than squashing the heading. */
.section-head {
  display: flex; align-items: center; justify-content: space-between;
  gap: 10px; flex-wrap: wrap; margin-bottom: 12px;
}
.section-head h2 { margin: 0; }

/* Buttons wrap to a second line rather than forcing horizontal scroll. The
   core sets `white-space: nowrap` on every cell, so the actions cell opts out
   of it while the buttons inside keep theirs. Deliberately NOT `display: flex`:
   this is a <td>, and flexing it drops the element out of the table's own
   layout (the browser then wraps it in an anonymous cell) and the column stops
   lining up with its header. */
.row-actions { min-width: 180px; white-space: normal; }
.row-actions .btn-small, .row-actions .btn-link {
  white-space: nowrap; vertical-align: middle; margin-bottom: 3px;
}
.row-actions > * + * { margin-left: 6px; }
/* One button per row now, so the column no longer needs room for four. */
#users-table .row-actions { min-width: 0; }

.row-inactive td { color: var(--muted); }
.row-inactive .rc-name { color: var(--ink-2); }

/* Stacked label/input form used by the announcement composer and reused by the
   time-off, profile and document-upload forms. */
.ann-form { display: flex; flex-direction: column; max-width: 560px; margin-bottom: 16px; }
.ann-form label { margin: 12px 0 5px; }
.ann-form label:first-child { margin-top: 0; }
.ann-form textarea { min-height: 88px; }
.ann-form input:disabled, .ann-form textarea:disabled, .ann-form select:disabled {
  background: var(--bg); color: var(--muted); cursor: not-allowed;
}
/* Transitional, same deal as the auth card: the submit button carries no class
   yet. Scoped to type="submit" so nothing else in the form is painted lime.
   Delete once the markup says class="btn btn-primary". */
.ann-form button[type="submit"] {
  align-self: flex-start; margin-top: 16px;
  height: var(--control-h); padding: 0 15px;
  display: inline-flex; align-items: center; justify-content: center;
  font: inherit; font-size: 14px; font-weight: 700;
  border: 1px solid var(--lime); border-radius: var(--radius-sm);
  background: var(--lime); color: var(--navy-deep); cursor: pointer;
  transition: background 0.12s, border-color 0.12s;
}
.ann-form button[type="submit"]:hover { background: var(--lime-hover); border-color: var(--lime-hover); }
.ann-form button[type="submit"]:disabled { opacity: 0.55; cursor: not-allowed; }
.ann-form button[type="submit"]:disabled:hover { background: var(--lime); }

/* ---------- pagehead metric row --------------------------------------------- */
/* The Goose-style KPI row: the counts that used to sit in .pagehead-chips as
   flat pills are now .stat tiles under the header band. The shared core already
   defines .stat / .stat-icon / .stat-body / .is-active - this is only the
   layout around them.

   .statrow on its own is `repeat(auto-fit, minmax(152px, 1fr))`, which stretches
   one or two tiles across the whole content column. Every portal page has one
   to three metrics, never Goose's four, so the compact variant caps a tile's
   width and packs the row from the left instead. */
.statrow-compact {
  grid-template-columns: repeat(auto-fit, minmax(158px, 232px));
  justify-content: start;
}
/* The metric row belongs to the header band above it, so it sits closer to the
   pagehead than to the content it introduces. */
.pagehead + .statrow-compact { margin-top: -6px; margin-bottom: 20px; }

/* A tile is a live count, not a control: no hover lift, no pointer. .is-active
   (at most one per row) marks the metric the page is really about - on Admin
   that is pending signups, which is the one number that needs acting on. */
.statrow-compact .stat { align-items: center; }
.statrow-compact .stat .value { font-size: 22px; }

/* The warning tile reuses the chip-warn intent: amber wash, amber icon. It
   outranks .is-active when a count is genuinely outstanding. */
.stat-warn { border-color: #f0dcae; background: var(--warning-soft); }
.stat-warn .stat-icon { background: #fff; color: var(--warning-text); }
.stat-warn .value { color: var(--warning-text); }

/* A zeroed warning tile is not a warning - admin.js and timeoff.js toggle this
   when the count lands on 0 so the row stops shouting about nothing. */
.stat-warn.is-clear { border-color: var(--border); background: var(--card); }
.stat-warn.is-clear .stat-icon { background: var(--navy-wash); color: var(--navy); }
.stat-warn.is-clear .value { color: var(--navy-deep); }

/* ---------- unbreakable column (header and cells) --------------------------- */
/* The core lets a thead th wrap (`white-space: normal`) so a long header does
   not force its column wide, and .cell-text does the same for body cells so
   prose can flow. Both are the right defaults. This is the opt-out for a column
   whose content is a single atomic value that reads as broken once split.
   "Last sign-in" is that column. The header needs ~97px on one line, and a
   timestamp ~140px; left to wrap, the header breaks three ways (on the space
   and again on its own hyphen) while every account still reads "Never", and the
   timestamps break three ways once they land. Applied to both, the column sizes
   to its widest real value and everything sits on one line.
   Widening it can push the table into its horizontal scroll, which is what
   .table-wrap's overflow-x is for - the same trade the All columns toggle
   already makes. */
.table-wrap .cell-nowrap { white-space: nowrap; }

/* ---------- table toolbar (segmented filter + column toggle) ----------------- */
/* Goose pairs a search field with segmented filters on the right. .table-tools
   already held the column toggle; it now carries the .seg group too. */
.table-tools {
  display: flex; align-items: center; justify-content: flex-end;
  gap: 10px; flex-wrap: wrap; margin-bottom: 10px;
}
.table-tools .seg { flex-shrink: 0; }
.table-tools-spacer { flex: 1; min-width: 0; }

/* ---------- <dialog class="detail-modal"> ----------------------------------- */
/* The old sheet had a blanket `.detail-modal button { background: accent }`
   rule, which painted EVERY button in a dialog as a primary action - the
   sheet's own account actions then had to opt back out of it by hand. That
   rule is deleted. Buttons now opt IN: a dialog's primary action is
   class="btn btn-primary", its secondary actions are .btn-secondary /
   .btn-small, and a destructive confirm is .btn-destructive. */
.detail-modal {
  border: none; border-radius: 16px; padding: 22px 24px;
  width: min(92vw, 420px);
  /* The add-user form is the tallest of these; scroll inside the dialog rather
     than letting it run off a short screen. */
  max-height: 88vh; overflow-y: auto;
  background: var(--card); color: var(--ink); box-shadow: var(--shadow-pop);
}
.detail-modal::backdrop { background: rgba(20, 40, 71, 0.45); }
/* Goose gives every dialog a solid header band rather than a bare heading. The
   band is built from the h2 itself - negative margins bleed it out to the
   dialog's own 22px/24px padding - so all five dialogs get it without any
   markup change. The dialog's border-radius plus `overflow-y: auto` clips the
   band's top corners, so it needs no radius of its own to sit flush.
   Not sticky on purpose: the tall Add user form scrolls, and pinning a band
   whose top margin is negative fights the scroll container for no real gain. */
.detail-modal h2 {
  margin: -22px -24px 16px; padding: 15px 24px;
  background: var(--navy-deep); color: #fff;
  font-size: 17px; font-weight: 700;
  text-transform: none; letter-spacing: -0.01em;
}
.detail-modal a { color: var(--navy); font-weight: 600; }
/* No label margins here on purpose: every dialog form carries class="stack"
   (and .form-grid inside it), so the 12px stack/grid gap plus the core label's
   own 5px gap own the whole vertical rhythm. The transitional
   `.detail-modal label` margins compounded with those gaps and were deleted. */
.detail-modal form { display: flex; flex-direction: column; }
.detail-modal .profile-list { margin-bottom: 4px; }

.modal-actions { display: flex; flex-wrap: wrap; gap: 10px; align-items: center; margin-top: 18px; }
.sheet-close-row { justify-content: flex-end; }

.delete-warning {
  background: var(--critical-soft); color: var(--critical-text);
  border: 1px solid #f0cfcb; border-left: 4px solid var(--critical);
  border-radius: var(--radius-sm); padding: 10px 12px;
  font-size: 13.5px; line-height: 1.5; margin: 12px 0 4px;
}

/* ---------- employee sheet (opened by Details) ------------------------------- */
.user-sheet { width: min(92vw, 460px); }
/* Only the bottom gap is tuned here - the negative side/top margins from
   .detail-modal h2 still bleed the band to the dialog edge. The sheet puts
   .sheet-sub directly under the band, so it sits tighter than a form does. */
.user-sheet h2 { margin-bottom: 12px; }

.sheet-sub {
  display: flex; align-items: center; justify-content: space-between;
  gap: 10px; flex-wrap: wrap; margin: 0 0 4px;
  color: var(--muted); font-size: 13.5px;
}
.sheet-saved { color: var(--good-text); font-size: 13px; font-weight: 600; margin: 10px 0 0; }

.sheet-actions { border-top: 1px solid var(--border); margin-top: 20px; padding-top: 16px; }
.sheet-actions h3 {
  margin: 0 0 10px; font-size: 11px; font-weight: 700;
  text-transform: uppercase; letter-spacing: 0.07em; color: var(--muted);
}
.sheet-action-row { display: flex; flex-wrap: wrap; gap: 8px; }

/* ---------- portal responsive ------------------------------------------------ */
@media (max-width: 720px) {
  .page-wrap { padding: 14px 12px 48px; }
  .quick-links { gap: 8px; }
  .quick-link { font-size: 12px; padding: 11px 6px; }
  .profile-list div { flex-direction: column; gap: 1px; }
  .profile-list dt { width: auto; }
  .row-actions { min-width: 0; }
  .detail-modal { width: min(94vw, 420px); padding: 18px 16px; }
}
