/*
 * Peddie Cost Calculator: design system and page shell.
 * A two-ink catalog: the P's navy and old gold on white (dark mode is the same job on navy stock),
 * Besley for the school's voice and Public Sans, with tabular figures, for everything you scan.
 * No shadows, no gradients: hierarchy comes from frame, rule and radius.
 *
 * Contents
 *   1. Tokens (colour, type, space, radius, motion, z-index) and the dark scheme
 *   2. Base, utilities, accessibility
 *   3. Shared components (buttons, fields, chips, tags, notices, cards, skeletons, ...)
 *   4. Shell (app bar, hero, steps, builder, panels, layout, review, why, footer, total bar)
 *   5. Toasts
 *   6. Motion, reduced motion, forced colors, print
 *
 * builder.css (courses, activities, trips) and estimate.css (rail, review, plan) load after this file and
 * only style their own blocks. Colours are tokens, never raw hex, outside the print block.
 */

/* ---------- 1. Tokens ---------- */
:root {
	color-scheme: light dark;

	/* Brand constants: the same in both schemes. */
	--navy: #0a2341;
	--navy-chip: #12305a;
	--navy-screen: #7e8ca3;
	--on-navy: #ffffff;
	--on-navy-2: #b9c4d6;
	--gold-bright: #d2af55;
	--gold-hover: #c79e38;
	--gold-press: #ddbe70;

	/* Scheme colours (light): two inks on white stock. Navy is ink, gold means "yours". */
	--bg: #ffffff;
	--surface: #ffffff;
	--surface-2: #eef1f5;
	--surface-hover: #eef1f5;
	--field: #ffffff;
	--border: #d3d9e3;
	--border-strong: #aab3c2;
	--control-border: #6e7b91;
	--ink: #0a2341;
	--text: #1a2e4c;
	--text-2: #536179;
	--muted: #536179;
	--primary: #0a2341;
	--primary-hover: #13325c;
	--primary-press: #061630;
	--on-primary: #ffffff;
	--primary-ink: #0a2341;
	--selected: #f1e4bf;
	--selected-2: #e8d6a4;
	--selected-ink: #0a2341;
	--selection: #ebd9a8;
	--focus: #0a2341;
	--gold-fill: #ab8322;
	--gold-ink: #7a5a10;
	--area-textbooks: #0a2341;
	--area-activities: #ab8322;
	--area-other: #6e7b91;
	--support: #ab8322;
	--support-track: #eef1f5;
	--error: #a3261b;
	--toast-bg: #0a2341;
	--toast-ink: #ffffff;
	--toast-action: #d2af55;
	--skeleton: #eef1f5;
	--tile: #0a2341;
	--tile-edge: #0a2341;
	--tile-gold: #b68d2c;
	--foot-bg: #ffffff;
	--foot-edge: #0a2341;
	--foot-ink: #0a2341;
	--foot-ink-2: #536179;

	/* Fonts: Besley (a Clarendon revival, like the P) speaks; Public Sans lists, with tabular figures. */
	--font-display: "Besley", "Clarendon", Georgia, serif;
	--font-ui: "Public Sans", system-ui, -apple-system, "Segoe UI", sans-serif;

	/* Type scale (The Elements of Typographic Style: 14 16 18 21 24 36 48 60 72). The display and h2 steps
	   are redefined per breakpoint below; each size has a line-height partner (--lh-*). */
	--fs-display: 36px;
	--lh-display: 38px;
	--fs-h2: 28px;
	--lh-h2: 32px;
	--fs-h3: 1.3125rem;
	--lh-h3: 26px;
	--fs-card: 1.3125rem;
	--fs-lede: 1.125rem;
	--lh-lede: 28px;
	--fs-hero-sub: 1.125rem;
	--lh-hero-sub: 28px;
	--fs-body: 1rem;
	--lh-body: 24px;
	--fs-small: 0.875rem;
	--fs-meta: 0.875rem;
	--lh-small: 20px;
	--fs-money-bar: 1.75rem;
	--measure-lede: 60ch;
	--measure-body: 70ch;

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

	/* Radius by hierarchy: the tile is cut to the P mark's corner; rows and ledgers stay square. */
	--r-tile: 24px;
	--r-folder: 10px;
	--r-control: 6px;
	--r-tag: 3px;
	--r-round: 999px; /* circles only (the count badge), never a pill-shaped control */

	/* There are no shadows: hierarchy is frame, rule and radius. */

	/* Layout. The toast placement in section 5 reuses these, so keep the names. */
	--gutter: 16px;
	--wrap-max: 1280px;
	--layout-gap: 2.5rem;
	--statement-col: clamp(340px, 28vw, 380px);

	/* Motion */
	--ease-out: cubic-bezier(0.2, 0.7, 0.2, 1);
	--ease-standard: cubic-bezier(0.4, 0, 0.2, 1);
	--dur-1: 120ms;

	/* z-index */
	--z-tab: 6; /* the open index tab stays above the panel lift (z-index 5) while a combobox is open */
	--z-rail: 10;
	--z-listbox: 20;
	--z-totalbar: 40;
	--z-toast: 50;
	--z-skip: 100;

	/* Checked-checkbox tick: navy on the gold fill in both schemes. The chevron mask draws the disclosure and select carets. */
	--check-mark: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%230a2341' stroke-width='3' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M5 12.5l4.5 4.5L19 7.5'/%3E%3C/svg%3E");
	--mask-chevron: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2.25' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M6 9.5l6 6 6-6'/%3E%3C/svg%3E");
}

@media (prefers-color-scheme: dark) {
	:root {
		/* The same job printed on the catalog's navy cover stock. Gold stays reserved for what the person chose. */
		--bg: #0a2341;
		--surface: #0c274a;
		--surface-2: #12305a;
		--surface-hover: #163766;
		--field: #12305a;
		--border: #2a4572;
		--border-strong: #4b6290;
		--control-border: #8193b4;
		--ink: #eef1f6;
		--text: #dce3ee;
		--text-2: #a9b6cc;
		--muted: #a9b6cc;
		--primary: #eef1f6;
		--primary-hover: #ffffff;
		--primary-press: #d5dce8;
		--on-primary: #0a2341;
		--primary-ink: #eef1f6;
		--selected: #1b3866;
		--selected-2: #274a80;
		--selected-ink: #eef1f6;
		--selection: #5c4b1c;
		--focus: #d2af55;
		--gold-fill: #d2af55;
		--gold-ink: #d2af55;
		--area-textbooks: #eef1f6;
		--area-activities: #d2af55;
		--area-other: #7e8ca3;
		--support: #d2af55;
		--support-track: #12305a;
		--error: #ff9c8a;
		--toast-bg: #eef1f6;
		--toast-ink: #0a2341;
		--toast-action: #7a5a10;
		--skeleton: #12305a;
		--tile: #061630;
		--tile-edge: #b68d2c;
		--tile-gold: #d2af55;
		--foot-bg: #061630;
		--foot-edge: #b68d2c;
		--foot-ink: #eef1f6;
		--foot-ink-2: #b9c4d6;
	}
}

@media (min-width: 768px) {
	:root {
		--gutter: 32px;
	}
}

/* Display and heading steps by breakpoint (display 72/60/48/36/32, h2 36/28). */
@media (max-width: 359px) {
	:root {
		--fs-display: 32px;
		--lh-display: 34px;
	}
}

@media (min-width: 600px) {
	:root {
		--fs-h2: 36px;
		--lh-h2: 40px;
	}
}

@media (min-width: 720px) {
	:root {
		--fs-display: 48px;
		--lh-display: 50px;
		--fs-hero-sub: 1.3125rem;
		--lh-hero-sub: 32px;
	}
}

@media (min-width: 900px) {
	:root {
		--fs-display: 60px;
		--lh-display: 62px;
	}
}

@media (min-width: 1200px) {
	:root {
		--fs-display: 72px;
		--lh-display: 72px;
	}
}

/* ---------- 2. Base, utilities, accessibility ---------- */
*,
*::before,
*::after {
	box-sizing: border-box;
}

