/**
 * Planner
 *
 * The project planner form. Loaded only on pages containing the [nf_planner]
 * shortcode — see nf_planner_enqueue_assets() in inc/planner.php.
 *
 * The planner sits on the cream page and has to read as a sequence of panels
 * *set into* it rather than floating on top, which is a job for the warm gold
 * at low opacity: a grey line goes cold against the brand, and gull at full
 * strength is too loud for a border that repeats a dozen times down the page.
 * The three surface levels are declared once here as planner-scoped custom
 * properties, so the whole form re-tones from four values.
 *
 * @package Norwegian_Flagstone
 */

.nf-planner {

	/* Surfaces -------------------------------------------------------------- */

	/*
	 * There are only two filled things in the planner, and knowing which is
	 * which is most of the design:
	 *
	 *   - The **panel** a question sits in. Deeper than the cream page, so the
	 *     question reads as set into it.
	 *   - A **selected** card. Deeper still, so choosing one reads as pressing
	 *     it rather than as tinting it.
	 *
	 * Every control between them — a card at rest, a text input, the textarea, a
	 * drop zone — is *unfilled*, and defined by its border alone. That is what
	 * leaves the fill free to mean "chosen" and nothing else. Filling the resting
	 * states too, as earlier passes did, spends the loudest signal available on
	 * the state that needs no signal at all, and the selected card then has to
	 * shout over it.
	 *
	 * --nf-planner-card is the one fill left outside that rule, and it is not a
	 * control: a chosen file is a *result*, something the visitor has already
	 * done and is being shown back to them.
	 *
	 * Each step is gull mixed into lys at a rising strength, and each is a flat
	 * colour rather than white at low opacity: that keeps the brand's warmth
	 * instead of washing towards grey, and means a step looks the same over any
	 * of the light backgrounds. It is the reasoning --nf-sand is built on in
	 * tokens.css, at other points along the same mix.
	 */

	/* Gull ~15% into lys — the panel a question sits in. */
	--nf-planner-surface: #f8efd5;

	/* Gull ~28% into lys — a selected card. */
	--nf-planner-card-selected: #f2e7cb;

	/*
	 * Gull ~20% — between the panel and a selection. For hovering something
	 * unfilled, so the hint moves *towards* what choosing it will look like.
	 */
	--nf-planner-card-hover: #f5ebd0;

	/* Near-white cream — the chosen-file chips, and nothing else. */
	--nf-planner-card: #fffdf5;

	/*
	 * Gull at 33%, which is what the design's filled boxes are: the reference
	 * panel, the notes, and the what-happens-next cards. Kept as an alpha
	 * rather than mixed flat, because 33% is the value in the design file and a
	 * flat equivalent would silently stop matching if the page colour changed.
	 *
	 * These boxes carry no border. The fill is the whole signal, and an outline
	 * as well would make them read as questions that happen to be tinted.
	 */
	--nf-planner-fill: rgb(209 188 146 / 33%);

	/* Gull at the two strengths the form needs: resting line, and active line. */
	--nf-planner-line: rgb(209 188 146 / 60%);
	--nf-planner-line-strong: var(--nf-gull);

	padding-block: var(--nf-section-space-m);
}

/*
 * The script hides and reveals questions and rows with the `hidden` attribute,
 * and this is the rule that makes that work. The browser's own
 * `[hidden] { display: none }` comes from the user-agent stylesheet, so *any*
 * author rule setting `display` beats it — and the rows and the add button are
 * flex, so without this they never hide at all. Easy to lose, so it is stated
 * once here rather than per component.
 *
 * The no-JS counterpart lives in the <noscript> block in
 * nf_planner_render_step(); a new hideable element type needs a line there too.
 */
.nf-planner [hidden] {
	display: none;
}

/* Loading a saved project --------------------------------------------------- */

/*
 * While a project is being decoded out of the URL the form is not shown at all.
 * Half a form is worse than none here: an empty first step looks ready, invites
 * typing, and then has whatever was typed overwritten when the answers land.
 */
.nf-planner.is-loading .nf-planner__position {
	display: none;
}

.nf-planner__loading {
	color: var(--nf-color-text-muted);
	font-size: var(--nf-fs-intro);
	margin: 0 auto;
	max-width: var(--nf-container);
	padding-inline: var(--nf-gutter);
}

/* Header ------------------------------------------------------------------- */

/*
 * Title and intro share a line at desktop width, with the intro sitting on the
 * title's baseline. They stack below 48rem rather than at a device width —
 * the point where the intro no longer has room to be a single line beside it.
 */
.nf-planner__header {
	align-items: baseline;
	column-gap: var(--nf-space-m);
	display: flex;
	flex-wrap: wrap;
	margin-bottom: var(--nf-space-l);
	row-gap: var(--nf-space-2xs);
}

.nf-planner__title {
	font-size: var(--nf-fs-h2);
}

.nf-planner__intro {
	color: var(--nf-color-text-muted);
	flex: 1 1 20rem;
	font-size: var(--nf-fs-small);
	line-height: var(--nf-lh-body);
	margin: 0;
	max-width: var(--nf-measure);
}

/* Question panels ---------------------------------------------------------- */

.nf-planner__fields {
	display: flex;
	flex-direction: column;
	gap: var(--nf-space-m);
}

/*
 * The panel a question sits in — an outline on the page, not a surface laid
 * over it. `display: block` is stated because it is what stops the
 * user-agent's `[hidden] { display: none }` from applying; see the top.
 */
.nf-planner-field {
	background-color: transparent;
	border: var(--nf-border-width) solid var(--nf-planner-line);
	border-radius: var(--nf-radius-l);
	display: block;
	margin: 0;
	padding: var(--nf-space-m);
}

/* The heading row. Named for the <legend> it replaces. */
.nf-planner-field__legend {
	margin-bottom: var(--nf-space-xs);
}

.nf-planner-field__heading {
	align-items: baseline;
	column-gap: var(--nf-space-s);
	display: flex;
	flex-wrap: wrap;
	row-gap: var(--nf-space-3xs);
}

/*
 * Number and title are one visual unit in the design — same face, same weight,
 * same size — so they are styled together and only separated in the markup so
 * the numbering can be derived from field order rather than typed into labels.
 */
.nf-planner-field__number,
.nf-planner-field__title {
	color: var(--nf-color-heading);
	font-family: var(--nf-font-display);
	font-size: 1rem;
	font-weight: var(--nf-font-weight-bold);
	line-height: var(--nf-lh-heading);
}

.nf-planner-field__hint,
.nf-planner-field__help {
	color: var(--nf-color-text-muted);
	font-family: var(--nf-font-body);
	font-size: var(--nf-fs-small);
	font-weight: var(--nf-font-weight-regular);
	line-height: var(--nf-lh-body);
}

/*
 * `help` is the longer form of `hint`: its own line, free to wrap, and sitting
 * between the heading and the answers — so it carries the same gap the legend
 * does and the rhythm holds whether a question has one or not.
 */
.nf-planner-field__help {
	margin: 0 0 var(--nf-space-xs);
	max-width: var(--nf-measure);
}

/*
 * A question revealed by an earlier answer fades and rises into place, so the
 * page growing under the visitor reads as a consequence of what they just did
 * rather than as a jump. Applied by a class the script adds and removes, since
 * an element coming out of `display: none` has nothing to transition from.
 */
.nf-planner-field--enter {
	animation: nf-planner-enter var(--nf-duration) var(--nf-ease) both;
}

@keyframes nf-planner-enter {

	from {
		opacity: 0;
		transform: translateY(0.5rem);
	}

	to {
		opacity: 1;
		transform: none;
	}
}

/* Option grid -------------------------------------------------------------- */

/*
 * Column count comes from the field definition as --nf-planner-columns, set
 * inline per question. The Responsive section at the foot of this file
 * overrides it rather than reading it, because a 4-up row and a 2-up row want
 * different minimum card widths and auto-fit would land on 3-up at widths
 * where the design asks for 2.
 */
.nf-planner-options,
.nf-planner-rows {
	display: grid;
	gap: var(--nf-space-s);
	grid-template-columns: repeat(var(--nf-planner-columns, 4), minmax(0, 1fr));
}

/* Option card -------------------------------------------------------------- */

/*
 * The grid cell. It only positions the radio and lets the card fill the track;
 * everything visible belongs to the card.
 */
.nf-planner-option {
	display: grid;
	position: relative;
}

/*
 * The radio is taken out of the visual layer but left in the accessible one —
 * not `display: none`, which would drop it from the tab order and stop the
 * arrow keys moving between options. Parked at the mark's position so a browser
 * scrolling to a focused input scrolls to the right part of the card.
 */
.nf-planner-option__input {
	appearance: none;
	block-size: 1px;
	border: 0;
	inline-size: 1px;
	inset-block-start: var(--nf-space-s);
	inset-inline-end: var(--nf-space-s);
	margin: 0;
	opacity: 0;
	padding: 0;
	position: absolute;
}

/*
 * The whole card is the <label>, so the hit area is the card and not just its
 * title. Content is pushed to the bottom — `margin-top: auto` on the body —
 * which is what puts a one-line and a two-line card's text on a common bottom
 * edge while their titles sit at different heights, as in the design.
 *
 * The generous top padding is the design's, and it is doing work: it holds the
 * mark and the text apart so the card reads as a label with a state rather
 * than a line of text with a dot after it. The height it buys is also what
 * makes the card a comfortable thing to hit.
 *
 * `min-height` is the floor; grid stretches every card in a row to the tallest
 * anyway. Right padding clears the mark.
 */
.nf-planner-option__card {
	background-color: transparent;
	border: var(--nf-border-width) solid var(--nf-planner-line);
	border-radius: var(--nf-radius);
	cursor: pointer;
	display: flex;
	flex-direction: column;
	min-height: 7rem;
	padding: var(--nf-space-xl) var(--nf-space-l) var(--nf-space-s) var(--nf-space-s);
	position: relative;
	transition:
		background-color var(--nf-transition),
		border-color var(--nf-transition),
		box-shadow var(--nf-transition);
}

.nf-planner-option__card:hover {
	background-color: var(--nf-planner-card-hover);
	border-color: var(--nf-planner-line-strong);
}

/* Focus is drawn on the card, since the input it belongs to is invisible. */
.nf-planner-option__input:focus-visible + .nf-planner-option__card {
	outline: 2px solid var(--nf-color-accent);
	outline-offset: 2px;
}

.nf-planner-option__input:checked + .nf-planner-option__card {
	background-color: var(--nf-planner-card-selected);
	border-color: var(--nf-planner-line-strong);

	/*
	 * An inset ring rather than a thicker border: it doubles the line weight
	 * the design asks for on a selected card without changing the box's size,
	 * so selecting an option cannot nudge the grid by a pixel.
	 */
	box-shadow: inset 0 0 0 var(--nf-border-width) var(--nf-planner-line-strong);
}

/* The selection mark ------------------------------------------------------- */

.nf-planner-option__mark {
	block-size: 1.125rem;
	border: var(--nf-border-width) solid var(--nf-planner-line);
	border-radius: var(--nf-radius-pill);
	inline-size: 1.125rem;
	inset-block-start: var(--nf-space-s);
	inset-inline-end: var(--nf-space-s);
	position: absolute;
	transition:
		background-color var(--nf-transition),
		border-color var(--nf-transition);
}

