@import url('https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700;800&display=swap');

*, *::before, *::after { margin: 0; padding: 0; box-sizing: border-box; }

:root {
  --bg: #fbfbfd;
  --surface: #ffffff;
  --surface2: #f5f5f7;
  --surface3: #ececf0;
  --border: #e8e8ed;
  --border2: #d9d9de;
  --brand: #0071e3;
  --brand-dark: #0060c0;
  --brand-light: #e7f1fd;
  --green: #0a7d54;
  --green-light: #e2f6ec;
  --blue: #0071e3;
  --pink: #b42318;
  --pink-light: #fbeeec;
  --yellow: #d97706;
  --text: #1d1d1f;
  --muted: #86868b;
  --muted2: #a1a1a6;
  --font: 'Inter', -apple-system, 'SF Pro Display', system-ui, sans-serif;
  --mono: 'Inter', -apple-system, 'SF Pro Display', system-ui, sans-serif;
  --radius: 20px;
  --shadow: 0 1px 2px rgba(0,0,0,.03), 0 12px 34px rgba(0,0,0,.05);
  --shadow-md: 0 2px 6px rgba(0,0,0,.05), 0 18px 44px rgba(0,0,0,.08);

  /* Aurora additions */
  --accent: #0071e3;
  --accent-soft: #e7f1fd;
  --surface-2: #f5f5f7;
  --c1: #0071e3;
  --c2: #4d9bec;
  --c3: #aecbf5;
  --up-fg: #0a7d54;
  --up-bg: #e2f6ec;
  --down-fg: #b42318;
  --down-bg: #fbeeec;
  /* Withheld / not-final / needs-attention, as TEXT. --yellow (#d97706) is
     3.19:1 on white — fine for the 4px card borders where 3:1 is the bar, and
     below AA for every word ever set in it. #b45309 is the same hue family and
     measures 5.02:1 on --surface, 4.86:1 on --bg, 4.61:1 on --surface-2.
     Added 9/24/26. Borders keep --yellow; words take --warn-fg. */
  --warn-fg: #b45309;
  --warn-bg: #fef6ec;   /* 4.69:1 under --warn-fg */
  --track: rgba(0,0,0,.06);
  --radius-sm: 12px;
  --nav-h: 76px;   /* the nav at 1280; app.js syncNavHeight() writes the measured value */
}

body {
  font-family: var(--font);
  background: var(--bg);
  min-height: 100vh;
  color: var(--text);
  line-height: 1.35;
}

body.login-page { display: flex; align-items: center; justify-content: center; }

.login-container {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 2.5rem;
  width: 100%;
  max-width: 400px;
  box-shadow: var(--shadow-md);
}

.logo { font-family: var(--font); font-size: 1.6rem; font-weight: 800; color: var(--text); text-align: center; margin-bottom: 0.25rem; }
.subtitle { text-align: center; color: var(--muted); margin-bottom: 2rem; font-size: 0.85rem; letter-spacing: 0.5px; }
.form-group { margin-bottom: 1.25rem; }

label {
  display: block;
  margin-bottom: 0.4rem;
  font-size: 0.75rem;
  text-transform: uppercase;
  letter-spacing: 1px;
  color: var(--muted);
}

input {
  width: 100%;
  padding: 0.75rem;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 8px;
  font-size: 0.9rem;
  font-family: var(--font);
  color: var(--text);
}

input:focus { outline: none; border-color: var(--accent); box-shadow: 0 0 0 3px var(--accent-soft); }

/* Controls in a horizontal filter/picker row size to their own content. The
   width:100% above is meant for stacked form fields; inside a wrapping flex row
   it gives each control a full-width basis, so it claims its own line and
   breaks the bar onto several rows (date pickers are the usual victim).
   Lives here so no page has to remember the override — see docs/STYLE.md. */
.filter-bar input, .filter-bar select, .filter-bar button,
.picker-row input, .picker-row select, .picker-row button,
.date-row input, .date-row select, .date-row button,
.opt-group button,
#custom-range input, #custom-dates input { width: auto; }

button {
  width: 100%;
  padding: 0.75rem;
  background: var(--accent);
  color: #fff;
  border: none;
  border-radius: 10px;
  font-family: var(--font);
  font-weight: 700;
  font-size: 0.9rem;
  cursor: pointer;
  letter-spacing: 0.5px;
  transition: opacity 0.15s;
}

button:hover { opacity: 0.85; }