html {
	scroll-padding-top: 1rem;
	-webkit-text-size-adjust: 100%;
	text-size-adjust: 100%;
}

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

[hidden] {
	display: none !important;
}

body {
	margin: 0;
	background: var(--bg);
	color: var(--text);
	font: 400 var(--fs-body)/var(--lh-body) var(--font-ui);
	font-variant-numeric: lining-nums;
	-webkit-font-smoothing: antialiased;
	-moz-osx-font-smoothing: grayscale;
	overflow-wrap: break-word;
}

h1,
h2,
h3,
h4,
h5,
p,
ul,
ol,
dl,
dd,
figure,
fieldset {
	margin: 0;
	padding: 0;
}

ul,
ol {
	list-style: none;
}

/* Besley speaks. It is never given tabular figures (its tabular zero is broken): money columns use .money. */
h1,
h2,
h3,
h4,
h5 {
	font-family: var(--font-display);
	font-weight: 700;
	color: var(--ink);
	line-height: 1.2;
	text-wrap: balance;
}

h1 {
	font-size: var(--fs-display);
	font-weight: 800;
	line-height: var(--lh-display);
	letter-spacing: -0.012em;
}

h2 {
	font-size: var(--fs-h2);
	line-height: var(--lh-h2);
}

h3 {
	font-size: var(--fs-h3);
	line-height: var(--lh-h3);
}

/* Line length: body copy stops at 70ch, ledes at 60ch. */
p {
	max-width: var(--measure-body);
	text-wrap: pretty;
}

[class*="__lede"] {
	max-width: var(--measure-lede);
}

fieldset {
	min-width: 0;
	border: 0;
}

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

button {
	cursor: pointer;
}

img,
svg {
	max-width: 100%;
}

/* Code and ISBNs use Public Sans with tabular figures, like every other figure. */
code {
	padding: 0.1em 0.4em;
	border-radius: var(--r-tag);
	background: var(--surface-2);
	color: var(--ink);
	font: 500 0.9em/1.4 var(--font-ui);
	font-variant-numeric: tabular-nums lining-nums;
	overflow-wrap: anywhere;
}

mark {
	padding: 0 0.1em;
	border-radius: var(--r-tag);
	background: var(--selected-2);
	color: var(--selected-ink);
}

::selection {
	background: var(--selection);
	color: var(--ink);
}

/* Money: Public Sans, tabular lining figures, so a column of prices shares one right edge. */
.money {
	font-family: var(--font-ui);
	font-variant-numeric: tabular-nums lining-nums;
	white-space: nowrap;
}

main:focus {
	outline: none;
}

[tabindex="-1"]:focus:not(:focus-visible) {
	outline: none;
}

a {
	color: var(--primary-ink);
	text-decoration: underline;
	text-decoration-thickness: 1px;
	text-underline-offset: 3px;
}

/* :where() keeps hover from out-ranking component colours such as .btn and .kpi__link. */
a:where(:hover) {
	color: var(--primary-hover);
	text-decoration-thickness: 2px;
}

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

.wrap {
	max-width: var(--wrap-max);
	margin-inline: auto;
	padding-inline: var(--gutter);
}

.visually-hidden {
	position: absolute !important;
	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;
}

.skip-link {
	position: fixed;
	z-index: var(--z-skip);
	top: var(--sp-2);
	left: var(--sp-2);
	padding: 0.75rem 1rem;
	border: 1.5px solid var(--on-primary);
	border-radius: var(--r-control);
	background: var(--primary);
	color: var(--on-primary);
	font-weight: 600;
	text-decoration: none;
	transform: translateY(-300%);
}

.skip-link:focus {
	transform: none;
}

/* Navy-filled controls ring in gold ink (light), never in the navy of their own fill. In dark the ring is gold already. */
.btn--primary:focus-visible,
.skip-link:focus-visible,
.chip:has(> input:checked:focus-visible),
.segmented__opt:has(> input:checked:focus-visible) {
	outline-color: var(--gold-ink);
}

svg.icon {
	width: 1.25em;
	height: 1.25em;
	flex: none;
	stroke-width: 1.75;
}

/* Audience copy: the audience never hides calculator content, only static wording. */
html:not([data-audience="exploring"]) [data-audience-show="exploring"] {
	display: none;
}

html[data-audience="exploring"] [data-audience-show="enrolled"] {
	display: none;
}

/* ---------- 3. Shared components ---------- */

/* Buttons */
.btn {
	position: relative;
	display: inline-flex;
	align-items: center;
	justify-content: center;
	gap: var(--sp-2);
	min-height: 48px;
	padding: 0 20px;
	border: 1.5px solid transparent;
	border-radius: var(--r-control);
	background: transparent;
	color: var(--ink);
	font: 600 var(--fs-body)/1.25 var(--font-ui);
	text-align: center;
	text-decoration: none;
	cursor: pointer;
	user-select: none;
	transition: background-color var(--dur-1) var(--ease-standard), border-color var(--dur-1) var(--ease-standard), color var(--dur-1) var(--ease-standard);
}

.btn .icon {
	width: 18px;
	height: 18px;
}

/* Primary: navy ink on paper; in dark, paper-white with navy text (gold stays reserved for what you chose). */
.btn--primary {
	border-color: var(--primary);
	background: var(--primary);
	color: var(--on-primary);
}

/* Secondary: a 1.5px outline in ink. */
.btn--secondary {
	border-color: var(--ink);
	background: transparent;
	color: var(--ink);
}

/* Quiet: underlined text with a 44px hit area. */
.btn--quiet {
	min-height: 44px;
	padding: 0 4px;
	color: var(--ink);
	font-weight: 500;
	text-decoration: underline;
	text-decoration-thickness: 1px;
	text-underline-offset: 3px;
}

/* Small buttons stay 44px tall. */
.btn--small {
	padding: 0 14px;
	font-size: 0.9375rem;
}

.btn--quiet.btn--small {
	padding: 0 4px;
}

.btn--block {
	width: 100%;
}

@media (hover: hover) {
	.btn--primary:hover {
		border-color: var(--primary-hover);
		background: var(--primary-hover);
		color: var(--on-primary);
	}

	.btn--secondary:hover {
		background: var(--surface-hover);
		color: var(--ink);
	}

	.btn--quiet:hover {
		background: transparent;
		text-decoration-thickness: 2px;
	}

	.btn--quiet.btn--danger:hover {
		color: var(--error);
	}
}

.btn--primary:active {
	border-color: var(--primary-press);
	background: var(--primary-press);
}

.btn[aria-disabled="true"],
.btn:disabled {
	border-color: var(--border-strong);
	background: transparent;
	color: var(--muted);
	cursor: not-allowed;
	text-decoration: none;
}

.btn--quiet[aria-disabled="true"],
.btn--quiet:disabled {
	border-color: transparent;
	text-decoration: underline;
}

/* Icon button: 44x44 hit area, a 34px visible square with a 6px radius and a 1px rule border. */
.icon-btn {
	position: relative;
	display: inline-grid;
	place-items: center;
	flex: none;
	width: 44px;
	height: 44px;
	padding: 0;
	border: 0;
	background: transparent;
	color: var(--ink);
}

.icon-btn::before {
	content: "";
	position: absolute;
	top: 50%;
	left: 50%;
	width: 34px;
	height: 34px;
	border: 1px solid var(--border-strong);
	border-radius: var(--r-control);
	transform: translate(-50%, -50%);
	transition: background-color var(--dur-1), border-color var(--dur-1);
}

.icon-btn .icon {
	position: relative;
	width: 16px;
	height: 16px;
}

@media (hover: hover) {
	.icon-btn:hover::before {
		border-color: var(--control-border);
		background: var(--surface-2);
	}
}

/* Fields */
.field {
	display: grid;
	gap: 6px;
	min-width: 0;
}

.field__label {
	color: var(--ink);
	font-size: var(--fs-body);
	font-weight: 600;
	line-height: 1.5;
}

