/* Design tokens (SU1-02, #373; final-spec §3.1; the Signal look, AI1-04 #692): every literal
	colour on every page lives in this first :root as one hex token, in GAIT's one light scheme
	(#1601); every text pair passes WCAG AA and --border-strong passes 3:1 on --surface and --bg
	(tests/unit/test_colour_tokens.py). A colour token's name is letters and hyphens only, and a
	gradient is built from var() stops, never stored with a literal (amendment 1). */
:root {
	color-scheme: light;

	/* Surfaces */
	--bg: #f5f7fb;
	--surface: #ffffff;
	--tint: #eef1f6;
	/* The document as paper on a desk */
	--desk: #e6eaf1;
	--paper: #ffffff;
	--paper-ink: #151a24;

	/* Ink */
	--fg: #0b1220;
	--muted: #586176;
	--border: #e4e8f0;
	--border-strong: #808a9d;

	/* Accent: cobalt, the one "act here" colour; never an outcome */
	--accent: #2440e6;
	--accent-dark: #1b31b8;
	--accent-bg: #eef1ff;
	--on-accent: #ffffff;

	/* Error */
	--error: #be123c;
	--error-bg: #fff1f3;

	/* Tag pairs: release, redaction (clip), medium, withhold and high, escalate, neutral */
	--ok-fg: #047857;
	--ok-bg: #d1fae5;
	--clip-fg: #0e7490;
	--clip-bg: #cffafe;
	--warn-fg: #92400e;
	--warn-bg: #fef3c7;
	--bad-fg: #be123c;
	--bad-bg: #ffe4e9;
	--hold-fg: #86198f;
	--hold-bg: #fae8ff;
	--neutral-fg: #2e3647;
	--neutral-bg: #eef1f6;

	/* Highlights in document text */
	--mark: #fef3c7;
	--mark-strong: #ffe7a3;

	/* Signal stops (decoration only: no text on --grad-signal) and deep stops (--on-deep text) */
	--signal-start: #2440e6;
	--signal-mid: #0ea5e9;
	--signal-end: #18d3a4;
	--deep-start: #1f3ad6;
	--deep-mid: #0a6fb8;
	--deep-end: #087a66;
	--on-deep: #ffffff;

	/* Shadow ink, used only through color-mix */
	--shadow-ink: #0f1115;

	/* Derived */
	--bg-clear: color-mix(in srgb, var(--surface) 0%, transparent);
	--edge-shade: color-mix(in srgb, var(--fg) 14%, transparent);
	--edge-clear: color-mix(in srgb, var(--fg) 0%, transparent);
	/* The ink of the home page's drawn sheet (SU-3): its lines, then its titles and labels. */
	--sheet-ink: color-mix(in srgb, var(--fg) 15%, transparent);
	--sheet-ink-strong: color-mix(in srgb, var(--fg) 28%, transparent);
	/* Gradients from the stops above, used only where amendment 1 names. */
	--grad-signal: linear-gradient(90deg, var(--signal-start), var(--signal-mid) 52%,
		var(--signal-end));
	--grad-deep: linear-gradient(110deg, var(--deep-start), var(--deep-mid) 55%, var(--deep-end));
	--grad-ring: conic-gradient(from 0deg, var(--signal-start), var(--signal-mid),
		var(--signal-end), var(--signal-start));
	/* The three shadows (amendment 1): the account menu; the document page and the home sheet;
		the thread's progress block. Nothing else casts one. */
	--shadow-float: 0 2px 4px color-mix(in srgb, var(--shadow-ink) 8%, transparent),
		0 12px 28px color-mix(in srgb, var(--shadow-ink) 16%, transparent);
	--shadow-paper: 0 1px 2px color-mix(in srgb, var(--shadow-ink) 8%, transparent),
		0 10px 30px color-mix(in srgb, var(--shadow-ink) 8%, transparent);
	--shadow-lift: 0 1px 2px color-mix(in srgb, var(--shadow-ink) 6%, transparent),
		0 12px 32px color-mix(in srgb, var(--shadow-ink) 16%, transparent);

	/* Type (AI1-07): Geist, Geist Mono and Source Serif 4, self-hosted in static/ (licence in
		fonts-OFL.txt), each over the system stack; the serif is for document text only. */
	--font-sans: "Geist", ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto,
		"Helvetica Neue", "Noto Sans", Arial, sans-serif;
	--font-mono: "Geist Mono", ui-monospace, "SF Mono", "Cascadia Mono", "Segoe UI Mono", Menlo,
		Consolas, "Liberation Mono", monospace;
	--font-serif: "Source Serif 4", Georgia, "Times New Roman", serif;
	--mono: var(--font-mono);
	--text-xs: 0.75rem;
	--text-sm: 0.8125rem;
	--text-md: 0.875rem;
	--text-base: 0.9375rem;
	--text-lg: 1.0625rem;
	--text-lead: 1.125rem;
	--text-h3: 1rem;
	--text-h2: 1.25rem;
	--text-h1: 1.75rem;
	/* The home page h1 alone (SU-3): 36px on a phone, 60px from about 1180px wide. */
	--text-display: clamp(2.25rem, 1.4rem + 3.2vw, 3.75rem);
	--leading-tight: 1.25;
	--leading: 1.55;

	/* Space (4px grid) */
	--space-1: 0.25rem;
	--space-2: 0.5rem;
	--space-3: 0.75rem;
	--space-4: 1rem;
	--space-5: 1.25rem;
	--space-6: 1.5rem;
	--space-8: 2rem;
	--space-10: 2.5rem;
	--space-12: 3rem;
	--space-16: 4rem;

	/* Layout gaps (SU2-11, spec 2.2): the only gaps between blocks. A label and its field, a
		heading and its first line, items of one list; two sections of one region; regions. */
	--gap-group: 0.5rem;
	--gap-section: 1.5rem;
	--gap-region: 3rem;

	/* Radii */
	--radius-sm: 0.25rem;
	--radius: 0.375rem;
	--radius-md: 0.625rem;
	--radius-lg: 0.875rem;
	--radius-xl: 1.25rem;
	--radius-full: 999px;

	/* Controls */
	--control-h: 2.5rem;
	--control-h-lg: 2.75rem;

	/* Layout */
	--w-page: 75rem;
	--w-reading: 48rem;
	--w-form: 25rem;
	--gutter: 1rem;
	--gutter-lg: 2rem;
	--header-h: 3.5rem;

	/* Motion (amendment 1, AI1-10); --dur-fast, --dur and --ease are the older names. Every
		keyframe runs only under prefers-reduced-motion: no-preference (tests/unit/test_motion.py). */
	--dur-instant: 120ms;
	--dur-quick: 180ms;
	--dur-base: 240ms;
	--dur-slow: 360ms; /* the home caption ends at 850ms + 360ms (test_ui_quality.py pins it) */
	--dur-draw: 400ms;
	--ease-out: cubic-bezier(0.16, 1, 0.3, 1);
	--ease-in: cubic-bezier(0.4, 0, 1, 1);
	--ease-inout: cubic-bezier(0.65, 0, 0.35, 1);
	--dur-fast: var(--dur-instant);
	--dur: var(--dur-quick);
	--ease: var(--ease-out);

	/* Stacking */
	--z-skip: 100;
}

