/* --- design-system.css ------------------------------------------------- */

 

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

*:not(dialog) {
	margin: 0;
}

@media (prefers-reduced-motion: no-preference) {
	html {
		 
		interpolate-size: allow-keywords;
		scroll-behavior: smooth;
	}
}

body {
	line-height: 1.5;
	-webkit-font-smoothing: antialiased;
}

img, picture, video, canvas, svg {
	display: block;
	max-width: 100%;
}

input, button, textarea, select {
	font: inherit;
}

p, h1, h2, h3, h4, h5, h6 {
	overflow-wrap: break-word;
}

p {
	text-wrap: pretty;
}

h1, h2, h3, h4, h5, h6 {
	text-wrap: balance;
}

#root, #__next {
	isolation: isolate;
}


 
:root,
:root[data-theme="dark"] {
	color-scheme: light dark;
	--color-background: hsl(167 30% 5%);
	--color-surface: hsl(167 26% 8%);
	--color-primary: hsl(147 30% 50%);
	--color-secondary: #166879;
	--color-tertiary: #49a0b6;
	--color-text: hsl(150 14% 84%);
	--color-text-muted: hsl(150 10% 62%);
	--color-border: hsl(160 18% 18%);
	--color-surface-raised: hsl(163 22% 12%);
	--color-border-strong: hsl(155 16% 27%);
	--color-heading: hsl(150 20% 96%);
	--color-accent: hsl(147 38% 62%);
	--color-accent-bright: hsl(147 45% 74%);
	--color-data-1: #ddb43c;
	--color-data-2: #3c87dd;
	--color-data-3: #dd3c3c;
	--color-data-4: #3cdd57;
	--color-data-5: #643cdd;
	--color-data-6: #dd8f3c;
	--color-error: hsl(0 40% 40%);
	--color-warning: hsl(35 55% 65%);
	--color-success: hsl(147 38% 62%);
	--color-info: hsl(200 40% 60%);
}



 
:root[data-theme="light"] {
	color-scheme: light;
	--color-background: hsl(150 20% 98%);
	--color-surface: hsl(150 16% 96%);
	--color-primary: hsl(147 30% 34%);
	--color-secondary: #166879;
	--color-tertiary: #49a0b6;
	--color-text: hsl(167 20% 18%);
	--color-text-muted: hsl(155 10% 42%);
	--color-border: hsl(155 12% 84%);
	--color-surface-raised: hsl(150 14% 92%);
	--color-border-strong: hsl(155 14% 70%);
	--color-heading: hsl(167 30% 8%);
	--color-accent: hsl(147 38% 30%);
	--color-accent-bright: hsl(147 45% 24%);
}


@media (prefers-color-scheme: light) {
	:root:not([data-theme]) {
		color-scheme: light;
		--color-background: hsl(150 20% 98%);
		--color-surface: hsl(150 16% 96%);
		--color-primary: hsl(147 30% 34%);
		--color-secondary: #166879;
		--color-tertiary: #49a0b6;
		--color-text: hsl(167 20% 18%);
		--color-text-muted: hsl(155 10% 42%);
		--color-border: hsl(155 12% 84%);
		--color-surface-raised: hsl(150 14% 92%);
		--color-border-strong: hsl(155 14% 70%);
		--color-heading: hsl(167 30% 8%);
		--color-accent: hsl(147 38% 30%);
		--color-accent-bright: hsl(147 45% 24%);
	}
}




 
:root {
	--font-family-base: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
	--font-family-mono: 'SF Mono', 'Monaco', 'Inconsolata', 'Fira Code', 'Droid Sans Mono', 'Source Code Pro', monospace;
	--font-size-xs: 0.694rem;
	--font-size-sm: 0.833rem;
	--font-size-base: 1rem;
	--font-size-lg: 1.2rem;
	--font-size-xl: 1.44rem;
	--font-size-2xl: 1.728rem;
	--font-size-3xl: 2.986rem;
	--font-weight-normal: 400;
	--font-weight-medium: 500;
	--font-weight-bold: 700;
	--line-height-tight: 1.2;
	--line-height-normal: 1.5;
	--line-height-relaxed: 1.75;
	--space-xs: 0.25rem;
	--space-sm: 0.5rem;
	--space-md: 1rem;
	--space-lg: 1.5rem;
	--space-xl: 2rem;
	--space-2xl: 3rem;
	--space-3xl: 4rem;
	 
	--measure: 68ch;
	--layout-max-width: 87.5rem;
	--layout-content-width: 75rem;
	--layout-sidebar-width: 17.5rem;
	--layout-header-height: var(--space-3xl);
	--layout-gap: var(--space-md);
	--layout-gap-lg: var(--space-lg);
	 
	--color-on-brand: #f3f7f5;
	--brand-from: #46795d;
	--brand-to: #204039;
	--gradient-surface: linear-gradient(180deg, var(--color-surface-raised), var(--color-surface));
	--gradient-primary: linear-gradient(160deg, var(--brand-from), var(--brand-to));
	--gradient-accent: linear-gradient(90deg, var(--brand-from), var(--color-accent));
	--gradient-border: linear-gradient(180deg, var(--color-border-strong), var(--color-border));
	--gradient-wash:
		radial-gradient(60rem 26rem at 50% -6rem, hsl(147 40% 30% / .38), transparent 70%),
		radial-gradient(34rem 18rem at 88% 2rem, hsl(167 45% 22% / .30), transparent 70%);
	--radius-sm: 4px;
	--radius-md: 8px;
	--radius-lg: 12px;
	--border-sm: 1px;
	--border-lg: 2px;
	--focus-ring-width: 3px;
	--tint-alpha: 10%;
	--focus-ring-color: color-mix(in srgb, var(--color-primary) var(--tint-alpha), transparent);
	--shadow-card: 0 2px 8px rgba(0, 0, 0, 0.1);
	--shadow-modal: 0 8px 32px rgba(0, 0, 0, 0.3);
	--modal-backdrop: rgba(0, 0, 0, 0.5);
	--modal-max-width: 40rem;
	--layout-grid-min: 250px;
	--transition-fast: 0.2s;
	--status-border-width: 3px;
	--table-max-height: 30rem;
	 
	--cell-align: middle;
}

 
a {
	color: var(--color-secondary);
	text-decoration: none;
}

 
a:visited {
	color: color-mix(in srgb, var(--color-accent), var(--color-text-muted) 45%);
}

a:hover {
	text-decoration: underline;
}

 
header a:visited,
nav a:visited,
footer a:visited {
	color: inherit;
}

/* --- code.css ---------------------------------------------------------- */
/* Code Blocks */
pre {
	background: var(--color-surface);
	border: var(--border-sm) solid var(--color-border);
	border-radius: var(--radius-sm);
	padding: var(--space-md);
	overflow-x: auto;
	margin: var(--space-md) 0;
}

code {
	font-family: var(--font-family-mono);
	font-size: var(--font-size-sm);
	color: var(--color-text);
}

pre code {
	display: block;
	line-height: var(--line-height-relaxed);
}

/* --- error.css --------------------------------------------------------- */
/* error.css — standard styling for the page-level error banner rendered from
   hypertext.TemplateData.Err. Included via the shared "imports" template so every
   page entrypoint can surface a receiver error consistently. */

.error-banner {
	margin: var(--space-md);
	padding: var(--space-md) var(--space-lg);
	border: var(--border-sm) solid var(--color-error);
	border-left-width: var(--space-xs);
	border-radius: var(--radius-md);
	background-color: var(--color-surface);
	color: var(--color-text);
}

.error-banner__title {
	margin: 0 0 var(--space-xs);
	font-weight: var(--font-weight-bold);
	color: var(--color-error);
}

.error-banner__detail {
	margin: 0;
	overflow-x: auto;
	white-space: pre-wrap;
	word-break: break-word;
	font-family: var(--font-family-mono);
	font-size: var(--font-size-xs);
	color: var(--color-text-muted);
}

/* Inline command-result states (SubmitDeviceCommand fragment). */
.validation-success {
	margin: 0;
	color: var(--color-primary);
	font-weight: var(--font-weight-medium);
}