.field__hint {
	color: var(--text-2);
	font-size: var(--fs-small);
	line-height: var(--lh-small);
}

.field__error {
	display: flex;
	align-items: flex-start;
	gap: 6px;
	color: var(--error);
	font-size: var(--fs-small);
	font-weight: 600;
	line-height: var(--lh-small);
}

.field__error .icon {
	margin-top: 1px;
	color: var(--error);
}

/* Fields are 52px with a 1.5px line; on focus the border goes ink at 2px, and the ring draws outside it. */
.input,
.select select {
	display: block;
	width: 100%;
	min-height: 52px;
	padding: 0 16px;
	border: 1.5px solid var(--control-border);
	border-radius: var(--r-control);
	background: var(--field);
	color: var(--ink);
	font-size: var(--fs-body);
	line-height: 1.4;
	transition: border-color var(--dur-1), background-color var(--dur-1);
}

.input--lg {
	min-height: 52px;
}

.input::placeholder {
	color: var(--text-2);
	opacity: 1;
}

@media (hover: hover) {
	.input:hover,
	.select select:hover {
		border-color: var(--ink);
	}
}

.input:focus,
.select select:focus {
	border-width: 2px;
	border-color: var(--ink);
}

.input:disabled,
.select select:disabled {
	border-style: dashed;
	border-color: var(--border-strong);
	background: var(--surface-2);
	color: var(--muted);
	cursor: not-allowed;
}

.input[aria-invalid="true"],
.select select[aria-invalid="true"] {
	border-width: 2px;
	border-color: var(--error);
}

.input[type="search"]::-webkit-search-cancel-button {
	cursor: pointer;
}

.input-icon,
.input-money,
.select {
	position: relative;
}

.input-icon > .icon {
	position: absolute;
	top: 50%;
	left: 16px;
	z-index: 1;
	width: 20px;
	height: 20px;
	color: var(--text-2);
	transform: translateY(-50%);
	pointer-events: none;
}

.input-icon > .input {
	padding-left: 48px;
}

.input-money__prefix {
	position: absolute;
	top: 50%;
	left: 16px;
	z-index: 1;
	color: var(--text-2);
	font-weight: 600;
	transform: translateY(-50%);
	pointer-events: none;
}

.input-money > .input {
	padding-left: 32px;
	font-variant-numeric: tabular-nums lining-nums;
}

.select select {
	padding-right: 44px;
	appearance: none;
	-webkit-appearance: none;
	text-overflow: ellipsis;
}

.select::after {
	content: "";
	position: absolute;
	top: 50%;
	right: 14px;
	width: 20px;
	height: 20px;
	background: var(--ink);
	-webkit-mask: var(--mask-chevron) center / contain no-repeat;
	mask: var(--mask-chevron) center / contain no-repeat;
	transform: translateY(-50%);
	pointer-events: none;
}

/* Checkbox row */
.check {
	display: flex;
	align-items: center;
	gap: var(--sp-3);
	min-height: 44px;
	cursor: pointer;
}

.check__text {
	font-size: var(--fs-body);
	color: var(--text);
}

/* 24px, 4px radius, 1.5px line. Checked is "yours": a gold fill with a navy tick and a navy border. */
.check__box {
	flex: none;
	width: 24px;
	height: 24px;
	margin: 0;
	border: 1.5px solid var(--control-border);
	border-radius: 4px;
	background: var(--field) center / 18px no-repeat;
	appearance: none;
	-webkit-appearance: none;
	cursor: pointer;
}

.check__box:checked {
	border-color: var(--navy);
	background-color: var(--gold-fill);
	background-image: var(--check-mark);
}

/* A ring the colour of the fill is no ring: a focused, checked box takes the ink ring. */
.check__box:checked:focus-visible {
	outline-color: var(--ink);
}

@media (hover: hover) {
	.check__box:not(:checked):hover {
		border-color: var(--ink);
	}
}

/* Chips and segmented controls (the radio is visually hidden but focusable). */
.chips {
	display: flex;
	flex-wrap: wrap;
	gap: var(--sp-2);
}

.chip {
	position: relative;
	display: inline-flex;
	align-items: center;
	gap: 6px;
	min-height: 44px;
	padding: 0 16px;
	border: 1.5px solid var(--control-border);
	border-radius: var(--r-control);
	background: var(--field);
	color: var(--text);
	font: 500 var(--fs-body)/1.25 var(--font-ui);
	cursor: pointer;
	transition: background-color var(--dur-1), border-color var(--dur-1);
}

.chip__input,
.segmented__opt > input {
	position: absolute;
	inset: 0;
	width: 100%;
	height: 100%;
	margin: 0;
	opacity: 0;
	cursor: pointer;
}

.chip__text {
	min-width: 0;
}

/* The count badge is a circle: a navy dot with a white figure (inverted on a selected, navy segment). */
.chip__count {
	display: inline-grid;
	place-items: center;
	min-width: 22px;
	height: 22px;
	padding: 0 6px;
	border-radius: var(--r-round);
	background: var(--primary);
	color: var(--on-primary);
	font-size: 0.8125rem;
	font-weight: 700;
	line-height: 1;
	font-variant-numeric: tabular-nums lining-nums;
}

.chip__meta {
	color: var(--text-2);
	font-size: var(--fs-small);
	font-weight: 500;
}

@media (hover: hover) {
	.chip:hover {
		background: var(--surface-hover);
	}
}

.chip:has(> input:focus-visible) {
	z-index: 2;
	outline: 3px solid var(--focus);
	outline-offset: 2px;
}

/* Selected is navy (browse and setting controls): a --primary fill, --on-primary text, and a heavier weight. */
.chip:has(> input:checked) {
	z-index: 1;
	border-color: var(--primary);
	background: var(--primary);
	color: var(--on-primary);
	font-weight: 600;
}

.chip:has(> input:checked) .chip__meta {
	color: var(--on-primary);
}

.chip:has(> input:checked) .chip__count {
	background: var(--on-primary);
	color: var(--primary);
}

/* Joined segments: one row, shared 1.5px borders, outer corners rounded to 6px. */
.chips--joined {
	display: inline-flex;
	flex-wrap: nowrap;
	gap: 0;
	max-width: 100%;
}

.chips--joined > .chip {
	border-radius: 0;
}

.chips--joined > .chip + .chip {
	margin-left: -1.5px;
}

.chips--joined > .chip:first-child {
	border-radius: var(--r-control) 0 0 var(--r-control);
}

.chips--joined > .chip:last-child {
	border-radius: 0 var(--r-control) var(--r-control) 0;
}

/* A suggestion fills a field; it is a text button, not a pill. */
.chip--suggest {
	padding: 0 4px;
	border-color: transparent;
	background: transparent;
	color: var(--ink);
	font-weight: 500;
	text-decoration: underline;
	text-decoration-thickness: 1px;
	text-underline-offset: 3px;
}

@media (hover: hover) {
	.chip--suggest:hover {
		background: transparent;
		text-decoration-thickness: 2px;
	}
}

.segmented__legend {
	margin-bottom: 6px;
	padding: 0;
	color: var(--text-2);
	font-size: var(--fs-small);
	font-weight: 600;
	line-height: var(--lh-small);
}

/* Joined segments in one 1.5px frame. The frame is drawn by the options, so the focus ring is never clipped. */
.segmented__track {
	display: inline-flex;
	max-width: 100%;
}

.segmented__opt {
	position: relative;
	display: flex;
	flex: 1 1 auto;
	align-items: center;
	justify-content: center;
	gap: 8px;
	min-height: 44px;
	padding: 0 16px;
	border: 1.5px solid var(--control-border);
	background: var(--field);
	color: var(--text);
	font-size: var(--fs-body);
	font-weight: 500;
	line-height: 1.25;
	text-align: center;
	cursor: pointer;
	transition: background-color var(--dur-1), color var(--dur-1);
}

.segmented__opt + .segmented__opt {
	margin-left: -1.5px;
}

.segmented__opt:first-child {
	border-radius: var(--r-control) 0 0 var(--r-control);
}

