/* Components — see docs/design-system.md. Tokens live in tokens.css. */

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

html { font-family: var(--font); font-size: var(--t-md); line-height: var(--lh-md); color: var(--ink); background: var(--page); -webkit-text-size-adjust: 100%; }
body { margin: 0; background: var(--page); min-height: 100vh; }
h1, h2, h3, h4 { margin: 0; font-weight: 500; }
h1 { font-size: var(--t-xl); line-height: var(--lh-xl); }
h2 { font-size: var(--t-lg); line-height: var(--lh-lg); }
h3 { font-size: var(--t-md); line-height: var(--lh-md); font-weight: 600; }
p { margin: 0 0 var(--s-3); }
a { color: var(--accent); text-decoration: none; }
a:hover { text-decoration: underline; }
:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
small, .muted { color: var(--ink-2); font-size: var(--t-sm); line-height: var(--lh-sm); }
.dim { color: var(--ink-3); }
code { font-family: ui-monospace, Consolas, monospace; font-size: 0.92em; background: var(--surface-2); padding: 0 var(--s-1); border-radius: var(--r-sm); }

/* App shell - the bar and the rail are one L-shaped frame of chrome; the content plane holds the data. */
.shell { display: grid; grid-template-columns: var(--rail) 1fr; grid-template-rows: var(--bar) 1fr; min-height: 100vh; }

/* App bar: who is signed in, which project the figures come from, how fresh they are.
   It is chrome, so it wears the shell ink and never the page ink. */
.appbar { grid-column: 1 / -1; position: sticky; top: 0; z-index: 30; display: flex; align-items: center; background: var(--shell); color: var(--shell-ink); border-bottom: 1px solid var(--shell-line); }
.appbar .brand { width: var(--rail); flex: none; height: 100%; padding: 0 var(--s-5); border-right: 1px solid var(--shell-line); }
.brand { display: flex; align-items: center; gap: var(--s-3); }
.brand .mark { width: 28px; height: 28px; border-radius: 7px; background: var(--accent); color: var(--accent-ink); display: grid; place-items: center; font-weight: 600; font-size: var(--t-sm); flex: none; }
.brand .name { font-weight: 600; font-size: var(--t-md); letter-spacing: -0.01em; color: var(--shell-ink); }
.brand small { display: block; font-weight: 400; color: var(--shell-ink-2); font-size: var(--t-xs); line-height: var(--lh-xs); }

/* The project the data comes from. There is one, so it states a fact rather than offering a switch. */
.ctx { display: flex; align-items: center; gap: var(--s-2); margin-left: var(--s-5); padding: var(--s-1) var(--s-3); border: 1px solid var(--shell-line); border-radius: var(--r-sm); font-size: var(--t-sm); line-height: var(--lh-sm); color: var(--shell-ink-2); }
.ctx b { color: var(--shell-ink); font-weight: 500; }
.bar-right { margin-left: auto; display: flex; align-items: center; gap: var(--s-3); padding: 0 var(--gutter) 0 var(--s-4); }
.appbar .btn { background: var(--shell-2); border-color: var(--shell-line); color: var(--shell-ink); }
.appbar .btn:hover { background: var(--shell-line); box-shadow: none; }
.appbar .progress { color: var(--shell-ink-2); font-size: var(--t-xs); }
.appbar .progress::before { border-color: var(--shell-line); border-top-color: var(--shell-ink); }
.appbar .freshness { color: var(--shell-ink-2); font-size: var(--t-xs); line-height: var(--lh-xs); }
.icon-btn { width: 30px; height: 30px; flex: none; display: grid; place-items: center; border: 1px solid transparent; border-radius: var(--r-sm); background: none; color: var(--shell-ink-2); cursor: pointer; }
.icon-btn svg { width: 16px; height: 16px; stroke-width: 1.75; }
.icon-btn:hover { background: var(--shell-2); color: var(--shell-ink); }
.icon-btn .i-light, .icon-btn .i-dark, .icon-btn .i-system { display: none; }
.icon-btn[data-mode="light"] .i-light, .icon-btn[data-mode="dark"] .i-dark, .icon-btn[data-mode="system"] .i-system { display: block; }