/* --- forms.css --------------------------------------------------------- */
/* Form structure and buttons.
   ==========================================================================
   inputs.css styles the CONTROLS — every input type, textarea, select, and
   their focus and error states. This file is the structure around them: how a
   label sits above its control, how controls sit beside each other, and the
   buttons that submit them.

   The controls are styled by element selector on purpose. The application this
   was extracted from had three input styles — a `.field input` descendant
   rule, a `.weight` class for numeric boxes, and a `.corr-input` for matrix
   cells — with overlapping declarations and no rule about which to reach for.
   An element selector needs no decision. */

/* A label above its control, with room for a message underneath. */
.field {
	display: flex;
	flex-direction: column;
	gap: var(--space-xs);
	/* min-width: 0 is load-bearing. A flex item defaults to min-width: auto and
	   refuses to shrink below its content's intrinsic width — a text input's is
	   about twenty characters. Chrome shrinks them anyway; Safari does not, so
	   without this the second field in a row overflows its container and
	   crosses the border. */
	min-width: 0;
}

.field > label {
	font-size: var(--font-size-sm);
	color: var(--color-text-muted);
}

.field > input,
.field > select,
.field > textarea { width: 100%; }

/* Fields side by side, wrapping before they are squeezed unusably narrow. */
.field-row {
	display: flex;
	flex-wrap: wrap;
	gap: var(--space-sm);
}

.field-row > .field {
	flex: 1 1 var(--field-min, 12rem);
	min-width: 0;
}

/* A vertical stack of fields with its own padding, for a form that sits
   directly inside a surface. */
.stack {
	display: flex;
	flex-direction: column;
	gap: var(--space-sm);
	padding: var(--space-md);
}

/* A note under a single field, as opposed to .surface-note under a whole card.
   No top border: it belongs to the control above it, not to the section. */
.field-note {
	margin: 0;
	padding-top: var(--space-xs);
	font-size: var(--font-size-xs);
	line-height: var(--line-height-relaxed);
	color: var(--color-text-muted);
}

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

.button {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	gap: var(--space-xs);
	padding: var(--space-sm) var(--space-md);
	border: var(--border-sm) solid var(--color-border-strong);
	border-radius: var(--radius-md);
	background: var(--color-surface-raised);
	color: var(--color-text);
	font-size: var(--font-size-sm);
	font-weight: var(--font-weight-medium);
	line-height: 1;
	text-decoration: none;
	cursor: pointer;
	transition:
		background var(--transition-fast) ease,
		border-color var(--transition-fast) ease,
		color var(--transition-fast) ease,
		transform var(--transition-fast) ease;
}

/* Movement, not just a colour change: a press should be felt on a touch screen
   where there is no hover to have told you the thing was pressable. */
.button:active { transform: translateY(1px); }

/* An <a class="button"> is a button to the reader, so it keeps its colour once
   followed. Without this the global a:visited rule repaints the label and a
   primary action goes a different colour the second time somebody sees it. */
.button:visited { color: inherit; }

.button:focus-visible {
	outline: var(--border-lg) solid var(--color-accent-bright);
	outline-offset: 2px;
}

.button:disabled,
.button[aria-disabled="true"] {
	opacity: .55;
	cursor: not-allowed;
	transform: none;
}

/* The primary action carries the brand gradient. One per view: a page with two
   primary actions has told the reader nothing about which to take. */
.button-primary {
	background: var(--gradient-primary);
	border-color: var(--color-primary);
	/* Not --color-heading: that follows the theme, and this button's background
	   does not. */
	color: var(--color-on-brand);
	/* A one-pixel inner highlight along the top edge, so the gradient reads as
	   lit rather than as a flat fill that happens to change colour. */
	box-shadow: inset 0 1px 0 color-mix(in srgb, var(--color-accent-bright) 18%, transparent);
}

.button-primary:visited { color: var(--color-on-brand); }

.button-primary:hover {
	background: var(--color-primary);
	color: var(--color-background);
}

.button-ghost {
	background: transparent;
	/* Border deliberately left as the base .button's --color-border-strong: a
	   ghost button is still a button, and dropping to the hairline made it read
	   as a disabled field rather than an action. */
}

.button-ghost:hover {
	background: var(--color-surface-raised);
	color: var(--color-heading);
}

.button-danger {
	background: transparent;
	border-color: var(--color-error);
	/* The border can be the full-strength error colour; the LABEL cannot. A
	   status colour is chosen to read as a border and a fill, and on a dark
	   surface it lands around 2:1 against the background — text at that
	   contrast is unreadable, and it was unreadable in the design this was
	   measured against too. Lifted toward the heading colour so the hue still
	   says "destructive" while the word stays legible. */
	color: color-mix(in srgb, var(--color-error), var(--color-heading) 55%);
}

.button-danger:visited { color: color-mix(in srgb, var(--color-error), var(--color-heading) 55%); }

.button-danger:hover {
	background: color-mix(in srgb, var(--color-error) 14%, transparent);
	color: var(--color-heading);
}

.button-small {
	padding: var(--space-xs) var(--space-sm);
	font-size: var(--font-size-xs);
}

/* --- segmented control -------------------------------------------------- */

/* Radio buttons that read as one control: a small closed set where every
   option is worth showing, which a <select> hides behind a click.

   The inputs stay in the DOM and keep their semantics — this is a radio group
   to a screen reader and to the keyboard, and only the painting changes. */
.segmented {
	/* fieldset carries a margin-bottom for the gap between form groups; this is
	   a control rather than a group, and its container spaces it. */
	margin-bottom: 0;
	display: flex;
	gap: var(--space-xs);
	padding: var(--space-xs);
	border: var(--border-sm) solid var(--color-border);
	border-radius: var(--radius-md);
	background: var(--color-background);
}

.segmented label { flex: 1; }

/* Not display: none and not visibility: hidden — either takes the input out
   of the tab order, and the control stops being keyboard-operable. */
.segmented input {
	position: absolute;
	opacity: 0;
	pointer-events: none;
}

.segmented span {
	display: block;
	padding: var(--space-xs) var(--space-sm);
	text-align: center;
	font-size: var(--font-size-sm);
	color: var(--color-text-muted);
	border-radius: var(--radius-sm);
	cursor: pointer;
}

.segmented label:hover span { color: var(--color-text); }

.segmented input:checked + span {
	background: var(--color-accent);
	color: var(--color-background);
	font-weight: var(--font-weight-bold);
}

/* The focus ring has to be drawn on the label, because the input it belongs to
   is invisible. Without this the control is operable by keyboard and gives no
   sign of where the focus is. */
.segmented input:focus-visible + span {
	outline: var(--border-lg) solid var(--color-accent-bright);
	outline-offset: 2px;
}

/* --- inputs.css -------------------------------------------------------- */
/* Text Inputs
   --------------------------------------------------------------------------
   A denylist, not a list of the types we thought of. `<input>` with no type
   attribute is a text input — it is what most markup actually writes — and an
   allowlist of input[type="..."] silently misses it, leaving the control with
   the browser's default chrome next to styled siblings. It also misses every
   type added after the list was written. Naming what must NOT look like a text
   box is the shorter and more durable half.

   :not() is chained rather than given a selector list: the list form is much
   newer than the chained form and the chained one costs only length.

   The whole chain is wrapped in :where() so it contributes NO specificity —
   the rule counts as plain `input`, which is what a base control style should
   be. Unwrapped, ten attribute :not()s make it (0,10,1), and a base style at
   that weight outranks every component rule written later: a table cell that
   wants its control to lose its corner radius silently loses instead. */
input:where(:not([type="checkbox"]):not([type="radio"]):not([type="range"]):not([type="color"]):not([type="file"]):not([type="submit"]):not([type="button"]):not([type="reset"]):not([type="image"]):not([type="hidden"])),
textarea {
	font-family: var(--font-family-base);
	font-size: var(--font-size-base);
	line-height: var(--line-height-normal);
	padding: var(--space-sm) var(--space-md);
	background: var(--color-background);
	color: var(--color-text);
	border: var(--border-sm) solid var(--color-border);
	border-radius: var(--radius-sm);
	width: 100%;
	box-sizing: border-box;
	transition: border-color var(--transition-fast), box-shadow var(--transition-fast);
}