.segmented__opt:last-child {
	border-radius: 0 var(--r-control) var(--r-control) 0;
}

@media (hover: hover) {
	.segmented__opt:hover {
		background: var(--surface-hover);
	}
}

.segmented__opt:has(> input:focus-visible) {
	z-index: 2;
	outline: 3px solid var(--focus);
	outline-offset: 2px;
}

/* Selected is navy: a --primary fill, --on-primary text and a heavier weight, so hue never carries the state. */
.segmented__opt:has(> input:checked) {
	z-index: 1;
	border-color: var(--primary);
	background: var(--primary);
	color: var(--on-primary);
	font-weight: 600;
}

/* Tags (text is always present: colour is never the only cue). */
.tag {
	display: inline-flex;
	align-items: center;
	padding: 1px 8px;
	border: 1px solid transparent;
	border-radius: var(--r-tag);
	font-size: var(--fs-small);
	font-weight: 500;
	line-height: 1.45;
	white-space: nowrap;
}

/* The border style says what kind of cost it is; the words say it too. */
.tag--required {
	border-style: solid;
	border-color: var(--ink);
	color: var(--ink);
}

.tag--optional {
	border-style: dashed;
	border-color: var(--text-2);
	color: var(--text-2);
}

.tag--provided {
	border-style: solid;
	border-color: var(--gold-fill);
	color: var(--gold-ink);
}

.tag--own {
	background: var(--surface-2);
	color: var(--ink);
}

.tag--unpriced {
	border-style: dotted;
	border-color: var(--text-2);
	color: var(--text-2);
}

.tag--once {
	border-style: solid;
	border-color: var(--border-strong);
	color: var(--text-2);
}

/* Notices */
.notice {
	display: flex;
	align-items: flex-start;
	gap: var(--sp-3);
	padding: 16px;
	border: 1.5px solid var(--ink);
	border-radius: var(--r-control);
	background: var(--surface);
	color: var(--text);
	font-size: var(--fs-body);
	line-height: var(--lh-body);
	overflow-wrap: anywhere;
}

.notice > .icon {
	width: 20px;
	height: 20px;
	margin-top: 2px;
	color: var(--ink);
}

.notice > div {
	min-width: 0;
}

.notice__title {
	color: var(--ink);
	font-weight: 600;
}

.notice__actions {
	display: flex;
	flex-wrap: wrap;
	gap: var(--sp-2);
	margin-top: var(--sp-2);
}

/* Every notice is paper in a navy frame; only the icon (and an error's title) takes a colour. */
.notice--warning > .icon {
	color: var(--gold-ink);
}

.notice--error > .icon,
.notice--error .notice__title {
	color: var(--error);
}

/* Page-level notices sit inside the wrap but keep their own box. */
.notice.wrap {
	width: calc(100% - 2 * var(--gutter));
	max-width: calc(var(--wrap-max) - 2 * var(--gutter));
	margin: var(--sp-4) auto;
	padding: 16px;
}

/* Empty states */
.empty {
	display: grid;
	justify-items: start;
	gap: var(--sp-2);
	padding: var(--sp-5);
	border: 1px dashed var(--control-border);
	border-radius: var(--r-control);
	color: var(--text);
}

.empty__icon {
	display: grid;
	place-items: center;
	flex: none;
	width: 24px;
	height: 24px;
	color: var(--ink);
}

.empty__icon .icon {
	width: 22px;
	height: 22px;
}

.empty__title {
	color: var(--ink);
	font-weight: 600;
}

.empty__text {
	max-width: 46ch;
}

.empty--inline {
	display: flex;
	align-items: center;
	justify-content: flex-start;
	gap: var(--sp-3);
	min-height: 56px;
	padding: var(--sp-3) var(--sp-4);
	text-align: left;
}

.empty--inline .empty__icon {
	width: 24px;
	height: 24px;
}

/* Nothing to buy: a gold check, never green. */
.empty--positive {
	border-style: solid;
	border-color: var(--border-strong);
}

.empty--positive .empty__icon {
	color: var(--gold-ink);
}

/* Cards, eyebrows, pills, checklists */
/* A framed card: 1.5px ink border, 10px radius, no shadow. Only interactive cards are framed;
   .card--plain keeps the same spacing and type without the frame (a reading card sits on paper). */
.card {
	padding: 28px;
	border: 1.5px solid var(--frame);
	border-radius: var(--r-folder);
	background: var(--surface);
}

.card--plain {
	padding: 0;
	border: 0;
	border-radius: 0;
	background: transparent;
}

@media (max-width: 599px) {
	.card {
		padding: 22px 16px 16px;
	}

	.card--plain {
		padding: 0;
	}
}

.card__title {
	font-size: var(--fs-card);
	line-height: var(--lh-h3);
}

.card__lede {
	margin-top: var(--sp-2);
	color: var(--text-2);
	font-size: var(--fs-body);
	line-height: var(--lh-body);
}

.card__body {
	margin-top: var(--sp-5);
}

.card__actions {
	display: flex;
	flex-wrap: wrap;
	gap: var(--sp-3);
	margin-top: var(--sp-5);
}

.card__actions:empty {
	display: none;
}

.card .checklist {
	margin-top: var(--sp-4);
}

/* An item count is plain text, never a pill. */
.count-pill {
	display: inline-block;
	color: var(--text-2);
	font-size: var(--fs-small);
	font-weight: 500;
	line-height: var(--lh-small);
	white-space: nowrap;
}

.checklist {
	display: grid;
	gap: 10px;
}

/* A 6px square bullet in ink (not a check icon). The pseudo-element name is pinned by the forced-colors rule. */
.checklist > li {
	position: relative;
	padding-left: 22px;
	color: var(--text);
	font-size: var(--fs-body);
	line-height: var(--lh-body);
}

.checklist > li::before {
	content: "";
	position: absolute;
	top: 9px;
	left: 2px;
	width: 6px;
	height: 6px;
	background: var(--ink);
}

/* Skeletons and loading text */
/* Screen blocks, standing still: no shimmer. */
.skeleton {
	border-radius: var(--r-control);
	background: var(--skeleton);
}

.skeleton--field {
	height: 52px;
}

.skeleton--chip {
	width: 96px;
	height: 44px;
}

.skeleton--row {
	height: 72px;
}

.skeleton--list {
	height: 320px;
}

.skeleton-stack {
	display: grid;
	gap: var(--sp-3);
}

.skeleton-row {
	display: flex;
	flex-wrap: wrap;
	gap: var(--sp-2);
}

.skeleton-split {
	display: grid;
	gap: var(--sp-5);
}

.panel__loading {
	margin-top: var(--sp-3);
	color: var(--muted);
	font-size: var(--fs-small);
}

/* ---------- 4. Shell ---------- */

/* Print-only header */
.print-head {
	display: none;
}

/* Shell-only tokens. The frame is the navy outline of the folder, the plan card and the section rule; in dark it
   steps down to the control line so a large frame does not glare on the navy page. */
:root {
	--frame: var(--ink);
}

@media (prefers-color-scheme: dark) {
	:root {
		--frame: var(--control-border);
	}
}

/* App bar: letterhead on paper, a 1px rule below. 60px on phones, 72px from 720px. */
.appbar {
	border-bottom: 1px solid var(--border);
	background: var(--bg);
	color: var(--ink);
}

.appbar__inner {
	display: flex;
	align-items: center;
	gap: var(--sp-4);
	min-height: 60px;
}

.appbar__brand {
	display: inline-flex;
	align-items: center;
	min-height: 44px;
	gap: var(--sp-3);
	min-width: 0;
	color: var(--ink);
	text-decoration: none;
}

/* The P mark brings its own navy rounded square. In dark it would vanish into the page, so it gets a gold keyline. */
.appbar__logo,
.site-footer__mark {
	flex: none;
	width: 40px;
	height: 40px;
	border-radius: 7px;
}