.error {
  color: var(--pink);
  font-size: 0.85rem;
  margin-bottom: 1rem;
  padding: 0.75rem;
  background: var(--pink-light);
  border-radius: 6px;
  border-left: 3px solid var(--pink);
}

/* A <canvas> whose chart never drew (failed load, empty result, CDN down)
   keeps its 300px default and, inside a padded card, pushed a 320px phone's
   body sideways. Chart.js sizes the ones it does draw; this caps the rest. */
canvas { max-width: 100%; }

/* showLoadError() in app.js: a failed request, in words, with Retry, in the
   section that failed. Not .error — that one is a form-submit message with a
   bottom margin; this sits where the data would have been. */
.load-error {
  display: flex; flex-wrap: wrap; align-items: center; gap: .5rem .75rem;
  padding: .75rem 1rem; margin: .25rem 0;
  color: var(--pink); background: var(--pink-light);
  border-left: 3px solid var(--pink); border-radius: 6px;
  font-size: .88rem; font-weight: 500; text-align: left; white-space: normal;
  text-transform: none; letter-spacing: 0;
}
.load-error span { flex: 1 1 14rem; min-width: 0; overflow-wrap: anywhere; }
.load-error button { width: auto; min-height: 44px; padding: .5rem 1.1rem; }
/* Inside a table wider than a phone, the cell is wider than the screen; pin the
   message to the visible left edge and keep it screen-width so it never clips. */
td > .load-error { position: sticky; left: 0; max-width: calc(100vw - 4.5rem); }

nav {
  background: var(--surface);
  padding: 0.8rem 2rem;
  display: flex;
  align-items: center;
  gap: 1.5rem;
  border-bottom: 1px solid var(--border);
  position: sticky;
  top: 0;
  z-index: 50;
}

nav .brand { font-family: var(--font); font-weight: 800; color: var(--text); font-size: 1rem; }

nav a {
  color: var(--muted);
  text-decoration: none;
  font-size: 0.85rem;
  padding: 0.4rem 0.75rem;
  border-radius: 6px;
  transition: color 0.15s, background 0.15s;
}

nav a:hover { color: var(--text); background: var(--surface3); }
nav a.active { color: var(--accent); background: var(--accent-soft); font-weight: 600; }
nav a.logout { color: var(--muted2); }

/* The nav is the reason the BODY scrolled sideways on every page in this repo.
   A non-wrapping flex row of eight menus plus the brand needs about 1000px; at
   390px it simply overflowed the document, so the whole page slid left and the
   right-hand gutter went with it. A table may scroll inside its own container;
   the page may not.

   Two changes below 760px, and they go together:
     - it wraps, so nothing overflows.
     - it stops being sticky. A wrapped nav is ~180px tall, and 180px pinned to
       the top of a 390px phone is a fifth of the screen gone for as long as the
       page is open. It scrolls away instead and the content gets the screen.
   Above 760px nothing changes: the row fits, and it stays sticky. 9/24/26. */
@media (max-width: 760px) {
  nav {
    flex-wrap: wrap;
    position: static;
    gap: .4rem .6rem;
    padding: .6rem 1rem;
  }
  nav .brand { flex-basis: 100%; }
  /* The flex spacer pushes Sign out to the far right on a wide row; on a
     wrapped one it forces a blank line. */
  nav > span[style*="flex"] { display: none; }
  /* Eleven pages pin their own filter bar at `top: var(--nav-h)` to sit under
     the sticky nav. With the nav scrolled away there is nothing to sit under,
     and a 57px offset would leave a strip of page sliding through the gap.
     Zero here, not a guess at the wrapped height — the bar goes to the top of
     the viewport, which is where it belongs once the nav has gone.

     Above this breakpoint app.js (syncNavHeight) measures the real nav and
     writes --nav-h inline — the declared 57px was 19px short of the 76px nav at
     1280, so pinned bars slid under it. 9/28/26. */
  :root { --nav-h: 0px; }
}