/* Account menu. The panel floats over the page, so it is a surface and carries page ink. */
.menu { position: relative; }
.menu-btn { display: flex; align-items: center; gap: var(--s-2); padding: var(--s-1) var(--s-2); border: 1px solid transparent; border-radius: var(--r-sm); background: none; color: var(--shell-ink); font: inherit; font-size: var(--t-sm); line-height: var(--lh-sm); cursor: pointer; }
.menu-btn:hover { background: var(--shell-2); }
.menu-btn .avatar { width: 26px; height: 26px; flex: none; display: grid; place-items: center; border-radius: 50%; background: var(--shell-2); border: 1px solid var(--shell-line); color: var(--shell-ink); font-size: var(--t-xs); font-weight: 600; }
.menu-btn svg { width: 14px; height: 14px; color: var(--shell-ink-2); stroke-width: 2; }
.menu-panel { position: absolute; right: 0; top: calc(100% + var(--s-2)); min-width: 224px; padding: var(--s-2); background: var(--surface); border: 1px solid var(--line); border-radius: var(--r-md); box-shadow: var(--lift); display: none; z-index: 40; }
.menu.open .menu-panel { display: block; }
.menu-head { padding: var(--s-2) var(--s-3) var(--s-3); border-bottom: 1px solid var(--line); margin-bottom: var(--s-2); }
.menu-head b { display: block; font-weight: 500; font-size: var(--t-sm); line-height: var(--lh-sm); color: var(--ink); }
.menu-head small { display: block; color: var(--ink-3); font-size: var(--t-xs); line-height: var(--lh-xs); word-break: break-all; }
.menu-head .badge { margin-top: var(--s-2); }
.menu-panel a, .menu-panel button { display: block; width: 100%; text-align: left; padding: var(--s-2) var(--s-3); border: 0; border-radius: var(--r-sm); background: none; color: var(--ink-2); font: inherit; font-size: var(--t-sm); line-height: var(--lh-sm); cursor: pointer; }
.menu-panel a:hover, .menu-panel button:hover { background: var(--surface-2); color: var(--ink); text-decoration: none; }
.menu-panel form { margin: 0; }

.rail { background: var(--shell); color: var(--shell-ink); border-right: 1px solid var(--shell-line); position: sticky; top: var(--bar); height: calc(100vh - var(--bar)); display: flex; flex-direction: column; padding: var(--s-4) 0; overflow-y: auto; }
.nav { display: flex; flex-direction: column; gap: 2px; padding: 0 var(--s-3); }
.nav a span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.nav a { display: flex; align-items: center; gap: var(--s-3); padding: var(--s-2) var(--s-3); color: var(--shell-ink-2); border-radius: var(--r-sm); font-size: var(--t-sm); line-height: 20px; }
.nav a svg { width: 16px; height: 16px; flex: none; stroke-width: 1.75; }
.nav a:hover { background: var(--shell-2); color: var(--shell-ink); text-decoration: none; }
.nav a.active { background: var(--accent-wash); color: var(--accent); font-weight: 500; }
.nav a.active svg { stroke-width: 2; }
.nav .group { padding: var(--s-4) var(--s-3) var(--s-1); font-size: var(--t-xs); color: var(--shell-ink-2); opacity: .7; }
/* Collapsed: icons only, group labels become the hairline they were standing in for, and every link
   keeps its title so the name is one hover away. */
.rail-foot { margin-top: auto; padding: var(--s-3) var(--s-3) 0; }
.rail-toggle { display: flex; align-items: center; gap: var(--s-3); width: 100%; padding: var(--s-2) var(--s-3); border: 0; border-radius: var(--r-sm); background: none; color: var(--shell-ink-2); font: inherit; font-size: var(--t-sm); line-height: 20px; cursor: pointer; }
.rail-toggle:hover { background: var(--shell-2); color: var(--shell-ink); }
.rail-toggle svg { width: 16px; height: 16px; flex: none; stroke-width: 1.75; }
:root[data-rail="min"] .rail-toggle svg { transform: scaleX(-1); }
:root[data-rail="min"] .nav a, :root[data-rail="min"] .rail-toggle { justify-content: center; padding-inline: 0; }
:root[data-rail="min"] .nav a span, :root[data-rail="min"] .rail-toggle span { display: none; }
:root[data-rail="min"] .nav .group { height: 1px; margin: var(--s-3) var(--s-3); padding: 0; overflow: hidden; background: var(--shell-line); color: transparent; }
:root[data-rail="min"] .appbar .brand { padding-inline: 0; justify-content: center; }
:root[data-rail="min"] .brand .name { display: none; }

.freshness { display: flex; align-items: center; gap: var(--s-2); }
.freshness .dot { width: 7px; height: 7px; border-radius: 50%; background: var(--good); flex: none; }
.freshness.stale .dot { background: var(--warn); }
.main { min-width: 0; display: flex; flex-direction: column; }
.content { flex: 1; width: 100%; max-width: var(--content-max); padding: var(--s-5) var(--gutter) var(--s-6); }

/* Settings sections: the page shows one section at a time, so the list of sections is the page's own
   navigation. It reads as page furniture, not as the rail: page ink, page surfaces. */
.settings { display: grid; grid-template-columns: 224px minmax(0, 1fr); gap: var(--s-4); align-items: start; }
/* A grid item's default min-width is its content, so without this the panel widens to the widest table and
   pushes the page sideways instead of letting .tbl-wrap scroll. */