@media (prefers-color-scheme: dark) {
	.appbar__logo,
	.site-footer__mark {
		outline: 1.5px solid var(--tile-edge);
	}
}

.appbar__text {
	display: grid;
	min-width: 0;
}

.appbar__name {
	font: 700 1.125rem/1.25 var(--font-display);
}

.appbar__school {
	color: var(--text-2);
	font-size: var(--fs-small);
	line-height: var(--lh-small);
}

.appbar__nav {
	display: none;
	margin-left: auto;
	gap: var(--sp-1);
}

/* A 2px ink underline marks hover and the section in view (aria-current). */
.appbar__nav a {
	display: inline-flex;
	align-items: center;
	min-height: 44px;
	padding: 0 12px;
	border-bottom: 2px solid transparent;
	color: var(--ink);
	font-weight: 500;
	text-decoration: none;
}

.appbar__nav a[aria-current] {
	border-bottom-color: var(--ink);
}

@media (hover: hover) {
	.appbar__nav a:hover {
		border-bottom-color: var(--ink);
		color: var(--ink);
	}
}

@media (min-width: 720px) {
	.appbar__inner {
		min-height: 72px;
	}

	.appbar__nav {
		display: flex;
	}
}

/* Hero: the question on paper, full measure, then the copy and the scope list on a 7/5 grid. No band. */
.hero {
	padding: 32px 0 40px;
	background: var(--bg);
	color: var(--text);
}

.hero__inner {
	display: grid;
	gap: var(--sp-6);
}

.hero__title {
	max-width: 17em;
}

.hero__copy {
	min-width: 0;
}

.hero__sub {
	color: var(--ink);
	font: 600 var(--fs-hero-sub)/var(--lh-hero-sub) var(--font-ui);
}

.hero__lede {
	max-width: 52ch;
	margin-top: var(--sp-2);
	color: var(--text-2);
	font-size: var(--fs-hero-sub);
	line-height: var(--lh-hero-sub);
}

.hero__actions {
	display: grid;
	gap: var(--sp-5);
	margin-top: var(--sp-6);
}

.hero__actions > .btn {
	width: 100%;
}

.hero__audience {
	min-width: 0;
}

.hero__audience .segmented__track {
	display: flex;
	width: 100%;
}

/* Under 360px the two options stack, so "Already at Peddie" never wraps inside its segment. */
@media (max-width: 359.98px) {
	.hero__audience .segmented__track {
		flex-direction: column;
	}

	.hero__audience .segmented__opt + .segmented__opt {
		margin-top: -1.5px;
		margin-left: 0;
	}

	.hero__audience .segmented__opt:first-child {
		border-radius: var(--r-control) var(--r-control) 0 0;
	}

	.hero__audience .segmented__opt:last-child {
		border-radius: 0 0 var(--r-control) var(--r-control);
	}
}

/* What's in the estimate: a disclosure on phones, a contents list under a 1.5px rule from 720px. */
.scope {
	min-width: 0;
	border-top: 1px solid var(--border);
	border-bottom: 1px solid var(--border);
}

.scope__summary {
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: var(--sp-3);
	min-height: 48px;
	color: var(--ink);
	font: 700 1.125rem/1.3 var(--font-display);
	list-style: none;
	cursor: pointer;
}

.scope__summary::-webkit-details-marker {
	display: none;
}

.scope__summary .icon {
	width: 20px;
	height: 20px;
}

.scope[open] .scope__summary .icon {
	transform: rotate(180deg);
}

.scope__title {
	display: none;
	color: var(--ink);
	font: 700 var(--fs-h3)/var(--lh-h3) var(--font-display);
}

.scope__list {
	display: grid;
	gap: var(--sp-3);
	padding-bottom: var(--sp-4);
}

.scope__item-title {
	color: var(--ink);
	font-weight: 600;
}

.scope__item-text {
	color: var(--text-2);
	font-size: var(--fs-small);
	line-height: var(--lh-small);
}

/* "Not included" is its own entry under a rule, in Ink 2. */
.scope__item--out {
	padding-top: var(--sp-3);
	border-top: 1px solid var(--border);
}

.scope__item--out .scope__item-title {
	color: var(--text-2);
}

@media (min-width: 720px) {
	.hero {
		padding: 56px 0 64px;
	}

	.hero__inner {
		gap: var(--sp-10);
	}

	.hero__actions {
		display: flex;
		flex-wrap: wrap;
		align-items: flex-end;
		gap: var(--sp-4) 28px;
		margin-top: var(--sp-8);
	}

	.hero__actions > .btn {
		width: auto;
	}

	.hero__audience .segmented__track {
		display: inline-flex;
		width: auto;
	}

	.scope {
		border-bottom: 0;
		border-top: 1.5px solid var(--frame);
	}

	.scope__summary {
		display: none;
	}

	.scope__title {
		display: block;
		margin: 14px 0 var(--sp-4);
	}

	.scope__list {
		padding-bottom: 0;
		gap: 14px;
	}
}

@media (min-width: 900px) {
	.hero__inner {
		grid-template-columns: minmax(0, 7fr) minmax(0, 5fr);
		column-gap: 72px;
		align-items: start;
	}

	.hero__title {
		grid-column: 1 / -1;
	}
}

/* A page-level source notice sits between the hero and the builder. */
#source-notice:not([hidden]) {
	margin-top: 0;
	margin-bottom: var(--sp-4);
}

/* Index tabs. They sit inside #build, on the folder panel they control. Narrow columns (and phones) get a 2x2 grid
   of separate boxed tabs; a column wide enough for four gets real tabs joined to the folder. */
.builder {
	container: build / inline-size;
	min-width: 0;
}

.steps {
	display: grid;
	grid-template-columns: repeat(2, minmax(0, 1fr));
	grid-template-rows: auto auto;
	gap: var(--sp-2);
	margin-bottom: var(--sp-3);
}

/* The tablist spans both rows on a subgrid, so tab 3 sits under tab 1 and the link tab under tab 2. */
.steps__list {
	display: grid;
	grid-column: 1 / -1;
	grid-row: 1;
	grid-template-columns: repeat(2, minmax(0, 1fr));
	gap: var(--sp-2);
	pointer-events: none;
}

.steps__list > .step {
	pointer-events: auto;
}

/* Without subgrid the list is its own 2-column grid and the link tab takes a full-width row under it. */
.step--link {
	grid-column: 1 / -1;
	grid-row: 2;
}

@supports (grid-template-columns: subgrid) {
	.steps__list {
		grid-row: 1 / span 2;
		grid-template-columns: subgrid;
		grid-template-rows: subgrid;
	}

	.step--link {
		grid-column: 2;
		grid-row: 2;
	}
}

.step {
	position: relative;
	display: grid;
	grid-template-columns: auto minmax(0, 1fr);
	column-gap: 8px;
	align-content: start;
	align-items: baseline;
	width: 100%;
	min-width: 0;
	min-height: 44px;
	margin: 0;
	padding: 14px 12px 12px;
	border: 1.5px solid var(--control-border);
	border-radius: var(--r-control);
	background: var(--surface-2);
	color: var(--ink);
	text-align: left;
	text-decoration: none;
	cursor: pointer;
}

.step__num {
	grid-row: 1 / span 2;
	color: var(--ink);
	font: 800 1.3125rem/24px var(--font-display);
}

.step__title {
	min-width: 0;
	color: var(--ink);
	font: 600 var(--fs-body)/24px var(--font-ui);
}

.step__meta {
	grid-column: 2;
	display: -webkit-box;
	overflow: hidden;
	-webkit-box-orient: vertical;
	-webkit-line-clamp: 2;
	line-clamp: 2;
	color: var(--text-2);
	font-size: var(--fs-meta);
	line-height: var(--lh-small);
}

.step__meta.is-done {
	color: var(--text);
	font-weight: 600;
}

@media (hover: hover) {
	.step:hover {
		background: var(--surface);
	}
}

/* The open tab: paper, a 2px frame, and a 4px gold band along its top edge. */
.step[aria-selected="true"] {
	border-color: var(--frame);
	background: var(--surface);
}