/* Nav dropdowns */
.nav-dropdown { position: relative; }
.nav-drop-btn {
  background: none; border: 1px solid var(--border); color: var(--muted);
  font-size: .82rem; padding: .35rem .75rem; border-radius: 6px;
  cursor: pointer; font-weight: 700; display: flex; align-items: center; gap: .3rem;
  font-family: var(--font);
}
.nav-drop-btn:hover { background: var(--surface3); color: var(--text); border-color: var(--border2); }
.nav-drop-btn.active { color: var(--accent); background: var(--accent-soft); border-color: var(--accent); }
.nav-drop-menu {
  display: none; position: absolute; top: calc(100% + .4rem); right: 0;
  background: var(--surface); border: 1px solid var(--border);
  border-radius: var(--radius-sm); min-width: 170px;
  box-shadow: 0 12px 34px rgba(0,0,0,.10); overflow: hidden; z-index: 200;
}
.nav-drop-menu.open { display: block; }
.nav-drop-menu a {
  display: block; padding: .6rem 1rem;
  color: var(--muted); font-size: .85rem; text-decoration: none;
  border-radius: 0; transition: background .12s;
}
.nav-drop-menu a:hover { background: var(--surface2); color: var(--text); }
.nav-drop-menu .drop-divider { height: 1px; background: var(--border); margin: .25rem 0; }
.nav-drop-menu .drop-label { font-size: .68rem; text-transform: uppercase; letter-spacing: .07em; color: var(--muted2); padding: .5rem 1rem .2rem; font-weight: 700; }

.container { max-width: 1200px; margin: 0 auto; padding: 1.5rem 2rem 3rem; }

/* 2rem each side is 64px of a 320px screen — a fifth of the width, spent on
   nothing, while the table inside gives up columns to pay for it. 1rem still
   clears the 16px gutter floor and hands 32px back to the content. 9/24/26. */
@media (max-width: 480px) {
  .container { padding: 1rem 1rem 2rem; }
}

.sync-banner {
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-radius: 8px;
  padding: 0.5rem 1rem;
  margin-bottom: 1.5rem;
  font-size: 0.8rem;
  color: var(--muted);
}

.cards { display: grid; grid-template-columns: repeat(auto-fit, minmax(240px, 1fr)); gap: 1.5rem; margin-bottom: 2rem; }

.card {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 16px 18px;
  box-shadow: var(--shadow);
}

.card-label { font-size: 0.75rem; color: var(--muted); text-transform: uppercase; letter-spacing: 1px; margin-bottom: 0.5rem; }
.card-value { font-family: var(--font); font-size: 2rem; font-weight: 700; color: var(--text); letter-spacing: -.035em; font-variant-numeric: tabular-nums; }
.card-value.green { color: var(--up-fg); }
.card-sub { font-size: 0.8rem; color: var(--muted); margin-top: 0.25rem; }

.chart-container {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 1.5rem;
  margin-bottom: 1.5rem;
  box-shadow: var(--shadow);
}

.chart-title { font-family: var(--font); font-size: 0.95rem; font-weight: 700; margin-bottom: 1rem; color: var(--text); }

.table-container {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  /* Was `overflow: hidden`, which is only here to clip the table's square
     corners to the 20px radius — and which also CLIPPED every table wider than
     its container, on every page, with no way to reach the columns past the
     cut. That is not a cramped table, it is columns that do not exist: the Past
     Payroll Runs table measured 476px inside 324px at 390px and the last two
     columns were simply unreachable. Pages that noticed patched themselves with
     an inline style="overflow-x:auto"; most did not. Both axes stay non-visible
     so the corners still clip. Fixed 9/24/26. */
  overflow-x: auto;
  overflow-y: hidden;
  margin-bottom: 1.5rem;
  box-shadow: var(--shadow);
}

table { width: 100%; border-collapse: collapse; }

th {
  text-align: left;
  padding: 0.75rem 1rem;
  font-size: 0.75rem;
  text-transform: uppercase;
  letter-spacing: 1px;
  color: var(--muted);
  border-bottom: 1px solid var(--border);
  background: var(--surface-2);
}

td { padding: 0.75rem 1rem; border-bottom: 1px solid var(--border); font-size: 0.85rem; color: var(--text); font-variant-numeric: tabular-nums; }
tr:last-child td { border-bottom: none; }
tr:hover td { background: var(--surface2); }

h1 { font-family: var(--font); font-size: 1.35rem; font-weight: 700; margin-bottom: 1.5rem; color: var(--text); letter-spacing: -.02em; }

.up { color: var(--up-fg); }
.down { color: var(--down-fg); }
.neutral { color: var(--muted); }

/* Clickable table rows */
.clickable-row { cursor: pointer; }
.member-link { color: var(--text); text-decoration: none; font-weight: 600; }
.member-link:hover { color: var(--brand); }

/* Member detail page */
.member-header { margin-bottom: 1.5rem; }
.back-link { font-size: 0.85rem; color: var(--muted); text-decoration: none; display: inline-block; margin-bottom: 0.5rem; }
.back-link:hover { color: var(--brand); }
.member-title { display: flex; align-items: center; gap: 0.75rem; }
.member-title h1 { margin-bottom: 0; }