.settings > * { min-width: 0; }
.subnav { display: flex; flex-direction: column; gap: 2px; position: sticky; top: calc(var(--bar) + var(--s-5)); }
.subnav a { display: flex; align-items: center; justify-content: space-between; gap: var(--s-2); padding: var(--s-2) var(--s-3); border-radius: var(--r-sm); color: var(--ink-2); font-size: var(--t-sm); line-height: var(--lh-sm); }
.subnav a:hover { background: var(--surface-2); color: var(--ink); text-decoration: none; }
.subnav a.active { background: var(--accent-wash); color: var(--accent); font-weight: 500; }
.subnav.across { flex-direction: row; position: static; margin-bottom: var(--s-4); }
.subnav .count { font-family: var(--mono); font-variant-numeric: tabular-nums; font-size: var(--t-xs); color: var(--ink-3); }
.subnav a.active .count { color: var(--accent); }

/* The person's own week, a day at a time. A day with nothing on it is stated, not coloured: this is
   somebody's own record, and the palette does not judge people (docs/design-system.md, Don'ts). */
.week { display: grid; grid-template-columns: repeat(auto-fit, minmax(96px, 1fr)); gap: var(--s-2); }
.week .day { border: 1px solid var(--line); border-radius: var(--r-sm); padding: var(--s-3); display: flex; flex-direction: column; gap: 2px; }
.week .day.gap { border-style: dashed; background: var(--surface-2); }
.week .dow { font-size: var(--t-xs); line-height: var(--lh-xs); color: var(--ink-3); }
.week .v { font-family: var(--mono); font-variant-numeric: tabular-nums; font-size: var(--t-lg); line-height: var(--lh-lg); color: var(--ink); }
.week .sub { font-size: var(--t-xs); line-height: var(--lh-xs); color: var(--ink-3); }

/* What the ticket says, quoted rather than copied: it is Jira's text, shown so the person does not have to
   go and read it, and never written into a field of ours. */
.ticket { background: var(--surface-2); border: 1px solid var(--line); border-radius: var(--r-md); padding: var(--s-3) var(--s-4); margin-bottom: var(--s-4); font-size: var(--t-sm); line-height: var(--lh-sm); }
.ticket strong { font-family: var(--mono); font-weight: 500; }
.ticket .prov { color: var(--ink-3); font-size: var(--t-xs); line-height: var(--lh-xs); margin-top: var(--s-2); }

/* Page foot: where the figures come from and how fresh they are. Quiet, and it never repeats the rail's
   navigation. Its rule lines up with the content edges. */
.appfoot { margin: 0 var(--gutter); max-width: calc(var(--content-max) - 2 * var(--gutter)); padding: var(--s-4) 0 var(--s-5); border-top: 1px solid var(--line); display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: var(--s-2) var(--s-5); color: var(--ink-3); font-size: var(--t-xs); line-height: var(--lh-xs); }
.appfoot b { color: var(--ink-2); font-weight: 500; }

.page-head { display: flex; flex-wrap: wrap; align-items: baseline; gap: var(--s-3) var(--s-4); margin-bottom: var(--s-5); }
.page-head h1 { margin-right: auto; }
.page-head .sub { flex-basis: 100%; color: var(--ink-2); font-size: var(--t-sm); line-height: var(--lh-sm); max-width: 100ch; }

/* Period selector */
.period { display: flex; flex-wrap: wrap; align-items: center; gap: var(--s-1); max-width: 100%; }
.period a, .period span.cur { padding: var(--s-1) var(--s-2); border-radius: var(--r-sm); color: var(--ink-2); font-size: var(--t-sm); line-height: var(--lh-sm); }
.period a:hover { background: var(--surface-2); text-decoration: none; color: var(--ink); }
.period span.cur { color: var(--ink); font-weight: 500; }
.period form { display: inline-flex; gap: var(--s-1); align-items: center; }
.period input[type="month"], .period select { font: inherit; font-size: var(--t-sm); padding: 2px var(--s-2); border: 1px solid var(--line-2); border-radius: var(--r-sm); background: var(--surface); color: var(--ink); }

/* KPI tiles - value, label, what it is based on, and a coverage hairline. */
.kpis { display: grid; grid-template-columns: repeat(auto-fit, minmax(190px, 1fr)); gap: var(--s-3); margin-bottom: var(--s-5); }
@media (min-width: 1340px) { .kpis { grid-template-columns: repeat(6, minmax(0, 1fr)); } }
.kpi { background: var(--surface); border: 1px solid var(--line); border-radius: var(--r-md); padding: var(--s-4) var(--s-4) var(--s-3); display: flex; flex-direction: column; min-height: 132px; }
.kpi .v { font-variant-numeric: tabular-nums; font-size: var(--t-kpi); line-height: var(--lh-kpi); font-weight: 600; letter-spacing: -0.025em; }
.kpi .l { font-size: var(--t-sm); line-height: var(--lh-sm); color: var(--ink); margin-top: 2px; }
.kpi .prov { margin-top: auto; padding-top: var(--s-3); }
.kpi .delta { font-family: var(--mono); font-size: var(--t-xs); margin-left: var(--s-2); color: var(--ink-3); }
.kpi .delta.up { color: var(--good); }
.cov { height: 3px; background: var(--line); margin-top: var(--s-3); border-radius: 2px; overflow: hidden; }
.cov i { display: block; height: 100%; background: var(--accent); }
.cov.low i { background: var(--age-3); }