.step[aria-selected="true"]::before {
	content: "";
	position: absolute;
	top: 0;
	right: 0;
	left: 0;
	height: 4px;
	border-radius: 4px 4px 0 0;
	background: var(--gold-fill);
}

@container build (min-width: 43rem) {
	.steps {
		grid-template-columns: repeat(4, minmax(0, 1fr));
		grid-template-rows: auto;
		gap: 6px;
		margin-bottom: 0;
	}

	.steps__list {
		grid-column: span 3;
		grid-row: 1;
		grid-template-columns: repeat(3, minmax(0, 1fr));
		grid-template-rows: auto;
		gap: 6px;
	}

	.step--link {
		grid-column: 4;
		grid-row: 1;
	}

	.step {
		column-gap: 10px;
		padding: 16px 14px 14px;
		border-bottom: 0;
		border-radius: var(--r-folder) var(--r-folder) 0 0;
	}

	.step[aria-selected="true"] {
		/* Open into the panel: overlaps its top edge by the frame width and hides it behind the paper fill. */
		z-index: var(--z-tab);
		margin-bottom: -1.5px;
		padding-bottom: 15.5px;
		border-bottom: 0;
		border-radius: var(--r-folder) var(--r-folder) 0 0;
	}

	.step[aria-selected="true"]::before {
		border-radius: 8px 8px 0 0;
	}

	/* .builder .panel outranks the base .panel rule below, so the folder's top-left corner is square under tab 1. */
	.builder .panel {
		border-top-left-radius: 0;
	}
}

/* Builder: the folder panel is the framed object; the builder wrapper itself has no chrome. */
.panel {
	padding: 24px 16px 20px;
	border: 1.5px solid var(--frame);
	border-radius: var(--r-folder);
	background: var(--surface);
}

.panel__head {
	margin-bottom: var(--sp-6);
}

.panel__lede {
	margin-top: var(--sp-2);
	color: var(--text-2);
	font-size: var(--fs-body);
	line-height: var(--lh-body);
}

.panel__body {
	container: panel / inline-size;
}

.panel__next {
	display: flex;
	justify-content: stretch;
	margin-top: var(--sp-8);
}

.panel__next .btn {
	width: 100%;
}

@media (min-width: 600px) {
	.panel__lede {
		font-size: var(--fs-lede);
		line-height: var(--lh-lede);
	}
}

@media (min-width: 720px) {
	.panel {
		padding: 36px 40px 32px;
	}

	.panel__next {
		justify-content: flex-end;
	}

	.panel__next .btn {
		width: auto;
	}
}

/* Layout: single column (builder, estimate, review); docked grid on large, tall screens. */
.layout {
	display: grid;
	grid-template-columns: minmax(0, 1fr);
	gap: var(--layout-gap);
	margin-top: 0;
	padding-bottom: var(--sp-10);
}

.layout > .builder {
	grid-area: auto;
}

@media screen and (min-width: 900px) and (min-height: 540px) {
	.layout {
		grid-template-columns: minmax(0, 1fr) var(--statement-col);
		grid-template-areas:
			"build rail"
			"review rail";
		gap: var(--layout-gap);
		align-items: start;
		padding-bottom: var(--sp-16);
	}

	.layout > .builder {
		grid-area: build;
	}

	.layout > .review {
		grid-area: review;
	}

	#estimate {
		grid-area: rail;
		align-self: start;
		position: sticky;
		top: 1rem;
		max-height: calc(100dvh - 2rem);
		overflow: auto;
		z-index: var(--z-rail);
		/* Room inside the scroll box so a focus ring (3px plus a 2px offset) is never clipped at its edge. */
		padding: 6px;
		margin: -6px;
	}
}

.estimate {
	min-width: 0;
}

/* Below the docked layout the rail flows after the builder; the tile does not need the whole width. */
@media screen and (max-width: 899.98px), screen and (max-height: 539.98px) {
	#estimate {
		max-width: 36rem;
	}
}

/* Review: no card around it. The plan card is the one framed object; Questions sits unframed beside it. */
.review {
	container: review / inline-size;
	min-width: 0;
	padding-top: var(--sp-8);
}

.section-head {
	margin-bottom: var(--sp-6);
}

.section-head__lede {
	margin-top: var(--sp-2);
	color: var(--text-2);
	font-size: var(--fs-lede);
	line-height: var(--lh-lede);
}

.review__body {
	display: grid;
	gap: var(--sp-6);
	min-width: 0;
}

.review__grid {
	display: grid;
	gap: var(--sp-8);
	margin-top: var(--sp-10);
}

@container review (min-width: 44rem) {
	.review__grid {
		grid-template-columns: 1fr 1fr;
	}

	/* The framed plan card stretches to the row's height and its buttons sit on its bottom edge. */
	.review__grid > .card {
		display: flex;
		flex-direction: column;
	}

	.review__grid > .card > .card__actions {
		padding-top: var(--sp-5);
	}

	.review__grid > .card:not(.card--plain) > .card__actions {
		margin-top: auto;
	}

	/* The unframed card has no bottom edge to sit on: it keeps its own height, with its button 20px under the list.
	   Its heading lines up with the framed card's heading (28px padding plus the 1.5px frame). */
	.review__grid > .card--plain {
		align-self: start;
		padding-top: 29.5px;
	}
}

/* Why this matters: paper in both modes, opened by a section rule. The reading entries hang their heads in a
   left column, like a course catalog. */
.why {
	padding: 0 0 var(--sp-12);
	background: var(--bg);
}

.why > .wrap::before {
	content: "";
	display: block;
	margin-bottom: var(--sp-12);
	border-top: 1.5px solid var(--frame);
}

.why .wrap > * + * {
	margin-top: var(--sp-10);
}

.why .section-head {
	margin-bottom: 0;
}

.why__lead {
	display: grid;
	gap: var(--sp-8);
}

/* The pull quote summarizes the finding, so it carries no quotation marks. */
.quote {
	align-self: start;
}

.quote__text {
	max-width: 26ch;
	color: var(--ink);
	font: 500 1.5rem/2rem var(--font-display);
	text-wrap: pretty;
}

.quote__cite {
	margin-top: var(--sp-4);
	color: var(--text-2);
	font-size: var(--fs-meta);
	line-height: var(--lh-small);
}

.why__subhead {
	font-size: var(--fs-h3);
	line-height: var(--lh-h3);
}

.why__subtext {
	max-width: var(--measure-lede);
	margin-top: var(--sp-2);
	color: var(--text-2);
	font-size: var(--fs-lede);
	line-height: var(--lh-lede);
}

/* Hanging-head entries: head column, text column, a rule between entries; stacked on phones. */
.why__cards,
.pillars {
	margin-top: var(--sp-4);
	border-bottom: 1px solid var(--frame);
}

.feature,
.pillar {
	display: grid;
	gap: var(--sp-2);
	padding: var(--sp-5) 0;
	border-top: 1px solid var(--frame);
}

.feature__title,
.pillar__title {
	color: var(--ink);
	font: 700 var(--fs-h3)/var(--lh-h3) var(--font-display);
}

.feature__text,
.pillar > p {
	color: var(--text);
	line-height: 26px;
}

.pillars {
	margin-top: var(--sp-5);
}

.why__method .checklist {
	max-width: var(--measure-body);
	margin-top: var(--sp-4);
}

.why__method .checklist > li {
	line-height: 26px;
}

/* Sources hang their lines 1.5em in. */
.sources {
	display: grid;
	gap: var(--sp-3);
	max-width: 80ch;
	margin-top: var(--sp-4);
	color: var(--text);
	font-size: var(--fs-small);
	line-height: 22px;
}

.sources > li {
	padding-left: 1.5em;
	text-indent: -1.5em;
}

.sources a {
	color: var(--ink);
	overflow-wrap: anywhere;
}

@media (hover: hover) {
	.sources a:hover {
		text-decoration-color: var(--gold-fill);
	}
}