.nf-planner-option__input:checked + .nf-planner-option__card .nf-planner-option__mark {
	background-color: var(--nf-gull);
	border-color: var(--nf-gull);
}

/*
 * The tick is two borders of a rotated empty box — no SVG and no icon font, so
 * there is nothing that can load late and shift the mark.
 */
.nf-planner-option__input:checked + .nf-planner-option__card .nf-planner-option__mark::after {
	block-size: 0.5rem;
	border-bottom: 2px solid var(--nf-white);
	border-right: 2px solid var(--nf-white);
	content: "";
	inline-size: 0.28rem;
	inset-block-start: 0.22rem;
	inset-inline-start: 0.36rem;
	position: absolute;
	transform: rotate(45deg);
}

.nf-planner-option__body {
	display: flex;
	flex-direction: column;
	gap: var(--nf-space-3xs);
	margin-top: auto;
}

.nf-planner-option__label {
	font-size: 1.0625rem;   /* 17px */
	line-height: var(--nf-lh-heading);
}

.nf-planner-option__description {
	color: var(--nf-color-text-muted);
	font-size: var(--nf-fs-small);
	line-height: var(--nf-lh-body);
}


/* Text rows ---------------------------------------------------------------- */

.nf-planner-row {
	display: flex;
	flex-direction: column;
	gap: var(--nf-space-3xs);
}

.nf-planner-row__label {
	color: var(--nf-color-text-muted);
	font-size: var(--nf-fs-small);
	line-height: var(--nf-lh-body);
}

.nf-planner-row__input {
	background-color: transparent;
	border: var(--nf-border-width) solid var(--nf-planner-line);
	border-radius: var(--nf-radius);
	color: var(--nf-color-text);
	font-family: var(--nf-font-body);
	font-size: var(--nf-fs-body);
	font-weight: var(--nf-font-weight-medium);
	line-height: var(--nf-lh-body);
	min-height: 2.75rem;
	padding: var(--nf-space-2xs) var(--nf-space-s);
	transition:
		background-color var(--nf-transition),
		border-color var(--nf-transition);
	width: 100%;
}

.nf-planner-row__input::placeholder {
	color: var(--nf-color-text-muted);
	font-weight: var(--nf-font-weight-regular);
	opacity: 1;   /* Firefox dims placeholders by default. */
}

.nf-planner-row__input:hover {
	background-color: var(--nf-planner-card-hover);
	border-color: var(--nf-planner-line-strong);
}

/*
 * The background stays put on focus. Tinting it towards the selected-card
 * colour would say "chosen" about a field that is merely being typed into, and
 * the outline says "focused" perfectly well on its own.
 */
.nf-planner-row__input:focus-visible {
	border-color: var(--nf-planner-line-strong);
	outline: 2px solid var(--nf-color-accent);
	outline-offset: 1px;
}

.nf-planner-field__add {
	font-size: var(--nf-fs-small);
	margin-top: var(--nf-space-s);
}

/* Repeated groups — the rooms ---------------------------------------------- */

.nf-planner-groups {
	display: flex;
	flex-direction: column;
	gap: var(--nf-space-m);
}

/*
 * Everything belonging to one floor area, gathered inside one outline — the
 * questions in step one, and the answers read back in the summary. One rule for
 * both, because they are the same device: with three areas on screen the
 * boundary is the only thing saying which material belongs to which floor, and
 * two ways of drawing it would be two chances to drift apart.
 *
 * A border and the page's own background, not a fill. Three nested fills —
 * page, area, panel — would leave the panels with nothing left to lift off,
 * and the panels are what the visitor is actually reading.
 */
.nf-planner-group,
.nf-planner-summary__block {
	border: var(--nf-border-width) solid var(--nf-planner-line);
	border-radius: var(--nf-radius-l);
	display: block;
	padding: var(--nf-space-m);
}

.nf-planner-group__header {
	margin-bottom: var(--nf-space-m);
}

/*
 * "4A. Floor area nr 1" — the address of the room. Small and quiet, because the
 * name below it is what the visitor recognises; this line is only there so the
 * room can be referred to.
 */
.nf-planner-group__eyebrow {
	color: var(--nf-color-text-muted);
	font-family: var(--nf-font-body);
	font-size: var(--nf-fs-small);
	line-height: var(--nf-lh-body);
	margin: 0 0 var(--nf-space-3xs);
}

/* The name the visitor gave the room. */
.nf-planner-group__title {
	font-size: var(--nf-fs-h3);
}

.nf-planner-group__fields {
	display: flex;
	flex-direction: column;
	gap: var(--nf-space-m);
}

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

/*
 * An icon card is taller than a plain one and its label sits under the icon, so
 * the two stack rather than the icon being pushed to a corner. The icon is
 * decorative — the label already says what it says — so it is `aria-hidden` in
 * the markup and free to be sized purely visually.
 */
.nf-planner-option__icon {
	color: var(--nf-color-accent);
	display: block;
	font-size: 1.5rem;
	line-height: 1;
	margin-bottom: var(--nf-space-2xs);
}

.nf-planner-options--icons .nf-planner-option__card {
	min-height: 8.5rem;
}

/* Checklists --------------------------------------------------------------- */

.nf-planner-checks {
	display: grid;
	gap: var(--nf-space-s) var(--nf-space-m);
	grid-template-columns: repeat(var(--nf-planner-columns, 4), minmax(0, 1fr));
}

.nf-planner-check {
	min-width: 0;
	position: relative;
}

/*
 * Same treatment as an option card's input: out of the visual layer, still in
 * the accessible one, and parked where its mark is drawn.
 */
.nf-planner-check__input {
	appearance: none;
	block-size: 1px;
	border: 0;
	inline-size: 1px;
	inset-block-start: 0.25rem;
	inset-inline-start: 0;
	margin: 0;
	opacity: 0;
	padding: 0;
	position: absolute;
}

.nf-planner-check__label {
	align-items: center;
	cursor: pointer;
	display: flex;
	gap: var(--nf-space-2xs);
}

.nf-planner-check__mark {
	block-size: 1.125rem;
	border: var(--nf-border-width) solid var(--nf-planner-line);
	border-radius: var(--nf-radius-pill);
	flex: 0 0 auto;
	inline-size: 1.125rem;
	position: relative;
	transition:
		background-color var(--nf-transition),
		border-color var(--nf-transition);
}

/*
 * The summary's read-only ticks share the interactive mark's drawing: one
 * `.is-on` alongside the `:checked` selector, so a tick can never end up
 * looking like two different things in two places.
 */
.nf-planner-check__input:checked + .nf-planner-check__label .nf-planner-check__mark,
.nf-planner-check__mark.is-on {
	background-color: var(--nf-gull);
	border-color: var(--nf-gull);
}

/* The same tick an option card draws. See .nf-planner-option__mark::after. */
.nf-planner-check__input:checked + .nf-planner-check__label .nf-planner-check__mark::after,
.nf-planner-check__mark.is-on::after {
	block-size: 0.5rem;
	border-bottom: 2px solid var(--nf-white);
	border-right: 2px solid var(--nf-white);
	content: "";
	inline-size: 0.28rem;
	inset-block-start: 0.22rem;
	inset-inline-start: 0.36rem;
	position: absolute;
	transform: rotate(45deg);
}

.nf-planner-check__input:focus-visible + .nf-planner-check__label {
	outline: 2px solid var(--nf-color-accent);
	outline-offset: 3px;
}

.nf-planner-check__text {
	font-size: 1rem;
	line-height: var(--nf-lh-heading);
}

.nf-planner-check__label:hover .nf-planner-check__mark {
	border-color: var(--nf-planner-line-strong);
}

/* Textarea ----------------------------------------------------------------- */

.nf-planner-textarea__input {
	background-color: transparent;
	border: var(--nf-border-width) solid var(--nf-planner-line);
	border-radius: var(--nf-radius);
	color: var(--nf-color-text);
	display: block;
	font-family: var(--nf-font-body);
	font-size: var(--nf-fs-body);
	line-height: var(--nf-lh-body);
	padding: var(--nf-space-s);
	resize: vertical;
	transition: border-color var(--nf-transition);
	width: 100%;
}

/*
 * Fainter than the muted text elsewhere, and fainter than the single-line
 * inputs' own placeholders: this one is a three-line worked example, so it fills
 * the box the way real content would. At the usual 70% it reads as something
 * already typed, and the visitor has to work out that it is not.
 *
 * Done with the alpha token rather than the `opacity` property. `opacity: 1` has
 * to stay to cancel Firefox's own dimming, so dropping the value there too
 * would leave the rule saying one thing and rendering another.
 */
.nf-planner-textarea__input::placeholder {
	color: var(--nf-mork-sort-50);
	opacity: 1;   /* Firefox dims placeholders by default. */
}

.nf-planner-textarea__input:hover {
	background-color: var(--nf-planner-card-hover);
	border-color: var(--nf-planner-line-strong);
}

.nf-planner-textarea__input:focus-visible {
	border-color: var(--nf-planner-line-strong);
	outline: 2px solid var(--nf-color-accent);
	outline-offset: 1px;
}

.nf-planner-textarea__count {
	color: var(--nf-color-text-muted);
	font-size: var(--nf-fs-small);
	font-variant-numeric: tabular-nums;
	line-height: var(--nf-lh-body);
	margin: var(--nf-space-2xs) 0 0;
}

/* At the limit the counter stops being a note and becomes the reason nothing
   more is being typed, so it says so. */
.nf-planner-textarea__count.is-full {
	color: var(--nf-color-text);
	font-weight: var(--nf-font-weight-medium);
}

/* Drop zones --------------------------------------------------------------- */

.nf-planner-zones {
	display: grid;
	gap: var(--nf-space-s);
	grid-template-columns: repeat(var(--nf-planner-columns, 2), minmax(0, 1fr));
}

.nf-planner-zone {
	min-width: 0;
	position: relative;
}

/*
 * The file input is hidden the same careful way every other input here is —
 * `opacity: 0`, not `display: none` — so it keeps its place in the tab order and
 * the label keeps working. Parked at the top of the zone so a browser scrolling
 * to it scrolls to the zone.
 */
.nf-planner-zone__input {
	block-size: 1px;
	inline-size: 1px;
	inset-block-start: var(--nf-space-s);
	inset-inline-start: var(--nf-space-s);
	opacity: 0;
	position: absolute;
}

/*
 * Dashed, per the design, and it is the right convention: a dashed edge reads
 * as somewhere to put something rather than as a filled control.
 */
.nf-planner-zone__body {
	align-items: center;
	border: var(--nf-border-width) dashed var(--nf-planner-line-strong);
	border-radius: var(--nf-radius);
	cursor: pointer;
	display: flex;
	flex-direction: column;
	gap: var(--nf-space-3xs);
	padding: var(--nf-space-l) var(--nf-space-s);
	text-align: center;
	transition:
		background-color var(--nf-transition),
		border-color var(--nf-transition);
}

.nf-planner-zone__body:hover,
.nf-planner-zone.is-dragging .nf-planner-zone__body {
	background-color: var(--nf-planner-card-hover);
}

