/* Smart Numbers — the whole design system, in one stylesheet.
   No frameworks, no client-side JavaScript, no external requests.

   Typography and palette follow the SMART Numbers design: Instrument Sans for
   text, JetBrains Mono for every number, and a deep purple brand against a warm
   off-white. Both fonts are self-hosted variable files, so the design's exact
   type renders without a request leaving the machine. */

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

@font-face {
  font-family: 'Instrument Sans';
  src: url('/fonts/instrument-sans.woff2') format('woff2-variations');
  font-weight: 400 700;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: 'JetBrains Mono';
  src: url('/fonts/jetbrains-mono.woff2') format('woff2-variations');
  font-weight: 400 700;
  font-style: normal;
  font-display: swap;
}

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

:root {
  --font: 'Instrument Sans', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
  --mono: 'JetBrains Mono', ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;

  --radius:    11px;
  --radius-md: 9px;
  --radius-sm: 7px;
  --radius-xs: 5px;
}

/* Light — taken directly from the design. */
:root,
:root[data-theme='light'] {
  color-scheme: light;

  --bg:        #f2f0f5;
  --surface:   #ffffff;
  --surface-2: #faf9fc;
  --surface-3: #f5f3f8;
  --surface-4: #efecf3;

  --ink:       #1d1826;
  --text:      rgba(29, 24, 38, .85);
  --text-soft: rgba(29, 24, 38, .62);
  --text-mute: rgba(29, 24, 38, .5);
  --text-dim:  rgba(29, 24, 38, .42);

  --line:        rgba(29, 24, 38, .09);
  --line-strong: rgba(29, 24, 38, .16);

  --brand:       #3f1d5c;
  --brand-hover: #5c2c85;
  --brand-ink:   #ffffff;
  --brand-soft:  rgba(63, 29, 92, .06);
  --brand-line:  rgba(63, 29, 92, .30);
  --on-brand:        rgba(255, 255, 255, .70);
  --on-brand-dim:    rgba(255, 255, 255, .50);
  --on-brand-fill:   rgba(255, 255, 255, .12);
  --on-brand-fill-2: rgba(255, 255, 255, .16);

  --ok-bg:   oklch(0.94 0.06 150);
  --ok-fg:   oklch(0.42 0.11 150);
  --ok-mark: oklch(0.62 0.12 150);

  --warn-bg:   oklch(0.95 0.06 85);
  --warn-fg:   oklch(0.47 0.11 70);
  --warn-mark: oklch(0.74 0.13 80);

  --bad-bg:   oklch(0.93 0.055 25);
  --bad-fg:   oklch(0.48 0.16 25);
  --bad-mark: oklch(0.66 0.15 25);

  --neu-bg:   rgba(29, 24, 38, .055);
  --neu-fg:   rgba(29, 24, 38, .62);
  --neu-mark: rgba(63, 29, 92, .30);

  /* A light theme has nowhere to go above white, so the header band goes the
     other way — and has to clear the page behind it as well as the card it sits
     on. #e4e0ec is 1.15:1 against the page and 1.30:1 against the card, which
     matches the separation the dark and blue themes get for free. */
  --card-head:      #e4e0ec;
  --card-head-line: rgba(29, 24, 38, .20);

  --shadow:    0 1px 3px rgba(29, 24, 38, .07);
  --shadow-lg: 0 10px 30px rgba(29, 24, 38, .13), 0 2px 6px rgba(29, 24, 38, .06);
}

/* Dark — the design ships light only, so this is derived from it: the same
   purple family and the same oklch status hues, re-anchored for a dark ground.
   Lightness inverts, chroma holds, hue never moves. */
:root[data-theme='dark'] {
  color-scheme: dark;

  --bg:        #100d16;
  --surface:   #191521;
  --surface-2: #1f1a29;
  --surface-3: #262031;
  --surface-4: #2c2539;

  --ink:       #ece8f3;
  --text:      rgba(236, 232, 243, .87);
  --text-soft: rgba(236, 232, 243, .64);
  --text-mute: rgba(236, 232, 243, .52);
  --text-dim:  rgba(236, 232, 243, .42);

  --line:        rgba(236, 232, 243, .11);
  --line-strong: rgba(236, 232, 243, .20);

  /* On a dark ground the brand reads as a lifted lilac; the filled header keeps
     a deep plum so the chrome stays recognisably the same surface. */
  --brand:       #b79ade;
  --brand-hover: #cbb4ea;
  --brand-ink:   #17101f;
  --brand-soft:  rgba(183, 154, 222, .12);
  --brand-line:  rgba(183, 154, 222, .38);
  --on-brand:        rgba(255, 255, 255, .70);
  --on-brand-dim:    rgba(255, 255, 255, .48);
  --on-brand-fill:   rgba(255, 255, 255, .10);
  --on-brand-fill-2: rgba(255, 255, 255, .14);

  --ok-bg:   oklch(0.30 0.06 150);
  --ok-fg:   oklch(0.82 0.14 150);
  --ok-mark: oklch(0.68 0.13 150);

  --warn-bg:   oklch(0.31 0.06 80);
  --warn-fg:   oklch(0.85 0.13 85);
  --warn-mark: oklch(0.74 0.13 80);

  --bad-bg:   oklch(0.30 0.07 25);
  --bad-fg:   oklch(0.78 0.14 25);
  --bad-mark: oklch(0.66 0.16 25);

  --neu-bg:   rgba(236, 232, 243, .07);
  --neu-fg:   rgba(236, 232, 243, .60);
  --neu-mark: rgba(183, 154, 222, .34);

  --card-head:      #2b2438;
  --card-head-line: rgba(236, 232, 243, .22);

  --shadow:    0 1px 3px rgba(0, 0, 0, .5);
  --shadow-lg: 0 10px 30px rgba(0, 0, 0, .6), 0 2px 6px rgba(0, 0, 0, .4);
}

/* Blue — a third option rather than a re-skin of dark: a deep navy ground with
   a genuinely vibrant blue accent. The status hues hold their positions (150
   green, 85 amber, 25 red) so a colour never changes meaning between themes,
   but chroma is lifted across the board to carry against the blue. */