/* Week navigator */
.week-nav { display: flex; align-items: center; gap: 0.75rem; margin-bottom: 1.5rem; flex-wrap: wrap; }
.week-label { font-family: var(--font); font-weight: 600; font-size: 0.95rem; color: var(--text); min-width: 200px; text-align: center; }
.week-btn { width: auto; padding: 0.4rem 0.9rem; font-size: 0.8rem; background: var(--surface); color: var(--text); border: 1px solid var(--border2); border-radius: 6px; font-family: var(--mono); cursor: pointer; transition: background 0.15s, color 0.15s; }
.week-btn:hover:not(:disabled) { background: var(--surface3); }
.week-btn:disabled { opacity: 0.35; cursor: default; }
.week-btn-today { background: var(--accent-soft); color: var(--accent); border-color: var(--accent); font-weight: 600; }
.week-btn-today:hover:not(:disabled) { background: var(--accent); color: #fff; }

/* Badges */
.badge { display: inline-block; padding: 0.2rem 0.5rem; border-radius: 999px; font-size: 0.75rem; font-weight: 600; letter-spacing: 0.5px; text-transform: uppercase; }
.badge-green { background: var(--green-light); color: var(--green); }
.badge-muted { background: var(--surface3); color: var(--muted); }
/* A qualifier on a figure, not a verdict on it — "growing", "on the clock".
   --muted on --surface3 is 3.07:1, which is fine for a status nobody has to
   read and wrong for one that changes what a number means. 14.28:1. */
.badge-neutral { background: var(--surface3); color: var(--text); }
/* The figure above me is not settled and here is the word for why. */
.badge-warn { background: var(--warn-bg); color: var(--warn-fg); }

/* Any figure outside a <td>. `td` already carries tabular-nums; a total in a
   <p> or a card does not, and jitters as it updates while the column above it
   holds still. */
.figure { font-variant-numeric: tabular-nums; }

/* A figure that is NOT being shown, as a word. Never a 0, never a dash in a
   numeric column -- both read as a measurement. The reason lives once,
   elsewhere on the page; this is only the word.
   --warn-fg, not --yellow: 5.02:1 on --surface and 4.61:1 on --surface-2, and
   none of these strings is large text. Lived in payroll.html's own <style> as
   `.hours-warn` until 9/24/26; cash-recon.html needed the same word for the
   same shift, and two screens reading one summarizeShifts row must not spell
   it two ways. */
.withheld { color: var(--warn-fg); font-weight: 600; }

/* Open/in-progress shift row */
.shift-open td { background: rgba(22,163,74,0.04); }

/* ==========================================================================
   Aurora shared primitives (lifted from docs/aurora-mockup.html)
   ========================================================================== */

.datebar { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.db-label { font-size: .68rem; letter-spacing: .07em; text-transform: uppercase; color: var(--muted); font-weight: 600; }
.db-select { position: relative; display: inline-flex; }
.db-select select { appearance: none; -webkit-appearance: none; border: 1px solid var(--border); background: var(--surface); border-radius: 10px; padding: 7px 27px 7px 12px; font: inherit; font-size: .78rem; color: var(--text); cursor: pointer; }
.db-select::after { content: '▾'; position: absolute; right: 11px; top: 50%; transform: translateY(-50%); font-size: .66rem; color: var(--muted); pointer-events: none; }
.db-range { display: inline-flex; align-items: center; gap: 7px; background: var(--surface); border: 1px solid var(--border); border-radius: 10px; padding: 7px 11px; font-size: .78rem; color: var(--text); white-space: nowrap; }
.db-refresh { border: 1px solid var(--border); background: var(--surface); border-radius: 10px; width: 34px; height: 34px; display: grid; place-items: center; cursor: pointer; color: var(--muted); }
.db-refresh:hover { color: var(--accent); border-color: var(--accent); }
/* The icon arrives as an unsized <svg viewBox> (AuroraCharts.refIco); in a grid
   cell with no size it collapsed to nothing and the button read as blank. */
.db-refresh svg { width: 16px; height: 16px; display: block; }

.stat { background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius); box-shadow: var(--shadow); padding: 16px 18px; display: flex; flex-direction: column; gap: 7px; }
.stat__label { font-size: .78rem; color: var(--muted); font-weight: 500; }
.stat__value { font-size: 1.85rem; font-weight: 700; letter-spacing: -.035em; line-height: 1; font-variant-numeric: tabular-nums; }
.stat__foot { display: flex; align-items: center; gap: 8px; font-size: .74rem; color: var(--muted); }

.delta { display: inline-flex; align-items: center; gap: 3px; font-weight: 600; font-size: .72rem; padding: 2px 7px; border-radius: 999px; }
.delta.up { color: var(--up-fg); background: var(--up-bg); }
.delta.down { color: var(--down-fg); background: var(--down-bg); }
.delta.flat { color: var(--text); background: var(--surface3); }

.card__head { display: flex; align-items: flex-start; justify-content: space-between; gap: 8px; margin-bottom: 13px; }
.card__head h3 { font-size: .82rem; font-weight: 600; color: var(--muted); margin: 0; }
.card__sub { font-size: .7rem; color: var(--muted); margin-top: 3px; }
.cardfoot { display: flex; align-items: center; justify-content: space-between; gap: 8px; margin-top: auto; padding-top: 12px; border-top: 1px solid var(--border); font-size: .74rem; color: var(--muted); }
.cardfoot b { color: var(--text); }

.card.col { display: flex; flex-direction: column; }
.card.col .donutwrap { margin: auto 0; }

.hbars { display: flex; flex-direction: column; gap: 13px; }
.hbar__top { display: flex; justify-content: space-between; font-size: .82rem; margin-bottom: 5px; gap: 8px; }
.hbar__name { font-weight: 500; }
.hbar__val { font-weight: 700; }
.hbar__track { height: 8px; border-radius: 999px; background: var(--track); overflow: hidden; }
.hbar__fill { height: 100%; border-radius: 999px; }
.hbar__sub { font-size: .68rem; color: var(--muted); margin-top: 4px; }

.donutwrap { display: flex; align-items: center; gap: 18px; flex-wrap: wrap; }
.donut { width: 128px; height: 128px; flex: 0 0 auto; }
.donut-c1 { font-size: 6px; font-weight: 800; fill: var(--text); }
.donut-c2 { font-size: 3px; fill: var(--muted); }
.legend { display: flex; flex-direction: column; gap: 9px; font-size: .8rem; min-width: 120px; }
.legend__i { display: flex; align-items: center; gap: 8px; color: var(--muted); }
.legend__i i { width: 10px; height: 10px; border-radius: 3px; display: inline-block; flex: 0 0 auto; }
.legend__i b { margin-left: auto; color: var(--text); }

.svgchart { width: 100%; height: auto; display: block; }
.svgtxt { fill: var(--muted); font-size: 13px; font-family: var(--font); }

.badge-live { display: inline-flex; align-items: center; gap: 6px; font-size: .72rem; font-weight: 600; color: var(--text); background: var(--surface-2); border: 1px solid var(--border); padding: 3px 10px; border-radius: 999px; white-space: nowrap; }
.badge-live .dot { width: 7px; height: 7px; border-radius: 50%; background: var(--accent); box-shadow: 0 0 0 3px var(--accent-soft); }

.section-title { font-size: .82rem; font-weight: 600; color: var(--muted); margin: 0 0 13px; }

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

/* ── Dashboard reminders ─────────────────────────────────────── */
#reminder-banners { display: flex; flex-direction: column; gap: 10px; margin: 0 0 16px; }
.reminder-banner {
  display: flex; align-items: center; gap: 12px;
  padding: 12px 14px; border-radius: var(--radius-sm);
  background: var(--accent-soft); border: 1px solid var(--accent);
  color: var(--text); font-size: .95rem; text-decoration: none;
}
.reminder-banner:hover { box-shadow: var(--shadow); }
.reminder-banner .rb-icon { font-size: 1.25rem; line-height: 1; }
.reminder-banner .rb-msg { flex: 1 1 auto; min-width: 0; font-weight: 500; }
.reminder-banner .rb-go { color: var(--accent); font-weight: 600; white-space: nowrap; }
.reminder-banner .rb-x {
  /* width:auto overrides the global button{width:100%}; without it the flex
     basis resolves to full width and the × swallows the whole banner row. */
  flex: 0 0 auto; width: auto; margin-left: 2px;
  border: none; background: transparent; cursor: pointer;
  color: var(--muted); font-size: 1.1rem; font-weight: 400; letter-spacing: 0;
  line-height: 1; padding: 4px 8px; border-radius: 8px;
}
.reminder-banner .rb-x:hover { color: var(--text); background: var(--track); }
@media (max-width: 560px) {
  .reminder-banner { flex-wrap: wrap; }
  .reminder-banner .rb-msg { flex-basis: 100%; }
}