/* Fonts (AI1-07): variable Latin subsets from 'self' (the CSP's default-src covers them); swap
	keeps the system face on screen until a file arrives. */
@font-face { font-family: "Geist"; font-style: normal; font-weight: 100 900;
	font-display: swap; src: url("geist.woff2") format("woff2"); }
@font-face { font-family: "Geist Mono"; font-style: normal; font-weight: 100 900;
	font-display: swap; src: url("geist-mono.woff2") format("woff2"); }
@font-face { font-family: "Source Serif 4"; font-style: normal; font-weight: 200 900;
	font-display: swap; src: url("source-serif-4.woff2") format("woff2"); }

/* Base (final-spec §3.2): headings carry no margins; spacing comes from the container. */
*, *::before, *::after { box-sizing: border-box; }
html { scroll-padding-top: var(--space-4); -webkit-text-size-adjust: 100%; }
body { margin: 0; min-height: 100vh; display: flex; flex-direction: column;
	font-family: var(--font-sans); font-size: var(--text-base); line-height: var(--leading);
	color: var(--fg); background: var(--bg); -webkit-font-smoothing: antialiased; }
h1, h2, h3, h4 { margin: 0; line-height: var(--leading-tight); font-weight: 600;
	color: var(--fg); overflow-wrap: anywhere; }