input:where(:not([type="checkbox"]):not([type="radio"]):not([type="range"]):not([type="color"]):not([type="file"]):not([type="submit"]):not([type="button"]):not([type="reset"]):not([type="image"]):not([type="hidden"])):focus,
textarea:focus {
	outline: none;
	border-color: var(--color-primary);
	box-shadow: 0 0 0 var(--focus-ring-width) var(--focus-ring-color);
}

input:where(:not([type="checkbox"]):not([type="radio"]):not([type="range"]):not([type="color"]):not([type="file"]):not([type="submit"]):not([type="button"]):not([type="reset"]):not([type="image"]):not([type="hidden"])):disabled,
textarea:disabled {
	opacity: 0.6;
	cursor: not-allowed;
	background: var(--color-surface);
}

input::placeholder,
textarea::placeholder {
	color: var(--color-text-muted);
	opacity: 0.7;
}

textarea {
	resize: vertical;
	min-height: 6rem;
}

/* Select */
select {
	font-family: var(--font-family-base);
	font-size: var(--font-size-base);
	padding: var(--space-sm) var(--space-md);
	background: var(--color-background);
	color: var(--color-text);
	border: var(--border-sm) solid var(--color-border);
	border-radius: var(--radius-sm);
	width: 100%;
	box-sizing: border-box;
	cursor: pointer;
	transition: border-color var(--transition-fast);
}

select:focus {
	outline: none;
	border-color: var(--color-primary);
	box-shadow: 0 0 0 var(--focus-ring-width) var(--focus-ring-color);
}

select:disabled {
	opacity: 0.6;
	cursor: not-allowed;
	background: var(--color-surface);
}

/* Checkbox & Radio */
input[type="checkbox"],
input[type="radio"] {
	width: 1.125rem;
	height: 1.125rem;
	margin-right: var(--space-sm);
	cursor: pointer;
	accent-color: var(--color-primary);
}

input[type="checkbox"]:disabled,
input[type="radio"]:disabled {
	opacity: 0.6;
	cursor: not-allowed;
}

/* Range */
input[type="range"] {
	width: 100%;
	height: 0.5rem;
	background: var(--color-border);
	border-radius: var(--radius-sm);
	outline: none;
	cursor: pointer;
	accent-color: var(--color-primary);
}

input[type="range"]:disabled {
	opacity: 0.6;
	cursor: not-allowed;
}

/* File */
input[type="file"] {
	font-family: var(--font-family-base);
	font-size: var(--font-size-sm);
	padding: var(--space-sm);
	background: var(--color-background);
	color: var(--color-text);
	border: var(--border-sm) solid var(--color-border);
	border-radius: var(--radius-sm);
	width: 100%;
	box-sizing: border-box;
	cursor: pointer;
}

input[type="file"]:disabled {
	opacity: 0.6;
	cursor: not-allowed;
}

/* Validation States */
input.error,
select.error,
textarea.error {
	border-color: var(--color-error);
}

input.error:focus,
select.error:focus,
textarea.error:focus {
	border-color: var(--color-error);
	box-shadow: 0 0 0 var(--focus-ring-width) color-mix(in srgb, var(--color-error) var(--tint-alpha), transparent);
}

label.error {
	color: var(--color-error);
}

.error-message {
	display: block;
	margin-top: var(--space-xs);
	font-size: var(--font-size-sm);
	color: var(--color-error);
}

/* Alerts */
.alert {
	padding: var(--space-md);
	border-radius: var(--radius-md);
	margin-bottom: var(--space-lg);
}

.alert-error {
	background: color-mix(in srgb, var(--color-error) var(--tint-alpha), transparent);
	border: var(--border-sm) solid var(--color-error);
	color: var(--color-error);
}

.alert-success {
	background: color-mix(in srgb, var(--color-success) var(--tint-alpha), transparent);
	border: var(--border-sm) solid var(--color-success);
	color: var(--color-success);
}

.alert h3 {
	margin-top: 0;
	margin-bottom: var(--space-sm);
}

.alert ul {
	margin: 0;
	padding-left: var(--space-lg);
}

.alert p {
	margin: 0;
}

.validation-success {
	margin-top: var(--space-sm);
	color: var(--color-success);
	font-weight: var(--font-weight-medium);
	cursor: not-allowed;
}

/* Labels */
label {
	display: block;
	font-weight: var(--font-weight-medium);
	margin-bottom: var(--space-xs);
	color: var(--color-text);
	font-size: var(--font-size-sm);
}

.input-box {
	padding: var(--space-md) 0;
}

.input-inline label {
	display: inline-block;
	margin-bottom: 0;
	margin-right: var(--space-sm);
	vertical-align: middle;
}

/* Fieldsets */
fieldset {
	border: var(--border-sm) solid var(--color-border);
	border-radius: var(--radius-md);
	padding: var(--space-lg);
	margin-bottom: var(--space-lg);
}

legend {
	font-weight: var(--font-weight-bold);
	font-size: var(--font-size-lg);
	color: var(--color-text);
	padding: 0 var(--space-sm);
}

/* Variations */
.input-sm {
	font-size: var(--font-size-sm);
	padding: var(--space-xs) var(--space-sm);
}

.input-lg {
	font-size: var(--font-size-lg);
	padding: var(--space-md) var(--space-lg);
}

.input-mono {
	font-family: var(--font-family-mono);
	font-size: var(--font-size-sm);
}

.input-error {
	border-color: var(--color-error);
}

.input-error:focus {
	border-color: var(--color-error);
	box-shadow: 0 0 0 var(--focus-ring-width) color-mix(in srgb, var(--color-error) var(--tint-alpha), transparent);
}

.input-success {
	border-color: var(--color-success);
}

.input-success:focus {
	border-color: var(--color-success);
	box-shadow: 0 0 0 var(--focus-ring-width) color-mix(in srgb, var(--color-success) var(--tint-alpha), transparent);
}

.help-text {
	display: block;
	font-size: var(--font-size-xs);
	color: var(--color-text-muted);
	margin-top: var(--space-xs);
}

.error-text {
	display: block;
	font-size: var(--font-size-xs);
	color: var(--color-error);
	margin-top: var(--space-xs);
}

/* --- layouts.css ------------------------------------------------------- */
/* Container & Grid */
.container {
	max-width: var(--layout-max-width);
	margin: 0 auto;
	padding: 0 var(--space-lg);
}

.container-narrow {
	max-width: var(--layout-content-width);
	margin: 0 auto;
	padding: 0 var(--space-lg);
}

.container-fluid {
	width: 100%;
	padding: 0 var(--space-lg);
}

.grid {
	display: grid;
	gap: var(--layout-gap);
	grid-template-columns: repeat(auto-fit, minmax(var(--layout-grid-min), 1fr));
}

.grid-2 {
	display: grid;
	gap: var(--layout-gap);
	grid-template-columns: repeat(2, 1fr);
}

.grid-3 {
	display: grid;
	gap: var(--layout-gap);
	grid-template-columns: repeat(3, 1fr);
}

.grid-4 {
	display: grid;
	gap: var(--layout-gap);
	grid-template-columns: repeat(4, 1fr);
}

@media (max-width: 768px) {
	.grid-2,
	.grid-3,
	.grid-4 {
		grid-template-columns: 1fr;
	}
}

/* Body */
body {
	font-family: var(--font-family-base);
	background: var(--color-background);
	color: var(--color-text);
	padding: 0;
}

/* Cards */
/* A card, addressed by class.
   This was `article { … }`: an element rule that painted a border, a radius, a
   background and padding onto every <article> on the page. <article> is a
   semantic element meaning "a self-contained composition" — a blog post, a
   comment, a product entry — and applications use it for page content, not to
   ask for a box. A consuming application found its page footer and its settings
   page wrapped in borders it never asked for, and had no way to decline short
   of overriding the system.

   A design system may claim class names. It may not claim the HTML vocabulary.

   .card carries the same painting, opt-in. See also .surface in surfaces.css,
   which is the same idea with a header strip and no padding of its own; .card
   is the one for a box of prose. */
