/*
  Qnorthwest design tokens — rev 2026/09/14 — screen only.

  This file IS the QNW visual system for this app. docs/BRAND.md explains the
  rules; the rendered reference is linked from there. Three things to hold on to:

  1. Components reference ROLES (--bg, --ink, --accent ...). Roles reference the
     RAMP (--qnw-slate-800 ...). No hex literal ever appears in a component. That
     is what makes dark mode a role swap instead of a rewrite.

  2. Every role is declared in the bare :root first, then redefined for dark in
     BOTH the prefers-color-scheme block and the [data-theme="dark"] block.
     Adding a role to only one place is the most common styling bug here.

  3. The fonts are self-hosted from wwwroot/fonts/ (Open Font License). Do not
     add a Google Fonts <link>: the CSP allows style-src 'self' and font-src
     'self', and a network font would be blocked silently.

  Retired and NOT to be used: Quiet Q #E1E2E2 (use slate 100 #E5ECF0).
*/

/* ---------------------------------------------------------------- fonts */

/* Montserrat: variable weight, latin. Display only, 24px and up (rule T-01). */
@font-face {
  font-family: 'Montserrat';
  font-style: normal;
  font-weight: 500 600;
  font-display: swap;
  src: url('../fonts/montserrat-latin.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

/* IBM Plex Sans: variable weight, latin. The body face on screen. */
@font-face {
  font-family: 'IBM Plex Sans';
  font-style: normal;
  font-weight: 400 600;
  font-display: swap;
  src: url('../fonts/ibm-plex-sans-latin.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

/* IBM Plex Mono: static 400 and 500, latin. Data, labels, IDs, dates. */
@font-face {
  font-family: 'IBM Plex Mono';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url('../fonts/ibm-plex-mono-400-latin.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

@font-face {
  font-family: 'IBM Plex Mono';
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url('../fonts/ibm-plex-mono-500-latin.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

/* --------------------------------------------------------------- tokens */

:root {
  color-scheme: light;

  /* slate ramp — hue 203, derived from Reliable Blue */
  --qnw-slate-25:  #F8FAFC;  --qnw-slate-500: #7591A3;
  --qnw-slate-50:  #F2F6F8;  --qnw-slate-600: #547487;
  --qnw-slate-100: #E5ECF0;  --qnw-slate-700: #3F5C6E;
  --qnw-slate-200: #CFDBE2;  --qnw-slate-800: #2F4858;  /* Reliable Blue */
  --qnw-slate-300: #B1C2CD;  --qnw-slate-900: #203441;
  --qnw-slate-400: #9BAEBC;  --qnw-slate-950: #13212A;
  /* ^ Northwest Fog */

  /* accents */
  --qnw-beacon-700: #0A6E99;  --qnw-beacon-500: #1492CC;
  --qnw-beacon-400: #209DD9;  --qnw-beacon-300: #51BDEC;
  --qnw-2700k-deep: #AE5609;  --qnw-2700k: #EB9928;  --qnw-2700k-lift: #FBB956;

  /* status — never reused as an accent or a chart series */
  --qnw-ok:   #1A7554;  --qnw-ok-dark:   #59CFA4;
  --qnw-warn: #8B5E04;  --qnw-warn-dark: #F5BE3D;
  --qnw-stop: #B4222C;  --qnw-stop-dark: #EF6C75;
  --qnw-note: #2B5EAB;  --qnw-note-dark: #74A2E7;

  /* chart series — fixed order, never cycled. Five slots, never a sixth. */
  --series-1: #1492CC; --series-2: #418432; --series-3: #754BA0;
  --series-4: #0A9C89; --series-5: #4252A5;
  --seq-1: #43B0EB; --seq-2: #1490CA; --seq-3: #0371A1;
  --seq-4: #025377; --seq-5: #023751;

  /* roles — light */
  --bg: var(--qnw-slate-25);       --panel: #FFFFFF;
  --bg-alt: var(--qnw-slate-100);  --ink: var(--qnw-slate-800);
  --ink-strong: var(--qnw-slate-900);
  --muted: var(--qnw-slate-600);   --faint: var(--qnw-slate-500);
  --rule: var(--qnw-slate-200);    --rule-strong: var(--qnw-slate-300);
  --accent: var(--qnw-beacon-700); --accent-fill: var(--qnw-beacon-500);
  --accent-contrast: #FFFFFF;      --warm: var(--qnw-2700k-deep);
  --ok: var(--qnw-ok); --warn: var(--qnw-warn);
  --stop: var(--qnw-stop); --note: var(--qnw-note);
  --raised:  0 1px 2px rgba(19, 33, 42, .06), 0 8px 24px -12px rgba(19, 33, 42, .18);
  --overlay: 0 2px 4px rgba(19, 33, 42, .08), 0 16px 40px -12px rgba(19, 33, 42, .28);

  /* type — screen */
  --qnw-display: 'Montserrat', Helvetica, Arial, sans-serif;   /* >= 24px only */
  --qnw-body:    'IBM Plex Sans', Aptos, 'Segoe UI', system-ui, sans-serif;
  --qnw-mono:    'IBM Plex Mono', 'Aptos Mono', Consolas, ui-monospace, monospace;

  /* space · radius */
  --space-1: 4px;  --space-2: 8px;  --space-3: 12px; --space-4: 16px;
  --space-5: 24px; --space-6: 32px; --space-7: 48px; --space-8: 64px; --space-9: 96px;
  --radius-sm: 3px; --radius-md: 4px; --radius-pill: 999px;
}

/* Dark: redefine ROLES only, never the ramp. Two scopes so the OS preference
   applies before the stored choice is read, and the stored choice then wins in
   either direction. */
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    color-scheme: dark;
    --bg: var(--qnw-slate-950);      --bg-alt: var(--qnw-slate-900);  --panel: #182A35;
    --ink: var(--qnw-slate-200);     --ink-strong: var(--qnw-slate-100);
    --muted: var(--qnw-slate-400);   --faint: var(--qnw-slate-500);
    --rule: #2A3F4D;                 --rule-strong: #3A5262;
    --accent: var(--qnw-beacon-300); --accent-fill: var(--qnw-beacon-400);
    --accent-contrast: var(--qnw-slate-950);
    --warm: var(--qnw-2700k);
    --ok: var(--qnw-ok-dark); --warn: var(--qnw-warn-dark);
    --stop: var(--qnw-stop-dark); --note: var(--qnw-note-dark);
    --series-1: #209DD9; --series-2: #509341; --series-3: #8D63BA;
    --series-4: #08A28F; --series-5: #5A6DC3;
    --seq-1: #C6EBFF; --seq-2: #7FCFFF; --seq-3: #43B0EB; --seq-4: #1490CA; --seq-5: #0371A1;
    --raised:  0 1px 2px rgba(0, 0, 0, .4), 0 8px 24px -12px rgba(0, 0, 0, .6);
    --overlay: 0 2px 4px rgba(0, 0, 0, .5), 0 16px 40px -12px rgba(0, 0, 0, .7);
  }
}

:root[data-theme="dark"] {
  color-scheme: dark;
  --bg: var(--qnw-slate-950);      --bg-alt: var(--qnw-slate-900);  --panel: #182A35;
  --ink: var(--qnw-slate-200);     --ink-strong: var(--qnw-slate-100);
  --muted: var(--qnw-slate-400);   --faint: var(--qnw-slate-500);
  --rule: #2A3F4D;                 --rule-strong: #3A5262;
  --accent: var(--qnw-beacon-300); --accent-fill: var(--qnw-beacon-400);
  --accent-contrast: var(--qnw-slate-950);
  --warm: var(--qnw-2700k);
  --ok: var(--qnw-ok-dark); --warn: var(--qnw-warn-dark);
  --stop: var(--qnw-stop-dark); --note: var(--qnw-note-dark);
  --series-1: #209DD9; --series-2: #509341; --series-3: #8D63BA;
  --series-4: #08A28F; --series-5: #5A6DC3;
  --seq-1: #C6EBFF; --seq-2: #7FCFFF; --seq-3: #43B0EB; --seq-4: #1490CA; --seq-5: #0371A1;
  --raised:  0 1px 2px rgba(0, 0, 0, .4), 0 8px 24px -12px rgba(0, 0, 0, .6);
  --overlay: 0 2px 4px rgba(0, 0, 0, .5), 0 16px 40px -12px rgba(0, 0, 0, .7);
}

/* ----------------------------------------------------------------- base */

* { box-sizing: border-box; }

html, body {
  margin: 0;
  padding: 0;
  min-height: 100%;
}

body {
  background: var(--bg);
  color: var(--ink);
  font-family: var(--qnw-body);
  font-size: 16px;
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;
}

a { color: var(--accent); }

:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }

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

/* ------------------------------------------------------------ type scale */
/* Montserrat lives in exactly three tokens, smallest 24px. Everything else is
   the body face. Figures that align get the mono face (rule T-03). */

.t-display-1 { font-family: var(--qnw-display); font-weight: 600; font-size: clamp(32px, 5.2vw, 48px); line-height: 1.08; letter-spacing: -.015em; color: var(--ink-strong); margin: 0; text-wrap: balance; }
.t-display-2 { font-family: var(--qnw-display); font-weight: 600; font-size: clamp(26px, 3.4vw, 34px); line-height: 1.14; letter-spacing: -.01em; color: var(--ink-strong); margin: 0; text-wrap: balance; }
.t-heading-1 { font-family: var(--qnw-display); font-weight: 600; font-size: 24px; line-height: 1.22; letter-spacing: -.005em; color: var(--ink-strong); margin: 0; text-wrap: balance; }
.t-heading-2 { font-family: var(--qnw-body); font-weight: 600; font-size: 19px; line-height: 1.32; color: var(--ink-strong); margin: 0; }
.t-heading-3 { font-family: var(--qnw-body); font-weight: 600; font-size: 16px; line-height: 1.40; color: var(--ink-strong); margin: 0; }
.t-body      { font-size: 16px; line-height: 1.6; margin: 0; max-width: 66ch; }
.t-body-sm   { font-size: 14px; line-height: 1.55; margin: 0; max-width: 70ch; }
.t-caption   { font-size: 13px; line-height: 1.5; color: var(--muted); margin: 0; max-width: 74ch; }
.t-label     { font-family: var(--qnw-mono); font-weight: 500; font-size: 11px; line-height: 1; letter-spacing: .14em; text-transform: uppercase; color: var(--faint); }
.t-data      { font-family: var(--qnw-mono); font-weight: 400; font-size: 13.5px; line-height: 1.7; font-variant-numeric: tabular-nums; }

.muted { color: var(--muted); }

/* Read by screen readers, not drawn: "today" on the calendar, row context. */
.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
  border: 0;
}

/* ----------------------------------------------------------------- mark */
/* The Qnorthwest mark, the supplied export in img/qnw-mark.png (375px,
   transparent). Never redrawn, recoloured or rotated. The plate keeps it on a plain light ground in dark
   mode, where Reliable Blue would otherwise vanish into the panel. */

.mark { display: block; width: 52px; height: auto; aspect-ratio: 1; }
.mark-plate {
  background: var(--qnw-slate-25);
  border: 1px solid var(--rule);
  border-radius: var(--radius-md);
  padding: 6px;
}

/* ----------------------------------------------------------------- boot */

.boot {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  min-height: 100vh;
  gap: var(--space-4);
  color: var(--muted);
}

/* --------------------------------------------------------------- layout */
/* Gaps, not margins (rule L-01). One wrapper carries the side gutter
   (rule L-02). Dense by default: this is scheduling and panel data. */

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

.topbar {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  padding-block: var(--space-2);
  padding-inline: var(--space-4);
  background: var(--panel);
  border-bottom: 1px solid var(--rule);
}

.topbar .spacer { flex: 1; }
.topbar .who { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; max-width: 40vw; }

.content {
  flex: 1;
  width: 100%;
  max-width: 920px;
  margin: 0 auto;
  padding-block: var(--space-5) var(--space-7);
  padding-inline: var(--space-4);
  display: flex;
  flex-direction: column;
  gap: var(--space-4);
}

/* A panel is a bordered surface. No shadow: a border already says "separate
   object" (rule L-03). --raised is for things that genuinely float. */
.panel {
  background: var(--panel);
  border: 1px solid var(--rule);
  border-radius: var(--radius-md);
  padding: var(--space-4);
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
}

.actions { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-3); }

/* A page's title with its one action beside it, wrapping under it on a phone. */
.page-head { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: var(--space-3); }

/* -------------------------------------------------------------- buttons */
/* One primary per view. A button says what happens. */

.btn {
  font-family: var(--qnw-body);
  font-size: 14px;
  font-weight: 500;
  line-height: 1;
  padding: 11px 18px;
  border-radius: var(--radius-md);
  border: 1px solid transparent;
  background: transparent;
  color: var(--ink);
  cursor: pointer;
  transition: background .12s, border-color .12s, color .12s;
}

.btn-primary { background: var(--accent); color: var(--accent-contrast); }
.btn-primary:hover:not(:disabled) { background: var(--accent-fill); }

.btn-secondary { color: var(--accent); border-color: var(--rule-strong); }
.btn-secondary:hover:not(:disabled) { border-color: var(--accent); }

.btn-ghost { color: var(--muted); }
.btn-ghost:hover:not(:disabled) { color: var(--ink); background: var(--bg-alt); }

.btn-danger { color: var(--stop); border-color: currentColor; }

.btn-icon { padding: 8px 10px; font-size: 15px; }
.btn-block { width: 100%; }

.btn:disabled { opacity: .45; cursor: not-allowed; }

/* A link that navigates but looks like a button ("Request time off", "Edit").
   A link, not a button, so it opens in a new tab and reads as navigation. */
a.btn { display: inline-flex; align-items: center; text-decoration: none; }

/* --------------------------------------------------------------- inputs */

.field { display: flex; flex-direction: column; gap: 6px; min-width: 210px; }
.field label { font-family: var(--qnw-mono); font-size: 10.5px; letter-spacing: .1em; text-transform: uppercase; color: var(--faint); }
.field input, .field select, .field textarea {
  font-family: var(--qnw-body);
  font-size: 14px;
  color: var(--ink);
  background: var(--panel);
  border: 1px solid var(--rule-strong);
  border-radius: var(--radius-md);
  padding: 10px 12px;
  width: 100%;
}
.field input:focus, .field select:focus, .field textarea:focus {
  border-color: var(--accent);
  outline: none;
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--accent) 22%, transparent);
}
.field.mono input { font-family: var(--qnw-mono); font-variant-numeric: tabular-nums; }

/* A checkbox with a two-line label, as on the sign-in card. */
.check {
  display: flex;
  align-items: flex-start;
  gap: var(--space-2);
  text-align: left;
  cursor: pointer;
}
.check input { margin: 3px 0 0; accent-color: var(--accent); flex: none; }
.check > span { display: flex; flex-direction: column; gap: 2px; }

/* ---------------------------------------------------------------- chips */
/* Status is never colour alone: a dot and a word, always (rule C-04). */

.chip {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  padding: 5px 12px 5px 9px;
  border-radius: var(--radius-pill);
  border: 1px solid currentColor;
  font-size: 13px;
  font-weight: 500;
  line-height: 1.3;
}
.chip::before { content: ""; width: 7px; height: 7px; border-radius: 50%; background: currentColor; flex: none; }
.chip-ok { color: var(--ok); }
.chip-warn { color: var(--warn); }
.chip-stop { color: var(--stop); }
.chip-note { color: var(--note); }
.chip-idle { color: var(--faint); }

/* --------------------------------------------------------------- alerts */
/* A note with a coloured left rule. The colour carries the status role; the
   text stays ink so it reads in both themes. */

.alert {
  padding: var(--space-3) var(--space-4);
  border-radius: var(--radius-md);
  background: var(--bg);
  border: 1px solid var(--rule);
  border-left: 2px solid var(--note);
  font-size: 14px;
  line-height: 1.55;
}
.alert-stop { border-left-color: var(--stop); }
.alert-warn { border-left-color: var(--warn); }
.alert-ok { border-left-color: var(--ok); }

/* ---------------------------------------------------------------- table */
/* Header row on --bg-alt with mono uppercase labels; numeric and code columns
   in mono with tabular figures; prose columns in the body face at 14px. Only
   the table scrolls sideways, inside its own wrapper (rule L-02). */

.tablewrap { overflow-x: auto; border: 1px solid var(--rule); border-radius: var(--radius-md); }

table { border-collapse: collapse; width: 100%; font-size: 14px; }
th, td { padding: 10px 14px; text-align: left; border-bottom: 1px solid var(--rule); vertical-align: top; }
tbody tr:last-child td { border-bottom: 0; }
th {
  font-family: var(--qnw-mono);
  font-size: 10.5px;
  font-weight: 500;
  letter-spacing: .12em;
  text-transform: uppercase;
  color: var(--faint);
  background: var(--bg-alt);
  white-space: nowrap;
}
td.num { font-family: var(--qnw-mono); font-variant-numeric: tabular-nums; font-size: 13px; white-space: nowrap; }
td.muted { color: var(--muted); }

.table-footnote { padding-top: var(--space-1); }
.empty { color: var(--muted); padding-block: var(--space-2); margin: 0; }

/* ---------------------------------------------------------------- tiles */

.tiles { display: grid; grid-template-columns: repeat(auto-fit, minmax(170px, 1fr)); gap: var(--space-3); }
.tile { background: var(--panel); border: 1px solid var(--rule); border-radius: var(--radius-md); padding: var(--space-4); display: flex; flex-direction: column; gap: 6px; }
.tile b { font-family: var(--qnw-mono); font-weight: 500; font-size: 30px; line-height: 1; color: var(--ink-strong); font-variant-numeric: tabular-nums; }
.tile .delta { font-family: var(--qnw-mono); font-size: 12px; font-variant-numeric: tabular-nums; }
.delta.up { color: var(--ok); }
.delta.down { color: var(--stop); }

/* -------------------------------------------------------------- sign-in */

.signin {
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: 100vh;
  padding-block: var(--space-5);
  padding-inline: var(--space-4);
}
.signin-card { max-width: 380px; width: 100%; align-items: center; text-align: center; padding: var(--space-6) var(--space-5); gap: var(--space-4); }
.signin-card .check { align-self: stretch; padding-top: var(--space-2); border-top: 1px solid var(--rule); }

/* -------------------------------------------------------- blazor error ui */

#blazor-error-ui {
  display: none;
  position: fixed;
  bottom: 0;
  left: 0;
  right: 0;
  padding-block: var(--space-3);
  padding-inline: var(--space-4);
  background: var(--panel);
  color: var(--ink);
  border-top: 2px solid var(--stop);
  box-shadow: var(--overlay);
  z-index: 1000;
  font-size: 14px;
}
#blazor-error-ui .dismiss { cursor: pointer; float: right; }
#blazor-error-ui .reload { margin-left: var(--space-2); }

/* ------------------------------------------------------------- responsive */

@media (max-width: 480px) {
  .topbar .who { display: none; }
  .actions { flex-direction: column; align-items: stretch; }
}