h1 { font-size: var(--text-h1); font-weight: 650; letter-spacing: -0.02em; }
h2 { font-size: var(--text-h2); letter-spacing: -0.005em; }
h3 { font-size: var(--text-h3); }
h4 { font-size: var(--text-md); }
p { margin: 0; }
a, a:visited { color: var(--accent); text-decoration: underline;
	text-decoration-thickness: 1px; text-underline-offset: 0.18em; }
a:hover { color: var(--accent-dark); text-decoration-thickness: 2px; }
code, kbd, pre { font-family: var(--mono); font-size: 0.925em; }
kbd { padding: 0 var(--space-1); border: 1px solid var(--border-strong);
	border-radius: var(--radius-sm); background: var(--surface); font-size: var(--text-xs); }
::selection { background: var(--accent-bg); color: var(--fg); }
main { flex: 1 0 auto; width: 100%; margin: 0 auto; display: flex; flex-direction: column;
	gap: var(--gap-region); padding: var(--space-8) var(--gutter) 0; }
main.wide, main.landing { max-width: calc(var(--w-page) + 2 * var(--gutter)); }
main.intake { max-width: calc(var(--w-reading) + 2 * var(--gutter)); }
main.narrow { max-width: calc(var(--w-form) + 2 * var(--gutter)); }
@media (min-width: 48rem) {
	main { padding: var(--space-10) var(--gutter-lg) 0; }
	main.wide, main.landing { max-width: calc(var(--w-page) + 2 * var(--gutter-lg)); }
	main.intake { max-width: calc(var(--w-reading) + 2 * var(--gutter-lg)); }
	main.narrow { max-width: calc(var(--w-form) + 2 * var(--gutter-lg)); padding-top: var(--space-16); }
}
main:focus { outline: none; }
/* The shell (SU1-08): skip link, a static 56px top bar, the footer. */
.skip-link { position: fixed; left: var(--space-2); top: -4rem; z-index: var(--z-skip);
	padding: var(--space-2) var(--space-4); border-radius: var(--radius);
	background: var(--accent); color: var(--on-accent); text-decoration: none; }
.skip-link:focus { top: var(--space-2); }
/* AI1-07: a 3px signal line (decoration, never under text) above the bar; the gate glyph sits
	on a 26px deep tile; the nav's current item is a tint pill. */
.site-header { background: var(--surface); border-bottom: 1px solid var(--border); }
.site-header::before { content: ""; display: block; height: 3px; background: var(--grad-signal); }
.site-header-inner { max-width: calc(var(--w-page) + 2 * var(--gutter)); margin: 0 auto;
	height: var(--header-h); padding: 0 var(--gutter); display: flex; align-items: center;
	gap: var(--space-6); }
.brand, .brand:visited { flex: none; display: inline-flex; align-items: center;
	gap: 0.625rem; color: var(--fg); text-decoration: none; }
.brand-mark { flex: none; width: 1.625rem; height: 1.625rem; padding: 0.25rem;
	border-radius: 0.4375rem; background: var(--grad-deep); }
.brand-mark-gate { fill: none; stroke: var(--on-deep); stroke-width: 2.25;
	stroke-linecap: round; stroke-linejoin: round; }