/* Any figure outside a table cell that should read as a measurement. */
.num { font-family: var(--mono); font-variant-numeric: tabular-nums; }

/* Where the time goes: width is duration, colour is which group owns the stage. */
.flow-bar { display: flex; height: 34px; border-radius: var(--r-sm); overflow: hidden; background: var(--surface-2); }
.flow-bar span { display: block; transition: filter 120ms linear; }
.flow-bar span:hover { filter: brightness(1.08); }
.flow-bar .approval { background: var(--stage-approval); }
.flow-bar .dev { background: var(--stage-dev); }
.flow-bar .testing { background: var(--stage-testing); }
.flow-bar .waiting { background: var(--stage-waiting); }
.flow-key { display: flex; flex-wrap: wrap; gap: var(--s-2) var(--s-5); margin-top: var(--s-3); font-size: var(--t-sm); }
.flow-key div { display: flex; align-items: baseline; gap: var(--s-2); }
.flow-key i { width: 9px; height: 9px; border-radius: 2px; flex: none; transform: translateY(1px); }
.flow-key b { font-family: var(--mono); font-weight: 500; font-variant-numeric: tabular-nums; }
.flow-key span { color: var(--ink-2); }

/* An age reads as heat, so the eye finds the old rows without reading every number. */
.age { display: inline-block; padding: 1px var(--s-2); border-radius: 3px; font-family: var(--mono); font-variant-numeric: tabular-nums; }
.age.a1 { background: var(--age-1); color: var(--age-ink-lo); }
.age.a2 { background: var(--age-2); color: var(--age-ink-lo); }
.age.a3 { background: var(--age-3); color: var(--age-ink-hi); }
.age.a4 { background: var(--age-4); color: var(--age-ink-hi); }
.age.a5 { background: var(--age-5); color: var(--age-ink-hi); }

/* Layout helpers */
.grid-2 { display: grid; grid-template-columns: 7fr 5fr; gap: var(--s-4); align-items: start; }
.grid-2 > *, .stack > *, .kpis > * { min-width: 0; }
.stack > * + * { margin-top: var(--s-4); }
.card { background: var(--surface); border: 1px solid var(--line); border-radius: var(--r-md); padding: var(--s-5) 0; }
.card > *:not(.tbl-wrap):not(table) { padding-left: var(--s-5); padding-right: var(--s-5); }
/* A bordered box inside a card is inset by margin, so its edge lines up with the text rather than the card. */
.card > .notice { margin-left: var(--s-5); margin-right: var(--s-5); }
.card > .tbl-wrap + .prov, .card > table + .prov { margin-top: var(--s-3); }

/* Facts: a few labelled values read across a row - the state of something before its history. */
.facts { display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: var(--s-4) var(--s-5); margin: 0 0 var(--s-5); }
.facts dt { color: var(--ink-3); font-size: var(--t-xs); line-height: var(--lh-xs); margin-bottom: var(--s-1); }
.facts dd { margin: 0; font-size: var(--t-md); line-height: var(--lh-md); color: var(--ink); }
.facts dd.muted { font-size: var(--t-sm); line-height: var(--lh-sm); color: var(--ink-2); margin-top: 2px; }

/* Help: setup detail most visits do not need, one click away instead of in the way. */
details.help { margin-top: var(--s-4); font-size: var(--t-sm); line-height: var(--lh-sm); color: var(--ink-2); }
details.help summary { cursor: pointer; color: var(--accent); width: fit-content; }
details.help ul { margin: var(--s-2) 0 0; padding-left: 1.2em; }
details.help li + li { margin-top: var(--s-1); }

/* A message exactly as it will be sent: line breaks and markup kept, so what the admin sees is what arrives. */
.ticket.digest { white-space: pre-wrap; font-size: var(--t-sm); line-height: var(--lh-sm); }
.ticket.digest strong { font-family: var(--font); font-weight: 600; }
.card h2, .card h3 { margin-bottom: var(--s-4); letter-spacing: -0.015em; }
.card-head { display: flex; align-items: baseline; justify-content: space-between; gap: var(--s-3); margin-bottom: var(--s-4); }
.card-head h2 { margin-bottom: 0; }
.card > .row.spread:first-child { margin-bottom: var(--s-3); }
.card > .row.spread:first-child h2 { margin-bottom: 0; }
.card .prov { color: var(--ink-3); font-size: var(--t-xs); line-height: var(--lh-xs); margin-top: var(--s-3); }
.row { display: flex; flex-wrap: wrap; gap: var(--s-2) var(--s-3); align-items: center; }
.row select, .row input[type="text"], .row input[type="email"], .row input[type="date"], .row input[type="month"] { width: auto; min-width: 8rem; }
form.row { gap: var(--s-2); }
.row input.grow { flex: 1 1 16rem; width: auto; }
.tbl.edit td.stack-dates input { display: block; width: auto; }
.tbl.edit td.stack-dates input + input { margin-top: var(--s-1); }
.reading { margin-top: var(--s-2); padding-top: var(--s-2); border-top: 1px solid var(--line); }
.reading > div { margin-top: var(--s-1); }
.notice form.row { margin-top: var(--s-2); }
.spread { justify-content: space-between; }