.card {
	background: var(--color-surface);
	border: var(--border-sm) solid var(--color-border);
	border-radius: var(--radius-md);
	padding: var(--space-lg);
	margin-bottom: var(--space-lg);

	> header {
		padding-bottom: var(--space-md);
		margin-bottom: var(--space-md);
		border-bottom: 1px solid var(--color-border);

		&:last-child {
			padding-bottom: 0;
			margin-bottom: 0;
			border-bottom: none;
		}

		h1, h2, h3, h4, h5, h6 {
			color: var(--color-text);
			font-weight: var(--font-weight-bold);
			margin: 0;
		}

		p {
			font-size: var(--font-size-sm);
			color: var(--color-text-muted);
			margin: var(--space-xs) 0 0;
		}
	}

	> footer {
		padding-top: var(--space-md);
		margin-top: var(--space-md);
		border-top: var(--border-sm) solid var(--color-border);

		&:last-child {
			padding-top: 0;
			margin-top: 0;
			border-top: none;
		}
	}

	&.card-compact {
		padding: var(--space-md);
	}

	&.card-elevated {
		box-shadow: var(--shadow-card);

		
		@media (prefers-color-scheme: dark) {
			box-shadow: 0 2px 8px rgba(0, 0, 0, 0.4);
		}
		
	}

	&.secondary > header {
		border-bottom-color: var(--color-secondary);
	}

	&.tertiary > header {
		border-bottom-color: var(--color-tertiary);
	}
}

/* Page Header & Navigation */
body > header {
	background: var(--color-surface);
	color: var(--color-text);
	position: sticky;
	top: 0;
	z-index: 100;
	border-bottom: var(--border-lg) solid var(--color-primary);

	h1 {
		margin-bottom: var(--space-sm);
		font-size: var(--font-size-3xl);
		font-weight: var(--font-weight-bold);
	}

	p {
		font-size: var(--font-size-lg);
	}

	> hgroup {
		padding: var(--space-sm) var(--space-lg);
		max-width: var(--layout-max-width);
		margin: 0 auto;

		h1, h2, h3 {
			font-size: var(--font-size-xl);
			font-weight: var(--font-weight-bold);
		}
	}

	> nav {
		display: flex;
		gap: var(--space-md);
		align-items: center;
		padding: var(--space-sm) var(--space-lg);
		border-top: var(--border-sm) solid var(--color-border);
		max-width: var(--layout-max-width);
		margin: 0 auto;

		> ul {
			display: flex;
			gap: var(--space-xs);
			list-style: none;
			padding: 0;
			align-items: center;

			&:first-child {
				margin-right: auto;
			}

			&:last-child:not(:first-child) {
				margin-left: auto;
			}
		}

		a {
			color: var(--color-text);
			text-decoration: none;
			font-weight: var(--font-weight-medium);
			padding: var(--space-sm) var(--space-md);
			transition: background-color var(--transition-fast), color var(--transition-fast);
			white-space: nowrap; /* not text-wrap: nowrap, which needs Safari 17.4 */
			border-radius: var(--radius-sm);

			&:hover {
				background: var(--color-background);
				color: var(--color-primary);
			}

			&[aria-current="page"] {
				background: var(--color-background);
				color: var(--color-primary);
				font-weight: var(--font-weight-bold);
			}
		}

		button {
			color: var(--color-text);
			font-weight: var(--font-weight-medium);
			padding: var(--space-sm) var(--space-md);
			transition: background-color var(--transition-fast), color var(--transition-fast), border-color var(--transition-fast);
			white-space: nowrap; /* not text-wrap: nowrap, which needs Safari 17.4 */
			background: transparent;
			border: var(--border-sm) solid var(--color-border);
			border-radius: var(--radius-sm);
			cursor: pointer;
			font-size: var(--font-size-base);

			&:hover {
				background: var(--color-background);
				border-color: var(--color-primary);
				color: var(--color-primary);
			}

			&.secondary {
				&:hover {
					border-color: var(--color-secondary);
					color: var(--color-secondary);
				}
			}

			&.tertiary {
				&:hover {
					border-color: var(--color-tertiary);
					color: var(--color-tertiary);
				}
			}
		}

		input[type="checkbox"] {
			display: none;
		}

		label[for] {
			display: none;
			cursor: pointer;
			padding: var(--space-sm);
			font-size: var(--font-size-xl);
			-webkit-user-select: none; /* the only form Safari honours */
			user-select: none;
		}

		@media (max-width: 768px) {
			flex-direction: column;
			position: relative;
			overflow: visible;
			padding-right: calc(var(--space-lg) * 3);

			label[for] {
				display: block;
				position: absolute;
				right: var(--space-lg);
				top: var(--space-md);
				transform: none;

				&::before {
					content: '☰';
				}
			}

			> ul {
				&:first-child {
					margin-right: 0;
				}

				&:last-child:not(:first-child) {
					margin-left: 0;
				}
			}

			input[type="checkbox"]:not(:checked) ~ ul {
				display: none;
			}

			input[type="checkbox"]:checked ~ ul {
				position: static;
				width: 100%;
				flex-direction: column;
				background: transparent;
				border: none;
				padding: var(--space-md) 0;
				gap: 0;
				display: flex;
				box-shadow: none;
				max-height: none;
				overflow-y: visible;

				li {
					width: 100%;
				}

				a, button {
					display: block;
					width: 100%;
					padding: var(--space-md);
					text-align: left;
				}
			}

			input[type="checkbox"]:checked ~ label[for]::before {
				content: '×';
				font-size: var(--font-size-2xl);
			}
		}
	}

	&.header-with-nav {
		display: flex;
		justify-content: space-between;
		align-items: center;
		flex-wrap: wrap;
		gap: var(--space-md);

		nav {
			background: transparent;
			border: none;
			padding: 0;
		}
	}
}

/* Page Footer */
body > footer {
	background: var(--color-surface);
	color: var(--color-text);
	padding: var(--space-xl) var(--space-lg);
	border-top: var(--border-sm) solid var(--color-border);
	margin-top: var(--space-3xl);

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

	.footer-columns {
		display: grid;
		grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
		gap: var(--space-xl);
		margin-bottom: var(--space-lg);
	}

	h3, h4 {
		margin-top: 0;
		margin-bottom: var(--space-md);
		font-size: var(--font-size-base);
		font-weight: var(--font-weight-bold);
	}

	ul {
		list-style: none;
		padding: 0;

		li {
			margin-bottom: var(--space-sm);
		}
	}

	a {
		color: var(--color-text);
		text-decoration: none;
		font-size: var(--font-size-sm);

		&:hover {
			color: var(--color-primary);
			text-decoration: underline;
		}
	}

	&.secondary a {
		&:hover {
			color: var(--color-secondary);
		}
	}

	&.tertiary a {
		&:hover {
			color: var(--color-tertiary);
		}
	}
}

/* Navigation Cards */
nav.card-list {
	margin-top: var(--space-lg);

	ul {
		display: flex;
		flex-wrap: wrap;
		gap: var(--space-sm);
		list-style: none;
		padding: 0;

		a {
			display: block;
			padding: var(--space-sm) var(--space-md);
			background: var(--color-surface);
			border: var(--border-sm) solid var(--color-border);
			border-radius: var(--radius-sm);
			text-decoration: none;
			color: var(--color-text);
			transition: all var(--transition-fast);

			&:hover {
				background: var(--color-background);
				border-color: var(--color-primary);
				color: var(--color-primary);
			}
		}
	}
}

/* Section Content Spacing */
section > div:first-child,
section > nav:first-child,
section > article:first-child {
	margin-top: var(--space-lg);
}

section > table {
	margin-top: var(--space-lg);
}