@media (min-width: 720px) {
	.why {
		padding-bottom: var(--sp-16);
	}

	.why > .wrap::before {
		margin-bottom: 72px;
	}

	.quote__text {
		font-size: 2.25rem;
		line-height: 2.75rem;
	}
}

@media (min-width: 900px) {
	.feature,
	.pillar {
		grid-template-columns: 16rem minmax(0, 60ch);
		column-gap: 48px;
		padding: 22px 0 24px;
	}

	/* The quote and the entries share the text column's left edge. */
	.quote {
		padding-left: calc(16rem + 48px);
	}
}

/* Method, sources and the phone folds: 48px rows with a chevron. */
.fold__summary {
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: var(--sp-3);
	min-height: 48px;
	padding-block: 10px;
	cursor: pointer;
	list-style: none;
}

.fold__summary::-webkit-details-marker {
	display: none;
}

.fold__summary::after {
	content: "";
	flex: none;
	width: 10px;
	height: 10px;
	margin-inline-end: 4px;
	border-right: 2px solid currentColor;
	border-bottom: 2px solid currentColor;
	transform: rotate(45deg);
}

.fold[open] > .fold__summary::after {
	transform: rotate(-135deg);
}

@media (max-width: 719.98px) {
	.why .wrap > * + * {
		margin-top: var(--sp-8);
	}

	.why__fishman > .why__fold {
		margin-top: var(--sp-4);
	}

	/* On a phone each fold is a 48px row between rules. */
	.why .fold {
		border-top: 1px solid var(--border);
	}

	.why .fold:last-child {
		border-bottom: 1px solid var(--border);
	}

	/* The pillars, the method and the sources chain into one list of rows: each rule is shared. */
	.why .wrap > .why__method,
	.why .wrap > .why__sources {
		margin-top: 0;
	}

	.why__fishman > .why__fold:last-child,
	.why__method .fold:last-child {
		border-bottom: 0;
	}

	.fold__summary .why__subhead {
		font-size: 1.125rem;
		line-height: 1.3;
	}
}

/* From 720px up the folds are plain content, not disclosures: their summaries are hidden (the static fold shows its
   own heading, .why__subhead--static, instead) and the chevron sits beside its title on phones. */
@media (min-width: 720px) {
	.fold__summary {
		justify-content: flex-start;
		gap: var(--sp-4);
	}

	.why__fold > .fold__summary,
	.fold--static > .fold__summary {
		display: none;
	}
}

/* The static fold's own heading is for the wide layout only; a phone gets the summary row. */
.why__subhead--static {
	display: none;
}

@media (min-width: 720px) {
	.why__subhead--static {
		display: block;
	}
}

/* Footer: paper under a 1.5px navy rule in light; a deeper navy band under a gold rule in dark (--foot-* tokens).
   The room for the fixed total bar is part of the footer's own bottom padding, so no strip of another colour shows. */
.site-footer {
	padding: var(--sp-12) 0 calc(var(--sp-12) + var(--totalbar-space, 0px));
	border-top: 1.5px solid var(--foot-edge);
	background: var(--foot-bg);
	color: var(--foot-ink);
	font-size: var(--fs-small);
}

.site-footer__inner {
	display: grid;
	gap: var(--sp-4);
}

.site-footer__body > * + * {
	margin-top: var(--sp-2);
}

.site-footer__project {
	color: var(--foot-ink-2);
	line-height: var(--lh-small);
}

.site-footer__project > span {
	display: block;
}

.site-footer__title {
	margin-top: 10px;
	color: var(--foot-ink);
	font: 700 var(--fs-h3)/var(--lh-h3) var(--font-display);
}

.site-footer__body > p:not([class]) {
	color: var(--foot-ink);
	font-size: var(--fs-body);
	line-height: var(--lh-body);
}

.site-footer__privacy,
.site-footer__source,
.site-footer__feedback {
	color: var(--foot-ink-2);
	font-size: var(--fs-meta);
	line-height: var(--lh-small);
}

.site-footer a {
	color: var(--foot-ink);
}

.site-footer a:where(:hover) {
	color: var(--foot-ink);
	text-decoration-color: var(--gold-fill);
}

@media (min-width: 720px) {
	.site-footer {
		padding-bottom: calc(var(--sp-16) + var(--totalbar-space, 0px));
	}

	.site-footer__inner {
		grid-template-columns: 40px minmax(0, 60ch);
		column-gap: var(--sp-5);
	}
}

@media screen and (min-width: 900px) and (min-height: 540px) {
	.site-footer {
		padding-bottom: var(--sp-16);
	}
}

/* Total bar (below the docked layout): the estimate tile rising from the bottom edge. Estimate and the count on
   the left over the total, Review as a gold button on the right. */
.totalbar {
	position: fixed;
	z-index: var(--z-totalbar);
	right: 0;
	bottom: 0;
	left: 0;
	display: grid;
	grid-template-columns: minmax(0, 1fr) auto;
	grid-template-areas:
		"text button"
		"total button";
	align-items: center;
	column-gap: var(--sp-3);
	padding: 12px var(--gutter) calc(12px + env(safe-area-inset-bottom));
	border: 1.5px solid var(--tile-edge);
	border-bottom: 0;
	border-radius: 20px 20px 0 0;
	background: var(--tile);
	color: var(--on-navy);
	/* Navy surfaces ring in bright gold, which clears 3:1 on navy (the estimate tile sets its own). Everything else
	   is paper, where --focus is navy (and gold in dark, where the whole page is navy). */
	--focus: var(--gold-bright);
	transition: opacity 160ms linear, visibility 0s;
}

.totalbar.is-hidden {
	opacity: 0;
	visibility: hidden;
	transition: opacity 160ms linear, visibility 0s linear 160ms;
}

/* The split stripe would fight the tile; its element stays for js/ui/summary.js. */
.totalbar__stripe {
	display: none;
}

.totalbar__text {
	grid-area: text;
	display: flex;
	flex-wrap: wrap;
	align-items: baseline;
	column-gap: var(--sp-2);
	min-width: 0;
}

.totalbar__label {
	color: var(--on-navy);
	font-size: var(--fs-small);
	font-weight: 600;
	line-height: 18px;
}

.totalbar__count,
.totalbar__note {
	color: var(--on-navy-2);
	font-size: var(--fs-small);
	line-height: 18px;
}

/* Besley with proportional lining figures: its tabular figures are broken. */
.totalbar__total {
	grid-area: total;
	min-width: 0;
	color: var(--tile-gold);
	font: 800 var(--fs-money-bar)/32px var(--font-display);
	white-space: nowrap;
}

.totalbar__button {
	grid-area: button;
	display: inline-flex;
	align-items: center;
	justify-content: center;
	min-height: 44px;
	padding: 0 18px;
	border: 0;
	border-radius: var(--r-control);
	background: var(--tile-gold);
	color: var(--navy);
	font: 600 var(--fs-body)/1.25 var(--font-ui);
}

/* The ring is white: a gold ring on a gold button is no ring. */
.totalbar__button:focus-visible {
	outline-color: var(--on-navy);
}

@media (hover: hover) {
	.totalbar__button:hover {
		background: var(--gold-hover);
	}
}

.totalbar__button:active {
	background: var(--gold-press);
}

@media screen and (min-width: 600px) {
	.totalbar {
		grid-template-columns: auto minmax(0, 1fr) auto;
		grid-template-areas: "text total button";
		column-gap: var(--sp-6);
	}
}

@media screen and (max-width: 359.98px) {
	.totalbar__button {
		padding: 0 14px;
	}
}

@media screen and (min-width: 900px) and (min-height: 540px) {
	.totalbar {
		display: none;
	}
}

/* ---------- 5. Toasts ---------- */
:root {
	/* How far the toasts sit above the bottom of the viewport: clear of the total bar. */
	--toast-offset: calc(var(--totalbar-space, 3.75rem + env(safe-area-inset-bottom)) + 1.25rem);
}

@media (min-width: 900px) and (min-height: 540px) {
	:root {
		--toast-offset: 1.5rem;
	}
}