/* Tables */
.tbl-wrap { overflow-x: auto; }
table.tbl { width: 100%; border-collapse: collapse; font-size: var(--t-sm); line-height: var(--lh-sm); }
.tbl th, .tbl td { padding: var(--s-3); border-bottom: 1px solid var(--line); text-align: left; vertical-align: baseline; }
.tbl th { position: sticky; top: var(--bar); z-index: 1; background: var(--surface); color: var(--ink-3); font-weight: 500; white-space: nowrap; font-size: var(--t-xs); border-bottom-color: var(--line-2); }
.tbl th:first-child, .tbl td:first-child { padding-left: var(--s-5); }
.tbl th:last-child, .tbl td:last-child { padding-right: var(--s-5); }

/* A hairline before a column group: which figures belong together is information, not decoration. */
.tbl th.group, .tbl td.group { border-left: 1px solid var(--line); }
.tbl th.n, .tbl td.n { text-align: right; white-space: nowrap; }
.tbl td.n { font-family: var(--mono); font-variant-numeric: tabular-nums; }
.tbl tbody tr { transition: background 90ms linear; }
.tbl tbody tr:hover { background: var(--accent-wash); }
.tbl tbody tr:hover td:first-child { box-shadow: inset 2px 0 0 var(--accent); }
/* The row a dialog is about, so it can be found again once the dialog closes. */
.tbl tbody tr.target { background: var(--accent-wash); }
.tbl tbody tr.target td:first-child { box-shadow: inset 2px 0 0 var(--accent); }
.tbl .sub.block, .tbl td .sub { font-family: var(--font); font-variant-numeric: normal; font-weight: 400; }
.tbl tfoot td { border-top: 1px solid var(--line-2); border-bottom: 0; background: var(--surface); }
.tbl tfoot td { font-weight: 500; }
.tbl .sub { color: var(--ink-3); font-size: var(--t-xs); }
.tbl a.sort { color: inherit; }
.tbl a.sort.on::after { content: " ↓"; color: var(--accent); }
.tbl a.sort.on.asc::after { content: " ↑"; }
.tbl td.t { max-width: clamp(16ch, 12vw, 44ch); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.tbl td.nw { white-space: nowrap; }

/* `.tbl-wrap` scrolls, which makes it the sticky header's containing block: measured from the wrapper, the
   app-bar offset is 52px of nothing that lands on top of the first row. Only an unwrapped table, which does
   stick to the viewport, needs to clear the bar. */
.tbl-wrap .tbl th { top: 0; }
.sub.block { display: block; font-weight: 400; }
/* Help under a form field: secondary, and never the size of the answer it explains. */
.field .sub { color: var(--ink-2); font-size: var(--t-sm); line-height: var(--lh-sm); }
.tbl th .sub.block { color: var(--ink-3); }

/* Badges: group + hygiene (always icon + text, never colour alone) */
.badge { display: inline-block; padding: 0 var(--s-2); border-radius: var(--r-sm); font-size: var(--t-xs); line-height: 18px; border: 1px solid var(--line-2); color: var(--ink-2); white-space: nowrap; }
.badge.warn { border-color: var(--warn); }
.badge.serious { border-color: var(--serious); }
.badge.critical { border-color: var(--critical); color: var(--critical); }
.badge.good { border-color: var(--good); color: var(--good); }
.badge.accent { border-color: var(--accent); color: var(--accent); }
.pill { display: inline-flex; align-items: center; gap: 5px; padding: 1px var(--s-2); border-radius: 20px; font-size: var(--t-xs); line-height: 18px; border: 1px solid var(--line-2); color: var(--ink-2); white-space: nowrap; }
.pill::before { content: ""; width: 6px; height: 6px; border-radius: 50%; background: currentColor; flex: none; }
.pill.warn { border-color: var(--warn); color: var(--warn); }
.pill.ok { border-color: var(--good); color: var(--good); }

/* Buttons and forms */
.btn { display: inline-block; font: inherit; font-size: var(--t-sm); line-height: var(--lh-sm); padding: var(--s-2) var(--s-4); border-radius: var(--r-sm); border: 1px solid var(--line-2); background: var(--surface); color: var(--ink); cursor: pointer; text-decoration: none; }
.btn:hover { background: var(--surface-2); text-decoration: none; box-shadow: var(--lift); }
.btn.primary { background: var(--accent); border-color: var(--accent); color: var(--accent-ink); }
.btn.primary:hover { filter: brightness(1.08); }
.btn.danger { border-color: var(--critical); color: var(--critical); }
.btn:disabled { opacity: 0.6; cursor: default; }
.btn.sm { padding: 2px var(--s-3); }
.btn.lg { padding: var(--s-3) var(--s-4); font-size: var(--t-md); line-height: var(--lh-md); }
.btn.block { display: block; width: 100%; text-align: center; }
label { display: block; font-size: var(--t-sm); line-height: var(--lh-sm); color: var(--ink-2); margin-bottom: var(--s-1); }
input[type="text"], input[type="email"], input[type="password"], input[type="search"], input[type="number"], input[type="date"], input[type="month"], select, textarea { font: inherit; font-size: var(--t-sm); padding: var(--s-2) var(--s-3); border: 1px solid var(--line-2); border-radius: var(--r-sm); background: var(--surface); color: var(--ink); width: 100%; max-width: 100%; }
textarea { min-height: 120px; line-height: var(--lh-sm); }
input:focus-visible, select:focus-visible, textarea:focus-visible { outline-offset: 0; border-color: var(--accent); }
input::placeholder, textarea::placeholder { color: var(--ink-3); }
.field { margin-bottom: var(--s-4); }
.field.inline { display: inline-block; margin-right: var(--s-4); }
.field.inline input, .field.inline select { width: auto; }
.form-row { display: grid; grid-template-columns: repeat(auto-fit, minmax(180px, 1fr)); gap: var(--s-3); }
/* A group of related settings, framed the same quiet way as a notice so it reads as one decision. */
fieldset.rules { border: 1px solid var(--line); border-radius: var(--r-md); padding: var(--s-3) var(--s-4); }
fieldset.rules legend { padding: 0 var(--s-1); font-size: var(--t-sm); color: var(--ink); font-weight: 500; }
fieldset.rules .check { margin: var(--s-2) 0; }
.check { display: inline-flex; align-items: center; gap: var(--s-1); margin-right: var(--s-3); color: var(--ink); font-size: var(--t-sm); }
.tbl select, .tbl input[type="text"], .tbl input[type="date"], .tbl input[type="number"] { padding: 2px var(--s-2); }
.tbl input[type="number"] { max-width: 6rem; }
.tbl input[type="date"] { max-width: 9.5rem; width: 8.5rem; }
.tbl.edit input[type="date"] { width: 7.5rem; }
.tbl.edit select { min-width: 8.5rem; }
/* A short, fixed set of options: as wide as the longest one, so an eight-column grid still fits at 1366px. */
.tbl.edit select.fit { min-width: 0; width: auto; }

/* An edit grid is a table of controls, not of readings: the controls carry their own height, so the cell
   padding that suits text rows turns 25 rows into a page and a half of scrolling. */
.tbl.edit td { padding-top: var(--s-2); padding-bottom: var(--s-2); }
/* Across as well: the controls bring their own inner padding, so the text-row gutter doubles it. This is what
   keeps People's seven columns inside 1366px. The card edges keep their inset. */
.tbl.edit th, .tbl.edit td { padding-left: var(--s-2); padding-right: var(--s-2); }
.tbl.edit th:first-child, .tbl.edit td:first-child { padding-left: var(--s-5); }
.tbl.edit th:last-child, .tbl.edit td:last-child { padding-right: var(--s-5); }
.tbl.edit textarea { padding: var(--s-1) var(--s-2); }
.tbl.edit input[type="number"] { width: 4.25rem; max-width: 4.25rem; }
/* A field with its own Save in one cell (Portal accounts: the email). The pair stays on one line; wrapped, the
   button doubles every row's height. The width fits a whole work address. */
.tbl.edit form.row { flex-wrap: nowrap; }
.tbl.edit input.email { width: 16rem; padding: 2px var(--s-2); }
.tbl.edit textarea.alias { width: 5rem; min-height: 1.875rem; }
/* A table's filter bar: the fields above an edit grid, applied with a button rather than on change, because a
   select that submitted itself would throw away the grid's unsaved edits. */
form.filters { margin: var(--s-4) 0 var(--s-3); }
form.filters .check { margin-right: 0; }
/* The same height as the small buttons beside them: a filter bar is a line of controls, not a form to fill in. */
form.filters input[type="text"], form.filters select { padding: var(--s-1) var(--s-2); min-width: 0; }
form.filters input[type="text"] { width: 12rem; }
/* A work timer under the hours field: one small button, accent while it runs. */
.timer { margin-top: var(--s-1); }
.timer .btn.on { border-color: var(--accent); color: var(--accent); }
.tbl .t { display: inline-block; max-width: clamp(16ch, 12vw, 44ch); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; vertical-align: bottom; }

/* Messages, empty states, progress */
.notice { padding: var(--s-3) var(--s-4); border: 1px solid var(--line-2); border-radius: var(--r-md); background: var(--surface); font-size: var(--t-sm); line-height: var(--lh-sm); margin-bottom: var(--s-4); }
.notice.ok { border-color: var(--good); }
.notice.err { border-color: var(--critical); }
.notice.warn { border-color: var(--warn); }
.notice .problems { margin: var(--s-2) 0 var(--s-2); padding-left: 1.2em; }
.notice .problems li + li { margin-top: var(--s-1); }

/* Dialog: a question the person has to answer before the save goes ahead. Native <dialog> opened modal, so
   focus is trapped and Escape closes it. The top rule carries the hygiene colour; the heading carries the words. */
.dialog { width: min(var(--dialog-w), calc(100vw - 2 * var(--gutter))); padding: 0; border: 1px solid var(--line); border-top: 3px solid var(--warn); border-radius: var(--r-md); background: var(--surface); color: var(--ink); box-shadow: var(--lift); }
.dialog.err { border-top-color: var(--critical); }
.dialog::backdrop { background: var(--scrim); }
.dialog-body { padding: var(--s-5) var(--s-5) var(--s-4); }
.dialog-head { display: flex; align-items: center; gap: var(--s-3); }
.dialog-head h2 { margin: 0; }
.dialog-icon { flex: none; display: grid; place-items: center; width: var(--s-5); height: var(--s-5); border-radius: 50%; border: 2px solid currentColor; color: var(--warn); font-size: var(--t-sm); font-weight: 600; line-height: 1; }
.dialog.err .dialog-icon { color: var(--critical); }
.dialog-subject { margin-top: var(--s-4); padding: var(--s-2) var(--s-3); border-radius: var(--r-sm); background: var(--surface-2); font-size: var(--t-sm); line-height: var(--lh-sm); overflow-wrap: anywhere; }
.dialog-subject .sub { margin-top: var(--s-1); color: var(--ink-2); }
.dialog .problems { margin: var(--s-4) 0 0; padding-left: 1.2em; font-size: var(--t-sm); line-height: var(--lh-sm); }
.dialog .problems li + li { margin-top: var(--s-2); }
.dialog-actions { display: flex; justify-content: flex-end; flex-wrap: wrap; gap: var(--s-2); padding: var(--s-3) var(--s-5); border-top: 1px solid var(--line); }

/* Inline status next to a field: colour plus the glyph already in the text, never colour alone. */
.good { color: var(--good); }
.bad { color: var(--critical); }
.attention { color: var(--serious); }
.jira-result { min-height: 1.3em; margin: calc(-1 * var(--s-2)) 0 var(--s-4); font-size: var(--t-sm); line-height: var(--lh-sm); }

/* The short list of rules beside the entry form. */
.rules { padding-left: 1.2em; margin: 0; font-size: var(--t-sm); line-height: var(--lh-sm); color: var(--ink-2); }
.rules li + li { margin-top: var(--s-2); }
.rules strong { color: var(--ink); }
.empty { padding: var(--s-6) var(--s-4); text-align: center; color: var(--ink-2); }

/* Pager: where you are in the list matters more than the page number, so the row count leads. */
.pager { display: flex; align-items: center; justify-content: flex-end; gap: var(--s-3); margin-top: var(--s-3); font-size: var(--t-sm); }
.empty .btn { margin-top: var(--s-3); }
.progress { display: inline-flex; align-items: center; gap: var(--s-2); color: var(--ink-2); font-size: var(--t-sm); }
.progress::before { content: ""; width: 12px; height: 12px; border: 2px solid var(--line-2); border-top-color: var(--accent); border-radius: 50%; animation: spin 0.9s linear infinite; }
@keyframes spin { to { transform: rotate(360deg); } }

/* Charts */
.chart { position: relative; height: 220px; }
.chart.tall { height: 300px; }
.chart-foot { display: flex; justify-content: space-between; align-items: center; margin-top: var(--s-2); }
.chart-foot small { color: var(--ink-3); }
.chart-table { display: none; }
.chart-table.show { display: block; margin-top: var(--s-2); }
.chart-table.show + .chart, .charts-as-table .chart { display: none; }
.legend { display: flex; flex-wrap: wrap; gap: var(--s-1) var(--s-3); font-size: var(--t-xs); color: var(--ink-2); }
.legend i { display: inline-block; width: 10px; height: 10px; border-radius: 2px; margin-right: var(--s-1); vertical-align: -1px; }

/* Report view */
.report { max-width: var(--prose-max); }
.page-head .sub { max-width: 110ch; }
.report h1 { margin-bottom: var(--s-2); }
.report h2 { margin: var(--s-6) 0 var(--s-3); padding-top: var(--s-3); border-top: 1px solid var(--line); }
.report h3 { margin: var(--s-4) 0 var(--s-2); }
.report table { width: 100%; border-collapse: collapse; font-size: var(--t-sm); margin: var(--s-3) 0; }
.report th, .report td { padding: var(--s-1) var(--s-2); border-bottom: 1px solid var(--line); text-align: left; vertical-align: top; }
.report th { color: var(--ink-2); font-weight: 500; }
.report td:not(:first-child), .report th:not(:first-child) { text-align: right; font-variant-numeric: tabular-nums; }
.report blockquote { margin: 0 0 var(--s-3); padding: var(--s-2) var(--s-4); border-left: 2px solid var(--accent); color: var(--ink-2); }
.report ul { padding-left: 1.2em; }
.report li { margin-bottom: var(--s-1); }
.report hr { border: 0; border-top: 1px solid var(--line); margin: var(--s-5) 0; }

/* Responsive */
/* Below 1500 px the 7/5 split leaves the person table too narrow to show its columns;
   one column per row keeps every figure visible and gives the charts the full width. */
@media (max-width: 1499px) {
  .grid-2 { grid-template-columns: 1fr; }
  .settings { grid-template-columns: 1fr; }
  /* Wraps rather than scrolls: nine Settings sections do not fit one row at 1366px, and a sideways scroll hid
     the last one without a hint it was there. */
  .subnav { position: static; flex-direction: row; flex-wrap: wrap; padding-bottom: var(--s-1); }
  .subnav a { white-space: nowrap; }

  /* Two title columns side by side are what pushes the eight-column Items table past its wrap at 1366 px.
     They are the only elastic columns, so they give up the width rather than the figures. */
  .tbl .t { max-width: clamp(14ch, 8vw, 30ch); }
}

/* The bar loses the parts that repeat what the page already says before it loses the account menu. */
@media (max-width: 1199px) {
  .ctx { display: none; }
}

@media (max-width: 899px) {
  .shell { grid-template-columns: 1fr; grid-template-rows: var(--bar) auto 1fr; }
  .appbar .brand { width: auto; border-right: 0; padding: 0 var(--s-4) 0 var(--gutter); }
  .appbar .brand small, .appbar .freshness { display: none; }
  .menu-btn .who { display: none; }
  .rail { position: static; height: auto; flex-direction: row; align-items: center; padding: var(--s-3) var(--gutter); gap: var(--s-2); overflow-x: auto; border-right: 0; border-bottom: 1px solid var(--shell-line); }
  .nav { flex-direction: row; padding: 0; }
  .nav a { white-space: nowrap; }
  .nav .group, .rail-foot { display: none; }
  .tbl th { top: 0; }
  .appfoot { flex-direction: column; align-items: flex-start; }
  .grid-2 { grid-template-columns: 1fr; }
  .tbl td.t { max-width: 26ch; }
  .period input[type="month"] { display: none; }
  .content { overflow-x: hidden; }
  .kpis { grid-template-columns: repeat(2, 1fr); }
}

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

/* Sign-in and other chrome-less pages. The brand sits above the card, so the card holds nothing but the
   two fields and the action - the shortest path from landing to signed in. */
body.bare { display: flex; align-items: center; justify-content: center; min-height: 100vh; padding: var(--s-6) var(--s-4); }
.signin { width: 100%; max-width: 380px; }
.signin > .brand { margin-bottom: var(--s-5); }
.signin > .brand .mark { width: 32px; height: 32px; font-size: var(--t-md); }
.signin > .brand .name { color: var(--ink); font-size: var(--t-lg); }
.signin > .brand small { color: var(--ink-3); }
.signin-card { background: var(--surface); border: 1px solid var(--line); border-radius: var(--r-md); padding: var(--s-6); box-shadow: var(--lift); }
.signin-card h1 { font-size: var(--t-lg); line-height: var(--lh-lg); margin-bottom: var(--s-1); }
.signin-card > .muted { margin-bottom: var(--s-5); }
.signin-card .notice { margin-bottom: var(--s-4); }
.signin-card .field { margin-bottom: var(--s-4); }
.signin-card label { color: var(--ink); margin-bottom: var(--s-2); }
.signin-card input { padding: var(--s-3); font-size: var(--t-md); }
.signin-card .btn { margin-top: var(--s-2); }
.signin-note { margin: var(--s-5) 0 0; color: var(--ink-3); font-size: var(--t-xs); line-height: var(--lh-xs); }

/* A button that reads as a link: sign out inside the account menu is a form post, not a link. */
.linkish { color: var(--accent); font-size: var(--t-xs); background: none; border: 0; padding: 0; cursor: pointer; text-align: left; font-family: inherit; }
.linkish:hover { text-decoration: underline; }