/* Tabs */
.tabs {
	border-bottom: 2px solid var(--color-border);
	margin-bottom: var(--space-lg);

	.tab-labels {
		display: flex;
		gap: var(--space-sm);

		a {
			padding: var(--space-md) var(--space-lg);
			border-bottom: 2px solid transparent;
			margin-bottom: -2px;
			transition: all var(--transition-fast);
			color: var(--color-text-muted);
			font-weight: var(--font-weight-medium);
			text-decoration: none;

			&:hover {
				color: var(--color-text);
				background: var(--color-surface);
			}

			&.active {
				color: var(--color-text);
				border-bottom-color: var(--color-primary);
			}
		}
	}
}

/* Accordion */
details {
	background: var(--color-surface);
	border: var(--border-sm) solid var(--color-border);
	border-radius: var(--radius-md);
	margin-bottom: var(--space-md);
	overflow: hidden;

	summary {
		cursor: pointer;
		padding: var(--space-md) var(--space-lg);
		font-weight: var(--font-weight-medium);
		color: var(--color-text);
		background: var(--color-surface);
		border-bottom: 1px solid transparent;
		transition: background-color var(--transition-fast);
		-webkit-user-select: none; /* the only form Safari honours */
		user-select: none;
		list-style: none;

		&::-webkit-details-marker {
			display: none;
		}

		&::marker {
			display: none;
		}

		&::before {
			content: '▶';
			display: inline-block;
			margin-right: var(--space-sm);
			transition: transform var(--transition-fast);
			font-size: var(--font-size-sm);
			color: var(--color-primary);
		}

		&:hover {
			background: var(--color-background);
		}

		&[role="button"] {
			display: block;
			width: 100%;
			background: var(--color-primary);
			color: var(--color-text);
			border-radius: var(--radius-sm);
			font-weight: var(--font-weight-bold);
			text-align: left;

			&:hover {
				opacity: 0.9;
			}
		}
	}

	&.secondary summary::before {
		color: var(--color-secondary);
	}

	&.tertiary summary::before {
		color: var(--color-tertiary);
	}

	&[open] summary {
		border-bottom-color: var(--color-border);

		&::before {
			transform: rotate(90deg);
		}

		&[role="button"] {
			border-bottom-left-radius: 0;
			border-bottom-right-radius: 0;
		}
	}

	> *:not(summary) {
		padding: var(--space-lg);
	}

	> p:first-of-type {
		margin-top: 0;
	}

	> p:last-child {
		margin-bottom: 0;
	}

	&.full-width > *:not(summary) {
		padding: 0;
	}

}

[role="group"]:has(> details) > details {
	margin-bottom: 0;
	border-radius: 0;
	border-bottom: none;

	&:first-child {
		border-top-left-radius: var(--radius-md);
		border-top-right-radius: var(--radius-md);
	}

	&:last-child {
		border-bottom-left-radius: var(--radius-md);
		border-bottom-right-radius: var(--radius-md);
		border-bottom: 1px solid var(--color-border);
	}
}

details[name] {
	margin-bottom: 0;
	border-radius: 0;
	border-bottom: none;

	&:first-of-type {
		border-top-left-radius: var(--radius-md);
		border-top-right-radius: var(--radius-md);
	}

	&:last-of-type {
		border-bottom-left-radius: var(--radius-md);
		border-bottom-right-radius: var(--radius-md);
		border-bottom: 1px solid var(--color-border);
	}
}

/* Sidebar Layout */
.layout-sidebar {
	display: grid;
	grid-template-columns: var(--layout-sidebar-width) 1fr;
	gap: var(--layout-gap-lg);
	min-height: 100vh;
}

.layout-sidebar > aside {
	background: var(--color-surface);
	padding: var(--space-lg);
	border-right: var(--border-sm) solid var(--color-border);
}

.layout-sidebar > main {
	padding: var(--space-lg);
}

@media (max-width: 1024px) {
	.layout-sidebar {
		grid-template-columns: 1fr;
	}

	.layout-sidebar > aside {
		border-right: none;
		border-bottom: 1px solid var(--color-border);
	}
}

/* Section Dividers */
hr {
	border: none;
	border-top: 1px solid var(--color-border);
	margin: var(--space-xl) 0;

	&.divider-thick {
		border-top-width: 2px;
	}

	&.divider-primary {
		border-top-color: var(--color-primary);
	}
}

/* Flex Utilities */
.flex {
	display: flex;
	gap: var(--layout-gap);
}

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

.flex-between {
	display: flex;
	justify-content: space-between;
	align-items: center;
}

.flex-column {
	display: flex;
	flex-direction: column;
	gap: var(--layout-gap);
}

/* Button Groups */
[role="group"] {
	&:has(> button),
	&:has(> [role="button"]) {
		display: inline-flex;
		border-radius: var(--radius-sm);
		overflow: hidden;
	}

	> button,
	> [role="button"] {
		border-radius: 0;
		margin: 0;
		border-right-width: 0;

		&:first-child {
			border-top-left-radius: var(--radius-sm);
			border-bottom-left-radius: var(--radius-sm);
		}

		&:last-child {
			border-top-right-radius: var(--radius-sm);
			border-bottom-right-radius: var(--radius-sm);
			border-right-width: 1px;
		}
	}
}

[role="group"] > button + button,
[role="group"] > button + [role="button"],
[role="group"] > [role="button"] + button,
[role="group"] > [role="button"] + [role="button"] {
	border-left: 1px solid rgba(0, 0, 0, 0.1);
}


@media (prefers-color-scheme: dark) {
	[role="group"] > button + button,
	[role="group"] > button + [role="button"],
	[role="group"] > [role="button"] + button,
	[role="group"] > [role="button"] + [role="button"] {
		border-left: 1px solid rgba(255, 255, 255, 0.1);
	}
}


/* Breadcrumbs */
nav[aria-label="Breadcrumb"] {
	ul, ol {
		display: flex;
		list-style: none;
		padding: 0;
		margin: 0;
		gap: var(--space-sm);
		align-items: center;
		flex-wrap: wrap;

		li {
			display: flex;
			align-items: center;
			gap: var(--space-sm);

			&:not(:last-child)::after {
				content: '›';
				color: var(--color-text-muted);
				font-weight: var(--font-weight-bold);
			}

			a {
				color: var(--color-text);
				text-decoration: none;
				padding: var(--space-xs) var(--space-sm);
				border-radius: var(--radius-sm);
				transition: background-color var(--transition-fast), color var(--transition-fast);

				&:hover {
					background: var(--color-background);
					color: var(--color-primary);
				}
			}

			&[aria-current="page"] {
				color: var(--color-text-muted);
				font-weight: var(--font-weight-medium);
			}
		}
	}
}

/* Main & Sections */
main {
	max-width: var(--layout-max-width);
	margin: 0 auto;
	padding: var(--space-lg);
}

/* Was `section { … }`, and the same mistake as `article` with a wider blast
   radius: <section> is the element every page reaches for to group anything at
   all, so styling it as a card put a border around every group on every page —
   including around cards that were already cards, which doubled their borders
   and their padding.

   Named .panel rather than folded into .card because the two differ: this one
   spaces itself from the next section below it. */
.panel {
	margin-bottom: var(--space-2xl);
	padding: var(--space-lg);
	background: var(--color-surface);
	border: 1px solid var(--color-border);
	border-radius: var(--radius-md);
}

/* Was `section h2`, which decorated the heading of anything grouped in a
   <section> — including the title inside a .surface's header strip, landing an
   accent rule a few pixels above that strip's own border. Scoped to the card
   that wants it. */
.panel > h2,
.card > h2 {
	color: var(--color-text);
	font-size: var(--font-size-2xl);
	font-weight: var(--font-weight-bold);
	border-bottom: 2px solid var(--color-primary);
	padding-bottom: var(--space-sm);
}

.bordered {
	border-color: var(--color-primary);
}

.panel.secondary > h2,
.card.secondary > h2 {
	border-bottom-color: var(--color-secondary);
}

.panel.tertiary > h2,
.card.tertiary > h2 {
	border-bottom-color: var(--color-tertiary);
}