.brand-name { font-size: var(--text-base); font-weight: 650; letter-spacing: 0.06em; }
.site-nav { flex: none; display: flex; align-items: center; gap: var(--space-4); }
.nav-links { list-style: none; margin: 0; padding: 0; display: flex; gap: var(--space-1); }
.nav-link, .nav-link:visited { display: inline-flex; align-items: center; height: 2rem;
	padding: 0 var(--space-3); border-radius: var(--radius-full); font-size: var(--text-md);
	font-weight: 500; color: var(--muted); text-decoration: none; white-space: nowrap;
	transition: color var(--dur-fast) var(--ease), background-color var(--dur-fast) var(--ease); }
.nav-link:hover { color: var(--fg); background: var(--tint); text-decoration: none; }
.nav-link[aria-current="page"] { color: var(--accent); background: var(--accent-bg); }
/* The account corner (SU2-07, spec 3.1-3.2): the name is a button that opens a popover panel
	(the UA puts it in the top layer, fixed); browsers without popover get a link to /account. */
.account { margin-left: auto; display: flex; align-items: center; gap: var(--space-3);
	min-width: 0; }
.account-guest { color: var(--muted); font-size: var(--text-sm); }
.account-link { display: none; }
.account-button { height: var(--control-h); min-width: var(--control-h); max-width: 100%;
	padding: 0 var(--space-2) 0 var(--space-3); gap: var(--space-1); color: var(--fg);
	background: transparent; font-weight: 500; }
.account-button:hover:not(:disabled), .account-button:has(+ :popover-open) {
	color: var(--fg); background: var(--tint); }
.account-name { min-width: 0; overflow: hidden; text-overflow: ellipsis; }
.account-chevron, .account-glyph { flex: none; fill: none; stroke: var(--muted);
	stroke-width: 1.5; stroke-linecap: round; stroke-linejoin: round; }
.account-glyph { display: none; stroke: var(--fg); }
/* Just under the bar: the signal line (3px) plus the bar, less a quarter rem. */
.account-panel { inset: auto; margin: 0; top: calc(var(--header-h) - 0.0625rem);
	right: max(var(--gutter), calc((100vw - var(--w-page)) / 2)); min-width: 14rem;
	padding: var(--space-2) 0; color: var(--fg); background: var(--surface);
	border: 1px solid var(--border); border-radius: var(--radius-md);
	box-shadow: var(--shadow-float); }
.account-who { margin: 0; padding: var(--space-2) var(--space-4) var(--space-3);
	display: flex; flex-direction: column; border-bottom: 1px solid var(--border); }
.account-who-name { font-weight: 600; overflow-wrap: anywhere; }
.account-who-role { color: var(--muted); font-size: var(--text-sm); }
.account-items { list-style: none; margin: 0; padding: var(--space-2) 0;
	border-bottom: 1px solid var(--border); }
.account-signout { margin: 0; padding-top: var(--space-2); }
.account-items a, .account-signout button.quiet { display: flex; align-items: center;
	justify-content: flex-start; width: 100%; height: var(--control-h-lg);
	padding: 0 var(--space-4); border: 0; border-radius: 0; color: var(--fg);
	font-size: var(--text-md); font-weight: 400; text-decoration: none; outline-offset: -2px; }
.account-items a:hover { background: var(--tint); text-decoration: none; }
@supports not selector(:popover-open) {
	.account-button, .account-panel { display: none; }
	.account-link { display: inline; }
}
.site-footer { margin-top: var(--space-16); border-top: 1px solid var(--border); }
.site-footer-inner { max-width: calc(var(--w-page) + 2 * var(--gutter)); margin: 0 auto;
	padding: var(--space-5) var(--gutter); }