.nf-planner-zone.is-dragging .nf-planner-zone__body {
	border-style: solid;
}

.nf-planner-zone__input:focus-visible + .nf-planner-zone__body {
	outline: 2px solid var(--nf-color-accent);
	outline-offset: 2px;
}

.nf-planner .nf-planner-zone__title {
	font-size: 1.0625rem;   /* 17px */
	line-height: var(--nf-lh-heading);
	margin-bottom: var(--nf-space-2xs);
}

/*
 * The icon is the zone's centre of gravity, and the design gives it room on
 * both sides rather than tucking it under the title.
 */
.nf-planner-zone__icon {
	color: var(--nf-color-accent);
	font-size: 2rem;
	line-height: 1;
	margin-block: var(--nf-space-2xs) var(--nf-space-s);
}

.nf-planner-zone__prompt {
	font-size: var(--nf-fs-small);
	font-weight: var(--nf-font-weight-medium);
	line-height: var(--nf-lh-body);
}

.nf-planner-zone__formats {
	color: var(--nf-color-text-muted);
	font-size: var(--nf-fs-small);
	line-height: var(--nf-lh-body);
}

.nf-planner-zone__button {
	margin-top: var(--nf-space-s);
	pointer-events: none;   /* The label above it already opens the picker. */
}

/*
 * The chosen files. Filled, unlike the zone above them, because these are the
 * one thing in the panel that is a *result* rather than a control — something
 * the visitor has already done, listed back to them.
 */
.nf-planner-zone__files {
	display: flex;
	flex-direction: column;
	gap: var(--nf-space-3xs);
	list-style: none;
	margin: var(--nf-space-2xs) 0 0;
	padding: 0;
}

.nf-planner-zone__file {
	align-items: center;
	background-color: var(--nf-planner-card);
	border: var(--nf-border-width) solid var(--nf-planner-line);
	border-radius: var(--nf-radius);
	display: flex;
	gap: var(--nf-space-2xs);
	padding: var(--nf-space-3xs) var(--nf-space-3xs) var(--nf-space-3xs) var(--nf-space-2xs);
}

/*
 * `min-width: 0` is what lets the ellipsis happen: without it a flex item
 * refuses to shrink below its content and a long file name pushes the remove
 * button off the panel instead of truncating.
 */
.nf-planner-zone__file-name {
	color: var(--nf-color-text);
	flex: 1 1 auto;
	font-size: var(--nf-fs-small);
	line-height: var(--nf-lh-body);
	min-width: 0;
	overflow: hidden;
	text-overflow: ellipsis;
	white-space: nowrap;
}

/*
 * The × is drawn rather than typed: two rotated rules, so it is the same weight
 * at any size, sits exactly on centre, and never reaches the accessibility tree
 * — the button's aria-label names the file instead.
 */
.nf-planner-zone__remove {
	background-color: transparent;
	border: 0;
	border-radius: var(--nf-radius-s);
	block-size: 1.5rem;
	cursor: pointer;
	flex: 0 0 auto;
	inline-size: 1.5rem;
	padding: 0;
	position: relative;
	transition: background-color var(--nf-transition);
}

.nf-planner-zone__remove::before,
.nf-planner-zone__remove::after {
	background-color: var(--nf-color-text-muted);
	block-size: 1px;
	content: "";
	inline-size: 0.625rem;
	inset-block-start: 50%;
	inset-inline-start: 50%;
	position: absolute;
	transition: background-color var(--nf-transition);
}

.nf-planner-zone__remove::before {
	transform: translate(-50%, -50%) rotate(45deg);
}

.nf-planner-zone__remove::after {
	transform: translate(-50%, -50%) rotate(-45deg);
}

.nf-planner-zone__remove:hover {
	background-color: var(--nf-planner-card-hover);
}

.nf-planner-zone__remove:hover::before,
.nf-planner-zone__remove:hover::after {
	background-color: var(--nf-color-text);
}

.nf-planner-zone__remove:focus-visible {
	outline: 2px solid var(--nf-color-accent);
	outline-offset: 1px;
}

/* The total-area boxes under the zones. */
.nf-planner-field__text {
	margin-top: var(--nf-space-m);
}

/*
 * Half the panel each. Equal because neither unit is the primary one — which
 * of them somebody thinks in depends on where they are, and making m² the
 * wide one would say otherwise.
 *
 * No max-width: they were capped at 26rem and sat as a pair of short boxes
 * against the left of a much wider panel, which read as unfinished rather
 * than as a deliberate measure.
 */
.nf-planner-units {
	display: grid;
	gap: var(--nf-space-s);
	grid-template-columns: repeat(2, minmax(0, 1fr));
}

.nf-planner-unit {
	position: relative;
}

/*
 * The suffix is drawn over the input rather than beside it, so the two boxes
 * stay the same width whatever the unit is called. `aria-hidden`, because the
 * input already has a real label naming its unit — see
 * nf_planner_render_units().
 */
.nf-planner-unit__input {
	background-color: transparent;
	border: var(--nf-border-width) solid var(--nf-planner-line);
	border-radius: var(--nf-radius);
	color: var(--nf-color-text);
	font-family: var(--nf-font-body);
	font-size: var(--nf-fs-body);
	font-weight: var(--nf-font-weight-medium);
	line-height: var(--nf-lh-body);
	min-height: 2.75rem;
	transition:
		background-color var(--nf-transition),
		border-color var(--nf-transition);
	width: 100%;

	/* Room for the suffix, which sits inside the box on the trailing side. */
	padding: var(--nf-space-2xs) 3.25rem var(--nf-space-2xs) var(--nf-space-s);
}

.nf-planner-unit__input::placeholder {
	color: var(--nf-color-text-muted);
	opacity: 0.55;
}

.nf-planner-unit__input:focus-visible {
	border-color: var(--nf-gull);
	outline: 2px solid var(--nf-gull);
	outline-offset: 1px;
}

.nf-planner-unit__suffix {
	color: var(--nf-color-text-muted);
	font-size: var(--nf-fs-small);
	inset-block-start: 50%;
	inset-inline-end: var(--nf-space-s);
	pointer-events: none;
	position: absolute;
	transform: translateY(-50%);
}

/* Footer bar — progress, summary, Next --------------------------------------- */

/*
 * `position: sticky` inside the planner, not `fixed` to the window, and that is
 * the whole trick: a sticky element is bounded by its containing block, so this
 * rides the bottom of the viewport while the step is on screen and then comes to
 * rest at the planner's own bottom edge — above the site footer — instead of
 * hanging over it forever.
 *
 * It needs an opaque background because content scrolls underneath, and it needs
 * `bottom: 0` rather than a gap: an inset here would show a strip of that
 * content between the bar and the window edge.
 */
.nf-planner__footer {
	align-items: center;
	background-color: var(--nf-lys);
	border: var(--nf-border-width) solid var(--nf-planner-line);
	border-radius: var(--nf-radius-l);
	bottom: 0;
	column-gap: var(--nf-space-m);
	display: flex;
	flex-wrap: wrap;
	justify-content: space-between;

	/*
	 * More than the gap between panels, because this is the last thing on the
	 * page and it floats: a bar that sits as close to the final panel as two
	 * panels sit to each other reads as jammed against it.
	 */
	margin-top: var(--nf-space-xl);
	padding: var(--nf-space-s) var(--nf-space-m);
	position: sticky;
	row-gap: var(--nf-space-s);

	/*
	 * A sticky bar cannot be transparent — the questions scroll underneath it —
	 * so it takes the page's own colour and lifts off with a border and a
	 * shadow rather than with a fill of its own. The effect is a bar that
	 * reads as part of the page while still hiding what passes behind it.
	 */
	box-shadow: var(--nf-shadow-m);

	/* Above the question panels it scrolls over, below the site header. */
	z-index: var(--nf-z-content);
}

/* Progress ------------------------------------------------------------------ */

.nf-planner-progress {
	align-items: center;
	column-gap: var(--nf-space-m);
	display: flex;
	flex: 1 1 20rem;
	flex-wrap: wrap;
	row-gap: var(--nf-space-2xs);
}

.nf-planner-progress__title {
	font-size: 1.0625rem;   /* 17px */
	margin: 0;
}

.nf-planner-progress__list {
	align-items: center;
	display: flex;
	flex: 1 1 12rem;
	list-style: none;
	margin: 0;
	max-width: 22rem;
	padding: 0;
}

/*
 * Each step is a circle, and every step after the first is preceded by the
 * dashed run that joins it to the one before. Drawing the connector as a
 * ::before on the *following* step rather than an ::after on the previous one
 * means the last step needs no exception — there is never a line trailing off
 * the end.
 */
.nf-planner-progress__step {
	align-items: center;
	display: flex;
	flex: 1 1 auto;
}

.nf-planner-progress__step:first-child {
	flex: 0 0 auto;
}

.nf-planner-progress__step:not(:first-child)::before {
	border-top: 1px dashed var(--nf-planner-line-strong);
	content: "";
	flex: 1 1 auto;
	min-width: var(--nf-space-s);
}

.nf-planner-progress__number {
	align-items: center;
	block-size: 1.625rem;
	border: var(--nf-border-width) dashed var(--nf-planner-line-strong);
	border-radius: var(--nf-radius-pill);
	color: var(--nf-color-text-muted);
	display: flex;
	flex: 0 0 auto;
	font-family: var(--nf-font-display);
	font-size: var(--nf-fs-small);
	inline-size: 1.625rem;
	justify-content: center;
	line-height: 1;
}

/*
 * The step you are on is the only solid circle in the row. A dashed ring reads
 * as provisional, which is exactly right for the steps not yet reached and
 * exactly wrong for the one being worked on.
 */
.nf-planner-progress__step.is-current .nf-planner-progress__number {
	border-style: solid;
	color: var(--nf-color-text);
}

.nf-planner-progress__step.is-done .nf-planner-progress__number {
	background-color: var(--nf-gull);
	border-color: var(--nf-gull);
	border-style: solid;
	color: var(--nf-mork-sort);
}

/* Summary and Next ---------------------------------------------------------- */

.nf-planner__actions {
	align-items: center;
	column-gap: var(--nf-space-m);
	display: flex;
	flex: 0 1 auto;
	flex-wrap: wrap;
	justify-content: flex-end;
	row-gap: var(--nf-space-2xs);
}

/*
 * Wide enough for a question's name to sit on two lines and no wider: past
 * that it starts pushing the Next button around, and the button's position is
 * the one thing in the bar that should not move as the answer changes.
 */
.nf-planner__summary {
	margin: 0;
	max-width: 16rem;
	text-align: right;
}

.nf-planner__summary-label,
.nf-planner__summary-value {
	display: block;
	font-size: var(--nf-fs-small);
	line-height: var(--nf-lh-body);
}

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

.nf-planner__summary-value {
	color: var(--nf-color-text);
	font-weight: var(--nf-font-weight-medium);
}

/*
 * A disabled Next is the point of the gate, but a control that looks broken is
 * not: it keeps its shape and loses its contrast, and `cursor: not-allowed`
 * says the press was received and declined rather than missed.
 */
.nf-planner__next[disabled] {
	cursor: not-allowed;
	opacity: 0.4;
}