section > dl,
section > details,
section > table,
section > [role="group"] {
	margin-top: var(--space-lg);
}

section dl {
	display: grid;
	grid-template-columns: auto 1fr;
	gap: var(--space-sm) var(--space-lg);

	dt {
		font-weight: var(--font-weight-bold);
		color: var(--color-text-muted);
	}

	dd {
		font-family: var(--font-family-mono), monospace;
	}
}

/* --- modals.css -------------------------------------------------------- */
/* Modal Dialog */
dialog {
	max-width: var(--modal-max-width);
	max-height: calc(100dvh - 4rem);
	margin: auto;
	padding: 0;
	border: none;
	border-radius: var(--radius-lg);
	box-shadow: var(--shadow-modal);
	background: transparent;
	overflow: visible;

	
	@media (prefers-color-scheme: dark) {
		box-shadow: 0 8px 32px rgba(0, 0, 0, 0.6);
	}
	

	&::backdrop {
		/* Re-declared here, not inherited. ::backdrop neither inherits from nor is
		   inherited by any element, and only Safari 17.4 / Chrome 122 began
		   resolving custom properties from the originating element. Before that
		   the var is unresolved and the backdrop paints transparent — while the
		   blur still applies, so the page behind goes blurry but unshaded and
		   the modal's own text loses its contrast. */
		--modal-backdrop: rgba(0, 0, 0, 0.5);
		background: var(--modal-backdrop);
		/* Both, and the prefixed one is not vestigial: unprefixed backdrop-filter
		   only became Baseline in September 2024 (Safari 18), so every earlier
		   Safari and iOS — still a live population — sees nothing without it. */
		backdrop-filter: blur(4px);
		-webkit-backdrop-filter: blur(4px);
	}

	> article {
		max-height: calc(100dvh - 4rem);
		overflow-y: auto;

		> header {
			display: flex;
			justify-content: space-between;
			align-items: center;
			gap: var(--space-md);

			button[aria-label="Close"] {
				margin-left: auto;
				padding: var(--space-xs);
				background: transparent;
				border: none;
				color: var(--color-text-muted);
				cursor: pointer;
				font-size: var(--font-size-xl);
				line-height: 1;
				transition: color var(--transition-fast);

				&:hover {
					color: var(--color-text);
				}

				&::before {
					content: '×';
				}
			}
		}

		> footer {
			display: flex;
			gap: var(--space-md);
			justify-content: flex-end;
			align-items: center;
		}
	}

	&.modal-is-opening {
		animation: modal-fade-in var(--transition-fast) ease-out;
	}

	&.modal-is-closing {
		animation: modal-fade-out var(--transition-fast) ease-out;
	}
}

html.modal-is-open {
	overflow: hidden;
}

dialog.modal-is-opening {
	animation: modal-fade-in var(--transition-fast) ease-out;
}

dialog.modal-is-closing {
	animation: modal-fade-out var(--transition-fast) ease-out;
}

@keyframes modal-fade-in {
	from {
		opacity: 0;
		transform: scale(0.95);
	}
	to {
		opacity: 1;
		transform: scale(1);
	}
}

@keyframes modal-fade-out {
	from {
		opacity: 1;
		transform: scale(1);
	}
	to {
		opacity: 0;
		transform: scale(0.95);
	}
}

/* --- prose.css --------------------------------------------------------- */
/* Prose — rendered Markdown.
   ==========================================================================
   One wrapper class rather than styling bare elements, because a document's
   headings and lists want different rules from an application's. Everything
   here is scoped to .prose so putting Markdown on a page cannot restyle the
   page around it. */

.prose {
	max-width: var(--measure);
	color: var(--color-text);
}

/* A document opens at its own top edge; the wrapper supplies the space. */
.prose > :first-child { margin-top: 0; }

.prose h1 {
	font-size: var(--font-size-2xl);
	margin-bottom: var(--space-lg);
}

/* Matched by ROLE rather than by level, and this is load-bearing for
   documents written by non-engineers: legal text routinely runs h1 → h3 → h4,
   skipping h2 entirely. Keying the major-section rule to h2 alone would leave
   those documents with no section breaks at all. h2 and h3 are both "a new
   section"; h4 and below are sub-headings. */
.prose h2,
.prose h3 {
	font-size: var(--font-size-lg);
	margin-top: var(--space-2xl);
	padding-top: var(--space-xl);
	border-top: var(--border-sm) solid var(--color-border);
}

.prose h4,
.prose h5,
.prose h6 {
	font-size: var(--font-size-base);
	font-weight: var(--font-weight-bold);
	letter-spacing: -.01em;
	margin-top: var(--space-xl);
	color: var(--color-heading);
}

.prose p { margin: 0 0 var(--space-md); }

.prose ul,
.prose ol {
	padding-left: var(--space-lg);
	margin: 0 0 var(--space-md);
}

.prose li { margin-bottom: var(--space-xs); }

/* Safari supports only color and font-size on ::marker; both are honoured. */
.prose li::marker { color: var(--color-primary); }

.prose strong {
	color: var(--color-heading);
	font-weight: var(--font-weight-bold);
}

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

.prose code {
	font-family: var(--font-family-mono);
	font-size: .875em;
	padding: .15em .4em;
	border-radius: var(--radius-sm);
	background: var(--color-surface-raised);
	border: var(--border-sm) solid var(--color-border);
	color: var(--color-accent-bright);
}

.prose blockquote {
	margin: var(--space-lg) 0;
	padding: var(--space-xs) 0 var(--space-xs) var(--space-md);
	border-left: var(--border-lg) solid var(--brand-from);
	color: var(--color-text-muted);
}

.prose table {
	width: 100%;
	border-collapse: collapse;
	margin: var(--space-lg) 0;
	font-size: var(--font-size-sm);
}

.prose th,
.prose td {
	padding: var(--space-sm);
	text-align: left;
	border-bottom: var(--border-sm) solid var(--color-border);
}

.prose thead th {
	color: var(--color-heading);
	font-weight: var(--font-weight-bold);
}

.prose hr {
	border: 0;
	border-top: var(--border-sm) solid var(--color-border);
	margin: var(--space-2xl) 0;
}

/* --- surfaces.css ------------------------------------------------------ */
/* Surfaces — one card, one action row.
   ==========================================================================
   Two of these existed in the application this was extracted from: a gradient
   .card used once on a marketing page, and a flat .panel used twenty-eight
   times in the app. Nobody chose to have both; the second was written when the
   first was somewhere else in the file. One component with a modifier is the
   fix, because the choice then has to be made out loud at the call site. */

.surface {
	background: var(--color-surface);
	border: var(--border-sm) solid var(--color-border);
	border-radius: var(--radius-lg);
	/* Clips a header strip's background to the rounded corner. */
	overflow: hidden;
}

/* The lit variant. This is the gradient the marketing card had, now available
   to anything rather than to one element. */
.surface-lit {
	background: var(--gradient-surface);
}

/* A gradient border, which a plain border-color cannot express: the border box
   is painted with the gradient and the padding box masked back over it.
   background-clip with two backgrounds is the technique that works without a
   pseudo-element, and it composites correctly over the page's wash. */
.surface-edge {
	border-color: transparent;
	background:
		linear-gradient(var(--color-surface), var(--color-surface)) padding-box,
		var(--gradient-border) border-box;
}

.surface-lit.surface-edge {
	background:
		var(--gradient-surface) padding-box,
		var(--gradient-border) border-box;
}

/* No `.surface + .surface { margin-top }`. A component that spaces itself from
   its siblings works only when siblings are stacked in normal flow, and breaks
   the moment a container lays them out itself: two surfaces side by side in a
   grid had the second pushed down by the margin, so a two-card row rendered
   with one card lower than the other. Spacing between children belongs to the
   container — grid and flex both have `gap` — and a card that is placed
   somewhere should look the same wherever it is placed. */

/* A surface's header strip: a title on the left, a count or status on the
   right, a rule underneath. */
.surface-head {
	display: flex;
	align-items: baseline;
	justify-content: space-between;
	gap: var(--space-md);
	padding: var(--space-sm) var(--space-md);
	border-bottom: var(--border-sm) solid var(--color-border);
}