.disclaimer { font-size: var(--text-sm); color: var(--muted); text-wrap: balance; }
@media (max-width: 47.99rem) {
	.site-header-inner { gap: var(--space-3); }
	.brand-name { position: absolute; width: 1px; height: 1px; overflow: hidden;
		clip-path: inset(50%); white-space: nowrap; }
	.nav-link { padding: 0 var(--space-2); }
	/* #692 saw "Admin" run under the account name at 390px: on a phone the button shows a
		person glyph and keeps the name for screen readers (the menu shows it in full). */
	.account-button { height: var(--control-h-lg); min-width: var(--control-h-lg);
		padding: 0 var(--space-1) 0 var(--space-2); }
	.account-glyph { display: block; }
	.account-name { position: absolute; width: 1px; height: 1px; overflow: hidden;
		clip-path: inset(50%); white-space: nowrap; }
	.account-panel { left: var(--gutter); right: var(--gutter); width: auto; min-width: 0; }
}
@media (min-width: 48rem) {
	.site-header-inner, .site-footer-inner { padding-left: var(--gutter-lg);
		padding-right: var(--gutter-lg);
		max-width: calc(var(--w-page) + 2 * var(--gutter-lg)); }
	.account-panel { right: max(var(--gutter-lg), calc((100vw - var(--w-page)) / 2)); }
}

/* The hidden attribute always hides (BH1-19, #940): the browser's own rule loses to any author
	display (.assistant-note, button), so the attribute is named twice to outrank a class and an
	element; !important stays for reduced motion and .visually-hidden (test_stylesheets.py). */
[hidden][hidden] { display: none; }

/* Present for assistive technology only (the table scroll hint, S4-11). */
.visually-hidden {
	position: absolute;
	width: 1px;
	height: 1px;
	margin: -1px;
	padding: 0;
	overflow: hidden;
	clip: rect(0 0 0 0);
	clip-path: inset(50%);
	white-space: nowrap;
	border: 0;
}

code {
	overflow-wrap: anywhere;
	word-break: normal;
}

/* Focus (final-spec §6.1): every keyboard-focusable thing shows the same ring (S4-09c checks
	each page for it). Never removed; no transition on outline. */
input:focus-visible,
select:focus-visible,
textarea:focus-visible,
button:focus-visible,
a:focus-visible,
summary:focus-visible,
[tabindex]:not([tabindex="-1"]):focus-visible {
	outline: 2px solid var(--accent);
	outline-offset: 2px;
}

/* Tags (SU2-11, spec 2.4; amendment 1, AI1-04): one shape for every value a page names
	(outcome, status, severity, advisory): the demo chip, a small bold label with nearly square
	corners, no border, no dot, no capsule. The word carries the meaning; the colour pair is a
	second signal (test_colour_tokens.py resolves each pair). A table cell that only names the
	column (td.severity, td.outcome) is not a tag. */
.tag {
	display: inline-flex;
	align-items: center;
	height: 1.375rem;
	padding: 0 0.5rem;
	border-radius: var(--radius-sm);
	font-size: var(--text-xs);
	font-weight: 600;
	line-height: 1;
	white-space: nowrap;
	color: var(--neutral-fg);
	background: var(--neutral-bg);
}

.tag.outcome-release {
	color: var(--ok-fg); background: var(--ok-bg); }
.tag.outcome-redact_and_release {
	color: var(--clip-fg); background: var(--clip-bg); }
.tag.outcome-withhold {
	color: var(--bad-fg); background: var(--bad-bg); }
.tag.outcome-escalate {
	color: var(--hold-fg); background: var(--hold-bg); }

/* The one status word (spec 2.10): neutral while nothing is settled. */
.tag.status-processing, .tag.status-awaiting, .tag.status-not_reviewed,
.tag.status-superseded, .tag.status-approved_escalation, .tag.status-earlier_copy,
.tag.status-sample_practice {
	color: var(--neutral-fg); background: var(--neutral-bg); }
.tag.status-released { color: var(--ok-fg); background: var(--ok-bg); }
.tag.status-released_redacted { color: var(--clip-fg); background: var(--clip-bg); }
.tag.status-withheld, .tag.status-unreadable { color: var(--bad-fg); background: var(--bad-bg); }
.tag.status-escalated, .tag.status-sent_back, .tag.status-stopped {
	color: var(--hold-fg); background: var(--hold-bg); }

.tag.severity-critical, .tag.severity-high {
	color: var(--bad-fg); background: var(--bad-bg); }
.tag.severity-medium {
	color: var(--warn-fg); background: var(--warn-bg); }