.nf-planner__next[disabled]:hover {
	background-color: var(--nf-mork-sort);
}

/* Positions ----------------------------------------------------------------- */

/*
 * One screenful. `display: block` is stated because it is what stops the
 * user-agent's `[hidden] { display: none }` from applying — see the rule at the
 * top of this file — and every position but one carries `hidden`.
 */
.nf-planner__position {
	display: block;
}

/* The heading takes focus when the visitor moves here, and should not ring. */
.nf-planner__title:focus {
	outline: none;
}

/*
 * "2B. Floor area nr 2 — Terrace, south". The number is server-rendered; the
 * name is written in by the script from what the visitor typed in step one.
 */
/*
 * `flex-basis: 100%` is what stacks it: the header is a flex row so the title
 * and the intro can share a line, and without this the eyebrow joins them there
 * as a third item. Taking the full basis pushes the other two onto the next
 * line, which is what puts the area's name above the step's rather than in
 * front of it. The gap comes from the header's own row-gap, so there is one
 * place that decides it.
 */
.nf-planner__eyebrow {
	color: var(--nf-color-text-muted);
	flex: 1 1 100%;
	font-family: var(--nf-font-body);
	font-size: var(--nf-fs-small);
	line-height: var(--nf-lh-body);
	margin: 0;
}

.nf-planner__area-name {
	color: var(--nf-color-text);
	font-weight: var(--nf-font-weight-medium);
}

/* Empty until the script fills it, so the dash must not be there before it. */
.nf-planner__area-name:not(:empty)::before {
	color: var(--nf-color-text-muted);
	content: " — ";
	font-weight: var(--nf-font-weight-regular);
}

.nf-planner-progress__area:not(:empty)::before {
	content: " · ";
}

/* Image frames -------------------------------------------------------------- */

/*
 * Every picture in the planner sits in one of these. The frame holds the aspect
 * ratio whether or not the image resolves, which is what lets the material cards
 * be laid out and reviewed before the photography exists — and what stops the
 * page reflowing when it arrives.
 */
.nf-planner-frame {
	aspect-ratio: var(--nf-planner-ratio, 4 / 3);
	background-color: var(--nf-planner-card-hover);
	display: block;
	overflow: hidden;
	position: relative;
	width: 100%;
}

/*
 * Targeted by position, not by class, and absolutely positioned. Both
 * details are load-bearing, and each fixes a real way this broke:
 *
 * 1. `> *` and `img`, rather than `.nf-planner-frame__image`. An
 *    image-optimisation plugin (Imagify, ShortPixel, EWWW) rewrites <img>
 *    into <picture><source><img> on the front end *and moves the class onto
 *    the wrapper* — so a rule naming the image by class lands on a box that
 *    is no longer the image. The inner <img> then falls back to base.css
 *    `img { height: auto }`, takes its intrinsic 3:2 height inside a 4:3
 *    frame, and sits top-aligned with 35px of frame background showing
 *    beneath it. That is invisible in an editor preview, because the plugin
 *    only rewrites the front end. The Projects, Card slider, Image Slider
 *    and project-gallery frames all carry the same fix.
 *
 * 2. `position: absolute` with `inset: 0`, rather than a percentage height.
 *    For an absolutely positioned box, top:0 and bottom:0 determine the
 *    height even when `height` computes to `auto` — so this holds whichever
 *    height declaration wins the cascade, and does not depend on the
 *    frame's own height being definite for a percentage to resolve against.
 *    The frame is `position: relative` for exactly this.
 */
.nf-planner-frame > img,
.nf-planner-frame > picture,
.nf-planner-frame picture img {
	block-size: 100%;
	display: block;
	inline-size: 100%;
	inset: 0;
	object-fit: cover;
	position: absolute;
}

/*
 * Why the selectors below are scoped with `.nf-planner`
 * -------------------------------------------------------------------------
 * Each of them sets a margin on an element that also carries `.nf-display`,
 * and that utility sets `margin-block: 0`. Both are single-class selectors,
 * so the winner is decided by stylesheet order — and on the front end
 * components.css is printed after planner.css, which meant every one of
 * these margins was silently dropped. It rendered correctly in a
 * concatenated preview, where the order happens to be the other way round,
 * which is exactly what made it hard to see.
 *
 * `.nf-planner` in front makes them (0,2,0) and takes stylesheet order out
 * of it. Any new rule putting a margin on a `.nf-display` element needs the
 * same prefix.
 */

/*
 * An image shown whole rather than filled to the frame. For a drawing — a
 * laying pattern, a diagram — cropping removes information, which is the
 * opposite of what cropping a photograph does.
 */
.nf-planner-frame--contain > img,
.nf-planner-frame--contain > picture,
.nf-planner-frame--contain picture img {
	object-fit: contain;
}

/* Picture cards — steps two and three -------------------------------------- */

.nf-planner-picks {
	display: grid;
	gap: var(--nf-space-s);
	grid-template-columns: repeat(var(--nf-planner-columns, 3), minmax(0, 1fr));
}

/* The grid cell — it positions the radio and lets the card fill the track. */
.nf-planner-pick {
	display: grid;
	min-width: 0;
	position: relative;
}

.nf-planner-pick__input {
	appearance: none;
	block-size: 1px;
	border: 0;
	inline-size: 1px;
	inset-block-start: var(--nf-space-s);
	inset-inline-end: var(--nf-space-s);
	margin: 0;
	opacity: 0;
	padding: 0;
	position: absolute;
}

/*
 * The card holds the label *and* the Explore link, which is why it is a box of
 * its own rather than the label itself: a link inside a label is swallowed by
 * it, and clicking "Explore Light Oppdal" would select the material instead of
 * going anywhere. Two siblings inside one bordered box, and
 * `:checked + .card` still styles the whole thing.
 *
 * `overflow: hidden` is what keeps the photo's square corners inside the card's
 * rounded ones.
 */
.nf-planner-pick__card {
	border: var(--nf-border-width) solid var(--nf-planner-line);
	border-radius: var(--nf-radius);
	display: flex;
	flex-direction: column;
	overflow: hidden;

	/* The containing block for the selected ring. See below. */
	position: relative;
	transition:
		background-color var(--nf-transition),
		border-color var(--nf-transition),
		box-shadow var(--nf-transition);
}

.nf-planner-pick__card:hover {
	background-color: var(--nf-planner-card-hover);
	border-color: var(--nf-planner-line-strong);
}

.nf-planner-pick__input:checked + .nf-planner-pick__card {
	background-color: var(--nf-planner-card-selected);
	border-color: var(--nf-planner-line-strong);
}

/*
 * The second ring of the selected state, drawn as an overlay rather than as
 * `box-shadow: inset`, which is what it was.
 *
 * An inset shadow is painted beneath the element's own children, and the
 * picture frame across the top of the card has a background of its own — so it
 * covered the ring wherever it reached the card's edges. The result was a
 * selected card whose outline read as two pixels along the bottom, where only
 * the card shows, and one along the top.
 *
 * A positioned pseudo-element paints above the in-flow children instead, so
 * the ring is the same weight the whole way round.
 */
.nf-planner-pick__input:checked + .nf-planner-pick__card::after {
	border: var(--nf-border-width) solid var(--nf-planner-line-strong);
	border-radius: calc(var(--nf-radius) - var(--nf-border-width));
	content: "";
	inset: 0;
	pointer-events: none;
	position: absolute;
}

.nf-planner-pick__input:focus-visible + .nf-planner-pick__card {
	outline: 2px solid var(--nf-color-accent);
	outline-offset: 2px;
}

/* The clickable part: everything except the link. */
.nf-planner-pick__main {
	cursor: pointer;
	display: block;
	flex: 1 1 auto;
	position: relative;
}

/* The mark sits over the photo, so it needs its own stacking and contrast. */
.nf-planner-pick__main .nf-planner-option__mark {
	background-color: var(--nf-lys-70);
	z-index: var(--nf-z-content);
}

.nf-planner-pick__input:checked + .nf-planner-pick__card .nf-planner-option__mark {
	background-color: var(--nf-gull);
	border-color: var(--nf-gull);
}

.nf-planner-pick__input:checked + .nf-planner-pick__card .nf-planner-option__mark::after {
	block-size: 0.5rem;
	border-bottom: 2px solid var(--nf-white);
	border-right: 2px solid var(--nf-white);
	content: "";
	inline-size: 0.28rem;
	inset-block-start: 0.22rem;
	inset-inline-start: 0.36rem;
	position: absolute;
	transform: rotate(45deg);
}

.nf-planner-pick__body {
	display: block;
	padding: var(--nf-space-s);
}

.nf-planner .nf-planner-pick__label {
	display: block;
	font-size: var(--nf-fs-h3);
	line-height: var(--nf-lh-heading);
	margin-bottom: var(--nf-space-2xs);
}

.nf-planner-pick__description {
	color: var(--nf-color-text-muted);
	display: block;
	font-size: var(--nf-fs-small);
	line-height: var(--nf-lh-body);
}

.nf-planner-pick__surfaces-title {
	display: block;
	font-size: var(--nf-fs-small);
	font-weight: var(--nf-font-weight-medium);
	line-height: var(--nf-lh-body);
	margin-top: var(--nf-space-s);
}

/*
 * The photograph strip along the foot of a material card. Not a scroller and
 * not a slideshow: five or six thumbnails fit across a card at every width the
 * cards are shown at, so a row of them shows the whole set at once, which is
 * what a carousel spends interaction budget failing to do.
 *
 * They sit *outside* the card's <label> — see nf_planner_render_thumbs() — so
 * clicking one opens the photograph rather than selecting the material.
 */
/*
 * As many columns as the row actually shows, which PHP puts in
 * `--nf-thumbs-shown`. The card shows three and hides the rest behind a
 * "+8"; the overview shows all of its case photographs. One rule serves
 * both because the count travels with the markup rather than being guessed
 * at here.
 *
 * Three is the cap on the card for a reason: three cards to a row leaves
 * about 280px inside one, and more than three thumbnails in that are too
 * small to tell one grey from another — which is the only thing a surface
 * shot is there to do.
 */
.nf-planner-thumbs {
	border-top: var(--nf-border-width) solid var(--nf-planner-line);
	display: grid;
	gap: var(--nf-space-3xs);
	grid-template-columns: repeat(var(--nf-thumbs-shown, 3), minmax(0, 1fr));
	padding: var(--nf-space-xs) var(--nf-space-s);
}

/*
 * The count of what is not shown, over the last one that is. The tint is on a
 * pseudo-element rather than on the link, so the number stays at full strength
 * while the photograph behind it is dimmed.
 */
.nf-planner-thumb__more {
	align-items: center;
	color: var(--nf-lys);
	display: flex;
	font-family: var(--nf-font-body);
	font-size: var(--nf-fs-body);
	font-weight: var(--nf-font-weight-bold);
	inset: 0;
	justify-content: center;
	position: absolute;
	z-index: 1;
}

.nf-planner-thumb__more::before {
	background-color: rgb(27 25 22 / 55%);
	content: "";
	inset: 0;
	position: absolute;
	z-index: -1;
}