.surface-head > :first-child {
	margin: 0;
	font-size: var(--font-size-base);
	font-weight: var(--font-weight-medium);
	color: var(--color-heading);
}

/* Plain content inside a surface. Without this a surface can only hold a header
   strip, a form, an action row, a note or a table — there was nowhere for a
   paragraph to live, and every consumer invented its own padded div. */
.surface-body {
	padding: var(--space-md);
}

/* A footnote inside a surface: methodology, a caveat, what a column means. */
.surface-note {
	margin: 0;
	padding: var(--space-sm) var(--space-md);
	font-size: var(--font-size-xs);
	line-height: var(--line-height-relaxed);
	color: var(--color-text-muted);
	border-top: var(--border-sm) solid var(--color-border);
}

/* THE action row. One component, and it carries its own padding.
   The version this replaces had two: one with padding that only worked inside
   a form wrapper, and one without that only worked as a direct child of a
   card. Using the wrong one put the button flush against the card's edge, and
   which was wrong depended on where you put it — so the rule was invisible
   until it looked wrong. */
.actions {
	display: flex;
	align-items: center;
	gap: var(--space-sm);
	padding: var(--space-sm) var(--space-md) var(--space-md);
}

/* Right-aligned, for a form's submit row. A modifier rather than a second
   component, so the padding cannot diverge again. */
.actions-end { justify-content: flex-end; }

/* Nothing here yet. A distinct component because "no rows" is a state worth
   designing, not an empty table. */
.empty {
	margin: 0;
	padding: var(--space-md);
	color: var(--color-text-muted);
	font-size: var(--font-size-sm);
}

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

/* --- tables.css -------------------------------------------------------- */
/* Base Table */
table {
	width: 100%;
	border-collapse: collapse;
	background: var(--color-background);
	font-family: var(--font-family-base);
	font-size: var(--font-size-base);
	color: var(--color-text);
	/* No margin. A bare `table` sitting in a document wants space around it,
	   but a table inside a card is the card's content and the card owns its
	   padding — a page-level margin there punches a hole under the last row.
	   Prose sets its own margin on .prose table, which is where the document
	   case actually lives. */

	&.caption-h3 {
		caption {
			color: var(--color-text);
			font-weight: var(--font-weight-bold);
			margin: 0;
			font-size:  var(--font-size-xl);
			text-align: start;
		}
	}

	thead {
		background: var(--color-surface);
		border-bottom: 2px solid var(--color-border);
	}

	th {
		text-align: left;
		font-weight: var(--font-weight-bold);
		padding: var(--space-md);
		color: var(--color-text);
	}

	td {
		padding: var(--space-md);
		border-bottom: 1px solid var(--color-border);
	}

	tbody tr:last-child td {
		border-bottom: none;
	}

	&.table-bordered {
		border: var(--border-sm) solid var(--color-border);
		border-radius: var(--radius-md);
		overflow: hidden;

		th, td {
			border: var(--border-sm) solid var(--color-border);
		}
	}

	&.table-striped tbody tr {
		&:nth-child(odd) {
			background: var(--color-surface);
		}

		&:nth-child(even) {
			background: var(--color-background);
		}
	}

	&.table-hover tbody tr {
		transition: background-color var(--transition-fast) ease;
		cursor: pointer;

		&:hover {
			background: var(--color-surface);
		}
	}

	&.table-striped.table-hover tbody tr {
		&:hover {
			background: var(--color-primary);
			color: var(--color-background);
		}
	}

	&.table-compact {
		th, td {
			padding: var(--space-sm);
			font-size: var(--font-size-sm);
		}
	}

	&.table-spacious {
		th, td {
			padding: var(--space-lg);
		}
	}
}

/* Status Indicators */
td.status-active,
tr.status-active {
	border-left: var(--status-border-width) solid var(--color-success);
}

td.status-error,
tr.status-error {
	border-left: var(--status-border-width) solid var(--color-error);
}

td.status-warning,
tr.status-warning {
	border-left: var(--status-border-width) solid var(--color-warning);
}

td.status-info,
tr.status-info {
	border-left: var(--status-border-width) solid var(--color-info);
}

/* Data Columns */
td.data-mono,
th.data-mono {
	font-family: var(--font-family-mono);
	font-size: var(--font-size-sm);
}

td.data-numeric,
th.data-numeric {
	text-align: right;
	font-family: var(--font-family-mono);
	font-size: var(--font-size-sm);
}

td.data-timestamp,
th.data-timestamp {
	font-family: var(--font-family-mono);
	font-size: var(--font-size-xs);
	color: var(--color-text-muted);
}

/* Status Badges */
.status-badge {
	display: inline-block;
	padding: var(--space-xs) var(--space-sm);
	border-radius: var(--radius-sm);
	font-size: var(--font-size-xs);
	font-weight: var(--font-weight-medium);
	text-transform: uppercase;
	letter-spacing: 0.05em;
}

.status-badge.badge-success {
	background: var(--color-success);
	color: var(--color-background);
}

.status-badge.badge-error {
	background: var(--color-error);
	color: var(--color-background);
}

.status-badge.badge-warning {
	background: var(--color-warning);
	color: var(--color-text);
}

.status-badge.badge-info {
	background: var(--color-info);
	color: var(--color-background);
}

/* Sortable */
th.sortable {
	cursor: pointer;
	-webkit-user-select: none; /* the only form Safari honours */
	user-select: none;
	position: relative;
	padding-right: var(--space-xl);
}

th.sortable:hover {
	background: var(--color-background);
}

th.sortable::after {
	content: '↕';
	position: absolute;
	right: var(--space-md);
	color: var(--color-text-muted);
	opacity: 0.5;
}

th.sortable.sort-asc::after {
	content: '↑';
	color: var(--color-primary);
	opacity: 1;
}

th.sortable.sort-desc::after {
	content: '↓';
	color: var(--color-primary);
	opacity: 1;
}

/* Responsive */
.table-container {
	overflow-x: auto;
	border: var(--border-sm) solid var(--color-border);
	border-radius: var(--radius-md);
	margin-bottom: var(--space-lg);
}

.table-container table {
	margin-bottom: 0;
	border: none;
}

@media (max-width: 768px) {
	table.table-responsive thead {
		display: none;
	}

	table.table-responsive tr {
		display: block;
		margin-bottom: var(--space-lg);
		border: var(--border-sm) solid var(--color-border);
		border-radius: var(--radius-md);
	}

	table.table-responsive td {
		display: block;
		text-align: right;
		padding: var(--space-sm) var(--space-md);
		border: none;
	}

	table.table-responsive td::before {
		content: attr(data-label);
		float: left;
		font-weight: var(--font-weight-bold);
		color: var(--color-text-muted);
	}
}

/* Fixed Header */
.table-fixed-header {
	max-height: var(--table-max-height);
	overflow-y: auto;
	border: var(--border-sm) solid var(--color-border);
	border-radius: var(--radius-md);
}

.table-fixed-header table {
	border: none;
}

.table-fixed-header thead {
	position: sticky;
	top: 0;
	z-index: 10;
}

/* Empty State */
.table-empty {
	text-align: center;
	padding: var(--space-3xl);
	color: var(--color-text-muted);
	font-style: italic;
}

/* --- vertical alignment ---------------------------------------------------
   How cell content sits vertically is a decision per table, per row, or per
   cell, and it is a real one once a row is taller than its shortest cell: a
   button beside a two-line name floats at the top of the row and reads as
   misaligned.

   Expressed as a custom property rather than as three unrelated classes,
   because custom properties inherit. Set --cell-align on the table and every
   cell follows; set it on one row or one cell to override just that. The
   classes are a spelling of the token, not a second mechanism. */

th, td { vertical-align: var(--cell-align, middle); }

.cell-top    { --cell-align: top; }
.cell-middle { --cell-align: middle; }
.cell-bottom { --cell-align: bottom; }