.tag.severity-low, .tag.severity-info {
	color: var(--neutral-fg); background: var(--neutral-bg); }

/* Notices (final-spec §6.3): inline, never toasts. The mark sits in its own column; the text
	beside it flows as ordinary inline content, so strong, code and links stay in the sentence. */
.notice,
.error {
	position: relative;
	padding: var(--space-3) var(--space-4) var(--space-3) calc(var(--space-4) + 1.5em);
	border: 1px solid;
	border-radius: var(--radius);
	font-size: var(--text-md);
}

.notice {
	color: var(--fg);
	background: var(--accent-bg);
	border-color: color-mix(in srgb, var(--accent) 30%, transparent);
}

.notice.success {
	background: var(--ok-bg);
	border-color: color-mix(in srgb, var(--ok-fg) 30%, transparent);
}

.notice.warning {
	background: var(--warn-bg);
	border-color: color-mix(in srgb, var(--warn-fg) 30%, transparent);
}

.error {
	color: var(--error);
	background: var(--error-bg);
	border-color: color-mix(in srgb, var(--error) 30%, transparent);
}

.notice::before,
.error::before {
	position: absolute;
	top: var(--space-3);
	left: var(--space-4);
	font-weight: 700;
}

/* Decorative: the "/ ''" alternative keeps the glyph out of the accessibility tree; the plain
	declaration before it is the fallback where alternative text is not supported. */
.notice::before { content: "i"; content: "i" / ""; color: var(--accent); }
.notice.success::before { content: "\2713"; content: "\2713" / ""; color: var(--ok-fg); }
.notice.warning::before { content: "!"; content: "!" / ""; color: var(--warn-fg); }
.error::before { content: "\2715"; content: "\2715" / ""; }

/* A notice arrives with a short fade and an 8px rise (AI1-10); it never leaves on its own. */
@media (prefers-reduced-motion: no-preference) {
	.notice, .error { animation: rise var(--dur-base) var(--ease-out) both; }
}

/* The shared keyframes (SC3-28): every sheet names these; each runs only under the
	no-preference guard of the rule that names it. */
@keyframes rise { from { opacity: 0; transform: translateY(8px); } }
@keyframes slide-in { from { opacity: 0; transform: translateX(12px); } }
@keyframes mark-in { from { background-color: transparent; } }
@keyframes spin { to { transform: rotate(1turn); } }

.help {
	margin: var(--space-1) 0 0;
	font-size: var(--text-sm);
	color: var(--muted);
}

/* A real content hash (sha256, record hash): monospace, wraps at any point so it never
	widens a phone page; inside a table cell td.hash keeps it on one line (the region scrolls). */
.hash {
	font-family: var(--mono);
	font-size: var(--text-sm);
	overflow-wrap: anywhere;
}

/* An empty state (spec 2.5): one muted sentence, left-aligned, at most one link at its end.
	No box, no centring, no title line. */
.empty {
	color: var(--muted);
}

/* Utilities (final-spec §6.15). */
.stack {
	display: flex;
	flex-direction: column;
	gap: var(--space-4);
}

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

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

/* Page enter (AI1-10): a same-origin navigation cross-fades the main column while the header
	and footer stay put; the new page rises 8px over --dur-base. CSS only: a browser without
	cross-document view transitions, and the first load, swap instantly. */
@media (prefers-reduced-motion: no-preference) {
	@view-transition { navigation: auto; }
	main { view-transition-name: page; }
	::view-transition-old(root), ::view-transition-new(root) { animation: none; }
	::view-transition-old(page) { animation: page-out var(--dur-quick) var(--ease-in) both; }
	::view-transition-new(page) { animation: rise var(--dur-base) var(--ease-out) both; }
}
@keyframes page-out { to { opacity: 0; } }

/* Reduced motion (final-spec §3.3): the last rule in app.css. */
@media (prefers-reduced-motion: reduce) {
	*, *::before, *::after {
		animation-duration: 0.01ms !important;
		animation-iteration-count: 1 !important;
		transition-duration: 0.01ms !important;
		scroll-behavior: auto !important;
	}
}