.toasts {
	position: fixed;
	z-index: var(--z-toast);
	left: 50%;
	bottom: var(--toast-offset);
	width: min(30rem, calc(100% - 2 * var(--gutter)));
	transform: translateX(-50%);
	display: grid;
	gap: 0.5rem;
	pointer-events: none;
}

/* Docked: centred over the panels column, never over the estimate. The
   estimate stays in place (sticky), so a control near its foot could not be
   scrolled out from under a toast that covered it. */
@media (min-width: 900px) and (min-height: 540px) {
	.toasts {
		--panels-width: calc(min(100%, var(--wrap-max)) - 2 * var(--gutter) - var(--layout-gap) - var(--statement-col));
		left: calc(max(0px, (100% - var(--wrap-max)) / 2) + var(--gutter) + var(--panels-width) / 2);
		width: min(30rem, var(--panels-width));
	}
}

/* Keep keyboard focus clear of the fixed total bar (WCAG 2.4.11). */
@media (max-width: 899.98px), (max-height: 539.98px) {
	html {
		scroll-padding-bottom: calc(var(--totalbar-space, 3.75rem + env(safe-area-inset-bottom)) + 1.25rem);
	}
}

/* While a toast is open (js/ui/feedback.js sets .has-toast and --toast-height),
   keep keyboard focus clear of it too (WCAG 2.4.11): anything scrolled into view
   stops above the toast, and the end of the page can scroll past it. */
html.has-toast {
	scroll-padding-bottom: calc(var(--toast-offset) + var(--toast-height, 0px) + 0.75rem);
}

html.has-toast body {
	padding-bottom: calc(var(--toast-offset) + var(--toast-height, 0px) + 0.75rem);
}

/* A toast is a small slab of the other ink: navy on paper, paper-white on the navy page. It fades in over 160ms
   and never slides. */
.toast {
	display: flex;
	align-items: center;
	gap: var(--sp-2);
	max-width: 26rem;
	padding: 6px 6px 6px 16px;
	border-radius: var(--r-control);
	background: var(--toast-bg);
	color: var(--toast-ink);
	pointer-events: auto;
	animation: toast-fade 160ms linear;
}

.toast__msg {
	flex: 1;
	min-width: 0;
	padding-block: 8px;
	font: 500 var(--fs-body)/var(--lh-body) var(--font-ui);
}

/* Undo is an underlined text button; its hit area is 44px tall. */
.toast__action {
	min-height: 44px;
	padding: 0 var(--sp-3);
	border: 0;
	border-radius: var(--r-control);
	background: transparent;
	color: var(--toast-action);
	font: 600 var(--fs-body)/1.25 var(--font-ui);
	text-decoration: underline;
	text-underline-offset: 3px;
}

.toast__close {
	display: grid;
	place-items: center;
	width: 44px;
	height: 44px;
	border: 0;
	border-radius: var(--r-control);
	background: transparent;
	color: inherit;
}

.toast :focus-visible {
	outline-color: currentColor;
}

@media (hover: hover) {
	.toast__action:hover,
	.toast__close:hover {
		background: color-mix(in srgb, currentColor 16%, transparent);
	}
}

/* ---------- 6. Motion, reduced motion, forced colors, print ---------- */
/* Motion answers an action and nothing else: a checked row's wash fades out (600ms), a toast fades in (160ms). There are no page-load reveals, hover lifts or slides. */
@keyframes toast-fade {
	from {
		opacity: 0;
	}
}

@media (prefers-reduced-motion: reduce) {
	*,
	*::before,
	*::after {
		animation-duration: 0.01ms !important;
		animation-iteration-count: 1 !important;
		animation-delay: 0s !important;
		transition-duration: 0.01ms !important;
		transition-delay: 0s !important;
		scroll-behavior: auto !important;
	}
}

/* Windows High Contrast. builder.css and estimate.css style their own components. */
@media (forced-colors: active) {
	.toast {
		border: 1px solid CanvasText;
	}

	/* The row gap keeps the total's text backplate off the label above it. */
	.totalbar {
		border-top: 1px solid CanvasText;
		row-gap: 6px;
	}

	.card,
	.builder,
	.step,
	.scope,
	.notice,
	.tag,
	.skeleton,
	.chip,
	.segmented__opt {
		border: 1px solid CanvasText;
	}

	.step[aria-selected="true"] {
		border-top: 4px solid Highlight;
	}

	.chip:has(> input:checked),
	.segmented__opt:has(> input:checked) {
		forced-color-adjust: none;
		background: Highlight;
		color: HighlightText;
	}

	.chip:has(> input:checked) .chip__meta {
		color: HighlightText;
	}

	.totalbar__stripe {
		display: none;
	}

	/* Boxes that have no padding on screen take no added frame. */
	.card--plain,
	.scope {
		border: 0;
	}

	.btn,
	.totalbar__button {
		border: 1px solid ButtonText;
	}

	/* The square bullet is drawn with a background colour, which forced colors replaces with Canvas. */
	.checklist > li::before {
		forced-color-adjust: none;
		background-color: CanvasText;
	}

	.check__box {
		appearance: auto;
	}
}

@media print {
	@page {
		margin: 14mm 14mm 16mm;
	}

	body {
		background: #fff;
		color: #000;
		padding: 0 !important;
	}

	/* Printing from dark mode still prints the light palette. */
	:root {
		--bg: #ffffff;
		--surface: #ffffff;
		--surface-2: #eef1f5;
		--surface-hover: #eef1f5;
		--field: #ffffff;
		--border: #d3d9e3;
		--border-strong: #aab3c2;
		--control-border: #6e7b91;
		--ink: #0a2341;
		--text: #1a2e4c;
		--text-2: #536179;
		--muted: #536179;
		--primary: #0a2341;
		--primary-hover: #13325c;
		--primary-press: #061630;
		--on-primary: #ffffff;
		--primary-ink: #0a2341;
		--selected: #f1e4bf;
		--selected-2: #e8d6a4;
		--selected-ink: #0a2341;
		--selection: #ebd9a8;
		--focus: #0a2341;
		--gold-fill: #ab8322;
		--gold-ink: #7a5a10;
		--area-textbooks: #0a2341;
		--area-activities: #ab8322;
		--area-other: #6e7b91;
		--support: #ab8322;
		--support-track: #eef1f5;
		--error: #a3261b;
		--toast-bg: #0a2341;
		--toast-ink: #ffffff;
		--toast-action: #d2af55;
		--skeleton: #eef1f5;
		--tile: #0a2341;
		--tile-edge: #0a2341;
		--tile-gold: #b68d2c;
		--foot-bg: #ffffff;
		--foot-edge: #0a2341;
		--foot-ink: #0a2341;
		--foot-ink-2: #536179;
	}

	.skip-link,
	.appbar,
	#file-notice,
	#source-notice,
	.hero,
	.steps,
	#build,
	#why,
	.site-footer,
	.totalbar,
	.toasts,
	#plan,
	#next-steps,
	#review > .section-head > .section-head__lede {
		display: none !important;
	}

	.layout {
		display: block;
		margin-top: 0;
		padding-bottom: 0;
	}

	.review {
		margin-top: 0;
	}

	/* The print head: the mark, the tool's name over what the page is, under a navy rule. */
	.print-head {
		display: flex;
		align-items: center;
		gap: 10px;
		margin-bottom: 10px;
		padding-bottom: 8px;
		border-bottom: 1.5pt solid var(--ink);
	}

	.print-head__logo {
		width: 28px;
		height: 28px;
		border-radius: 5px;
		print-color-adjust: exact;
		-webkit-print-color-adjust: exact;
	}

	.print-head__title {
		display: grid;
		color: var(--ink);
	}

	.print-head__name {
		font: 700 12pt/1.25 var(--font-display);
	}

	.print-head__sub {
		color: var(--text-2);
		font: 400 9pt/1.3 var(--font-ui);
	}

	.section-head {
		margin-bottom: 8px;
	}

	.review__grid {
		display: none;
	}
}