/* --- controls in cells ---------------------------------------------------
   A table of inputs is an editable grid, and an input floating inside a
   padded cell reads as a box inside a box: two borders a few pixels apart,
   neither of which is the cell. The control should BE the cell.

   Two cases, and the difference is whether anything else is visible in there.

   1. The control is the cell's only visible content. The cell drops its
      padding, the control fills it, and its border lands exactly on the cell
      edge with no radius — so a column of them reads as one grid rather than
      as a stack of pills.

   2. Something else is visible too — a slug under a name, a validation
      message. Then the control keeps its own shape and only stretches to the
      full width, because the cell still has other content to space. */

/* Case 2 first, so case 1 can override it. */
td > input,
td > select,
td > textarea { width: 100%; }

/* Case 1. "Only visible content" is not the same as :only-child: a real cell
   also holds a visually-hidden <label> naming the control, and often a hidden
   input carrying an id. Both are elements and neither is on screen, so
   :only-child would never match the markup that needs this most.
   
   So: a cell that HAS a control, and does NOT have any element child that is
   something other than a control or visually hidden. input[type=hidden] is an
   input, so it is already excluded by :not(input).

   The :not()s are chained rather than written as one selector list, and the
   reason is SPECIFICITY, not compatibility — both forms work everywhere :has()
   does. :not() takes the specificity of its most specific argument, so the list
   form :not(input, select, textarea, .sr-only) counts once, as .sr-only, and the
   whole selector lands at (0,1,2). Chained, each :not() contributes separately
   and it lands at (0,1,5) — enough to outrank the per-table padding rules a
   consumer writes for its own cells, which is what this has to beat to work at
   all. Do not "simplify" the chain to a list without re-checking that.

   One limit worth knowing: this inspects ELEMENT children only. A cell holding
   an input plus a bare text node still matches, because text nodes are
   invisible to selectors. */
td:has(> input, > select, > textarea):not(:has(> *:not(input):not(select):not(textarea):not(.sr-only))) {
	/* One pixel, so the control sits just INSIDE the cell's rule rather than
	   flush against it. Flush, the control's own border is eclipsed by the
	   cell's — and the focus border with it, which is the one that has to be
	   seen. */
	padding: 1px;
	/* The CELL draws the grid line. Both were drawing one: the control's border
	   sat a pixel inside the cell's, so two filled cells side by side showed a
	   two-pixel seam, and the row separator underneath — a different colour —
	   made a third line. With border-collapse: collapse, which every table here
	   uses, adjacent cell borders merge into one. */
	border: var(--border-sm) solid var(--color-border);
	/* height: 1px is not a height, it is a declaration that the height is
	   DEFINITE — which is what a percentage height on the child needs in order
	   to resolve. The row still sizes the cell; without this the child's
	   height: 100% is treated as auto and a short control floats at the top of
	   a cell made tall by its neighbours. Measured: 30px in an 82px cell.
	   Nothing else works — not height:100% on the cell, not align-self, and
	   making the cell a flex container collapses the row. */
	height: 1px;
}

td:has(> input, > select, > textarea):not(:has(> *:not(input):not(select):not(textarea):not(.sr-only))) > input,
td:has(> input, > select, > textarea):not(:has(> *:not(input):not(select):not(textarea):not(.sr-only))) > select,
td:has(> input, > select, > textarea):not(:has(> *:not(input):not(select):not(textarea):not(.sr-only))) > textarea {
	/* border-box, so the border is drawn INSIDE the 100% and the control cannot
	   grow past the cell it is filling. */
	box-sizing: border-box;
	width: 100%;
	height: 100%;
	border-radius: 0;

	/* The border stays, always, and only its colour changes. Removing it when
	   idle and adding it on focus would reflow the row by a pixel every time
	   the caret moved; translucent means the space is always reserved. Faint
	   rather than absent so a filled cell still reads as a field. */
	border: var(--border-sm) solid color-mix(in srgb, var(--color-border) 45%, transparent);

	/* Keeps the field's own ground, so a filled cell reads as something you can
	   type into rather than as a cell that happens to accept a caret. */
	background: var(--color-background);
}

/* Focus draws inside the cell. outline-offset is negative so the ring lands
   within the padding rather than on top of — or outside — the cell's rule,
   where the grid line would swallow it. The border colours up with it; on its
   own a one-pixel colour change is a weak indicator, and the two together
   are unambiguous without either of them moving anything. */
td:has(> input, > select, > textarea):not(:has(> *:not(input):not(select):not(textarea):not(.sr-only))) > input:focus-visible,
td:has(> input, > select, > textarea):not(:has(> *:not(input):not(select):not(textarea):not(.sr-only))) > select:focus-visible,
td:has(> input, > select, > textarea):not(:has(> *:not(input):not(select):not(textarea):not(.sr-only))) > textarea:focus-visible {
	border-color: var(--color-accent-bright);
	outline: var(--border-lg) solid var(--color-accent-bright);
	outline-offset: -2px;
}

/* --- tabs.css ---------------------------------------------------------- */
/* Tab Navigation */
[role="tablist"] {
    display: flex;
    gap: var(--space-sm);
    border-bottom: 2px solid var(--color-border);
    margin-bottom: var(--space-lg);
    overflow-x: auto;
}

[role="tab"] {
    padding: var(--space-sm) var(--space-md);
    background: none;
    border: none;
    border-bottom: 2px solid transparent;
    cursor: pointer;
    font-weight: var(--font-weight-medium);
    color: var(--color-text-muted);
    transition: color var(--transition-fast), border-color var(--transition-fast);
    white-space: nowrap;
}

[role="tab"]:hover {
    color: var(--color-text);
}

[role="tab"][aria-selected="true"] {
    color: var(--color-primary);
    border-bottom-color: var(--color-primary);
}

[role="tabpanel"] {
    animation: fadeIn var(--transition-fast) ease-in;
}

@keyframes fadeIn {
    from { opacity: 0; }
    to { opacity: 1; }
}

/* --- utilities.css ----------------------------------------------------- */
/* Utilities — the handful of classes every page reaches for.
   ==========================================================================
   Deliberately few. A utility earns its place by being needed on elements
   that share nothing else; anything that describes a component belongs to
   that component instead. */

/* Visible to a screen reader, to nothing else.
   Not display: none, which removes it from the accessibility tree as well,
   and not width/height 0, which some browsers collapse out of it too. The
   clip-path rectangle is what keeps the text rendered and unreadable. */
.sr-only {
	position: absolute;
	width: 1px;
	height: 1px;
	padding: 0;
	margin: -1px;
	overflow: hidden;
	clip-path: inset(50%);
	white-space: nowrap;
	border: 0;
}

/* The small capitalised label above a heading, with a lit dot. Names the
   section a heading belongs to without competing with it. */
.eyebrow {
	display: inline-flex;
	align-items: center;
	gap: var(--space-sm);
	margin: 0 0 var(--space-md);
	font-family: var(--font-family-mono);
	font-size: var(--font-size-xs);
	font-weight: var(--font-weight-medium);
	letter-spacing: .16em;
	text-transform: uppercase;
	color: var(--color-accent);
}

.eyebrow::before {
	content: '';
	width: .4rem;
	height: .4rem;
	border-radius: 50%;
	background: var(--color-accent);
	box-shadow: 0 0 0 .2rem color-mix(in srgb, var(--color-accent) 18%, transparent);
}

/* The opening paragraph, set larger than body copy and held to a readable
   measure. Line length is a legibility constraint, not a layout preference. */
.lede {
	font-size: var(--font-size-lg);
	line-height: var(--line-height-relaxed);
	color: var(--color-text);
	max-width: var(--measure);
}

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

.mono {
	font-family: var(--font-family-mono);
	/* em, not rem: a monospace face at the same nominal size reads larger than
	   the body face beside it, so this shrinks relative to wherever it sits. */
	font-size: .95em;
	letter-spacing: -.01em;
}

/* Figures that change in place — a live total, a column of returns. Tabular
   numerals keep the digits from shifting sideways as the value updates. */
.num {
	text-align: right;
	font-variant-numeric: tabular-nums;
}

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