/* Inside the overview a strip is a section of its own, not a card foot. */
.nf-planner-overview__cases .nf-planner-thumbs,
.nf-planner-overview__surfaces .nf-planner-thumbs {
	border-top: 0;
	padding: 0;
}

/*
 * The surfaces wrap into rows instead of taking a column each. A column each is
 * right on the card, where there are three of them; here there are eleven, and
 * eleven columns inside the dialog is a filmstrip of 80px squares — too small
 * to tell one grey from another, which is the only thing a surface shot is for.
 *
 * auto-fill rather than a count, and no breakpoint: the dialog is 1100px wide
 * at desk size and a single column on a phone, and one floor value covers both.
 *
 * 10rem is that floor because of what it lands on. It gives six across in the
 * open dialog, which splits eleven surfaces 6 and 5 — two rows of nearly equal
 * length — and puts them on the same six-column rhythm as the project strip
 * directly below. A 7.5rem floor fitted eight, and left a second row of three
 * under a full row of eight, which reads as a mistake rather than as a wrap.
 */
.nf-planner-overview__surfaces .nf-planner-thumbs {
	grid-template-columns: repeat(auto-fill, minmax(10rem, 1fr));

	/*
	 * And a real gap between the rows, which the other strips do not need. This
	 * is the one with captions under it, and at the 4px the columns use, the
	 * last line of one row's caption sits against the top of the next row's
	 * photographs and reads as a label for them.
	 */
	row-gap: var(--nf-space-s);
}

/*
 * The link is the photograph *and* whatever caption sits under it, stacked. A
 * column rather than flow, so that the squares in a row line up with each other
 * whether or not the captions beneath them run to the same number of lines.
 */
.nf-planner-thumb {
	color: var(--nf-color-text);
	cursor: zoom-in;
	display: flex;
	flex-direction: column;
	gap: var(--nf-space-3xs);
	min-width: 0;

	/* A photograph, not a link: none of the theme's link decoration. */
	text-decoration: none;
}

/*
 * The square, and the reason it is a element of its own rather than the link
 * itself: a ratio on the link would divide the cell between the picture and its
 * caption, shrinking the photograph by however much text happens to be under it.
 *
 * The ratio is here and not only on the image inside. These are 500KB–1.2MB
 * photographs loaded lazily, so for the first moment there is no image to give
 * the cell a size — and without this the strip renders as a row of holes that
 * fills in one square at a time. It also covers the case where the file cannot
 * be resolved at all.
 */
.nf-planner-thumb__frame {
	aspect-ratio: 1 / 1;
	background-color: var(--nf-planner-card);
	border-radius: var(--nf-radius-s);
	display: block;
	overflow: hidden;
	position: relative;
}

/*
 * What the media library was given to say about this surface. Centred under the
 * square, which is what makes a row of them read as labels on a set rather than
 * as a paragraph broken into columns.
 */
.nf-planner-thumb__caption {
	color: var(--nf-color-text);
	font-size: var(--nf-fs-small);
	line-height: var(--nf-lh-body);
	text-align: center;
}

/*
 * Past the cap. Still in the markup — the viewer pages through the whole set,
 * so they have to be — but out of sight and out of the tab order.
 *
 * It has to come *after* `.nf-planner-thumb`, which sets `display: block`.
 * Both are single-class selectors, so the later one wins, and written above it
 * this rule simply lost.
 */
.nf-planner-thumb--over {
	display: none;
}

.nf-planner-thumb:focus-visible {
	outline: 2px solid var(--nf-gull);
	outline-offset: 2px;
}

/*
 * By position and absolutely placed, for the reasons on .nf-planner-frame.
 * Named rather than `> *`: the frame also holds the "+8" badge, and the link
 * around it holds the caption and the screen-reader label.
 */
.nf-planner-thumb__frame > img,
.nf-planner-thumb__frame > picture,
.nf-planner-thumb__frame picture img {
	block-size: 100%;
	display: block;
	inline-size: 100%;
	inset: 0;
	object-fit: cover;
	position: absolute;
}

/*
 * The Explore link, along the foot of the card. A top border rather than a gap,
 * so it reads as part of the card it belongs to and not as a stray link beneath
 * it.
 */
.nf-planner-pick__link {
	background-color: transparent;
	border: 0;
	border-top: var(--nf-border-width) solid var(--nf-planner-line);
	color: var(--nf-color-text);
	cursor: pointer;
	display: block;
	font-family: var(--nf-font-body);
	font-size: var(--nf-fs-small);
	text-align: left;
	width: 100%;
	padding: var(--nf-space-xs) var(--nf-space-s);
	text-decoration: underline;
	text-decoration-thickness: 1px;
	text-underline-offset: 0.25em;
}

.nf-planner-pick__link:hover,
.nf-planner-pick__link:focus {
	color: var(--nf-color-link-hover);
	text-decoration-thickness: 2px;
}

/* Info panel ---------------------------------------------------------------- */

/*
 * The exception, and the only filled box in the form: the edge-and-thickness
 * panel is reference rather than a question, and the gull fill is what says so
 * at a glance — nothing in here is being asked of you. Full strength rather
 * than a tint, because it has to read as a different *kind* of thing from the
 * outlined panels above and below it, not as a slightly warmer one.
 *
 * Dark text on gull is the theme's `nf-on-light` pairing, so the type inside
 * needs no adjusting.
 */
.nf-planner-field--spec {
	background-color: var(--nf-planner-fill);
	border-color: transparent;
}

/*
 * Three parts, and the reason it is a grid rather than two columns: the intro
 * spans the full width, and beneath it the illustration and the table sit side
 * by side. The table takes the free space because it is the part that is read;
 * the picture is sized to what it needs.
 */
.nf-planner-spec {
	display: grid;
	gap: var(--nf-space-m) var(--nf-space-l);
	grid-template-columns: minmax(0, 22rem) minmax(0, 1fr);
}

.nf-planner-spec__intro {
	grid-column: 1 / -1;
}

.nf-planner .nf-planner-spec__title {
	font-size: var(--nf-fs-h3);
	margin-bottom: var(--nf-space-2xs);
}

.nf-planner-spec__text {
	color: var(--nf-color-text);
	font-size: var(--nf-fs-small);
	line-height: var(--nf-lh-body);
	margin: 0;
	max-width: 42ch;
}

/* Edge photograph with numbered markers ------------------------------------- */

.nf-planner-edges {
	margin: 0;
}

/*
 * The positioning context for the markers, and it has to be the image's own box:
 * a wrapper that also held the caption would put the percentages against the
 * wrong height and slide every dot upwards.
 */
.nf-planner-edges__frame {
	line-height: 0;
	position: relative;
}

.nf-planner-edges__image {
	block-size: auto;
	border-radius: var(--nf-radius);
	display: block;
	inline-size: 100%;
}

/*
 * One marker per profile, placed from the edge's own `hotspot` percentages, so
 * the pair travels with the picture at any size. Translated by half its own
 * width so the coordinate is its centre and not its top-left corner — otherwise
 * every dot reads as sitting low and to the right of the point it names.
 */
.nf-planner-edges__dot {
	background-color: var(--nf-mork-sort);
	border: 2px solid var(--nf-lys);
	border-radius: var(--nf-radius-pill);
	block-size: 1.75rem;
	box-shadow: 0 1px 6px rgb(27 25 22 / 45%);
	color: var(--nf-lys);
	cursor: help;
	inline-size: 1.75rem;
	inset-block-start: var(--nf-dot-y, 50%);
	inset-inline-start: var(--nf-dot-x, 50%);
	padding: 0;
	position: absolute;
	transform: translate(-50%, -50%);
	transition: background-color var(--nf-transition);

	/*
	 * Above its neighbours, and further above them while it is being used.
	 * Without this the markers paint in source order, so an earlier one's
	 * label appeared *behind* every marker below it — marker 1's label had
	 * marker 2 sitting on top of the word it was trying to show.
	 */
	z-index: 1;
}

.nf-planner-edges__dot:hover,
.nf-planner-edges__dot:focus-visible {
	z-index: 3;
}

/*
 * The pulse is a separate ring rather than the dot itself scaling: scaling the
 * dot would scale the number inside it, and a figure that breathes is harder to
 * read than one that sits still inside a ring that does.
 */
.nf-planner-edges__dot::before {
	/*
	 * Deliberately quiet. Four rings expanding in step every 2.4s read as an
	 * alarm rather than a hint, and the markers do not need to shout — the
	 * number inside each one is what carries the meaning, and it is legible
	 * standing still.
	 *
	 * Three things make it calmer, and the last matters most: a 1px ring at a
	 * third of the opacity, a much smaller expansion, and a *stagger*, so they
	 * ripple in sequence instead of together. Synchronised motion is what the
	 * eye reads as urgent; the same movement out of phase reads as ambient.
	 *
	 * Most of the cycle is also spent at rest — see the keyframes — so what the
	 * eye catches is an occasional ripple rather than continuous breathing.
	 */
	animation: nf-planner-pulse 4.5s ease-out infinite;
	animation-delay: var(--nf-dot-delay, 0s);

	/*
	 * `backwards`, or the stagger shows its own seams: during the delay an
	 * element uses its own computed values, not the animation's first keyframe —
	 * so markers 2, 3 and 4 sat with a solid ring at full opacity for up to
	 * 1.65s after load, then snapped to invisible when their turn began. This
	 * makes the 0% frame apply while they wait.
	 */
	animation-fill-mode: backwards;
	border: 1px solid var(--nf-gull);
	border-radius: var(--nf-radius-pill);
	content: "";
	inset: -2px;
	pointer-events: none;
	position: absolute;
}

.nf-planner-edges__dot:hover,
.nf-planner-edges__dot:focus-visible {
	background-color: var(--nf-gull);
	color: var(--nf-mork-sort);
}

.nf-planner-edges__dot:focus-visible {
	outline: 2px solid var(--nf-gull);
	outline-offset: 3px;
}

/* The pulse has done its job once the marker is being used. */
.nf-planner-edges__dot:hover::before,
.nf-planner-edges__dot:focus-visible::before {
	animation: none;
	opacity: 0;
}

.nf-planner-edges__number {
	display: block;
	font-family: var(--nf-font-body);
	font-size: 0.8125rem;   /* 13px — a figure inside a 28px disc. */
	font-weight: var(--nf-font-weight-bold);
	line-height: 1.6;
}

/*
 * The tooltip. `aria-hidden`, because the marker already carries the same words
 * in `.screen-reader-text` — a label that exists only while hovered is not
 * something a screen reader should have to find.
 *
 * It opens **sideways**, level with its marker, and that is the third
 * arrangement tried. Upwards covered the markers above it; downwards covered
 * the ones below. Neither can be avoided by choosing a direction, because the
 * markers are stacked vertically about 14% apart and the label is taller than
 * that — so whichever way it opens, it lands on a neighbour, and the
 * neighbours are exactly what the reader is comparing against.
 *
 * Sideways works because all four markers sit at x≈20-26%: to their right is
 * the picture's own empty ground, and no other marker is ever there.
 */