:root[data-theme='blue'] {
  color-scheme: dark;

  --bg:        #070d1a;
  --surface:   #0f1830;
  --surface-2: #14203c;
  --surface-3: #1b2a4c;
  --surface-4: #22345c;

  --ink:       #e8efff;
  --text:      rgba(232, 239, 255, .88);
  --text-soft: rgba(232, 239, 255, .66);
  --text-mute: rgba(232, 239, 255, .54);
  --text-dim:  rgba(232, 239, 255, .44);

  --line:        rgba(126, 168, 255, .16);
  --line-strong: rgba(126, 168, 255, .30);

  --brand:       #5b9cff;
  --brand-hover: #7db3ff;
  --brand-ink:   #06101f;
  --brand-soft:  rgba(91, 156, 255, .14);
  --brand-line:  rgba(91, 156, 255, .42);
  --on-brand:        rgba(255, 255, 255, .74);
  --on-brand-dim:    rgba(255, 255, 255, .52);
  --on-brand-fill:   rgba(255, 255, 255, .12);
  --on-brand-fill-2: rgba(255, 255, 255, .18);

  --ok-bg:   oklch(0.32 0.08 160);
  --ok-fg:   oklch(0.86 0.17 160);
  --ok-mark: oklch(0.74 0.16 160);

  --warn-bg:   oklch(0.34 0.08 80);
  --warn-fg:   oklch(0.88 0.15 85);
  --warn-mark: oklch(0.80 0.15 80);

  --bad-bg:   oklch(0.33 0.09 20);
  --bad-fg:   oklch(0.80 0.16 22);
  --bad-mark: oklch(0.70 0.18 22);

  --neu-bg:   rgba(126, 168, 255, .12);
  --neu-fg:   rgba(232, 239, 255, .62);
  --neu-mark: rgba(91, 156, 255, .42);

  --card-head:      #1b2a4c;
  --card-head-line: rgba(126, 168, 255, .34);

  --shadow:    0 1px 3px rgba(0, 0, 0, .55);
  --shadow-lg: 0 12px 34px rgba(2, 8, 22, .7), 0 2px 6px rgba(0, 0, 0, .45);
}
:root[data-theme='blue'] { --chrome: #0d1c3d; --chrome-ink: #eaf1ff; }

/* No stored preference: follow the operating system. The [data-theme] rules
   above win when the reader has chosen explicitly. */
@media (prefers-color-scheme: dark) {
  :root:not([data-theme='light']):not([data-theme='dark']):not([data-theme='blue']) {
    color-scheme: dark;

    --bg:        #100d16;
    --surface:   #191521;
    --surface-2: #1f1a29;
    --surface-3: #262031;
    --surface-4: #2c2539;

    --ink:       #ece8f3;
    --text:      rgba(236, 232, 243, .87);
    --text-soft: rgba(236, 232, 243, .64);
    --text-mute: rgba(236, 232, 243, .52);
    --text-dim:  rgba(236, 232, 243, .42);

    --line:        rgba(236, 232, 243, .11);
    --line-strong: rgba(236, 232, 243, .20);

    --brand:       #b79ade;
    --brand-hover: #cbb4ea;
    --brand-ink:   #17101f;
    --brand-soft:  rgba(183, 154, 222, .12);
    --brand-line:  rgba(183, 154, 222, .38);
    --on-brand:        rgba(255, 255, 255, .70);
    --on-brand-dim:    rgba(255, 255, 255, .48);
    --on-brand-fill:   rgba(255, 255, 255, .10);
    --on-brand-fill-2: rgba(255, 255, 255, .14);

    --ok-bg:   oklch(0.30 0.06 150);
    --ok-fg:   oklch(0.82 0.14 150);
    --ok-mark: oklch(0.68 0.13 150);

    --warn-bg:   oklch(0.31 0.06 80);
    --warn-fg:   oklch(0.85 0.13 85);
    --warn-mark: oklch(0.74 0.13 80);

    --bad-bg:   oklch(0.30 0.07 25);
    --bad-fg:   oklch(0.78 0.14 25);
    --bad-mark: oklch(0.66 0.16 25);

    --neu-bg:   rgba(236, 232, 243, .07);
    --neu-fg:   rgba(236, 232, 243, .60);
    --neu-mark: rgba(183, 154, 222, .34);

    --card-head:      #2b2438;
    --card-head-line: rgba(236, 232, 243, .22);

    --shadow:    0 1px 3px rgba(0, 0, 0, .5);
    --shadow-lg: 0 10px 30px rgba(0, 0, 0, .6), 0 2px 6px rgba(0, 0, 0, .4);
  }
}

/* The header bar is brand-filled in light and a deep plum in dark. */
:root { --chrome: var(--brand); --chrome-ink: #ffffff; }
:root[data-theme='dark'] { --chrome: #241436; --chrome-ink: #f0eaf8; }
@media (prefers-color-scheme: dark) {
  :root:not([data-theme='light']):not([data-theme='dark']):not([data-theme='blue']) {
    --chrome: #241436; --chrome-ink: #f0eaf8;
  }
}

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

*, *::before, *::after { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; }

body {
  margin: 0;
  background: var(--bg);
  color: var(--text);
  font-family: var(--font);
  font-size: 14px;
  line-height: 1.5;
  -webkit-font-smoothing: antialiased;
}

h1, h2, h3 { margin: 0; color: var(--ink); font-weight: 600; letter-spacing: -.01em; }
h1 { font-size: 19px; line-height: 1.2; }
h2 { font-size: 13.5px; }
p { margin: 0 0 .5rem; }
p:last-child { margin-bottom: 0; }

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

code, .mono, .num { font-family: var(--mono); font-variant-numeric: tabular-nums; }

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

.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;
}

.muted { color: var(--text-mute); }
.small { font-size: 11.5px; }
.strong { font-weight: 600; }
.num { text-align: right; }
.eyebrow {
  font-size: 10px; font-weight: 500; letter-spacing: .07em;
  text-transform: uppercase; color: var(--text-dim);
}

/* ---------------------------------------------------------------- top bar -- */

.topbar {
  position: sticky; top: 0; z-index: 40;
  display: flex; align-items: center; gap: 14px;
  padding: 13px clamp(16px, 3vw, 24px);
  background: var(--chrome); color: var(--chrome-ink);
}
.topbar a { color: var(--chrome-ink); }

.brand { display: flex; align-items: center; gap: 12px; }
.brand:hover { text-decoration: none; }
.brand-mark {
  display: grid; place-items: center;
  width: 26px; height: 26px; border-radius: var(--radius-sm);
  background: var(--on-brand-fill-2); color: inherit;
  font-family: var(--mono); font-size: 11px; font-weight: 600;
}
.brand-mark--lg {
  width: 48px; height: 48px; border-radius: 13px; font-size: 17px;
  background: var(--brand); color: var(--brand-ink);
}
.brand-text { font-size: 15px; font-weight: 600; letter-spacing: -.01em; }
@media (max-width: 700px) { .brand-text { display: none; } }

.entity-label, .entity-switch { display: flex; align-items: center; gap: 6px; }
.entity-label { font-size: 12px; font-weight: 500; color: var(--on-brand); }
.entity-switch select {
  padding: 5px 8px; max-width: 11rem;
  background: var(--on-brand-fill); color: var(--chrome-ink);
  border-color: transparent; font-size: 12px;
}
.entity-switch select option { background: var(--surface); color: var(--ink); }

.mainnav { display: flex; gap: 2px; margin-left: auto; }
.navlink {
  display: flex; align-items: center; gap: 7px;
  padding: 6px 11px; border-radius: var(--radius-sm);
  color: var(--on-brand); font-size: 12px; font-weight: 500;
}
.navlink:hover { background: var(--on-brand-fill); color: var(--chrome-ink); text-decoration: none; }
.navlink.is-current { background: var(--on-brand-fill-2); color: var(--chrome-ink); }
.navlink svg { width: 16px; height: 16px; fill: currentColor; flex: none; }
/* Below this the labels come off, but they stay in the accessibility tree —
   `display: none` would take them out of it and leave five unlabelled icons.
   The title attribute covers sighted readers who need the reminder. */
@media (max-width: 900px) {
  .navlink-label {
    position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
    overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
  }
  .navlink { padding: 6px 8px; }
}

.account { position: relative; }
.account > summary { list-style: none; cursor: pointer; }
.account > summary::-webkit-details-marker { display: none; }

.avatar {
  display: grid; place-items: center;
  width: 30px; height: 30px; border-radius: 50%;
  background: var(--on-brand-fill-2); color: var(--chrome-ink);
  font-size: 11px; font-weight: 600;
}
.avatar--sm {
  width: 24px; height: 24px; font-size: 10px;
  background: var(--brand-soft); color: var(--brand); border: 1px solid var(--brand-line);
}

.account-menu {
  position: absolute; right: 0; top: calc(100% + 10px); z-index: 50;
  min-width: 16rem; padding: 14px;
  background: var(--surface); border: 1px solid var(--line);
  border-radius: var(--radius); box-shadow: var(--shadow-lg);
  color: var(--text);
}
.account-menu a { color: var(--brand); }
.account-name  { color: var(--ink); font-weight: 600; }
.account-email { font-size: 11.5px; color: var(--text-mute); word-break: break-all; }
.account-role  { margin: 6px 0 0; font-size: 10px; letter-spacing: .07em;
                 text-transform: uppercase; color: var(--text-dim); }

.themepick { margin: 12px 0; padding-top: 12px; border-top: 1px solid var(--line); }
.themepick .eyebrow { display: block; margin-bottom: 6px; }

/* ----------------------------------------------------------------- layout -- */

.main { max-width: 1400px; margin: 0 auto; padding: clamp(16px, 2.5vw, 26px) clamp(16px, 2.5vw, 26px) 72px; }
.main--wide { max-width: none; }

.pagehead {
  display: flex; flex-wrap: wrap; align-items: flex-end;
  justify-content: space-between; gap: 16px; margin-bottom: 18px;
}
.pagehead-sub { margin: 4px 0 0; font-size: 12px; color: var(--text-mute); }

.breadcrumb {
  display: flex; flex-wrap: wrap; gap: 8px; align-items: center;
  margin-bottom: 10px; font-size: 11.5px; color: var(--text-mute);
}
.breadcrumb span[aria-hidden] { opacity: .45; }
.pageactions { margin-top: 20px; }

/* ------------------------------------------------------------------ cards -- */

.card {
  background: var(--surface); border: 1px solid var(--line);
  border-radius: var(--radius-md); box-shadow: var(--shadow);
  margin-bottom: 14px; overflow: hidden;
}
.card--muted { background: var(--surface-2); box-shadow: none; }
.card-title {
  padding: 13px 16px; font-size: 12.5px;
  background: var(--card-head);
  border-bottom: 1px solid var(--card-head-line);
}
.card--inline > .inlineform, .card--muted > .rolelist { padding: 16px; }
.card > .formhelp { padding: 12px 16px 14px; }
.card--inline > .formhelp, .card--muted > .formhelp { padding: 0 16px 16px; }

.card--details > summary {
  display: flex; align-items: center; justify-content: space-between;
  gap: 16px; padding-right: 16px; cursor: pointer; list-style: none;
}
.card--details > summary::-webkit-details-marker { display: none; }
.card--details > summary .card-title { flex: 1; border-bottom: 0; }
.card--details[open] > summary .card-title { border-bottom: 1px solid var(--line); }

.callout {
  padding: 13px 16px; margin-bottom: 16px;
  background: var(--brand-soft); border: 1px solid var(--brand-line);
  border-radius: var(--radius-md); font-size: 12.5px;
}
.callout strong { display: block; margin-bottom: 3px; color: var(--brand);
                  font-size: 10px; letter-spacing: .07em; text-transform: uppercase; }

/* -------------------------------------------------------------- KPI strip -- */

/* Four figures answering "am I on track" before any table appears. The 1px gap
   over a line-coloured ground gives hairline dividers without extra borders. */
.kpis {
  display: grid; grid-template-columns: repeat(4, 1fr); gap: 1px;
  margin-bottom: 14px; background: var(--line);
  border: 1px solid var(--line); border-radius: var(--radius-md); overflow: hidden;
}
@media (max-width: 1000px) { .kpis { grid-template-columns: repeat(2, 1fr); } }
@media (max-width: 560px)  { .kpis { grid-template-columns: 1fr; } }

.kpi { padding: 18px 20px; background: var(--surface-2); }
.kpi-value {
  font-family: var(--mono); font-size: 32px; font-weight: 600;
  letter-spacing: -.02em; line-height: 1; color: var(--ink);
}
.kpi-value--bad { color: var(--bad-fg); }
.kpi-row { display: flex; align-items: baseline; gap: 8px; margin-top: 9px; }
.kpi-of { font-family: var(--mono); font-size: 15px; font-weight: 500; color: var(--text-dim); }
.kpi-note { margin-top: 8px; font-size: 11.5px; color: var(--text-mute); }
.kpi-note--ok  { color: var(--ok-fg); font-weight: 500; }
.kpi-note--bad { color: var(--bad-fg); font-weight: 500; }
.kpi-bar { margin-top: 13px; height: 6px; }
.kpi-dots { display: flex; gap: 3px; margin-top: 15px; height: 18px; }
.kpi-dot { flex: 1; border-radius: 2px; min-width: 2px; }
.kpi-dot--on-track  { background: var(--ok-mark); }
.kpi-dot--at-risk   { background: var(--warn-mark); }
.kpi-dot--off-track { background: var(--bad-mark); }
.kpi-dot--none, .kpi-dot--no-target { background: var(--neu-bg); }

/* ---------------------------------------------------------------- toolbar -- */

.toolbar {
  display: flex; flex-wrap: wrap; align-items: center;
  justify-content: space-between; gap: 10px; margin-bottom: 12px;
}
.toolbar-right { display: flex; flex-wrap: wrap; align-items: center; gap: 7px; }
.counter { font-family: var(--mono); font-size: 11.5px; color: var(--text-mute); }

.segmented { display: inline-flex; padding: 3px; gap: 2px; background: var(--neu-bg); border-radius: var(--radius-sm); }
.segmented a, .segmented button {
  padding: 5px 11px; border: 0; border-radius: var(--radius-xs); background: none;
  color: var(--text-mute); font: 500 11.5px var(--font); cursor: pointer;
}
.segmented a:hover, .segmented button:hover { color: var(--ink); text-decoration: none; }
.segmented a.is-active, .segmented button.is-active {
  background: var(--surface); color: var(--ink); font-weight: 600; box-shadow: var(--shadow);
}

.periodnav { display: flex; align-items: center; gap: 6px; }
.periodnav-label { min-width: 8.5rem; text-align: center; font-size: 12.5px; font-weight: 600; color: var(--ink); }
.datepick { display: flex; gap: 6px; align-items: center; }

.daychip {
  display: inline-flex; align-items: center; gap: 7px; white-space: nowrap;
  padding: 6px 12px; border-radius: var(--radius-sm);
  background: var(--on-brand-fill); font-size: 12px; font-weight: 500;
}
/* The month and the day count are both repeated in the page heading, so the
   chip is the first thing to go when the bar gets tight. */
@media (max-width: 900px) { .daychip { display: none; } }
.daychip .num { color: var(--on-brand); font-size: 11.5px; }
.daychip-sep { color: var(--on-brand-dim); }

.iconbtn {
  display: grid; place-items: center; width: 30px; height: 30px; flex: none;
  border: 1px solid var(--line-strong); border-radius: var(--radius-sm);
  background: var(--surface); color: var(--text-mute);
}
.iconbtn:hover { background: var(--surface-3); color: var(--ink); text-decoration: none; }
.iconbtn svg { width: 15px; height: 15px; }

/* ---------------------------------------------------------------- buttons -- */

.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 7px;
  padding: 8px 14px; border: 1px solid var(--line-strong); border-radius: var(--radius-sm);
  background: var(--surface); color: var(--text);
  font: 600 12px var(--font); cursor: pointer; white-space: nowrap;
  transition: background .12s ease, border-color .12s ease;
}
.btn:hover { background: var(--surface-3); text-decoration: none; }
.btn:disabled { opacity: .5; cursor: not-allowed; }
.btn--sm { padding: 5px 10px; font-size: 11.5px; font-weight: 500; }
.btn--block { width: 100%; }
.btn--primary { background: var(--brand); border-color: var(--brand); color: var(--brand-ink); }
.btn--primary:hover { background: var(--brand-hover); border-color: var(--brand-hover); color: var(--brand-ink); }
.btn--ghost { background: transparent; border-color: var(--line-strong); color: var(--text-soft); }
.btn--ghost:hover { background: var(--surface-3); color: var(--ink); }
.btn--danger { background: transparent; border-color: var(--line-strong); color: var(--bad-fg); }
.btn--danger:hover { background: var(--bad-bg); border-color: var(--bad-fg); }
.btn--google { padding: 11px 16px; font-size: 13px; }
.btn--google svg.g { width: 18px; height: 18px; }
/* On the brand-filled header bar the primary button inverts. */
.topbar .btn--primary { background: var(--surface); border-color: var(--surface); color: var(--brand); }
.topbar .btn--primary:hover { background: var(--surface-3); color: var(--brand); }

/* ----------------------------------------------------------------- tables -- */

.tablewrap { overflow-x: auto; }
.table { width: 100%; border-collapse: collapse; font-size: 12.5px; }
.table th, .table td { padding: 9px 14px; text-align: left; vertical-align: middle; }
.table thead th {
  position: sticky; top: 0; z-index: 2;
  background: var(--surface-2); color: var(--text-mute);
  font-size: 10px; font-weight: 600; letter-spacing: .07em; text-transform: uppercase;
  border-bottom: 1px solid var(--line-strong); white-space: nowrap;
}
.table thead th.num, .table td.num { text-align: right; }
.table td.num, .table th.num { font-family: var(--mono); }
.table tbody tr { border-top: 1px solid var(--line); }
.table tbody tr:hover { background: var(--surface-2); }
.table tbody tr.is-inactive { opacity: .55; }
.table tbody tr.is-current { background: var(--brand-soft); }
.table tbody tr.is-today > * { background: var(--brand-soft); }
.table tbody tr.is-future { opacity: .5; }
.table tbody th[scope='row'] { font-weight: 500; color: var(--text); }

.table--targets th[scope='row'] { max-width: 26rem; }
/* A form living inside a table cell. Inputs default to width:100%, which in a
   wide column stretches a role picker across half the table — size to content
   instead. */
.rowform { display: flex; align-items: center; gap: 6px; }
.rowform input, .rowform select { width: auto; min-width: 9rem; max-width: 18rem; }
.rowactions { display: flex; gap: 6px; justify-content: flex-end; }

.person { display: flex; align-items: center; gap: 9px; }
.person-name  { display: block; color: var(--ink); font-weight: 500; }
.person-email { display: block; font-size: 11px; color: var(--text-mute); }

.rolelist { margin: 0; display: grid; gap: 10px; }
.rolelist dt { font-size: 12.5px; font-weight: 600; color: var(--ink); }
.rolelist dd { margin: 0; font-size: 11.5px; color: var(--text-mute); }

/* ------------------------------------------------------- scorecard groups -- */

/* One block per section: a header carrying the section's own pace, then its
   metrics. The inline bars are the month's shape at a glance. */
.groups { display: flex; flex-direction: column; gap: 10px; }

.group { border: 1px solid var(--line); border-radius: var(--radius-md); overflow: hidden; background: var(--surface); }
.group-head {
  display: grid; grid-template-columns: 1fr 120px 130px;
  align-items: center; gap: 12px; padding: 12px 14px;
  background: var(--card-head); border-bottom: 1px solid var(--card-head-line);
}
@media (max-width: 720px) { .group-head { grid-template-columns: 1fr auto; } .group-head .bar { display: none; } }
.group-name { display: flex; align-items: center; gap: 9px; min-width: 0; }
.group-dot { width: 7px; height: 7px; border-radius: 50%; flex: none; }
.group-dot--on-track  { background: var(--ok-mark); }
.group-dot--at-risk   { background: var(--warn-mark); }
.group-dot--off-track { background: var(--bad-mark); }
.group-dot--none, .group-dot--no-target { background: var(--neu-mark); }
.group-title { font-size: 12.5px; font-weight: 600; color: var(--ink); }
.group-count { font-family: var(--mono); font-size: 11px; color: var(--text-dim); white-space: nowrap; }
.group-pace { text-align: right; font-family: var(--mono); font-size: 12.5px; font-weight: 600; }
.group-pace span { font-family: var(--font); font-size: 11px; font-weight: 400; color: var(--text-dim); }

.mrow {
  display: grid; grid-template-columns: 1fr 96px 150px 74px;
  align-items: center; gap: 12px; padding: 9px 14px; border-top: 1px solid var(--line);
}
.mrow:hover { background: var(--surface-2); }
.mrow-name {
  font-size: 12px; color: var(--text);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.mrow-name:hover { color: var(--brand); text-decoration: none; }
.mrow-result { text-align: right; font-family: var(--mono); font-size: 12px; font-weight: 500; color: var(--ink); }
.mrow-pct { justify-self: end; }
@media (max-width: 860px) {
  .mrow { grid-template-columns: 1fr 90px 64px; }
  .mrow .sparkbars { display: none; }
}

/* A row of daily bars, one per recorded day. Height is a share of the row's own
   maximum, so every metric is legible regardless of its units. Drawn as SVG so
   the heights are geometry, not inline styles — see the CSP in lib/http.js. */
.sparkbars { display: block; width: 100%; height: 20px; }
.sparkbars--tall { height: 62px; }
.sparkbar--on-track  { fill: var(--ok-mark); }
.sparkbar--at-risk   { fill: var(--warn-mark); }
.sparkbar--off-track { fill: var(--bad-mark); }
.sparkbar--none, .sparkbar--no-target { fill: var(--neu-mark); }

.pct {
  display: inline-block; padding: 2px 7px; border-radius: var(--radius-xs);
  font-family: var(--mono); font-size: 11px; font-weight: 600; white-space: nowrap;
}
.pct--on-track  { background: var(--ok-bg);   color: var(--ok-fg); }
.pct--at-risk   { background: var(--warn-bg); color: var(--warn-fg); }
.pct--off-track { background: var(--bad-bg);  color: var(--bad-fg); }
.pct--none, .pct--no-target { background: var(--neu-bg); color: var(--neu-fg); }

.pill {
  display: inline-block; padding: 3px 9px; border-radius: 999px;
  font-size: 11px; font-weight: 600; white-space: nowrap;
}
.pill--on-track  { background: var(--ok-bg);   color: var(--ok-fg); }
.pill--at-risk   { background: var(--warn-bg); color: var(--warn-fg); }
.pill--off-track { background: var(--bad-bg);  color: var(--bad-fg); }
.pill--none, .pill--no-target { background: var(--neu-bg); color: var(--neu-fg); }

.bar { display: block; width: 100%; height: 6px; }
.bar--lg { height: 8px; }
.bar-track { fill: var(--neu-bg); }
.bar-fill--on-track  { fill: var(--ok-mark); }
.bar-fill--at-risk   { fill: var(--warn-mark); }
.bar-fill--off-track { fill: var(--bad-mark); }
.bar-fill--none, .bar-fill--no-target { fill: var(--neu-mark); }
.bar-mark { stroke: var(--line-strong); stroke-width: 1; vector-effect: non-scaling-stroke; }

.tag {
  display: inline-block; margin-left: 6px; padding: 1px 6px; border-radius: var(--radius-xs);
  background: var(--neu-bg); color: var(--text-mute);
  font-size: 10.5px; font-weight: 600; white-space: nowrap;
}
.tag--lock { background: var(--warn-bg); color: var(--warn-fg); }
.notedot {
  display: inline-block; width: 5px; height: 5px; margin-left: 6px;
  border-radius: 50%; background: var(--warn-mark); cursor: help;
}

/* ---------------------------------------------------------- dashboard rail -- */

.dash { display: grid; grid-template-columns: 1fr 384px; gap: 14px; align-items: start; }
@media (max-width: 1180px) { .dash { grid-template-columns: 1fr; } }

.rail {
  padding: 20px; background: var(--surface-2);
  border: 1px solid var(--line); border-radius: var(--radius-md);
}
.rail-title { font-size: 12.5px; font-weight: 600; color: var(--ink); }
.rail-sub { margin: 4px 0 14px; font-size: 11.5px; line-height: 1.5; color: var(--text-mute); }
.leaks { display: flex; flex-direction: column; gap: 8px; }
.leak {
  position: relative; padding: 12px 13px 12px 16px; overflow: hidden;
  background: var(--surface); border: 1px solid var(--line); border-radius: var(--radius-sm);
}
.leak::before { content: ''; position: absolute; left: 0; top: 0; bottom: 0; width: 3px; }
.leak--on-track::before  { background: var(--ok-mark); }
.leak--at-risk::before   { background: var(--warn-mark); }
.leak--off-track::before { background: var(--bad-mark); }
.leak--none::before, .leak--no-target::before { background: var(--neu-mark); }
.leak-head { display: flex; align-items: baseline; justify-content: space-between; gap: 10px; }
.leak-name { font-size: 12px; font-weight: 600; color: var(--ink); }
.leak-name:hover { color: var(--brand); text-decoration: none; }
.leak-pct { font-family: var(--mono); font-size: 12px; font-weight: 600; }
.leak-pct--on-track  { color: var(--ok-fg); }
.leak-pct--at-risk   { color: var(--warn-fg); }
.leak-pct--off-track { color: var(--bad-fg); }
.leak-pct--none, .leak-pct--no-target { color: var(--text-mute); }
.leak-line { margin: 6px 0 0; font-size: 11.5px; line-height: 1.45; color: var(--text-soft); }
.leak-foot { margin-top: 9px; font-family: var(--mono); font-size: 10.5px; color: var(--text-dim); }

.railbox {
  margin-top: 18px; padding: 14px;
  border: 1px dashed var(--line-strong); border-radius: var(--radius-sm);
}
.railbox-title { font-size: 11.5px; font-weight: 600; color: var(--ink); margin-bottom: 6px; }
.railbox-text { font-size: 11.5px; line-height: 1.5; color: var(--text-mute); }
.railbox .btn { margin-top: 10px; }

/* ------------------------------------------------------------ month grid -- */

.gridwrap {
  overflow: auto; max-height: calc(100vh - 15rem);
  background: var(--surface); border: 1px solid var(--line);
  border-radius: var(--radius-md); box-shadow: var(--shadow);
}
.table--grid { font-size: 12px; border-collapse: separate; border-spacing: 0; }
.table--grid th, .table--grid td { padding: 4px 6px; white-space: nowrap; border: 0; }
.table--grid tbody tr { border: 0; }
.table--grid tbody tr:hover { background: transparent; }

.table--grid .col-metric {
  position: sticky; left: 0; z-index: 3;
  min-width: 17rem; max-width: 22rem; padding-left: 14px;
  background: var(--surface); border-right: 1px solid var(--line);
}
.table--grid thead .col-metric { z-index: 5; background: var(--surface-2); }
.table--grid tbody tr:hover .col-metric,
.table--grid tbody tr:hover td { background: var(--surface-2); }
.col-metric a { color: var(--text); font-size: 12px; }
.col-metric a:hover { color: var(--brand); text-decoration: none; }

.table--grid .col-dt { min-width: 5rem; color: var(--text-mute); }
.table--grid .col-day { min-width: 3rem; text-align: center; }
.day-dow { display: block; font-size: 9.5px; color: var(--text-dim); }
.day-num { display: block; font-family: var(--mono); font-size: 11px; color: var(--text-soft); }

/* Heatmap cells: a filled chip only where the day missed, so the eye lands on
   problems rather than on a wall of colour. */
.hcell {
  display: grid; place-items: center; height: 22px; margin: 0 1px;
  border-radius: 3px; font-family: var(--mono); font-size: 10.5px; font-weight: 500;
}
.hcell--good  { background: var(--neu-bg);  color: var(--neu-fg); }
.hcell--great { background: var(--ok-bg);   color: var(--ok-fg); }
.hcell--miss  { background: var(--bad-bg);  color: var(--bad-fg); }
.hcell--blank { color: var(--text-dim); }

.table--grid .col-result, .table--grid .col-pct, .table--grid .col-target {
  background: var(--surface-2); border-left: 1px solid var(--line); text-align: right;
}
.table--grid tbody .col-result { font-weight: 600; color: var(--ink); }
.grid-section th {
  position: sticky; left: 0; z-index: 4;
  padding: 11px 14px 7px; background: var(--card-head);
  border-block: 1px solid var(--card-head-line);
  font-size: 11px; font-weight: 600; letter-spacing: .03em; color: var(--ink);
}
.gridnote { margin-top: 10px; font-size: 11.5px; color: var(--text-mute); }

/* ------------------------------------------------------------ metric page -- */

.statgrid {
  display: grid; gap: 1px; margin-bottom: 14px; background: var(--line);
  border: 1px solid var(--line); border-radius: var(--radius-md); overflow: hidden;
  grid-template-columns: repeat(auto-fit, minmax(10rem, 1fr));
}
.stat { display: flex; flex-direction: column; gap: 6px; padding: 16px 18px; background: var(--surface-2); }
.stat-value { font-family: var(--mono); font-size: 21px; font-weight: 600; letter-spacing: -.02em; color: var(--ink); }
.stat-value--soft { color: var(--text-soft); }

.chartwrap { position: relative; height: 220px; border-bottom: 1px solid var(--line-strong); }
.chart { display: block; width: 100%; height: 100%; }
.chart-bar--on-track  { fill: var(--ok-mark); }
.chart-bar--off-track { fill: var(--bad-mark); }
.chart-bar--none      { fill: var(--neu-mark); }
.chart-daily { stroke: var(--line-strong); stroke-width: 1.5; }
.chart-req   { stroke: var(--text-dim); stroke-width: 2; stroke-dasharray: 7 6; fill: none; }
.chart-cum   { stroke: var(--brand); stroke-width: 2.5; fill: none; stroke-linejoin: round; }

.axis { display: flex; gap: 4px; margin-top: 7px; }
.axis-tick { flex: 1; text-align: center; }
.axis-dow { font-size: 9.5px; color: var(--text-dim); }
.axis-dom { font-family: var(--mono); font-size: 10.5px; color: var(--text-mute); }

.legend { display: flex; flex-wrap: wrap; gap: 20px; margin-top: 18px; font-size: 11px; color: var(--text-mute); }
.legend-item { display: flex; align-items: center; gap: 7px; }
.legend-swatch { width: 12px; height: 9px; border-radius: 2px; }
.legend-swatch--ok  { background: var(--ok-mark); }
.legend-swatch--bad { background: var(--bad-mark); }
.legend-swatch--neu { background: var(--neu-mark); }
.legend-line { width: 14px; height: 2px; background: var(--brand); }
.legend-dash { width: 14px; height: 0; border-top: 2px dashed var(--text-dim); }

.readout { margin-top: 9px; font-size: 12.5px; line-height: 1.6; color: var(--text-soft); }
.statlist { margin-top: 9px; display: flex; flex-direction: column; gap: 8px; }
.statlist-row {
  display: flex; align-items: center; justify-content: space-between; gap: 10px;
  padding-bottom: 8px; border-bottom: 1px solid var(--line);
}
.statlist-row:last-child { border-bottom: 0; padding-bottom: 0; }
.statlist-k { font-size: 11.5px; color: var(--text-mute); }
.statlist-v { font-family: var(--mono); font-size: 11.5px; font-weight: 600; color: var(--ink); }

.split { display: grid; grid-template-columns: 1fr 316px; }
@media (max-width: 1080px) { .split { grid-template-columns: 1fr; } }
.split > :first-child { padding: 20px; border-right: 1px solid var(--line); }
.split > :last-child { padding: 20px; background: var(--surface-2); }
@media (max-width: 1080px) {
  .split > :first-child { border-right: 0; border-bottom: 1px solid var(--line); }
}

.chips { display: flex; flex-wrap: wrap; align-items: center; gap: 7px; }
.chip {
  padding: 5px 11px; border-radius: var(--radius-sm);
  background: var(--neu-bg); color: var(--text-soft); font-size: 11.5px; font-weight: 500;
}
.chip:hover { color: var(--ink); text-decoration: none; }
.chip.is-active { background: var(--brand); color: var(--brand-ink); font-weight: 600; }
.chip.is-active:hover { color: var(--brand-ink); }

/* ------------------------------------------------------------------ forms -- */

input[type='text'], input[type='email'], input[type='number'],
input[type='date'], select, textarea {
  width: 100%; padding: 8px 11px;
  border: 1px solid var(--line-strong); border-radius: var(--radius-sm);
  background: var(--surface); color: var(--ink);
  font: 400 12.5px var(--font);
}
input:focus, select:focus, textarea:focus { border-color: var(--brand); }
input[readonly] { background: var(--surface-3); color: var(--text-mute); }
select { cursor: pointer; }
textarea { resize: vertical; }
input::placeholder { color: var(--text-dim); }

.inputwrap { position: relative; display: flex; align-items: center; }
.inputwrap input { font-family: var(--mono); font-weight: 500; }
.inputwrap--currency input { padding-left: 22px; text-align: right; }
.inputwrap--percent  input { padding-right: 22px; text-align: right; }
.inputwrap--number   input { text-align: right; }
.inputwrap--tight { width: 9rem; min-width: 0; margin-left: auto; }
.inputwrap--tight input { padding-block: 5px; }
@media (max-width: 640px) { .inputwrap--tight { width: 100%; } }
.affix { position: absolute; left: 11px; font-size: 11.5px; color: var(--text-mute); pointer-events: none; }
.affix--end { left: auto; right: 11px; }

.formgrid { display: grid; gap: 16px; padding: 18px; grid-template-columns: repeat(auto-fit, minmax(15rem, 1fr)); }
.formcard { max-width: 56rem; }

/* Grouped radio controls use a real <fieldset>/<legend> for the accessibility
   tree. Both carry browser defaults — an inset border and a legend notched into
   it — that have to be cleared, or the label collides with the border. */
fieldset { min-width: 0; margin: 0; padding: 0; border: 0; }
legend {
  display: block; width: 100%; padding: 0; margin-bottom: 6px;
  font-size: 11px; font-weight: 500; color: var(--text-soft);
}
.formfield { display: flex; flex-direction: column; gap: 6px; }
.formfield--full { grid-column: 1 / -1; }
.formfield--grow { flex: 1 1 14rem; }
.formfield > label { font-size: 11px; font-weight: 500; color: var(--text-soft); }
.formhelp { margin: 0; font-size: 11px; color: var(--text-mute); }

/* A row of fields that must line up whatever they contain.
   Flexbox cannot do this: aligning to the bottom drops a field that has no help
   text below one that does, and aligning to the top staggers the inputs
   instead. A three-row grid fixes the rows themselves — labels, then controls,
   then help text — and `display: contents` lets each field hand its children
   straight to that grid, so every input sits on one line no matter which fields
   carry a label or a hint. */
.inlineform {
  display: grid;
  grid-template-rows: auto auto auto;
  grid-auto-flow: column;
  grid-auto-columns: auto;
  justify-content: start;
  align-items: center;
  gap: 6px 10px;
}
.inlineform > * { grid-row: 2; }                        /* buttons and lone controls */
.inlineform .formfield { display: contents; }
.inlineform .formfield > label { grid-row: 1; align-self: end; }
.inlineform .formfield > .formhelp { grid-row: 3; align-self: start; }
.inlineform .formfield > :not(label):not(.formhelp) { grid-row: 2; }
.inlineform .formfield input,
.inlineform .formfield select { min-width: 9rem; }
.inlineform .formfield--grow input,
.inlineform .formfield--grow select { min-width: 16rem; }
/* Help text that belongs to the form rather than to one field. */
.card--inline > .formhelp { grid-row: auto; }

@media (max-width: 640px) {
  /* Stacked, one field per line, when there is no room to line anything up. */
  .inlineform {
    grid-auto-flow: row; grid-template-rows: none;
    /* An implicit column sizes to its content; name one so the fields fill it. */
    grid-template-columns: 1fr; justify-items: stretch;
  }
  /* These repeat the selectors above verbatim: :not() carries the specificity
     of its argument, so a shorter override would lose to them even here. */
  .inlineform > * { grid-row: auto; }
  .inlineform .formfield > label,
  .inlineform .formfield > .formhelp,
  .inlineform .formfield > :not(label):not(.formhelp) { grid-row: auto; align-self: auto; }
  .inlineform .formfield input, .inlineform .formfield select,
  .inlineform .formfield--grow input, .inlineform .formfield--grow select { min-width: 0; width: 100%; }
}
.checkfield { display: flex; align-items: center; gap: 8px; font-size: 12.5px; }
.checkfield input { width: auto; }

/* Radio cards — the design's two-up "Higher / Lower is better" chooser. Styling
   keys off :checked, so the selected state needs no JavaScript. */
.choices { display: grid; grid-template-columns: 1fr 1fr; gap: 8px; }
@media (max-width: 560px) { .choices { grid-template-columns: 1fr; } }
.choice { position: relative; display: block; cursor: pointer; }
.choice input {
  position: absolute; inset: 0; width: 100%; height: 100%;
  margin: 0; opacity: 0; cursor: pointer;
}
.choice-body {
  display: block; height: 100%;
  padding: 11px; border: 1px solid var(--line-strong); border-radius: var(--radius-sm);
  background: var(--surface); transition: border-color .12s ease, background .12s ease;
}
.choice input:checked + .choice-body {
  border-color: var(--brand); background: var(--brand-soft);
  box-shadow: inset 0 0 0 1px var(--brand);
}
.choice input:focus-visible + .choice-body { outline: 2px solid var(--brand); outline-offset: 2px; }
.choice-title { display: block; font-size: 12px; font-weight: 600; color: var(--text-soft); }
.choice input:checked + .choice-body .choice-title { color: var(--ink); }
.choice-sub { display: block; margin-top: 3px; font-size: 10.5px; color: var(--text-mute); }

/* Segmented radio group — "Sum of days / Latest value". */
.radiobar { display: flex; flex-wrap: wrap; gap: 7px; }
.radiobar label { position: relative; display: block; cursor: pointer; }
.radiobar input { position: absolute; inset: 0; width: 100%; height: 100%; margin: 0; opacity: 0; cursor: pointer; }
.radiobar span {
  display: block; padding: 7px 12px; border-radius: var(--radius-sm);
  border: 1px solid var(--line-strong); color: var(--text-soft);
  font-size: 11.5px; font-weight: 500;
}
.radiobar input:checked + span {
  background: var(--ink); border-color: var(--ink); color: var(--surface); font-weight: 600;
}
.radiobar input:focus-visible + span { outline: 2px solid var(--brand); outline-offset: 2px; }

.preview {
  padding: 12px 13px; background: var(--surface-2);
  border: 1px solid var(--line); border-radius: var(--radius-sm);
}
.preview .eyebrow { display: block; margin-bottom: 6px; }
.preview-row { display: flex; align-items: baseline; gap: 10px; }
.preview-value { font-family: var(--mono); font-size: 17px; font-weight: 600; color: var(--ink); }

.savebar {
  position: sticky; bottom: 0; z-index: 20;
  display: flex; flex-wrap: wrap; align-items: center; justify-content: flex-end; gap: 10px;
  padding: 12px 16px; background: var(--surface); border-top: 1px solid var(--line);
}
.savebar-text { margin-right: auto; font-size: 11.5px; color: var(--text-mute); }
.entryform > .savebar {
  border: 1px solid var(--line); border-radius: var(--radius-md); box-shadow: var(--shadow-lg);
}

.fieldlist { margin: 0; padding: 0; list-style: none; }
.field {
  display: grid; grid-template-columns: 1fr 12rem 9rem; gap: 16px; align-items: start;
  padding: 12px 16px; border-top: 1px solid var(--line);
}
.field:first-child { border-top: 0; }
.field:hover { background: var(--surface-2); }
.field.is-filled { box-shadow: inset 3px 0 0 var(--ok-mark); }
.field-info { min-width: 0; }
.field-label { font-size: 12.5px; font-weight: 500; color: var(--ink); cursor: pointer; }
.field-meta { display: flex; flex-wrap: wrap; gap: 12px; margin: 3px 0 0; font-size: 11px; color: var(--text-mute); }
.field-meta .num { font-size: 11px; }
.field-note { margin: 4px 0 0; font-size: 11px; color: var(--warn-fg); }
.field-input { display: flex; flex-direction: column; gap: 4px; }
.field-help { font-size: 10.5px; color: var(--text-dim); }

/* The number being aimed at, beside the number being typed. */
.field-target {
  display: flex; flex-direction: column; gap: 2px;
  border-left: 1px solid var(--line); padding-left: 14px; min-height: 34px;
}
.field-target-label {
  font-size: 10px; font-weight: 500; letter-spacing: .06em;
  text-transform: uppercase; color: var(--text-dim); white-space: nowrap;
}
.field-target-value {
  font-family: var(--mono); font-size: 13px; font-weight: 500; color: var(--text-soft);
}
@media (max-width: 760px) {
  .field-target { border-left: 0; padding-left: 0; padding-top: 0; align-items: flex-end; }
}
/* Stacked, but the value and the target stay on one line together — separating
   them is the one thing this layout exists to avoid. */
@media (max-width: 760px) {
  .field { grid-template-columns: 1fr auto; gap: 10px 14px; }
  .field-info { grid-column: 1 / -1; }
}

/* ---------------------------------------------------------------- notices -- */

.flash {
  display: flex; align-items: flex-start; gap: 9px;
  padding: 11px 14px; margin-bottom: 16px;
  border: 1px solid transparent; border-radius: var(--radius-md); font-size: 12.5px;
}
.flash--ok    { background: var(--ok-bg);   border-color: var(--ok-mark);   color: var(--ok-fg); }
.flash--warn  { background: var(--warn-bg); border-color: var(--warn-mark); color: var(--warn-fg); }
.flash--error { background: var(--bad-bg);  border-color: var(--bad-mark);  color: var(--bad-fg); }
.flash code { padding: 0 3px; border-radius: 3px; background: var(--neu-bg); font-size: 11.5px; }

.empty {
  padding: 32px 20px; text-align: center;
  background: var(--surface); border: 1px dashed var(--line-strong);
  border-radius: var(--radius-md); color: var(--text-mute);
}
.empty--page { padding: clamp(40px, 8vw, 80px) 24px; }
.empty h1, .empty h2 { margin-bottom: 8px; }
.empty .btn { margin-top: 16px; }
.errcode { font-family: var(--mono); font-size: 44px; font-weight: 600; line-height: 1; color: var(--line-strong); }

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

.signin { display: grid; place-items: center; min-height: 84vh; padding: 24px; }
.signin-card {
  width: 100%; max-width: 24rem; padding: 32px; text-align: center;
  background: var(--surface); border: 1px solid var(--line);
  border-radius: 16px; box-shadow: var(--shadow-lg);
}
.signin-card .brand-mark { margin: 0 auto 16px; }
.signin-card h1 { font-size: 21px; }
.signin-sub { margin-bottom: 22px; font-size: 12.5px; color: var(--text-mute); }
.signin-card .flash { text-align: left; }
.signin-foot { margin-top: 20px; font-size: 11px; line-height: 1.5; color: var(--text-mute); }

/* ----------------------------------------------------------------- motion -- */

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

@media print {
  .topbar, .toolbar, .savebar, .periodnav, .pageactions, .rail { display: none; }
  body { background: #fff; }
  .card, .gridwrap, .kpis { box-shadow: none; break-inside: avoid; }
  .dash { grid-template-columns: 1fr; }
}

/* ------------------------------------------------ progressive enhancement -- */

/* Controls that exist only so the no-JavaScript path can submit a form. When
   the enhancement layer loads it sets `js` on <html> and the control that
   changed becomes the action, so these are redundant. */
.js [data-nojs] { display: none; }

/* Native <dialog>: the platform handles modality, Escape and focus return, so
   there is nothing here but appearance. */
.confirm {
  max-width: 27rem; padding: 0; border: 1px solid var(--line);
  border-radius: var(--radius); background: var(--surface); color: var(--text);
  box-shadow: var(--shadow-lg);
}
.confirm::backdrop { background: rgba(16, 13, 22, .5); backdrop-filter: blur(2px); }
.confirm form { padding: 20px; }
.confirm-title { margin-bottom: 8px; font-size: 15px; }
.confirm-body { font-size: 12.5px; line-height: 1.55; color: var(--text-soft); }
.confirm-actions { display: flex; justify-content: flex-end; gap: 8px; margin-top: 20px; }
.confirm-actions .btn--danger { border-color: var(--bad-fg); }

/* Per-field save states on the entry form. */
.field-help[data-state='saving'] { color: var(--text-mute); }
.field-help[data-state='saved']  { color: var(--ok-fg); }
.field-help[data-state='remote'] { color: var(--brand); }
.field-help[data-state='error'],
.field-help[data-state='conflict'] { color: var(--bad-fg); }
.field.is-saving .inputwrap input { border-color: var(--line-strong); }
.field.is-conflict { box-shadow: inset 3px 0 0 var(--bad-mark); }
.field.is-conflict .inputwrap input { border-color: var(--bad-fg); }
.field.is-error .inputwrap input { border-color: var(--bad-fg); }

/* A button that reads as a link — used for the inline conflict choices. */
.linkbtn {
  padding: 0; border: 0; background: none; color: var(--brand);
  font: inherit; font-size: inherit; text-decoration: underline; cursor: pointer;
}
.linkbtn:hover { color: var(--brand-hover); }

/* With per-field saving the bulk button is a fallback, not the main action. */
.entryform.is-autosaving .savebar { position: static; box-shadow: none; }
.entryform.is-autosaving .savebar .btn--primary { font-weight: 500; }

.livebanner { align-items: center; justify-content: space-between; gap: 12px; }
.livebanner-text { flex: 1; }

/* -------------------------------------------------- password-manager noise -- */

/* This app has no password field — Google handles sign-in — so an injected key
   icon over a metric's value box is only ever noise. Every field opts out via
   data-lpignore / data-1p-ignore / data-form-type, but LastPass honours its own
   attribute only sometimes and injects regardless.
   
   Two things learned the hard way: `display: none` loses, because LastPass sets
   its own !important inline styles on the icon root — hide with inherited
   properties instead. And it paints a second copy as a background-image on the
   input itself, which has to be cleared separately. */
div[data-lastpass-icon-root],
div[data-lastpass-root],
[data-lastpass-infield],
[id^='__lpform'],
com-1password-button {
  visibility: hidden !important;
  opacity: 0 !important;
  pointer-events: none !important;
  width: 0 !important;
  height: 0 !important;
}
input, textarea { background-image: none !important; }

/* The balance chart: one series against its target, not a bar/line pair. */
.chart-area { fill: var(--brand); opacity: .10; }
.chart-target {
  stroke: var(--text-dim); stroke-width: 2; stroke-dasharray: 7 6;
  vector-effect: non-scaling-stroke;
}
.chart-dot { fill: var(--brand); }
.chart-hit { fill: transparent; }
/* preserveAspectRatio="none" stretches strokes horizontally; this keeps every
   line the width it was authored at, whatever the chart is scaled to. */
.chart-cum, .chart-req, .chart-daily, .chart-target { vector-effect: non-scaling-stroke; }
.legend-dash--target { border-top-color: var(--text-dim); }

/* Movement between two readings of a balance. */
.delta--up   { color: var(--ok-fg); }
.delta--down { color: var(--bad-fg); }

/* Four options need to breathe in a menu this narrow. */
.themepick .segmented { display: grid; grid-template-columns: repeat(4, 1fr); }
.themepick .segmented a { text-align: center; padding-inline: 4px; }