.nf-planner-edges__tip {
	background-color: var(--nf-mork-sort);
	border-radius: var(--nf-radius);
	color: var(--nf-lys);
	display: block;
	font-family: var(--nf-font-body);
	font-size: var(--nf-fs-small);
	inset-block-start: 50%;
	/*
	 * A wider gap than it looks like it needs. The markers descend diagonally
	 * down and to the right, so a label opening leftwards travels back into that
	 * diagonal — at a smaller gap it caught the corner of the marker above it.
	 * 24px clears the whole stagger at the narrowest size the picture is shown
	 * at, and the clearance only grows as the picture does.
	 */
	inset-inline-start: calc(100% + var(--nf-space-m));
	line-height: var(--nf-lh-body);
	/*
	 * Wide enough for the longest edge name on two lines rather than three.
	 * At three it was taller than the space above the marker and got clipped
	 * by the top of the photograph.
	 */
	max-inline-size: 22ch;
	opacity: 0;
	padding: var(--nf-space-3xs) var(--nf-space-2xs);
	pointer-events: none;
	position: absolute;
	text-align: left;
	transform: translateY(-50%);
	transition: opacity var(--nf-transition);
	white-space: normal;
	inline-size: max-content;
}

.nf-planner-edges__dot:hover .nf-planner-edges__tip,
.nf-planner-edges__dot:focus-visible .nf-planner-edges__tip {
	opacity: 1;
}

.nf-planner-edges__tip-name {
	display: block;
	font-weight: var(--nf-font-weight-medium);

	/* The name on one line; the range gets its own below it. */
	white-space: nowrap;
}

/*
 * Which way the label opens. PHP decides from each marker's coordinate —
 * see nf_planner_render_edge_figure() — because CSS cannot ask where it is.
 */
/* A marker in the right third opens leftwards instead, for the same reason. */
.nf-planner-edges__dot--end .nf-planner-edges__tip {
	inset-inline-end: calc(100% + var(--nf-space-m));
	inset-inline-start: auto;
}

.nf-planner-edges__tip-range {
	color: var(--nf-lys-70);
	display: block;
}

.nf-planner-edges__caption {
	color: var(--nf-color-text-muted);
	font-size: var(--nf-fs-small);
	line-height: var(--nf-lh-body);
	margin-top: var(--nf-space-2xs);
}

/*
 * The badge beside an edge's name, matched by eye against the marker on the
 * photograph. Fixed width rather than padded, so four of them down a column line
 * up and the names start on one edge.
 */
.nf-planner-num {
	background-color: var(--nf-planner-fill);
	border-radius: var(--nf-radius-pill);
	color: var(--nf-color-text);
	display: inline-block;
	font-size: 0.75rem;   /* 12px */
	font-weight: var(--nf-font-weight-bold);
	inline-size: 1.375rem;
	line-height: 1.375rem;
	margin-inline-end: var(--nf-space-2xs);
	text-align: center;
	vertical-align: 0.1em;
}

/*
 * One ripple, then a rest for more than half the cycle. It starts *from*
 * nothing rather than at full strength, so there is no hard blink at the top
 * of each loop, and it never reaches an opacity that competes with the number
 * inside the marker.
 */
@keyframes nf-planner-pulse {

	0% {
		opacity: 0;
		transform: scale(1);
	}

	8% {
		opacity: 0.35;
		transform: scale(1);
	}

	40% {
		opacity: 0;
		transform: scale(1.5);
	}

	100% {
		opacity: 0;
		transform: scale(1.5);
	}
}


/*
 * The table's own scroller. Five columns of stone names do not fit a phone, and
 * a table is the one thing allowed to scroll sideways inside a page that must
 * not — so the overflow is put on a wrapper around it rather than anywhere it
 * could take the layout with it.
 */
.nf-planner-spec__scroll {
	max-inline-size: 100%;
	overflow-x: auto;
}

.nf-planner-spec__table {
	border-collapse: collapse;
	font-size: var(--nf-fs-small);
	inline-size: 100%;
	min-inline-size: 26rem;
	text-align: left;
}

.nf-planner-spec__table th,
.nf-planner-spec__table td {
	border-bottom: var(--nf-border-width) solid var(--nf-planner-line);
	padding: var(--nf-space-2xs) var(--nf-space-xs);
	vertical-align: middle;
}

.nf-planner-spec__table thead th {
	font-family: var(--nf-font-display);
	font-weight: var(--nf-font-weight-bold);
	line-height: var(--nf-lh-heading);
}

.nf-planner-spec__table tbody tr:last-child th,
.nf-planner-spec__table tbody tr:last-child td {
	border-bottom: 0;
}

.nf-planner-spec__row-head {
	font-weight: var(--nf-font-weight-medium);
	padding-inline-start: 0;
}

.nf-planner-spec__corner {
	padding-inline-start: 0;
}

.nf-planner-spec__range {
	color: var(--nf-color-text-muted);
	white-space: nowrap;
}

/* The availability columns are narrow and their marks are centred in them. */
.nf-planner-spec__table thead th:nth-child(n + 3),
.nf-planner-spec__cell {
	text-align: center;
}

/*
 * Drawn, not a glyph: a font's tick and dash vary with whatever is installed,
 * and a tick made of two borders is the same tick the option cards use. The
 * word beside it in `.screen-reader-text` is what a screen reader announces —
 * see nf_planner_render_spec_table(), which explains why a bare mark will not
 * do.
 */
.nf-planner-spec__mark {
	display: inline-block;
	vertical-align: middle;
}

.is-yes .nf-planner-spec__mark {
	block-size: 0.5rem;
	border-bottom: 2px solid currentcolor;
	border-left: 2px solid currentcolor;
	inline-size: 0.875rem;
	transform: rotate(-45deg) translate(1px, -2px);
}

.is-no .nf-planner-spec__mark {
	background-color: var(--nf-color-text-muted);
	block-size: 2px;
	inline-size: 0.75rem;
	opacity: 0.6;
}

/* Specification lists — the material overview -------------------------------- */

/*
 * Surfaces and edges, as terms and definitions. They used to be pictures; see
 * nf_planner_render_overview_specs() for why they cannot be — two of the four
 * surfaces are the same stone sorted differently and photograph identically.
 *
 * Nothing renders these at present: both sections have left the material
 * dialog. They are kept for the same reason the renderer is — see its docblock.
 */
.nf-planner-specs {
	display: grid;
	gap: var(--nf-space-xs);
	margin: 0;
}

.nf-planner-specs__row {
	border-top: var(--nf-border-width) solid var(--nf-planner-line);
	display: grid;
	gap: var(--nf-space-3xs) var(--nf-space-m);
	grid-template-columns: minmax(0, 14rem) minmax(0, 1fr);
	padding-top: var(--nf-space-xs);
}

.nf-planner-specs__term {
	font-weight: var(--nf-font-weight-medium);
	margin: 0;
}

/* The qualifier — a slip class, or a thickness range — under the name. */
.nf-planner-specs__detail {
	color: var(--nf-color-text-muted);
	display: block;
	font-size: var(--nf-fs-small);
	font-weight: var(--nf-font-weight-regular);
}

.nf-planner-specs__note {
	color: var(--nf-color-text-muted);
	font-size: var(--nf-fs-small);
	line-height: var(--nf-lh-body);
	margin: 0;
}

/* Card extras — step three's eyebrow and bullets ---------------------------- */

.nf-planner-pick__eyebrow {
	color: var(--nf-color-text-muted);
	display: block;
	font-size: var(--nf-fs-small);
	line-height: var(--nf-lh-body);
	margin-bottom: var(--nf-space-3xs);
}

.nf-planner-pick__points {
	display: block;
	margin-top: var(--nf-space-s);
}

/*
 * `display: list-item` on a <span>, because these bullets live inside a <label>
 * and its content model is phrasing content only — a <ul> there would be
 * invalid markup. The generated marker is the same one a list item gets.
 */
.nf-planner-pick__point {
	color: var(--nf-color-text);
	display: list-item;
	font-size: var(--nf-fs-small);
	line-height: var(--nf-lh-body);
	list-style-type: disc;
	margin-left: 1.1em;
}

/* Comparison table ---------------------------------------------------------- */

/*
 * No padding on the panel, so the header row can reach its rounded corners the
 * way the design has it; `overflow: hidden` is what clips it to them.
 */
.nf-planner-field--compare {
	overflow: hidden;
	padding: 0;
}

/*
 * The table scrolls inside its own box rather than making the page scroll
 * sideways: three columns of prose cannot be squeezed into a phone, and of the
 * two evils a table you can swipe is much the lesser.
 */
.nf-planner-compare {
	overflow-x: auto;
}

.nf-planner-compare__table {
	border-collapse: collapse;
	font-size: var(--nf-fs-small);
	line-height: var(--nf-lh-body);
	min-width: 40rem;
	width: 100%;
}

/*
 * A lighter tan than the reference panel's gull. Both are "not a question", but
 * the panel is a block of guidance and this is a header row — full strength here
 * would make the table shout louder than the cards it is describing.
 */
.nf-planner-compare__table thead th {
	background-color: var(--nf-planner-card-selected);
	font-size: var(--nf-fs-body);
	padding: var(--nf-space-xs) var(--nf-space-s);
	text-align: center;
}

/* The corner cell names the row axis, so it aligns with the row headings. */
.nf-planner-compare__table thead th:first-child {
	font-family: var(--nf-font-body);
	font-weight: var(--nf-font-weight-medium);
	text-align: left;
}

.nf-planner-compare__table th,
.nf-planner-compare__table td {
	border-top: var(--nf-border-width) solid var(--nf-planner-line);
	padding: var(--nf-space-xs) var(--nf-space-s);
	vertical-align: top;
}

.nf-planner-compare__table tbody th {
	font-family: var(--nf-font-display);
	font-weight: var(--nf-font-weight-bold);
	text-align: left;
	white-space: nowrap;
}

.nf-planner-compare__table tbody td {
	color: var(--nf-color-text-muted);
	text-align: center;
}

/*
 * Zebra striping, and it is doing real work here rather than decorating: the
 * rows are the comparison, and a reader tracking one of them across three
 * columns of similar-length prose loses their place without it.
 */
.nf-planner-compare__table tbody tr:nth-child(even) {
	background-color: var(--nf-planner-card-hover);
}

/*
 * A single-input question. Capped in width because a project name is short, and
 * an input stretched across 1400px invites the visitor to write an essay in it.
 */
.nf-planner-field--text .nf-planner-row__input {
	max-width: var(--nf-measure-narrow);
}

/* Project summary ----------------------------------------------------------- */

.nf-planner-summary {
	display: flex;
	flex-direction: column;
	gap: var(--nf-space-l);
}

/* The project, beside the list of its areas. */
.nf-planner-summary__top,
.nf-planner-summary__panels {
	display: grid;
	gap: var(--nf-space-m);
	grid-template-columns: repeat(2, minmax(0, 1fr));
}

/*
 * Outlined, like a question panel: these are the answers, and they belong to the
 * same family of boxes as the questions that collected them. The filled boxes
 * stay reserved for the things nobody is being asked about.
 */
.nf-planner-summary__panel {
	border: var(--nf-border-width) solid var(--nf-planner-line);
	border-radius: var(--nf-radius-l);
	padding: var(--nf-space-m);
}

.nf-planner-summary__panel-head {
	align-items: start;
	display: flex;
	gap: var(--nf-space-s);
	justify-content: space-between;
	margin-bottom: var(--nf-space-s);
}

.nf-planner-summary__panel-title {
	font-size: 1rem;
	line-height: var(--nf-lh-heading);
}

/*
 * The pencil. Its accessible name says which panel it edits — a row of six
 * buttons all called "Edit" tells a screen-reader user nothing — so the glyph
 * itself is decorative.
 */
.nf-planner-summary__edit {
	background-color: transparent;
	border: 0;
	border-radius: var(--nf-radius-s);
	color: var(--nf-color-text-muted);
	cursor: pointer;
	flex: 0 0 auto;
	font-size: var(--nf-fs-body);
	line-height: 1;
	padding: var(--nf-space-3xs);
	transition: background-color var(--nf-transition), color var(--nf-transition);
}

.nf-planner-summary__edit:hover {
	background-color: var(--nf-planner-card-hover);
	color: var(--nf-color-text);
}

.nf-planner-summary__edit:focus-visible {
	outline: 2px solid var(--nf-color-accent);
	outline-offset: 1px;
}

/* Label-and-value rows ------------------------------------------------------ */

.nf-planner-summary__rows {
	display: grid;
	gap: var(--nf-space-s);
	margin: 0;
}

.nf-planner-summary__label {
	color: var(--nf-color-text-muted);
	font-size: var(--nf-fs-small);
	line-height: var(--nf-lh-body);
	margin: 0;
}

.nf-planner-summary__value {
	color: var(--nf-color-text);
	font-size: var(--nf-fs-body);
	font-weight: var(--nf-font-weight-medium);
	line-height: var(--nf-lh-body);
	margin: 0;

	/* A description can be a paragraph, and its line breaks are meaningful. */
	white-space: pre-line;
}

/* Areas --------------------------------------------------------------------- */

/*
 * "Missing information" sits where an answer would, so it has to read as the
 * absence of one: lighter, unemphasised, italic. Given a real answer's weight
 * it would scan as one.
 */
.nf-planner-summary__value.is-missing {
	color: var(--nf-color-text-muted);
	font-style: italic;
	font-weight: var(--nf-font-weight-regular);
}

.nf-planner-summary__areas {
	display: grid;
	gap: var(--nf-space-s) var(--nf-space-m);
	grid-template-columns: repeat(2, minmax(0, 1fr));
}

/*
 * An area entry is two label-and-value pairs stacked — its number and name,
 * then its size. One even gap made them read as four loose lines, so the space
 * between the pairs is opened up and the space inside one closed down.
 */
.nf-planner-summary__area {
	display: grid;
	gap: var(--nf-space-3xs);
}

.nf-planner-summary__area-name + .nf-planner-summary__label {
	margin-top: var(--nf-space-s);
}

.nf-planner-summary__area-label {
	color: var(--nf-color-text-muted);
	font-size: var(--nf-fs-small);
	line-height: var(--nf-lh-body);
	margin: 0;
}

.nf-planner-summary__area-name {
	font-size: var(--nf-fs-body);
	margin: 0;
}

.nf-planner-summary__header {
	margin-bottom: var(--nf-space-m);
}

/* Empty until the area is named; the label above it carries the identity. */
.nf-planner-summary__title:empty,
.nf-planner-summary__area-name:empty {
	display: none;
}

.nf-planner-summary__title {
	font-size: var(--nf-fs-h3);
	margin: 0;
}

/* Ticked options ------------------------------------------------------------ */

.nf-planner-summary__ticks {
	display: grid;
	gap: var(--nf-space-2xs) var(--nf-space-s);
	grid-template-columns: repeat(2, minmax(0, 1fr));
	list-style: none;
	margin: 0;
	padding: 0;
}

.nf-planner-summary__tick {
	align-items: center;
	display: flex;
	gap: var(--nf-space-2xs);
	min-width: 0;
}

/*
 * An option nobody ticked is shown, and faded rather than removed: "we did not
 * record a fireplace" and "you told us there is no fireplace" are different
 * things, and only the whole list says which this is.
 */
.nf-planner-summary__tick:not(.is-on) .nf-planner-summary__tick-text {
	color: var(--nf-color-text-muted);
}

.nf-planner-summary__tick-text {
	font-size: var(--nf-fs-small);
	line-height: var(--nf-lh-body);
}

/* Files, and the empty case ------------------------------------------------- */

.nf-planner-summary__files {
	display: grid;
	gap: var(--nf-space-3xs);
	list-style: none;
	margin: 0;
	padding: 0;
}

.nf-planner-summary__file {
	font-size: var(--nf-fs-small);
	line-height: var(--nf-lh-body);
	overflow-wrap: anywhere;
}

.nf-planner-summary__empty {
	color: var(--nf-color-text-muted);
	font-size: var(--nf-fs-small);
	font-style: italic;
	line-height: var(--nf-lh-body);
	margin: 0;
}

/* What happens next --------------------------------------------------------- */

/*
 * A block that is not a question: no border and no padding, so its heading sits
 * on the page rather than inside a panel.
 */
.nf-planner-field--plain {
	border: 0;
	margin-top: var(--nf-space-l);
	padding: 0;
}

/*
 * The gap beneath is set against the type, not against the spacing scale's
 * mid-point: at 25px display, 24px was about 1.0x the heading's own size,
 * which reads as tight — and tighter still with 56px of air above it. A
 * heading this size wants 1.2-1.6x beneath, and it must stay clearly closer
 * to the cards it introduces than to whatever sits above.
 */
.nf-planner .nf-planner-outline__title {
	font-size: var(--nf-fs-h3);
	margin-bottom: var(--nf-space-l);
}

.nf-planner-outline {
	display: grid;
	gap: var(--nf-space-s);
	grid-template-columns: repeat(var(--nf-planner-columns, 3), minmax(0, 1fr));
	list-style: none;
	margin: 0;
	padding: 0;
}

/*
 * Filled, unlike a question panel: these are reassurance rather than something
 * to answer, which is the same argument the reference panels make — the fill is
 * what says "nothing here is being asked of you". Lighter than the gull notes,
 * because there are three of them side by side.
 */
.nf-planner-outline__card {
	background-color: var(--nf-planner-fill);
	border-radius: var(--nf-radius-l);
	padding: var(--nf-space-m);
}

.nf-planner .nf-planner-outline__heading {
	font-size: 1.0625rem;   /* 17px */
	line-height: var(--nf-lh-heading);
	margin-bottom: var(--nf-space-xs);
}

.nf-planner-outline__text {
	color: var(--nf-color-text-muted);
	font-size: var(--nf-fs-small);
	line-height: var(--nf-lh-body);
	margin: 0;
}

/* Note panel ---------------------------------------------------------------- */

/*
 * The same gull fill as the reference panel, and for the same reason: it is not
 * a question. Title beside the prose rather than above it, so a paragraph this
 * long does not read as a wall of text.
 */
.nf-planner-field--note {
	background-color: var(--nf-planner-fill);
	border-color: transparent;
}

.nf-planner-note {
	display: grid;
	gap: var(--nf-space-s) var(--nf-space-xl);
	grid-template-columns: minmax(0, 1fr) minmax(0, 4fr);
}

.nf-planner-note__title {
	font-size: 1.0625rem;   /* 17px */
}

.nf-planner-note__text {
	font-size: var(--nf-fs-small);
	line-height: var(--nf-lh-body);
	margin: 0;
}

/* Project actions ----------------------------------------------------------- */

/*
 * No panel: these are controls, not a question, and the four of them share the
 * width evenly the way a toolbar does. The wrapper keeps the field's border off
 * them.
 */
.nf-planner-field--actions {
	border: 0;
	padding: 0;
}

.nf-planner-actions {
	display: grid;
	gap: var(--nf-space-s);
	grid-auto-columns: minmax(0, 1fr);
	grid-auto-flow: column;
}

.nf-planner-actions__button {
	gap: var(--nf-space-2xs);
	min-height: 2.75rem;
}

.nf-planner-actions__icon {
	font-size: 1rem;
	line-height: 1;
}

/*
 * Download PDF is not built yet, and says so rather than looking broken: it
 * keeps its shape and loses its contrast, and `not-allowed` says the press was
 * received and declined rather than missed.
 */
.nf-planner-actions__button[disabled] {
	cursor: not-allowed;
	opacity: 0.5;
}

.nf-planner-actions__button[disabled]:hover {
	background-color: var(--nf-gull);
}

/* Where "Link copied" is said. Empty until something has happened. */
.nf-planner-actions__status {
	color: var(--nf-color-text-muted);
	font-size: var(--nf-fs-small);
	line-height: var(--nf-lh-body);
	margin: var(--nf-space-2xs) 0 0;
	max-width: var(--nf-measure);
}

.nf-planner-actions__status:empty {
	display: none;
}

/* Material overview dialog -------------------------------------------------- */

/*
 * A native <dialog>. The reset matters more than it looks: a dialog comes with a
 * UA border, a white background and `margin: auto`, and it is `display: none`
 * until opened — so everything here has to be written against `[open]` or the
 * closed dialog claims space.
 */
.nf-planner-overview {
	background-color: transparent;
	border: 0;
	max-height: none;
	max-width: none;
	padding: var(--nf-gutter);
	width: 100%;
}

.nf-planner-overview[open] {
	display: flex;
}

/*
 * Fills the viewport so the panel can be centred in it and so a click anywhere
 * outside the panel still lands on the dialog — which is what the backdrop
 * dismissal depends on. `inset: 0` with `position: fixed` beats the UA's
 * centring maths, which a `max-width: none` dialog otherwise fights.
 */
.nf-planner-overview[open] {
	align-items: center;
	inset: 0;
	justify-content: center;
	position: fixed;
}

.nf-planner-overview::backdrop {
	background-color: rgb(27 25 22 / 55%);
}

/*
 * The panel. `overflow: auto` on the panel rather than the dialog so the
 * backdrop stays clickable at the edges even when the content is long, and
 * `max-height` in `svh` so a phone's collapsing address bar cannot leave the
 * actions off screen.
 */
/*
 * Two full-width bands, not two columns — what it looks like, then what it
 * does. It was two columns, and the long content was in the narrower of
 * them: the surfaces and edges ran to about 1070px while the three short
 * panels beside them came to 540, so the reader scrolled a tall left column
 * past 500px of empty right one.
 *
 * Banding fixes it by using the width. The two spec lists sit side by side
 * in the first band at about 490px each instead of stacking at 465, which
 * roughly halves that part of the height; the three panels share the second.
 */
.nf-planner-overview__inner {
	background-color: var(--nf-lys);
	border-radius: var(--nf-radius-l);
	box-shadow: var(--nf-shadow-m);
	display: grid;
	gap: var(--nf-space-l);
	grid-template-columns: minmax(0, 1fr);
	max-height: 90svh;
	max-width: var(--nf-content);
	overflow: auto;
	padding: var(--nf-space-l);
	width: 100%;
}

/*
 * The first band: the title, the lead, and the photographs of the stone laid.
 * One column at every width — it was two while the edge photograph sat beside
 * the edge names, and both of those moved out to step two, where the same
 * picture carries the numbered markers and the availability table reads
 * against it.
 *
 * Still a grid rather than flow: the gap is what separates the three, and it
 * is the one that stays right when a material has no lead paragraph.
 */
.nf-planner-overview__main {
	display: grid;
	gap: var(--nf-space-m);
	grid-template-columns: minmax(0, 1fr);
}

.nf-planner .nf-planner-overview__title {
	font-size: var(--nf-fs-h3);
	margin-bottom: var(--nf-space-2xs);
}

.nf-planner-overview__lead {
	color: var(--nf-color-text-muted);
	font-size: var(--nf-fs-small);
	line-height: var(--nf-lh-body);
	margin: 0;
	max-width: var(--nf-measure);
}


.nf-planner-overview__heading {
	font-family: var(--nf-font-body);
	font-size: var(--nf-fs-body);
	font-weight: var(--nf-font-weight-medium);
	margin: 0 0 var(--nf-space-2xs);
}

/* Right column -------------------------------------------------------------- */

/*
 * Characteristics and thicknesses sit side by side; applications span both. The
 * side column is its own grid rather than a flex column so that spanning is a
 * single declaration on the panel that does it.
 */
/*
 * The second band: the two short lists side by side, and the applications
 * across the full width beneath them. Three-in-a-row was tried and left the
 * applications panel a third of the width, where five labels of the length
 * of "Pool surrounds & landscape" each wrapped onto three lines.
 */
.nf-planner-overview__side {
	align-content: start;
	display: grid;
	gap: var(--nf-space-s);
	grid-template-columns: repeat(2, minmax(0, 1fr));
}

.nf-planner-overview__panel {
	background-color: var(--nf-planner-fill);
	border-radius: var(--nf-radius);
	padding: var(--nf-space-s);
}

/* The applications, across the whole band. */
.nf-planner-overview__panel--wide {
	grid-column: 1 / -1;
}

.nf-planner-overview__list {
	font-size: var(--nf-fs-small);
	line-height: var(--nf-lh-body);
	margin: 0;
	padding-left: 1.1em;
}

.nf-planner-overview__list li + li {
	margin-top: var(--nf-space-3xs);
}

/*
 * One row, however many applications a material lists. `auto-fit` with a
 * minimum would wrap the fifth onto a line of its own — which is what it is
 * for, but here the five are a set to be taken in at a glance, and a stray
 * one underneath reads as an afterthought.
 */
/*
 * `auto-fit` rather than a column each: five tiles fit the full band, and on
 * anything narrower they wrap to as many as will hold a label on one or two
 * lines instead of being squeezed to five regardless.
 */
.nf-planner-overview__uses {
	display: grid;
	gap: var(--nf-space-s);
	grid-template-columns: repeat(auto-fit, minmax(8rem, 1fr));
	list-style: none;
	margin: 0;
	padding: 0;
}

/*
 * A tile: the icon above its label, both centred. It used to be a
 * `list-item` with the icon inline, which in a 92px grid column read as an
 * icon stuck to the first word of a phrase wrapping under it — "Interior"
 * on one line beside the couch, "living spaces" below. Nothing about that
 * said the two belonged together.
 */
/*
 * A flex column, and that is the fix rather than a nicety. The icon already
 * carried `display: block`, but Font Awesome's kit CSS is injected by a
 * script and so lands *after* the theme's stylesheets, where its own
 * single-class `.fa-light { display: inline-block }` wins the tie on source
 * order. The icon then sat inline with the first word of its label —
 * "Interior" beside the couch, "living spaces" wrapped underneath — which
 * read as two unrelated things.
 *
 * A flex container settles it without a specificity war: flex items are
 * blockified, so whatever value Font Awesome computes for `display` is
 * discarded. Any planner rule that has to beat the icon font should reach
 * for this rather than for a longer selector.
 */
.nf-planner-overview__use {
	align-items: center;
	display: flex;
	flex-direction: column;
	font-size: var(--nf-fs-small);
	gap: var(--nf-space-3xs);
	line-height: var(--nf-lh-body);
	text-align: center;
}

.nf-planner-overview__icon {
	color: var(--nf-color-accent);
	font-size: 1.5rem;
	line-height: 1;
}

/* Actions ------------------------------------------------------------------- */

.nf-planner-overview__actions {
	display: flex;
	flex-wrap: wrap;
	gap: var(--nf-space-s);
	grid-column: 1 / -1;
	justify-content: flex-end;
}

/*
 * The unscripted send button. It exists only inside <noscript>, so none of
 * this applies to anybody who can see the footer.
 */
.nf-planner__noscript-send {
	display: flex;
	justify-content: flex-end;
	padding: var(--nf-space-l) var(--nf-gutter);
}

/* Motion ------------------------------------------------------------------- */

@media (prefers-reduced-motion: reduce) {

	/*
	 * The pulse stops; the marker and its number do not. The ring was only ever
	 * an invitation to notice the dot, and the number is what carries the
	 * meaning — so nothing is lost by holding it still.
	 */
	.nf-planner-edges__dot::before {
		animation: none;
		opacity: 0.35;
	}

	.nf-planner-field--enter {
		animation: none;
	}

	.nf-planner-option__card,
	.nf-planner-option__mark,
	.nf-planner-check__mark,
	.nf-planner-row__input,
	.nf-planner-textarea__input,
	.nf-planner-zone__body,
	.nf-planner-zone__remove,
	.nf-planner-zone__remove::before,
	.nf-planner-zone__remove::after,
	.nf-planner-pick__card {
		transition: none;
	}
}

/* Responsive --------------------------------------------------------------- */

/*
 * Every width breakpoint lives here, at the foot of the file, and nowhere else.
 * A media query carries no extra specificity of its own, so a breakpoint placed
 * beside the component it adjusts loses to any equally specific rule written
 * below it — silently, and only at the width nobody is looking at. Keeping them
 * last means they always win, and there is one place to look.
 */

/* Tablet — every grid drops to two columns. */
@media (max-width: 62rem) {

	.nf-planner-options,
	.nf-planner-rows,
	.nf-planner-checks,
	.nf-planner-zones,
	.nf-planner-picks {
		grid-template-columns: repeat(2, minmax(0, 1fr));
	}

	/*
	 * The illustration stops sitting beside the table and goes above it. Two
	 * columns of this at tablet width would leave the table too narrow to hold
	 * five headings without scrolling, and the picture too small to read.
	 */
	.nf-planner-spec {
		grid-template-columns: minmax(0, 1fr);
	}

	/* The note drops under the term rather than beside it. */
	.nf-planner-specs__row {
		grid-template-columns: minmax(0, 1fr);
	}

	/*
	 * And the side column stops being two columns at the same width. Below this
	 * it was still splitting into 228px columns, which is not enough for a term
	 * and its note however they are arranged.
	 */
	.nf-planner-overview__side {
		grid-template-columns: minmax(0, 1fr);
	}
}

/* Phone — single column, and the cards stop reserving height. */
@media (max-width: 36rem) {

	.nf-planner-options,
	.nf-planner-rows,
	.nf-planner-checks,
	.nf-planner-zones,
	.nf-planner-picks {
		grid-template-columns: minmax(0, 1fr);
	}

	/*
	 * One card per row, so there is no neighbour to align a bottom edge with.
	 * The reserved height, the deep top padding and the bottom-anchored text
	 * all stop earning their keep and start reading as dead space above every
	 * title — and on a phone that space is scroll the visitor pays for.
	 */
	.nf-planner-option__card,
	.nf-planner-options--icons .nf-planner-option__card {
		min-height: 0;
		padding-top: var(--nf-space-s);
	}

	.nf-planner-option__body {
		margin-top: 0;
	}

	/* An icon beside the label rather than above it, for the same reason. */
	.nf-planner-options--icons .nf-planner-option__body {
		align-items: baseline;
		column-gap: var(--nf-space-2xs);
		display: flex;
		flex-wrap: wrap;
	}

	.nf-planner-options--icons .nf-planner-option__icon {
		margin-bottom: 0;
	}

	/* An area's own padding on top of the panels' is too much on a narrow page. */
	.nf-planner-group,
	.nf-planner-summary__block {
		padding: var(--nf-space-s);
	}

	/*
	 * The bar is sticky, so on a phone every row it takes is a quarter of the
	 * screen the visitor cannot use. Two rows is the floor — progress, then
	 * summary and button — and getting there is a matter of deciding what
	 * gives way.
	 *
	 * The connectors do: their length is decoration, and shortening them lets
	 * the dots sit beside the step name instead of below it. The name stays,
	 * because once the page heading has scrolled away this bar is the only
	 * thing still saying which step this is.
	 */
	.nf-planner__footer {
		padding: var(--nf-space-s);
	}

	.nf-planner-progress {
		column-gap: var(--nf-space-s);
	}

	.nf-planner-progress__list {
		flex: 1 1 auto;
	}

	.nf-planner-progress__step:not(:first-child)::before {
		min-width: var(--nf-space-3xs);
	}

	/*
	 * Summary and button share the second row. A full-width button would be a
	 * bigger target, but it costs a whole third row, and "Next: Choose
	 * material" is already a comfortable size to hit.
	 */
	.nf-planner__actions {
		column-gap: var(--nf-space-s);
		flex: 1 1 100%;
		justify-content: space-between;
	}

	.nf-planner__next {
		flex: 0 1 auto;
	}

	/*
	 * The overview becomes one column and takes the whole screen: at this
	 * width a centred panel with a margin is mostly backdrop.
	 */
	.nf-planner-overview {
		padding: 0;
	}

	.nf-planner-overview__inner {
		grid-template-columns: minmax(0, 1fr);
	}

	/*
	 * Both strips in the dialog go three across, the same as the strip on the
	 * card. The surfaces would otherwise take the 10rem floor's two columns and
	 * stack eleven of them six rows deep, burying Seen in place and every panel
	 * under it behind a scroll of grey squares — on the one screen where
	 * scrolling costs the most.
	 *
	 * And the project photographs would otherwise hold the six columns their
	 * count sets, which at this width is 55px each: a row of stamps of rooms,
	 * where the whole point of them is seeing the stone laid.
	 */
	.nf-planner-overview__surfaces .nf-planner-thumbs,
	.nf-planner-overview__cases .nf-planner-thumbs {
		grid-template-columns: repeat(3, minmax(0, 1fr));
	}

	.nf-planner-overview__inner {
		border-radius: 0;
		max-height: 100svh;
		padding: var(--nf-space-m);
	}

	/*
	 * The unit boxes stack. Side by side on a 320px screen each box is about
	 * 130px wide, of which 52px is the suffix — not enough left to see a
	 * four-digit number.
	 */
	.nf-planner-units {
		grid-template-columns: minmax(0, 1fr);
	}

	/* Four buttons in a column, and the note's title above its prose. */
	.nf-planner-actions {
		grid-auto-flow: row;
	}

	.nf-planner-outline,
	.nf-planner-summary__top,
	.nf-planner-summary__panels,
	.nf-planner-summary__areas,
	.nf-planner-summary__ticks {
		grid-template-columns: minmax(0, 1fr);
	}

	.nf-planner-note {
		grid-template-columns: minmax(0, 1fr);
	}


	.nf-planner-overview__actions {
		justify-content: stretch;
	}

	.nf-planner-overview__actions > * {
		flex: 1 1 auto;
		justify-content: center;
	}
}
