/*
 * House3D application surface.
 *
 * One visual system (UI rework P1, 2026-10-13): a pale green-grey ground with
 * near-white sheets, one green accent, and IBM Plex Sans throughout — it covers
 * Cyrillic, including the Mongolian letters, and stays legible small. Nothing
 * is set below 13 px: the explanations are what a homeowner most needs to read.
 * Status is always carried by words as well as colour.
 *
 * Inputs are sized by what they hold rather than by their column: numbers are
 * narrow, choices take their content's width, and only free text runs long.
 * `data-size` overrides the default where a field needs it.
 */

:root {
	color-scheme: light;

	/* Ground is darker than the sheets, so a pane reads as sitting on the
	   surface rather than floating over it. */
	--bg: #eef1f0;
	--panel: #fbfcfb;
	--control: #ffffff;
	--input: #ffffff;
	--hover: #e4ebe7;
	--line: #cdd5d1;
	--fg: #17201c;
	--dim: #4b5751;
	--dim-band: #3d4842;
	--sel: #d6e8de;

	/* One pair for every list in the app — the project tree, the properties
	   grid, the result lists: a group sits on its own band, and every row is
	   separated from the next by a hairline. */
	--group-bg: #e6ebe8;
	--view-bg: #f3f5f4;
	--row-line: #dce2df;

	/* House3D's accent: green, the product's identity. */
	--accent: #1d6a45;
	--accent-strong: #14532d;
	--accent-wash: #dcebe3;

	--bad: #b42323;
	--bad-wash: #f7e3e3;
	--good: #1d6a45;
	--review: #9a5a0c;
	--review-wash: #f6ead9;
	/* The user's own prices and cost items: theirs, not the catalog's. */
	--user: #2b5797;
	--user-wash: #e6edf8;
	/* A required field still empty: amber, so it reads as "to do", not as an error. */
	--warn-line: #c4900c;
	--earth: #765b3d;
	--earth-wash: #f3eee7;

	--radius: 6px;
	--radius-s: 5px;
	--shadow-float: 0 1px 2px rgb(20 30 25 / 8%), 0 10px 32px rgb(20 30 25 / 16%);

	/* The type scale: 13 / 14 / 16 / 20. --text-s is the floor. */
	--text-s: .8125rem;
	--text-m: .875rem;
	--text-l: 1rem;
	--text-xl: 1.25rem;
	--target: 2rem;

	/* Input widths by what the field holds. */
	--size-xs: 7ch;
	--size-s: 11ch;
	--size-m: 18ch;
	--size-l: 28ch;

	font-family: "IBM Plex Sans", system-ui, -apple-system, "Segoe UI", sans-serif;
	font-variant-numeric: tabular-nums;
	color: var(--fg);
	background: var(--bg);
}

* { box-sizing: border-box; }
/* The browser's own `small` is about 11.7 px, below the floor. */
small { font-size: var(--text-s); }
html, body { height: 100%; margin: 0; }

body {
	display: grid;
	grid-template-rows: auto minmax(0, 1fr) auto auto;
	font-size: var(--text-m);
	line-height: 1.45;
}

:where(button, select, input, textarea):focus-visible,
:where(a, [tabindex]):focus-visible {
	outline: 1px solid var(--accent);
	outline-offset: 1px;
}
/* A field already has a border: focus turns that border green, one ring only. */
:where(select, input:not([type="checkbox"], [type="radio"]), textarea):focus-visible {
	outline: none;
	border-color: var(--accent);
	box-shadow: inset 0 0 0 1px var(--accent);
}
/* Required and still empty: an amber border until something is chosen. */
select:is([required], [aria-required="true"]):has(option:checked[value=""]):not(:focus),
:is(input, textarea):is([required], [aria-required="true"]):placeholder-shown:not(:focus) {
	border-color: var(--warn-line);
	box-shadow: inset 0 0 0 1px var(--warn-line);
}

.skip-link {
	position: absolute;
	left: -100vw;
	z-index: 1200;
	padding: .5rem .8rem;
	border-radius: 0 0 var(--radius) 0;
	color: #fff;
	background: var(--accent-strong);
}
.skip-link:focus { left: 0; }

/* ---------------------------------------------------------------- chrome */

.app-bar {
	display: flex;
	align-items: center;
	flex-wrap: wrap;
	gap: .5rem 1rem;
	padding: .5rem .75rem;
	border-bottom: 1px solid var(--line);
	background: var(--panel);
}

/* The app's mark only marks; the menus and commands follow it. */
.app-mark {
	display: grid;
	place-items: center;
	flex: none;
	width: 1.75rem;
	height: 1.75rem;
	color: var(--accent);
}
.app-mark svg { width: 1.15rem; height: 1.15rem; fill: none; stroke: currentColor; stroke-width: 1.4; stroke-linejoin: round; }

/* A menu title is text on the bar until pointed at or opened. */
.menubar { display: flex; }
.menu-title { min-height: 1.9rem; padding: 0 .65rem; border-color: transparent; background: none; font-weight: 600; }
.menu-title:hover:not(:disabled), .menu-title.on { border-color: var(--line); background: var(--hover); }

/* Undo, redo and delete are glyphs, named in their tooltips. */
.icon-button { display: grid; place-items: center; width: 1.9rem; min-height: 1.9rem; padding: 0; border-color: transparent; background: none; }
.icon-button:hover:not(:disabled) { border-color: var(--line); background: var(--hover); }
.icon-button:disabled { border-color: transparent; background: none; }
.icon-button svg { width: 1.1rem; height: 1.1rem; fill: none; stroke: currentColor; stroke-width: 1.7; stroke-linecap: round; stroke-linejoin: round; }
.bar-separator { flex: none; width: 1px; height: 1.4rem; background: var(--line); }

/* The project's name, on one line at the bar's far end; its site is the tooltip. */
.app-identity { min-width: 0; margin-left: auto; }
/* The account menu's button: the user's initials in a circle, or Sign in. */
.account-button { flex: none; display: inline-flex; align-items: center; gap: 6px; height: 30px; min-width: 30px; padding: 0 10px;
	border: 1px solid var(--line); border-radius: 15px; background: var(--control); color: var(--fg); font: inherit; font-size: var(--text-s); cursor: pointer; }
.account-button.initials { width: 30px; padding: 0; justify-content: center; border-radius: 50%; background: var(--accent); border-color: var(--accent); color: #fff; font-weight: 600; letter-spacing: .02em; }
.account-button:hover, .account-button.on { border-color: var(--accent); }
.account-button .glyph { width: 16px; height: 16px; }
.app-identity h1 { margin: 0; font-size: var(--text-l); font-weight: 600; line-height: 1.25; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* Setup stands apart; Design and Results are the pair that says where you are. */
.mode-bar { display: flex; align-items: center; gap: .5rem; }
.mode-switch button, .mode-setup { min-height: 2rem; padding: 0 1rem; font-weight: 600; }
.mode-setup[aria-pressed="true"] { border-color: var(--accent-strong); color: var(--accent-strong); }

.history-group { display: flex; gap: .1rem; }

/* A hairline between groups, rather than a gap: the bar reads as one strip of
   commands sorted into kinds, not as three floating clusters. */
.command-group { display: flex; flex-wrap: wrap; gap: .25rem; padding-left: .5rem; border-left: 1px solid var(--line); }
.command-group:first-child { padding-left: 0; border-left: 0; }
/* Buttons reached only from a menu or a key stay in the DOM, off the page,
   since `display: flex` above would otherwise outrank `[hidden]`. */
.command-group[hidden] { display: none; }
.workspace[hidden], .results-page[hidden] { display: none; }

button {
	min-height: var(--target);
	padding: .25rem .55rem;
	border: 1px solid var(--line);
	border-radius: var(--radius-s);
	color: var(--fg);
	background: var(--control);
	font: inherit;
	font-size: var(--text-m);
	white-space: nowrap;
	cursor: pointer;
}
button:hover:not(:disabled) { border-color: var(--accent); }
button:disabled { color: var(--dim); background: var(--bg); cursor: default; opacity: .7; }

button.is-primary { color: #fff; border-color: var(--accent-strong); background: var(--accent); }
button.is-primary:hover:not(:disabled) { background: var(--accent-strong); }
button.is-destructive { color: var(--bad); }
button.is-destructive:hover:not(:disabled) { color: #fff; border-color: var(--bad); background: var(--bad); }
button[aria-pressed="true"] { color: #fff; border-color: var(--accent-strong); background: var(--accent); }
button:disabled, button.is-destructive:disabled { color: var(--dim); border-color: var(--line); background: var(--bg); }

select, input[type="text"], input[type="search"], input[type="number"], input[type="date"], input[type="time"] {
	min-height: var(--target);
	padding: .25rem .4rem;
	border: 1px solid var(--line);
	border-radius: var(--radius-s);
	color: var(--fg);
	background: var(--input);
	font: inherit;
	font-size: var(--text-m);
}
select:hover, input:hover { border-color: #a3aea8; }
select { max-width: 100%; text-overflow: ellipsis; }

/* A number field is as wide as the numbers it takes, never as its column. */
input[type="number"] { inline-size: var(--size-s); }
:is(input, select)[data-size="xs"] { inline-size: var(--size-xs); }
:is(input, select)[data-size="s"] { inline-size: var(--size-s); }
:is(input, select)[data-size="m"] { inline-size: var(--size-m); }
:is(input, select)[data-size="l"] { inline-size: var(--size-l); }
:is(input, select)[data-size="fill"] { inline-size: 100%; }

input[type="checkbox"] {
	appearance: none;
	position: relative;
	flex: none;
	width: 14px;
	height: 14px;
	margin: 0;
	border: 1px solid var(--line);
	border-radius: 2px;
	background: var(--input);
	cursor: pointer;
}
input[type="checkbox"]:hover { border-color: var(--accent); }
input[type="checkbox"]:checked { border-color: var(--accent); background: var(--accent); }
input[type="checkbox"]:checked::after {
	content: '';
	position: absolute;
	left: 4px;
	top: 1px;
	width: 3px;
	height: 7px;
	border: solid #fff;
	border-width: 0 2px 2px 0;
	transform: rotate(45deg);
}

.inline-field { display: flex; align-items: center; gap: .35rem; font-size: var(--text-s); }
.inline-field > span { color: var(--dim); white-space: nowrap; }
.inline-field[hidden] { display: none; }

/* ------------------------------------------------------------- workspace */

.workspace {
	--left-w: 16rem;
	--right-w: 21rem;
	min-height: 0;
	display: grid;
	grid-template-columns: var(--left-w) 6px minmax(18rem, 1fr) 6px var(--right-w);
	/* One constrained row, so a long Project Tree scrolls inside its pane
	   instead of stretching the workspace past the window. */
	grid-template-rows: minmax(0, 1fr);
	padding: .35rem;
	gap: 0;
	background: var(--bg);
}

.project-pane, .properties-pane {
	min-width: 0;
	min-height: 0;
	display: grid;
	grid-template-rows: auto minmax(0, 1fr);
	border: 1px solid var(--line);
	border-radius: var(--radius);
	background: var(--panel);
}
/* The tree has no heading: it is the pane. */
.project-pane { grid-template-rows: minmax(0, 1fr); }

.properties-header { padding: .45rem .6rem; border-bottom: 1px solid var(--line); }

/* Visible at rest, not only on hover: a divider nobody can see is a divider
   nobody drags. */
.workspace-splitter { position: relative; background: none; cursor: col-resize; touch-action: none; }
.workspace-splitter::after {
	content: '';
	position: absolute;
	inset: 0 2px;
	background: transparent;
	transition: background .12s;
}
.workspace-splitter:hover::after,
.workspace-splitter:focus-visible::after,
.workspace-splitter.dragging::after { background: var(--accent); }
.workspace-splitter:focus-visible { outline: none; }
body.resizing { cursor: col-resize; user-select: none; }

/* ----------------------------------------------------------- project tree */

/* A visibility filter, not a selection list. Every row is one grid of three
   tracks — caret, name, eye — whose name track is the only one that shrinks,
   so the eye stays at the right edge however narrow the pane is dragged. */
.project-tree { padding: .2rem 0; overflow-x: hidden; overflow-y: auto; }
.project-tree [role="treeitem"] { display: grid; grid-template-columns: minmax(0, 1fr); min-width: 0; }
.project-tree .tree-group {
	display: grid;
	grid-template-columns: minmax(0, 1fr);
	min-width: 0;
	margin-left: .7rem;
	border-left: 1px solid var(--row-line);
}
.project-tree .tree-group.is-top { margin-left: 0; border-left: 0; }

.tree-row {
	display: grid;
	grid-template-columns: 1.35rem minmax(0, 1fr) auto;
	align-items: center;
	min-width: 0;
	min-height: 1.55rem;
	border-bottom: 1px solid var(--row-line);
	font-size: var(--text-m);
}
.tree-row:hover { background: var(--hover); }
.tree-row.is-root {
	grid-template-columns: minmax(0, 1fr);
	min-height: 1.9rem;
	padding: 0 .5rem;
	font-size: var(--text-l);
	font-weight: 600;
	letter-spacing: .01em;
	background: var(--group-bg);
}
.tree-row.depth-1 { font-weight: 600; }
.tree-row.is-hidden .tree-label { color: var(--dim); }

.tree-toggle,
.tree-toggle-spacer {
	width: 1.35rem;
	height: 100%;
	min-height: 1.55rem;
	border: 0;
	background: transparent;
	color: var(--dim);
	font-size: var(--text-s);
	line-height: 1;
	display: flex;
	align-items: center;
	justify-content: center;
}
.tree-toggle:hover { color: var(--fg); }

.tree-label {
	min-width: 0;
	padding: .12rem .3rem .12rem 0;
	overflow: hidden;
	white-space: nowrap;
	text-overflow: ellipsis;
	cursor: default;
}
.tree-row .tree-toggle ~ .tree-label { cursor: pointer; }
.tree-count { color: var(--dim); font-weight: 400; }

/* The eye: a filter on the viewport, never a project edit. */
.tree-visibility {
	width: 2.1rem;
	height: 100%;
	min-height: 1.55rem;
	display: flex;
	align-items: center;
	justify-content: center;
	border: 0;
	background: transparent;
	color: var(--dim);
}
/* On reads as a dark, open eye; off as a pale, struck-through one. The two
   must be told apart at a glance down a long column. */
.tree-visibility[aria-pressed] { color: var(--fg); border: 0; background: transparent; }
.tree-visibility svg { width: 1.25rem; height: 1.25rem; fill: none; stroke: currentColor; stroke-width: 1; }
.tree-visibility:hover { color: var(--accent); background: var(--hover); }
.tree-visibility.is-hidden { color: #a4acb6; }
.tree-visibility.is-hidden svg { stroke-width: 1.3; }
/* On, but hidden anyway because its level is off. */
.tree-visibility.is-inherited { color: #a4acb6; }

/* -------------------------------------------------------------- viewport */

.viewport-pane {
	min-width: 0;
	min-height: 0;
	display: grid;
	/* The view takes every pixel. Its toolbars, tool options and notices float
	   over it rather than taking rows of their own: a notice changing length
	   mid-edit must never resize the plan under the user's pointer. */
	grid-template-rows: minmax(0, 1fr);
	overflow: hidden;
	gap: .35rem;
	/* The view meets the panels' edges: the workspace already spaces them. */
	padding: 0;
}

/* Mutually exclusive choices read as one control with a current setting, so the
   segments share a border and only the active one is filled. */
.segmented { display: inline-flex; }
.segmented button {
	min-height: 1.85rem;
	margin-left: -1px;
	border-radius: 0;
	color: var(--dim);
}
.segmented button:first-child { margin-left: 0; border-radius: var(--radius-s) 0 0 var(--radius-s); }
.segmented button:last-child { border-radius: 0 var(--radius-s) var(--radius-s) 0; }
.segmented button:hover:not(:disabled) { z-index: 1; color: var(--fg); }
.segmented button[aria-pressed="true"] { z-index: 1; color: #fff; background: var(--accent); border-color: var(--accent-strong); }

.tool-options {
	display: grid;
	justify-self: start;
	max-width: 100%;
	gap: .35rem;
	padding: .4rem .55rem;
	border: 1px solid var(--accent);
	border-radius: var(--radius);
	background: var(--accent-wash);
}
.tool-options[hidden] { display: none; }
.tool-options-title { margin: 0; font-size: var(--text-s); font-weight: 600; }
.tool-options-head { display: flex; align-items: center; gap: .75rem; }
.tool-options-head button { min-height: 1.85rem; margin-left: auto; }
/* The fields are equal columns, each name above its choice, wrapping as a
   row when the view is narrow, so a longer (Mongolian) choice cannot push the
   next field or Finish off the row.
   A select is only as wide as its column and cuts its text with an ellipsis;
   its open list is drawn as wide as the longest choice, and the full current
   choice is in its tooltip. */
.tool-options-fields { display: flex; flex-wrap: wrap; gap: .35rem .6rem; }
.tool-options-fields .inline-field { display: grid; flex: 0 0 12rem; gap: .1rem; min-width: 0; }
.tool-options-fields .inline-field[hidden] { display: none; }
.tool-options-fields select { width: 100%; min-width: 0; text-overflow: ellipsis; }

.model-view-stack { grid-row: 1; position: relative; min-height: 0; overflow: hidden; }
.view-overlays {
	position: absolute;
	/* Below the view's toolbars. */
	top: 2.4rem;
	left: .45rem;
	right: .45rem;
	z-index: 2;
	display: grid;
	gap: .35rem;
	/* Only the panels themselves take the pointer; the plan between them stays live. */
	pointer-events: none;
}
.view-overlays > * { pointer-events: auto; }
.model-view {
	width: 100%;
	height: 100%;
	/* Small enough that opening the checks drawer compresses the view rather
	   than pushing the canvas out of its stack and over the drawer below. */
	min-height: 6rem;
	border: 1px solid var(--line);
	border-radius: var(--radius);
	background: var(--view-bg);
}
.model-view[hidden] { display: none; }


/* The three toolbars over the view are one size (owner 2026-10-15). */
:root { --view-tool-h: 1.5rem; --view-tool-text: .75rem; }

/* Design tools float over the view, grouped: Select, then walls, then doors,
   windows and the stair opening. Delete is a key and a right-click item. */
.tool-palette {
	position: absolute;
	left: 50%;
	bottom: .55rem;
	z-index: 2;
	transform: translateX(-50%);
	display: flex;
	align-items: center;
	gap: .1rem;
	max-width: calc(100% - 1.1rem);
	padding: .15rem;
	overflow-x: auto;
	border: 1px solid var(--line);
	border-radius: var(--radius);
	background: var(--panel);
	box-shadow: 0 1px 2px rgb(0 0 0 / 10%), 0 6px 18px rgb(0 0 0 / 10%);
}
.tool-palette button { min-height: var(--view-tool-h); padding: 0 .5rem; border-color: transparent; background: none; font-size: var(--view-tool-text); font-weight: 600; white-space: nowrap; }
.tool-palette button:hover:not(:disabled) { background: var(--hover); border-color: var(--line); }
.tool-palette button[aria-pressed="true"], .tool-palette button[aria-pressed="true"]:hover:not(:disabled) { color: #fff; background: var(--accent); border-color: var(--accent-strong); }
/* The view's own toolbars float over its top corners, of the palette's kind
   but smaller: Model and the story plans on the left, how the 3D model is
   drawn on the right. One button is pressed for the setting shown. */
.view-toolbar {
	position: absolute;
	top: .45rem;
	z-index: 3;
	display: flex;
	align-items: center;
	gap: .1rem;
	max-width: calc(50% - .6rem);
	padding: .15rem;
	overflow-x: auto;
	border: 1px solid var(--line);
	border-radius: var(--radius);
	background: var(--panel);
	box-shadow: 0 1px 2px rgb(0 0 0 / 10%), 0 4px 12px rgb(0 0 0 / 8%);
}
.view-switch { left: .45rem; }
.scene-modes { right: .45rem; }
.view-toolbar button { flex: none; min-height: var(--view-tool-h); padding: 0 .5rem; border-color: transparent; background: none; font-size: var(--view-tool-text); font-weight: 600; white-space: nowrap; }
.view-toolbar button:hover:not(:disabled) { background: var(--hover); border-color: var(--line); }
.view-toolbar button[aria-pressed="true"], .view-toolbar button[aria-pressed="true"]:hover:not(:disabled) { color: #fff; background: var(--accent); border-color: var(--accent-strong); }
.tool-separator { flex: none; width: 1px; height: 1rem; margin: 0 .2rem; background: var(--line); }
#wall-scene { overflow: hidden; }
#wall-scene canvas { display: block; width: 100%; height: 100%; }


/* A newer catalog, offered once on open. It names what would change and stays
   out of the way: the design is usable while it shows, and closing it keeps the
   catalog the project was designed with. */
.catalog-banner {
	display: grid;
	gap: .3rem;
	max-height: 12rem;
	overflow: auto;
	padding: .45rem .6rem;
	border: 1px solid var(--accent);
	border-left-width: 3px;
	border-radius: var(--radius-s);
	background: var(--accent-wash);
	font-size: var(--text-s);
}
.catalog-banner[hidden] { display: none; }
.catalog-banner-head { display: flex; align-items: start; gap: .5rem; }
.catalog-banner-title { flex: 1; margin: 0; font-weight: 600; color: var(--accent-strong); }
.catalog-banner-close { min-height: 0; padding: 0 .4rem; line-height: 1.2; border: 1px solid transparent; background: none; color: var(--fg); cursor: pointer; }
.catalog-banner-close:hover { border-color: var(--line); background: var(--hover); }
.catalog-banner-items { margin: 0; padding-left: 1.1rem; }
.catalog-banner-items[hidden] { display: none; }
.catalog-banner-items li { overflow-wrap: anywhere; }
.catalog-banner-estimate { margin: 0; }
.catalog-banner-estimate[hidden] { display: none; }
.catalog-banner-actions { display: flex; gap: .35rem; }

/* ----------------------------------------------------- bill of materials */

.bom-table-host { overflow-x: auto; }
.bom-table { width: 100%; border-collapse: collapse; font-size: var(--text-s); }
.bom-table th, .bom-table td {
	padding: .22rem .5rem;
	border-bottom: 1px solid var(--row-line);
	text-align: left;
	vertical-align: top;
}
.bom-table thead th {
	position: sticky;
	top: 0;
	background: var(--group-bg);
	color: var(--dim);
	font-size: var(--text-s);
	font-weight: 600;
	white-space: nowrap;
}
.bom-table .numeric { text-align: right; white-space: nowrap; }
.bom-table th[scope="row"] a { color: inherit; text-decoration: underline dotted; text-underline-offset: 2px; }
.bom-table th[scope="row"] a:hover { color: var(--accent); text-decoration-style: solid; }
.bom-table tbody th { font-weight: 500; }
/* A group heading carries that group's total, so the eye can stop there: it
   stands apart from the lines under it, and the whole row folds them. */
.bom-table .bom-group { cursor: pointer; }
.bom-table .bom-group th, .bom-table .bom-group td {
	padding-top: .55rem;
	padding-bottom: .55rem;
	background: var(--group-bg);
	color: var(--fg);
	font-size: var(--text-l);
	font-weight: 600;
	border-top: 2px solid var(--accent);
	border-bottom: 1px solid var(--line);
}
.bom-table .bom-group:hover th, .bom-table .bom-group:hover td { background: color-mix(in srgb, var(--group-bg) 80%, var(--accent) 20%); }
/* A group folds to its heading and total; the chevron says which way it is. */
.bom-group-toggle {
	display: inline-flex;
	align-items: baseline;
	gap: .5rem;
	min-height: 0;
	padding: 0;
	border: 0;
	color: inherit;
	background: transparent;
	font: inherit;
	cursor: pointer;
}
.bom-group-toggle::before { content: "\25BE"; display: inline-block; width: .8rem; transition: transform .12s; }
.bom-group-toggle[aria-expanded="false"]::before { transform: rotate(-90deg); }
.bom-group-count { color: var(--dim); font-size: var(--text-s); font-weight: 400; }
.bom-group-body[data-collapsed] > tr:not(.bom-group) { display: none; }
.bom-table .bom-measures { color: var(--dim); }
.bom-table .bom-note { margin: .1rem 0 0; color: var(--dim); font-size: var(--text-s); }
.bom-table .state-unavailable { color: var(--dim); }
.bom-table .state-attention { color: var(--review); }
/* VAT is stated, never inferred: an unknown one must look unknown. */
.bom-vat { white-space: nowrap; font-size: var(--text-s); }
.bom-vat.vat-included { color: var(--good); }
.bom-vat.vat-excluded { color: var(--fg); }
.bom-vat.vat-unknown { color: var(--review); }

/* A price of the user's own, and their cost items, read as theirs. */
.bom-table tr.user-priced > * { background: var(--user-wash); }
.user-price-mark { display: inline-block; padding: 0 .3rem; border-radius: var(--radius-s); color: #fff; background: var(--user); font-size: .7rem; font-weight: 600; cursor: help; }
.live-price-mark { display: inline-block; padding: 0 .3rem; border: 1px solid var(--line); border-radius: var(--radius-s); font-size: .7rem; font-weight: 600; cursor: help; }
.price-edit { min-height: 0; padding: .05rem .3rem; border: 1px dashed transparent; color: inherit; background: transparent; font: inherit; text-align: right; cursor: pointer; }
.price-edit:hover, .price-edit:focus-visible { border-color: var(--user); color: var(--user); }
.price-edit.price-add { border-color: var(--line); color: var(--user); font-weight: 600; }
.price-editor-row > td, .cost-editor-row > td { background: var(--user-wash); }
.price-editor { display: flex; flex-wrap: wrap; align-items: end; gap: .4rem .6rem; padding: .3rem 0; }
.price-editor label { display: grid; gap: .15rem; color: var(--dim); font-size: var(--text-s); }
.price-editor input, .price-editor select { min-height: 1.75rem; color: var(--fg); }
.price-editor input[type="number"] { width: 8rem; text-align: right; }
.price-editor .unit-input { width: 5rem; }
.price-editor button { min-height: 1.75rem; }
.price-editor .property-edit-feedback { flex-basis: 100%; margin: 0; color: var(--bad); }
.price-editor .property-edit-feedback:empty { display: none; }
.link-button, .cost-item-tools button { min-height: 0; padding: 0 .2rem; border: 0; color: var(--accent-strong); background: transparent; text-decoration: underline; }
.cost-item-tools { white-space: nowrap; text-align: right; }
.cost-item-tools .danger-link { color: var(--bad); }
.cost-add { margin: .45rem .5rem .5rem; }
.cost-items-empty { margin: .45rem .5rem 0; color: var(--dim); font-size: var(--text-s); }

/* ------------------------------------------------- drawers and status bar */

.results-drawer {
	max-height: 40vh;
	margin: 0 .35rem .35rem;
	padding: .6rem .7rem .7rem;
	border: 1px solid var(--line);
	border-radius: var(--radius);
	background: var(--panel);
	overflow: auto;
}
.results-drawer[hidden] { display: none; }
.results-drawer h2 {
	margin: 0 0 .5rem;
	color: var(--dim);
	font-size: var(--text-s);
	font-weight: 600;
}
.results-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(15rem, 1fr)); gap: .5rem; }
.results-grid[hidden] { display: none; }
/* The cost first, then the quantities under it, each the page's full width:
   side by side, both were squeezed. */
.results-grid-bom { grid-template-columns: minmax(0, 1fr); }
/* Full width, the summary's few rows would put each value a page from its name. */
.cost-card .result-list { max-width: 30rem; }
.results-head { display: flex; flex-wrap: wrap; align-items: center; gap: .4rem 1rem; margin-bottom: .5rem; }
.results-head h2 { margin: 0; }
.results-tabs { display: flex; gap: .25rem; }
.results-tabs [role="tab"] { padding: .2rem .7rem; border-radius: var(--radius-s); }
.results-tabs [role="tab"][aria-selected="true"] { color: #fff; border-color: var(--accent-strong); background: var(--accent); }

.result-card { min-width: 0; border: 1px solid var(--line); border-radius: var(--radius-s); background: var(--control); }
.result-card h3 {
	margin: 0;
	padding: .3rem .5rem;
	border-bottom: 1px solid var(--row-line);
	background: var(--group-bg);
	color: var(--dim);
	font-size: var(--text-s);
	font-weight: 600;
}

.result-list { display: grid; grid-template-columns: minmax(4.5rem, 1fr) minmax(0, 1.3fr); gap: 0 .6rem; margin: 0; font-size: var(--text-s); }
.result-list dt { padding: .18rem .5rem; border-bottom: 1px solid var(--row-line); color: var(--dim); overflow-wrap: anywhere; }
.result-list dd { padding: .18rem .5rem; border-bottom: 1px solid var(--row-line); margin: 0; text-align: right; font-weight: 600; overflow-wrap: anywhere; }

.result-state { display: inline-block; padding: 0 .35rem; border-radius: 2px; font-size: var(--text-s); font-weight: 600; }
.result-state.state-available { color: var(--good); background: var(--accent-wash); }
.result-state.state-unavailable { color: var(--dim-band); background: var(--group-bg); }
.result-state.state-attention { color: var(--review); background: var(--review-wash); }

.results-disclaimer { margin: .6rem 0 0; color: var(--dim); font-size: var(--text-s); }

/* ------------------------------------------------------------- results page */

/* Results mode takes the workspace's place: a list of what the design
   produces, and the one chosen. */
.results-page {
	min-height: 0;
	display: grid;
	grid-template-columns: 15rem minmax(0, 1fr);
	background: var(--bg);
}
.results-nav { padding: .9rem .6rem; border-right: 1px solid var(--line); background: var(--panel); overflow-y: auto; }
.results-nav h2 { margin: 0 .5rem .6rem; font-size: var(--text-l); font-weight: 600; }
.results-nav ol { display: grid; gap: .15rem; margin: 0; padding: 0; list-style: none; }
.results-nav-link { width: 100%; min-height: 2.1rem; padding: 0 .6rem; border-color: transparent; background: none; text-align: left; font-weight: 500; }
.results-nav-link:hover:not(:disabled) { background: var(--hover); }
.results-nav-link[aria-current="page"] { color: var(--accent-strong); border-color: var(--line); background: var(--panel); box-shadow: inset 3px 0 0 var(--accent); font-weight: 600; }
.results-pane { min-width: 0; padding: 1rem 1.2rem 1.5rem; overflow: auto; }
/* A section fills the width beside the list. */
.results-section { display: grid; gap: .8rem; align-content: start; }
.results-section[hidden] { display: none; }
.results-section[aria-busy="true"] { opacity: .6; }
@font-face { font-family: 'osifont-h3d'; font-display: swap; src: url(../vendor/osifont/osifont-2021-h3d.woff) format('woff'); }
.drawing-viewer { display: grid; grid-template-columns: 8.5rem minmax(0, 1fr); gap: .6rem; height: calc(100dvh - 9rem); min-height: 20rem; }
.drawing-thumbs { display: flex; flex-direction: column; gap: .5rem; overflow-y: auto; padding: .1rem .3rem .1rem .1rem; }
.drawing-thumb { display: grid; grid-template-rows: auto auto; height: auto; min-height: 0; flex: none; gap: .2rem; justify-items: center; padding: .3rem; border: 2px solid transparent; border-radius: var(--radius-s); background: none; }
.drawing-thumb:hover { background: var(--hover); }
.drawing-thumb svg { display: block; width: 100%; height: auto; aspect-ratio: 420 / 297; color: #000; box-shadow: 0 1px 3px rgb(0 0 0 / 18%); }
.drawing-thumb span { font-size: var(--text-s); color: var(--dim); }
.drawing-thumb .drawing-paper, .drawing-sheet .drawing-paper { fill: #fff; }
.drawing-stage { position: relative; min-width: 0; min-height: 0; border: 1px solid var(--line); border-radius: var(--radius); background: var(--view-bg); }
.drawing-scroll { position: absolute; inset: 0; overflow: auto; padding: 24px; cursor: zoom-in; user-select: none; }
.drawing-scroll.panning { cursor: grabbing; }
.drawing-scroll.zooming { cursor: zoom-in; }
.drawing-tools { right: .45rem; }
.drawing-tools button { display: inline-flex; align-items: center; gap: .25rem; }
.drawing-sheet { margin: 0 auto 1.2rem; width: max-content; display: grid; gap: .3rem; }
.drawing-sheet svg { display: block; height: auto; color: #000; box-shadow: 0 2px 8px rgb(0 0 0 / 16%); }
.drawing-sheet figcaption { font-size: var(--text-s); color: var(--dim); }
.results-section-title { margin: 0; font-size: var(--text-l); font-weight: 600; }
.results-section > .results-disclaimer { margin: 0; }
.results-section h3 { margin: .4rem 0 0; font-size: var(--text-m); font-weight: 600; }
.results-section .buttons { display: flex; gap: .5rem; }
.table-scroll { max-width: 100%; overflow-x: auto; }
.pricing-panel { display: grid; border: 1px solid var(--line); border-radius: var(--radius); background: var(--panel); }
.pricing-panel .pricing-body { overflow: visible; }
@media (max-width: 48rem) {
	.results-page { grid-template-columns: 1fr; grid-template-rows: auto minmax(0, 1fr); }
	.results-nav { border-right: 0; border-bottom: 1px solid var(--line); }
	.results-nav ol { grid-auto-flow: column; overflow-x: auto; }
	.results-nav-link { white-space: nowrap; }
}

/* ------------------------------------------------------------- checks panel */

.checks-drawer:focus { outline: none; }
#checks-toggle[data-state="bad"] { color: var(--bad); }
#checks-toggle[data-state="review"] { color: var(--review); }
.check-list { display: grid; gap: .8rem; }
.check-list > .foundation-basis { margin-top: .2rem; }
.check-group { display: grid; gap: .45rem; }
.check-group > h3 { margin: 0; font-size: var(--text-m); font-weight: 600; }
.check-group[data-group="MUST_FIX"] > h3 { color: var(--bad); }
.check-group[data-group="TO_REVIEW"] > h3 { color: var(--review); }
.check-group-lead { margin: -.2rem 0 .1rem; color: var(--dim); font-size: var(--text-s); }
.check-empty { margin: 0; color: var(--good); font-size: var(--text-m); }
.check {
	min-width: 0;
	padding: .45rem .6rem .5rem;
	border: 1px solid var(--line);
	border-left: 3px solid var(--line);
	border-radius: var(--radius-s);
	background: var(--control);
	display: grid;
	gap: .25rem;
}
.check[data-group="MUST_FIX"] { border-left-color: var(--bad); }
.check[data-group="TO_REVIEW"] { border-left-color: var(--review); }
.check-head { display: flex; flex-wrap: wrap; align-items: baseline; gap: .2rem .6rem; }
.check-head h4 { margin: 0; font-size: var(--text-m); font-weight: 600; overflow-wrap: anywhere; }
.check-kind { color: var(--dim); font-size: var(--text-s); }
.check-actions { display: flex; gap: .6rem; margin-left: auto; align-items: baseline; }
.check-show { padding: 0 .55rem; font-size: var(--text-s); }
.check-message, .check-action { margin: 0; overflow-wrap: anywhere; }
.check-action { color: var(--dim); }
.check-source { margin: 0; color: var(--dim); font-size: var(--text-s); overflow-wrap: anywhere; }
.check-details { color: var(--dim); font-size: var(--text-s); }
.check-details summary { cursor: pointer; width: max-content; }
.check-details p { margin: .2rem 0 0; overflow-wrap: anywhere; }
.check-not-checked { color: var(--dim); font-size: var(--text-s); }
.check-not-checked summary { cursor: pointer; font-weight: 600; }
.check-not-checked ul { margin: .3rem 0 .4rem; padding-left: 1.1rem; display: grid; gap: .15rem; }
.check-not-checked code { color: var(--fg); }
.check-not-checked .check-group-lead { margin: .35rem 0 0; }


.cost-card { border-color: var(--accent); }
.cost-card h3 { color: var(--accent-strong); background: var(--accent-wash); }
.cost-total { margin: .45rem .5rem .35rem; font-size: var(--text-xl); font-weight: 600; overflow-wrap: anywhere; }
.cost-total[data-status="incomplete"]::after { content: ' · incomplete'; color: var(--review); font-size: var(--text-s); font-weight: 600; }
.cost-total[data-status="unavailable"] { color: var(--dim); font-size: var(--text-m); }
.cost-unpriced { margin: .35rem .5rem 0; }
.cost-unpriced > details > summary { font-size: var(--text-s); font-weight: 600; cursor: pointer; }
.cost-unpriced ul { margin: .3rem 0 0; padding-left: 1rem; font-size: var(--text-s); }
.cost-unpriced li { overflow-wrap: anywhere; }
.cost-scope { margin: .45rem .5rem .5rem; color: var(--dim); font-size: var(--text-s); }

.status-bar {
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: 1rem;
	padding: .35rem .75rem;
	border-top: 1px solid var(--line);
	background: var(--panel);
}
.status-message { margin: 0; font-size: var(--text-s); overflow-wrap: anywhere; }
.status-message[data-state="unavailable"] { color: var(--bad); font-weight: 600; }
.status-message[data-state="ready"]::before { content: '● '; color: var(--good); }
.status-message[data-state="busy"]::before { content: '▶ '; color: var(--dim); }
.status-message[data-state="unavailable"]::before { content: '▲ '; }
.status-bar button { min-height: 1.75rem; }
.status-bar-actions { display: flex; gap: .5rem; }

/* ------------------------------------------------------------ properties */

.properties-header { display: flex; align-items: flex-start; justify-content: space-between; gap: .6rem; }
.properties-heading { flex: 1; min-width: 0; }
/* The name box is a Properties text box, not bold like the title around it. */
.properties-header h2 input { min-height: 1.75rem; font-weight: normal; }
/* A name the user may change: click it, or the pencil, to edit it in place. */
.properties-name { cursor: text; }
.properties-name:hover { text-decoration: underline dotted var(--dim); text-underline-offset: 3px; }
.properties-rename { display: inline-grid; place-items: center; width: 1.4rem; min-height: 1.4rem; margin-left: .25rem; padding: 0; border-color: transparent; background: none; color: var(--dim); vertical-align: -.2rem; }
.properties-rename:hover:not(:disabled) { color: var(--fg); border-color: var(--line); background: var(--hover); }
.properties-rename svg { width: .9rem; height: .9rem; fill: none; stroke: currentColor; stroke-width: 1.8; stroke-linecap: round; stroke-linejoin: round; }
.properties-header h2 { margin: .05rem 0 0; font-size: var(--text-l); font-weight: 600; overflow-wrap: anywhere; }
.eyebrow { color: var(--dim); font-size: var(--text-s); font-weight: 600; }
.property-kind { flex: 0 0 auto; padding: 0 .35rem; border-radius: 2px; color: var(--dim-band); background: var(--group-bg); font-size: var(--text-s); font-weight: 600; }

.properties-content { display: grid; align-content: start; gap: .4rem; padding: .5rem .6rem .8rem; overflow: auto; }
.properties-empty { margin: 0; color: var(--dim); }
.properties-error { margin: 0; padding: .5rem; border: 1px solid var(--bad); border-radius: var(--radius-s); color: var(--bad); background: var(--bad-wash); }

/* Groups are cards like House Setup's: a quiet title, the values carry the weight. */
.property-group { border: 1px solid var(--line); border-radius: var(--radius-s); background: var(--control); }
.property-group > summary {
	padding: .35rem .55rem .15rem;
	color: var(--dim);
	font-size: var(--text-s);
	font-weight: 500;
	cursor: pointer;
}
.property-group > summary:hover { color: var(--fg); }
.property-group dl { display: grid; margin: 0; padding: 0 0 .2rem; }

.property-row { display: grid; grid-template-columns: minmax(0, 1fr) auto; align-items: baseline; gap: .15rem .6rem; padding: .3rem .55rem; }
.property-row + .property-row { border-top: 1px solid var(--row-line); }
.property-row dt { display: flex; align-items: center; flex-wrap: wrap; gap: 0 .1rem; min-width: 0; color: var(--dim); font-size: var(--text-s); }
.property-row dd { display: grid; justify-items: end; gap: .2rem; min-width: 0; margin: 0; text-align: right; }
/* A control or a sentence goes under its name, at the row's full width. */
.property-row.is-stacked { grid-template-columns: minmax(0, 1fr); }
.property-row.is-stacked dd { justify-items: stretch; text-align: left; }
.property-row dt .property-source { margin-left: .4rem; }
.properties-content .help-tip-bubble { max-width: 15rem; }
.property-row dt.is-unnamed:empty { display: none; }
.property-row dt.is-unnamed .help-tip { margin-left: 0; }
.property-row:not(.is-stacked) .property-edit input { width: 6.5rem; text-align: right; }

.property-value { max-width: 100%; font-size: var(--text-m); font-weight: 600; overflow-wrap: anywhere; }
.property-source { padding: 0 .3rem; border-radius: 2px; color: var(--dim-band); background: var(--group-bg); font-size: var(--text-s); }
.property-source.source-project { color: var(--accent-strong); background: var(--accent-wash); }
.property-source.source-instance { color: var(--review); background: var(--review-wash); }

.property-setup-link { min-height: 0; margin-left: auto; padding: 0 .2rem; border: 0; color: var(--accent-strong); background: transparent; font-size: var(--text-s); text-decoration: underline; }
.property-setup-link:hover:not(:disabled) { background: var(--accent-wash); }

.property-edit { display: grid; grid-template-columns: minmax(0, 1fr) auto auto; align-items: center; gap: .3rem; width: 100%; }
.property-edit input, .property-edit select { min-width: 0; width: 100%; min-height: 1.75rem; }
.property-edit button { min-height: 1.75rem; padding: .15rem .5rem; font-size: var(--text-s); }
.property-edit button[hidden] { display: none; }
.property-unit:empty { display: none; }
.property-unit { color: var(--dim); font-size: var(--text-s); }
.property-restore { min-height: 0; margin-left: auto; padding: 0 .2rem; border: 0; color: var(--accent-strong); background: transparent; font-size: var(--text-s); text-decoration: underline; }
.property-edit-feedback { grid-column: 1 / -1; max-width: 100%; color: var(--bad); font-size: var(--text-s); overflow-wrap: anywhere; }

/* A field whose value is a shape is chosen as a shape. The grid is wide enough
   that a division reads at a glance, so it spans both columns of the row. */
.property-row:has(.property-thumbnails) { grid-template-columns: 1fr; }
.property-row:has(.property-thumbnails) dd { justify-items: stretch; text-align: left; }
.property-thumbnails { display: grid; gap: .3rem; width: 100%; }
/* Three fixed tracks rather than auto-fill: a track that may not shrink below a
   minimum lets a long template name push the whole grid wider than the pane. */
.thumbnail-options { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: .3rem; }
.thumbnail-option { display: grid; align-content: start; gap: .12rem; min-width: 0; padding: .25rem; border: 1px solid var(--line); border-radius: var(--radius-s); background: var(--panel); text-align: center; cursor: pointer; overflow: hidden; }
.thumbnail-option:hover:not(:disabled) { border-color: var(--accent-strong); background: var(--hover); }
.thumbnail-option:disabled { opacity: .5; cursor: default; }
.thumbnail-option.is-chosen { border-color: var(--accent-strong); background: var(--accent-wash); box-shadow: inset 0 0 0 1px var(--accent-strong); }
.thumbnail-figure { display: grid; place-items: center; height: 3.1rem; min-width: 0; border-radius: 2px; background: var(--group-bg); overflow: hidden; }
.thumbnail-figure img { max-width: 100%; max-height: 100%; }
.thumbnail-figure.is-automatic { color: var(--dim); font-size: var(--text-s); font-weight: 600; }

/* ------------------------------------------------- transaction outcomes */

.transaction-outcome { display: grid; gap: .4rem; padding: .5rem; border: 1px solid var(--line); border-radius: var(--radius-s); font-size: var(--text-s); }
.transaction-outcome[hidden] { display: none; }
/* The outcome of the last change sits under the properties, pinned to the
   pane's foot so a refusal stays in view however far the groups scroll. */
.properties-pane { grid-template-rows: auto minmax(0, 1fr) auto; }
.properties-pane > .transaction-outcome { margin: 0 .6rem .6rem; }
.transaction-outcome.status-permitted { color: var(--good); border-color: var(--good); background: var(--accent-wash); }
.transaction-outcome.status-denied { color: var(--bad); border-color: var(--bad); background: var(--bad-wash); }
.transaction-outcome.status-review-required { color: var(--review); border-color: var(--review); background: var(--review-wash); }
.transaction-outcome strong { font-size: var(--text-m); }
.transaction-outcome ul { margin: 0; padding-left: 1rem; }
.transaction-actions { display: flex; justify-content: flex-end; gap: .35rem; }
.transaction-actions .primary { color: #fff; border-color: var(--accent-strong); background: var(--accent); }

/* ----------------------------------------------------------- dialogs */

.overlay-dialog { position: fixed; inset: 0; z-index: 1000; display: grid; place-items: center; padding: 1rem; background: rgb(27 32 39 / 45%); }
/* Laid out as the app's other dialogs: a head band, a body, a foot band with
   the buttons (prompt.js frames each one so). */
.overlay-dialog .dialog { width: min(28rem, 100%); padding: 0; overflow: hidden; border: 1px solid var(--line); border-radius: var(--radius); background: var(--panel); box-shadow: var(--shadow-float); }
.overlay-dialog .setup-head h3 { margin: 0; font-size: var(--text-l); font-weight: 600; }
.overlay-dialog .setup-body > :first-child { margin-top: 0; }
.overlay-dialog .setup-body > :last-child { margin-bottom: 0; }
.overlay-dialog .dialog label { display: flex; align-items: center; gap: .5rem; }
.overlay-dialog .dialog input { min-width: 0; margin-top: 0; }
.overlay-dialog .dialog input[type="text"] { flex: 1 1 auto; inline-size: auto; }
.overlay-dialog .buttons { display: flex; justify-content: flex-end; gap: .5rem; }
.overlay-dialog .danger { color: #fff; border-color: var(--bad); background: var(--bad); }
.overlay-dialog .primary { color: #fff; border-color: var(--accent-strong); background: var(--accent); }
.overlay-dialog .review-reasons { margin: .5rem 0 0; padding-left: 1.1rem; color: var(--fg); }
.overlay-dialog .review-reasons li + li { margin-top: .25rem; }
/* A note under a dialog's content: a warning reads in the error colour. */
.overlay-dialog .dialog-note { margin: .6rem 0 0; color: var(--dim); font-size: var(--text-s); }
.overlay-dialog .dialog-note.is-warning { color: var(--bad); }
/* Open project: the saved projects as one list, rows like the app's other lists. */
.project-choices { max-height: min(20rem, 55vh); margin-top: .6rem; overflow-y: auto; border: 1px solid var(--line); border-radius: var(--radius-s); background: var(--input); }
.project-choices:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }
.overlay-dialog .dialog.is-wide { width: min(40rem, 100%); }
.project-choice { display: grid; grid-template-columns: minmax(0, 1fr) auto 8.5rem; align-items: baseline; gap: 1rem; padding: .45rem .7rem; border-bottom: 1px solid var(--row-line); cursor: pointer; }
.project-choice:last-child { border-bottom: 0; }
.project-choice:hover { background: var(--hover); }
.project-choice[aria-selected="true"] { background: var(--sel); box-shadow: inset 3px 0 0 var(--accent); }
.project-choice-name { overflow: hidden; font-weight: 600; text-overflow: ellipsis; white-space: nowrap; }
.project-choice-saved { color: var(--dim); font-size: var(--text-s); font-variant-numeric: tabular-nums; white-space: nowrap; }
.project-choice-ago { color: var(--dim); font-size: var(--text-s); text-align: right; white-space: nowrap; }

dialog { border: 0; padding: 0; color: var(--fg); }
dialog::backdrop { background: rgb(27 32 39 / 45%); }

/* --------------------------------------------------------- House Setup */

.house-setup-dialog {
	/*
	 * Three quarters of the viewport. The materials table wants three columns of menus side
	 * by side, and a dialog fixed in rem was too narrow for them on a wide
	 * screen and too wide on a small one. The lower bound keeps the three
	 * columns from collapsing on a laptop.
	 */
	width: clamp(min(44rem, calc(100vw - 2rem)), 75vw, calc(100vw - 2rem));
	/*
	 * A fixed height, not a content-driven one: switching to the Windows and
	 * doors tab holds far less content than the building profile, and letting
	 * the dialog shrink to fit made the whole surface jump under the pointer.
	 */
	height: 90vh;
	max-height: 90vh;
	border: 1px solid var(--line);
	border-radius: var(--radius);
	background: var(--panel);
	box-shadow: var(--shadow-float);
	overflow: hidden;
}
.house-setup-dialog form { display: grid; grid-template-rows: auto auto minmax(0, 1fr) auto; height: 100%; }

.setup-head { padding: .7rem .9rem .55rem; border-bottom: 1px solid var(--line); }
.setup-head h2 { margin: 0; font-size: var(--text-l); font-weight: 600; }
.setup-head p { margin: .15rem 0 0; color: var(--dim); font-size: var(--text-s); }

.setup-body { min-width: 0; padding: .8rem .9rem; overflow-y: auto; overflow-x: hidden; }
/* An approved product set: a summary line that opens the Vendor's products with
   a checkbox on each. Collapsed by default, because approving everything is the
   ordinary case and a list of twelve blocks is noise until someone wants it. */
.approved-set { min-width: 0; font-size: var(--text-s); }
/* Shaped like the menus beside it, so it reads as a control. */
.approved-set > summary {
	display: flex;
	align-items: center;
	gap: .35rem;
	min-height: var(--target);
	cursor: pointer;
	padding: .25rem .4rem;
	border: 1px solid var(--line);
	border-radius: var(--radius-s);
	background: var(--input);
	font-size: var(--text-m);
	font-weight: 600;
}
.approved-set > summary:hover { background: var(--hover); }
/* The arrow a menu has; display: flex drops the summary's own marker. */
.approved-set > summary::after { content: '▾'; margin-left: auto; color: var(--dim); font-size: var(--text-s); }
.approved-set[open] > summary::after { content: '▴'; }
.approved-set > summary::-webkit-details-marker { display: none; }
.approved-set-list {
	display: grid;
	gap: .1rem;
	max-height: 11rem;
	margin-top: .3rem;
	padding: .3rem .4rem;
	border: 1px solid var(--line);
	border-radius: var(--radius);
	overflow-y: auto;
}
.approved-set-row { display: flex; gap: .4rem; align-items: center; font-weight: 400; }
.approved-set-row input { margin: 0; }

.setup-identity { display: grid; grid-template-columns: repeat(auto-fit, minmax(10rem, 1fr)); gap: .6rem; }
/* Name and value share one row: a label column of consistent width, then the
   control. Anything past the first two children (a hint, a derived note, a
   status chip) drops to its own full-width row underneath. */
.setup-field {
	display: grid;
	grid-template-columns: minmax(7rem, 13rem) minmax(0, 1fr);
	align-items: center;
	gap: .2rem .6rem;
	min-width: 0;
	font-size: var(--text-s);
	font-weight: 600;
}
.setup-field > span:first-child { color: var(--dim); font-weight: 500; overflow-wrap: anywhere; }
/* A name with a "?" beside it: the two centred on one line. */
.setup-field-name, legend:has(> .help-tip), h3:has(> .help-tip) { display: flex; align-items: center; }
.setup-field select, .setup-field input { justify-self: start; min-width: 0; max-width: 100%; margin-top: 0; }
/* Free text is the one kind that may run long, and even it stops at a line's worth. */
.setup-field input[type="text"]:not([data-size]) { inline-size: 100%; max-width: 36rem; }
/* A checkbox keeps its own size and sits beside its label. */
.setup-checkbox { display: flex; align-items: center; gap: .4rem; }
.setup-field .setup-checkbox input[type="checkbox"] { width: 1rem; min-width: 1rem; height: 1rem; flex: none; margin: 0; appearance: auto; accent-color: var(--accent); }
.setup-field > :nth-child(n+3) { grid-column: 1 / -1; }
.setup-field .property-source { justify-self: start; }
.setup-hint { margin: 0; color: var(--dim); font-size: var(--text-s); font-weight: 400; }
/* Provisional dimensions rather than choices: present, but out of the way. */
.setup-advanced > summary { color: var(--dim); cursor: pointer; font-size: var(--text-s); }
.setup-advanced[open] > summary { margin-bottom: .4rem; }
.decision-status[data-resolution="REVIEW_REQUIRED"] { color: inherit; font-weight: 600; }

/* Ground reads like the other decisions: cards with a quiet title and the
   value first. Inside, the three ways of knowing the soil are tiles. */
.ground-how { color: var(--dim); font-size: var(--text-s); font-weight: 500; }
.ground-how[hidden] { display: none; }
.ground-routes { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: .5rem; }
.ground-route {
	display: grid;
	grid-template-columns: auto minmax(0, 1fr);
	gap: .08rem .45rem;
	align-content: start;
	min-width: 0;
	padding: .55rem .6rem;
	border: 1px solid var(--line);
	border-radius: var(--radius-s);
	background: var(--control);
	cursor: pointer;
}
.ground-route:hover { border-color: var(--accent); }
.ground-route:has(input:checked) { border-color: var(--accent); background: var(--accent-wash); box-shadow: inset 0 0 0 1px var(--accent); }
.ground-route input { grid-row: 1 / span 2; align-self: start; margin: .15rem 0 0; accent-color: var(--accent); }
.ground-route strong { min-width: 0; line-height: 1.25; }
.ground-route small { color: var(--dim); line-height: 1.35; }
.ground-choice { display: grid; grid-template-columns: minmax(10rem, .7fr) minmax(16rem, 1.3fr); gap: .55rem; }
.ground-choice .setup-field { grid-template-columns: 1fr; align-content: start; }
.ground-choice[data-mode="direct"] { grid-template-columns: 1fr; }
.ground-choice [hidden] { display: none; }
.decision-current .link-button[hidden] { display: none; }
.ground-screening[hidden], .lateral-pressure[hidden] { display: none; }
.ground-screening [hidden], .lateral-pressure [hidden] { display: none; }
.ground-screening-fields { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: .55rem; }
.ground-screening-fields .setup-field { grid-template-columns: 1fr; }
.ground-warning-list { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: .35rem .7rem; }
.ground-warning-list label { display: flex; gap: .45rem; align-items: flex-start; font-size: var(--text-s); line-height: 1.35; }
.ground-warning-list input { margin-top: .15rem; accent-color: var(--accent); }
.ground-special-stop { margin: 0; padding: .55rem .7rem; border-left: 3px solid var(--review); color: var(--fg); font-weight: 500; }
.lateral-pressure-fields { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: .45rem; }
.lateral-pressure-fields .setup-field { grid-template-columns: 1fr; align-content: start; }
.lateral-pressure-fields textarea { min-height: 4.6rem; resize: vertical; font: inherit; }
.lateral-actions { display: flex; flex-wrap: wrap; gap: .3rem .7rem; }
.lateral-actions label { display: flex; align-items: center; gap: .3rem; font-size: var(--text-s); }

/*
 * The vertical house profile. Rows are ordered Roof → Story N … Story 1 →
 * Foundation and are separated by datum lines rather than table cells, so the
 * drawing reads like the real building instead of a spreadsheet.
 */
.house-profile { display: grid; gap: 0; }

.profile-row { display: grid; grid-template-columns: 7.5rem minmax(0, 1fr); gap: .8rem; padding: .65rem 0; }
.profile-row + .profile-row,
.story-defaults + .profile-row { border-top: 1px dashed #aab3bf; }

/*
 * Wall construction defaults sit within the story band. The empty first cell
 * keeps them under the story bodies rather than under the story figures, and
 * the missing separator keeps them attached to the story rows above.
 */
.story-defaults { display: grid; grid-template-columns: 7.5rem minmax(0, 1fr); gap: .8rem; padding: 0 0 .65rem; }

.profile-figure { display: grid; align-content: start; gap: .25rem; }
.profile-figure svg { width: 100%; height: 2.6rem; fill: none; stroke: var(--dim); stroke-width: 1.3; stroke-linejoin: round; }
/* A card's name, as quiet as every card title; the values carry the weight. */
.profile-title { margin: 0; color: var(--dim); font-size: var(--text-s); font-weight: 500; }
.profile-kind { color: var(--dim); font-size: var(--text-s); font-weight: 500; }

.profile-body { display: grid; gap: .45rem; min-width: 0; }
.profile-datum { display: flex; align-items: center; gap: .4rem; color: var(--dim); font-size: var(--text-s); }
.profile-datum::after { content: ''; flex: 1 1 auto; height: 0; border-top: 1px solid var(--line); }
.profile-datum b { color: var(--fg); font-weight: 600; }
.profile-datum .help-tip { margin-left: 0; }
.setup-section[hidden], .setup-rows[hidden], .setup-field[hidden] { display: none; }
.setup-rows { display: grid; gap: .55rem; }
/* The basis value is a sentence the engine wrote, not a figure. */
.decision-value.basis-value { font-size: var(--text-m); }

.profile-fields { display: grid; grid-template-columns: repeat(auto-fit, minmax(11.5rem, 1fr)); gap: .5rem; }
.profile-fields[hidden] { display: none; }
/* The attic floor's Connection and Plank side sit in the Attic floor's own row. */
.attic-floor-fields > .floor-connection-fields.profile-fields:not([hidden]) { display: contents; }
/* One row on a wide step: the three share it, their menus shrinking to fit;
   a narrow screen lets them wrap (below). */
.setup-step-content .attic-floor-fields:not([hidden]) { flex-wrap: nowrap; }
.setup-step-content .attic-floor-fields .setup-field { flex: 1 1 0; min-width: 0; grid-template-columns: minmax(0, 1fr); }
.setup-step-content .attic-floor-fields select { width: 100%; min-width: 0; }
.profile-note { display: flex; flex-wrap: wrap; align-items: center; gap: .35rem; margin: 0; color: var(--dim); font-size: var(--text-s); }
.profile-note[hidden] { display: none; }
/* What a value was actually built to, when the request could not be met exactly. */
.derived-note { margin: .3rem 0 0; color: var(--dim); font-size: var(--text-s); }
/* One material per line: its name and "?", then the Vendor and the Model, lined
   up across a card. A note or suggestion runs across the card under its row. */
.material-rows { display: grid; grid-template-columns: minmax(7rem, 13rem) minmax(0, 1fr) minmax(0, 1.3fr); gap: .5rem .6rem; align-items: start; }
.material-rows select, .material-rows .approved-set > summary { font-weight: 600; }
.material-name { display: flex; align-items: center; min-height: var(--target); color: var(--dim); font-size: var(--text-s); font-weight: 500; }
.material-cell.material-cell-pair { flex-direction: row; gap: .4rem; }
.material-cell-pair select:last-child { width: auto; flex: none; }
.material-wide { grid-column: 1 / -1; display: grid; justify-items: start; gap: .3rem; margin-top: -.2rem; }
.material-wide .derived-note { margin: 0; }
/* What this design does not use: one closed group, there to look at. */
.material-unused > summary { color: var(--dim); font-size: var(--text-s); font-weight: 500; cursor: pointer; }
.material-unused[open] > summary { margin-bottom: .25rem; }
.material-cell { display: flex; flex-direction: column; gap: .15rem; min-width: 0; }
.material-cell select { width: 100%; }
.material-note { color: var(--dim); font-size: var(--text-s); }
.material-note-attention { color: var(--fg); }
.derived-note-attention { color: var(--fg); }
.derived-note[hidden] { display: none; }
.derived-note .help-tip { vertical-align: middle; }
/* Story 2: the checkbox that builds it leads; an unbuilt story reads as greyed out. */
.second-story-toggle { display: flex; flex-wrap: wrap; align-items: center; gap: .25rem .6rem; font-weight: 600; }
.second-story-toggle .help-tip { margin-left: -.35rem; }
.second-story-toggle input[type="checkbox"] { width: 1rem; height: 1rem; margin: 0; accent-color: var(--accent); }
.profile-row.is-off .profile-figure, .profile-row.is-off .profile-body > :not(.second-story-toggle) { opacity: .5; }
.catalog-choice { display: grid; grid-template-columns: repeat(auto-fit, minmax(9rem, 1fr));
	gap: .5rem; padding: .55rem; border: 1px solid var(--row-line); border-radius: var(--radius-s); background: var(--panel); }
.catalog-choice h4 { grid-column: 1 / -1; margin: 0; font-size: var(--text-m); }
.catalog-choice .setup-hint { grid-column: 1 / -1; }

.foundation-dimensions { display: grid; grid-template-columns: minmax(7rem, 13rem) minmax(0, 1fr); gap: 0 .6rem; margin: 0; font-size: var(--text-s); }
.foundation-dimensions dt { padding: .12rem 0; border-bottom: 1px solid var(--row-line); color: var(--dim); overflow-wrap: anywhere; }
.foundation-dimensions dd { display: flex; align-items: center; justify-content: flex-start; gap: .35rem; padding: .12rem 0; border-bottom: 1px solid var(--row-line); margin: 0; font-weight: 600; }

.foundation-basis {
	display: grid;
	gap: .25rem;
	padding: .65rem .7rem;
	border: 1px solid var(--line);
	border-left: 4px solid var(--accent);
	border-radius: var(--radius-s);
	background: var(--accent-wash);
}
.foundation-basis[data-status="WAITING_FOR_INPUT"],
.foundation-basis[data-status="REVIEW_REQUIRED"] { border-left-color: var(--review); background: var(--review-wash); }
.foundation-basis-head { display: flex; align-items: center; justify-content: space-between; gap: .7rem; }
.foundation-basis h2, .foundation-basis h4, .foundation-basis p { margin: 0; }
.foundation-basis h2, .foundation-basis h4 { font-size: var(--text-m); }
.foundation-basis-head span { flex: none; padding: .08rem .4rem; border-radius: 999px; color: var(--accent-strong); background: var(--control); font-size: var(--text-s); font-weight: 600; }
.foundation-basis[data-status="WAITING_FOR_INPUT"] .foundation-basis-head span,
.foundation-basis[data-status="REVIEW_REQUIRED"] .foundation-basis-head span { color: var(--review); }
.foundation-basis p { font-size: var(--text-s); font-weight: 600; }
.foundation-basis small { color: var(--dim); }

.status-chip { padding: 0 .35rem; border-radius: 2px; font-size: var(--text-s); font-weight: 600; }
.status-chip.kind-inherited { color: var(--accent-strong); background: var(--accent-wash); }
.status-chip.kind-custom { color: var(--review); background: var(--review-wash); }
.status-chip.kind-planning { color: var(--dim-band); background: var(--group-bg); }

.setup-section { display: grid; gap: .55rem; padding: .65rem; border: 1px solid var(--line); border-radius: var(--radius-s); background: var(--control); }
.setup-section h3 {
	margin: 0;
	color: var(--dim);
	font-size: var(--text-s);
	font-weight: 600;
}
.setup-section > p { margin: 0; color: var(--dim); font-size: var(--text-s); }

.opening-defaults { display: grid; grid-template-columns: repeat(auto-fit, minmax(14rem, 1fr)); gap: .6rem; }
.opening-defaults > .setup-section { align-content: start; }

.setup-foot { display: grid; gap: .45rem; padding: .6rem .9rem .7rem; border-top: 1px solid var(--line); background: var(--group-bg); }
.setup-impact { margin: 0; padding: .4rem .5rem; border: 1px solid var(--line); border-radius: 2px; background: var(--control); font-size: var(--text-s); }
.setup-feedback { margin: 0; min-height: 1rem; font-size: var(--text-s); }
.setup-feedback[data-state="error"] { color: var(--bad); font-weight: 600; }
.house-setup-dialog .buttons { display: flex; justify-content: flex-end; gap: .5rem; }
.house-setup-dialog .primary { color: #fff; border-color: var(--accent-strong); background: var(--accent); }
.house-setup-dialog .primary:hover:not(:disabled) { background: var(--accent-strong); }
/* A dialog's own buttons (Cancel, Apply, Render, Close …) one width, so a row reads as a row. */
.setup-foot .buttons button, .overlay-dialog .buttons button, .view-options-dialog .buttons button { min-width: 6.5rem; }
.render-surface-swatch { display: block; width: 100%; aspect-ratio: 1; border: 1px solid var(--line); border-radius: var(--radius-s); background-position: center; background-size: cover; }
/* Render materials: the types, the library and the material picked (CCAD's Library). */
.render-materials-dialog { width: clamp(min(48rem, calc(100vw - 2rem)), 80vw, calc(100vw - 2rem)); height: 90vh; max-height: 90vh; border: 1px solid var(--line); border-radius: var(--radius); background: var(--panel); box-shadow: var(--shadow-float); overflow: hidden; }
.render-materials-dialog[open] { display: grid; grid-template-rows: auto minmax(0, 1fr) auto; }
.render-materials-title { display: flex; gap: .4rem; align-items: center; }
.render-materials-body { display: grid; grid-template-columns: minmax(13rem, 17rem) minmax(0, 1fr) minmax(14rem, 18rem); min-height: 0; }
.render-materials-body > * { min-height: 0; overflow-y: auto; }
.render-materials-types { display: grid; align-content: start; gap: .7rem; padding: .7rem; border-right: 1px solid var(--line); background: var(--group-bg); }
.render-materials-type-group { display: grid; gap: .25rem; }
.render-materials-type-group h3 { margin: 0 0 .1rem; color: var(--accent-strong); font-size: var(--text-s); font-weight: 600; }
.render-materials-type { display: grid; grid-template-columns: 2.4rem minmax(0, 1fr) auto; gap: .5rem; align-items: center; width: 100%; padding: .25rem .35rem; text-align: left; background: var(--panel); }
.render-materials-type span { display: grid; min-width: 0; }
.render-materials-type strong, .render-materials-type small { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.render-materials-type small { color: var(--dim); font-weight: 400; }
.render-materials-type[aria-pressed="true"] { color: var(--fg); border-color: var(--accent-strong); background: var(--accent-wash); box-shadow: inset 0 0 0 1px var(--accent-strong); }
.render-materials-changed { color: var(--accent-strong); font-weight: 700; }
.render-materials-unused summary { color: var(--dim); font-size: var(--text-s); cursor: pointer; }
.render-materials-unused[open] summary { margin-bottom: .35rem; }
.render-materials-body > .render-materials-middle { display: grid; grid-template-rows: auto minmax(0, 1fr); overflow: hidden; }
.render-materials-search { padding: .7rem .9rem .55rem; border-bottom: 1px solid var(--line); }
.render-materials-search input { width: 100%; max-width: 26rem; min-height: var(--target); }
.render-materials-library { display: grid; align-content: start; gap: .6rem; min-height: 0; padding: .7rem .9rem; overflow-y: auto; }
.render-materials-library section { display: grid; gap: .45rem; }
.render-materials-fold { justify-self: start; padding: .1rem .3rem; border: 0; background: none; color: var(--dim); font-size: var(--text-s); font-weight: 600; }
.render-materials-fold::before { content: "▸"; display: inline-block; width: 1em; }
.render-materials-fold[aria-expanded="true"]::before { content: "▾"; }
.render-materials-tiles { display: grid; grid-template-columns: repeat(auto-fill, minmax(7.5rem, 1fr)); gap: .5rem; }
.render-materials-tile { position: relative; display: grid; gap: .25rem; min-width: 0; padding: .35rem; background: var(--control); text-align: left; }
.render-materials-tile:hover { border-color: var(--accent-strong); }
.render-materials-tile strong { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.render-materials-tile small { overflow: hidden; color: var(--dim); text-overflow: ellipsis; white-space: nowrap; }
.render-materials-tile.is-assigned { border-style: dashed; border-color: var(--accent-strong); }
.render-materials-tile[aria-pressed="true"] { color: var(--fg); border-style: solid; border-color: var(--accent-strong); background: var(--accent-wash); box-shadow: inset 0 0 0 1px var(--accent-strong); }
.render-materials-detail { display: grid; grid-template-columns: minmax(0, 1fr); align-content: start; gap: .6rem; padding: .9rem; border-left: 1px solid var(--line); }
.render-materials-detail h3 { margin: 0; font-size: var(--text-m, 1rem); }
.render-materials-detail dl { display: grid; grid-template-columns: auto minmax(0, 1fr); gap: .3rem .7rem; margin: 0; font-size: var(--text-s); }
.render-materials-detail dt { color: var(--dim); }
.render-materials-detail dd { margin: 0; overflow-wrap: anywhere; }
.render-materials-technical { display: inline-flex; gap: .4rem; align-items: center; }
.render-materials-chip { width: 1rem; height: 1rem; border: 1px solid var(--line); border-radius: 3px; }
.render-materials-note { margin: 0; color: var(--dim); font-size: var(--text-s); }
.render-materials-detail .primary { color: #fff; border-color: var(--accent-strong); background: var(--accent); }
/* A long material name ends in an ellipsis rather than widening the column (owner 2026-10-22). */
.render-materials-wide { width: 100%; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.render-materials-licence { display: inline-flex; gap: .3rem; align-items: center; }
.render-materials-detail .primary:disabled { opacity: .55; }
.render-materials-paint { position: absolute; top: .55rem; right: .55rem; width: .95rem; height: .95rem; border: 2px solid #fff; border-radius: 50%; box-shadow: 0 0 0 1px rgb(0 0 0 / 35%); }
.render-materials-picture[role="button"] { cursor: zoom-in; }
.render-materials-picture[role="button"]:focus-visible { outline: 2px solid var(--accent-strong); outline-offset: 2px; }
.render-materials-colour { display: grid; gap: .4rem; margin: 0; padding: .5rem .6rem .6rem; border: 1px solid var(--line); border-radius: var(--radius-s); }
.render-materials-colour legend { padding: 0 .25rem; color: var(--dim); font-size: var(--text-s); }
.render-materials-colour-row { display: flex; flex-wrap: wrap; gap: .4rem; align-items: center; }
.render-materials-colour-row input[type="color"] { width: 2.6rem; height: var(--target); padding: 0 .1rem; cursor: pointer; }
.render-materials-colour-value { margin-right: auto; font-variant-numeric: tabular-nums; }
.render-materials-lightbox { max-width: 92vw; max-height: 92vh; padding: .6rem; border: 1px solid var(--line); border-radius: var(--radius); background: var(--panel); box-shadow: var(--shadow-float); }
.render-materials-lightbox[open] { display: grid; gap: .5rem; justify-items: center; }
.render-materials-lightbox img { display: block; max-width: calc(92vw - 1.2rem); max-height: calc(92vh - 5rem); object-fit: contain; cursor: zoom-out; }
.render-materials-lightbox p { margin: 0; color: var(--dim); font-size: var(--text-s); }
/* A hint may reach past the edge rather than scroll the dialog. */
.view-options-dialog { width: min(28rem, calc(100vw - 2rem)); overflow: visible; border: 1px solid var(--line); border-radius: var(--radius); background: var(--panel); box-shadow: var(--shadow-float); }
.view-options-dialog form { display: grid; gap: .7rem; padding: .9rem; }
.view-options-dialog h2 { display: flex; gap: .4rem; align-items: center; margin: 0; font-size: var(--text-l); font-weight: 600; }
.view-options-dialog .buttons { display: flex; justify-content: flex-end; }
.view-options-card { display: grid; gap: .6rem; margin: 0; padding: .5rem .8rem .8rem; border: 1px solid var(--line); border-radius: var(--radius); }
.view-options-card legend { padding: 0 .3rem; font-weight: 600; }
.view-options-card .setup-field > span:first-child { display: flex; align-items: center; }

/* ------------------------------------------------ opening editor/schedule */

/* Placing a door or window: a small dialog that reads like Properties — a
   name and its value per row, explanations behind "?" (owner 2026-10-15). */
.opening-dialog {
	width: min(24rem, calc(100vw - 2rem));
	max-height: calc(100vh - 2rem);
	padding: 0;
	border: 1px solid var(--line);
	border-radius: var(--radius);
	color: var(--fg);
	background: var(--panel);
	box-shadow: var(--shadow-float);
}
.opening-dialog::backdrop { background: rgb(27 32 39 / 45%); }
.opening-dialog form { display: grid; gap: .7rem; padding: .9rem 1rem; }
.opening-dialog h2 { margin: 0; font-size: var(--text-l); font-weight: 600; }
.opening-fields { display: grid; grid-template-columns: max-content minmax(0, 1fr); gap: .35rem .75rem; align-items: center; margin: 0; }
.opening-fields dt { display: flex; align-items: center; color: var(--dim); font-size: var(--text-s); }
.opening-fields dd { display: flex; align-items: center; gap: .35rem; min-width: 0; margin: 0; font-size: var(--text-s); }
.opening-fields dd > input, .opening-fields dd > select { flex: 1 1 0; width: 100%; min-width: 0; margin: 0; text-overflow: ellipsis; }
.opening-fields .unit { color: var(--dim); }
.opening-fields .help-tip-bubble { max-width: 15rem; }
.opening-issue { margin: 0; color: var(--bad); font-size: var(--text-s); }
.opening-dialog .buttons { display: flex; justify-content: flex-end; gap: .5rem; }
.opening-dialog .primary { color: #fff; border-color: var(--accent-strong); background: var(--accent); }
.danger-text { color: var(--bad); border-color: var(--bad); }

.opening-schedule-dialog { width: min(70rem, calc(100vw - 2rem)); padding: 1rem; }
.foundation-basis-report { width: min(38rem, calc(100vw - 2rem)); padding: 1rem; }
.foundation-basis-report > .buttons { margin-top: .8rem; }
.opening-schedule-table { width: 100%; margin: .8rem 0; border-collapse: collapse; font-size: var(--text-s); }
.opening-schedule-table th, .opening-schedule-table td { padding: .3rem .45rem; border: 1px solid var(--row-line); text-align: left; vertical-align: top; }
.opening-schedule-table th { background: var(--group-bg); color: var(--dim-band); font-weight: 600; }

/* --------------------------- Project Pricing & Vendor Quotes ------------- */

.pricing-dialog {
	width: min(50rem, calc(100vw - 2rem));
	height: 90vh;
	max-height: 90vh;
	display: grid;
	grid-template-rows: auto minmax(0, 1fr) auto;
	border: 1px solid var(--line);
	border-radius: var(--radius);
	background: var(--panel);
	box-shadow: var(--shadow-float);
	overflow: hidden;
}
.pricing-head { padding: .7rem .9rem .55rem; border-bottom: 1px solid var(--line); }
.pricing-head h2 { margin: 0; font-size: var(--text-l); font-weight: 600; }
.pricing-head p { margin: .15rem 0 0; color: var(--dim); font-size: var(--text-s); }
.pricing-body { display: grid; gap: .8rem; align-content: start; padding: .8rem .9rem; overflow-y: auto; overflow-x: hidden; }
.pricing-foot { display: grid; gap: .45rem; padding: .6rem .9rem .7rem; border-top: 1px solid var(--line); background: var(--group-bg); }
.pricing-section-head { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: .4rem; }
.pricing-section-head h3, .pricing-section-head h4 { margin: 0; font-size: var(--text-s); font-weight: 600; color: var(--dim); }
.quote-card { display: grid; gap: .45rem; padding: .55rem; border: 1px solid var(--line); border-radius: var(--radius-s); background: var(--control); }
.quote-card h4 { color: var(--fg); text-transform: none; letter-spacing: 0; font-size: var(--text-m); }
.quote-drift { margin: 0; padding-left: 1rem; color: var(--review); font-size: var(--text-s); }
.quote-drift li { overflow-wrap: anywhere; }
.quote-form { display: grid; gap: .55rem; padding: .65rem; border: 1px solid var(--accent); border-radius: var(--radius-s); background: var(--accent-wash); }
.quote-form h4 { margin: 0; font-size: var(--text-m); font-weight: 600; }
.quote-lines { display: grid; gap: .25rem; }
.quote-lines p { margin: 0; color: var(--dim); font-size: var(--text-s); }
.quote-line-row { display: grid; grid-template-columns: auto minmax(0, 1fr) 8rem; align-items: center; gap: .4rem; font-size: var(--text-s); }
.quote-line-row span { overflow-wrap: anywhere; }
.quote-line-row input[type="number"] { min-height: 1.75rem; width: 100%; }
.quote-line-row input[hidden] { display: none; }

/* ---------------------------------------------------------- context menu */

.context-menu {
	position: fixed;
	z-index: 1100;
	min-width: 12rem;
	padding: .2rem;
	border: 1px solid var(--line);
	border-radius: var(--radius);
	background: var(--panel);
	box-shadow: var(--shadow-float);
}
.context-menu button {
	display: flex;
	align-items: center;
	gap: .4rem;
	width: 100%;
	min-height: 1.85rem;
	border: 1px solid transparent;
	border-radius: 2px;
	background: transparent;
	text-align: left;
}
.context-menu button:hover:not(:disabled) { background: var(--sel); border-color: var(--accent); }
.context-menu .ctx-icon { display: grid; place-items: center; width: 1rem; height: 1rem; color: var(--dim); }
.context-menu .ctx-icon svg { width: 1rem; height: 1rem; fill: none; stroke: currentColor; stroke-width: 1.2; }
.context-menu .ctx-label { flex: 1 1 auto; }
.context-menu .ctx-hint { color: var(--dim); font-size: var(--text-s); }
.ctx-sep { height: 1px; margin: .2rem .25rem; background: var(--line); }

/* ------------------------------------------------------------ responsive */

@media (max-width: 1000px) {
	body { height: auto; min-height: 100%; }
	.command-bar { justify-content: flex-start; }
	.command-group { padding-left: 0; border-left: 0; }
	/* Narrow screens stack, and the model comes first: the primary view and its
	   status stay above the fold, with navigation and properties following as
	   sequential sections. */
	.workspace { grid-template-columns: 1fr; grid-template-rows: auto auto auto; gap: .35rem; }
	.workspace-splitter { display: none; }
	.viewport-pane { order: 1; min-height: 68vh; padding: 0; }
	.properties-pane { order: 2; }
	.project-pane { order: 3; }
	.project-pane, .properties-pane { max-height: 26rem; }
	.profile-row, .story-defaults { grid-template-columns: 1fr; gap: .4rem; }
	.story-defaults > :first-child { display: none; }
	.profile-figure { grid-template-columns: 2.5rem 1fr; align-items: center; }
	.profile-figure svg { height: 2rem; }
	.ground-routes, .ground-choice, .ground-screening-fields, .ground-warning-list, .lateral-pressure-fields { grid-template-columns: 1fr; }
	.foundation-basis-head { align-items: flex-start; flex-direction: column; gap: .25rem; }
	.results-drawer { margin: 0 .35rem .35rem; }
	.marketplace-filters { grid-template-columns: repeat(2, minmax(0, 1fr)); }
	.marketplace-results { grid-template-columns: 1fr; }
}

/* ------------------------------------------------------ House Setup page */

/*
 * A page, not a dialog box: the step list down the left, one step at a time
 * beside it, and the step's own Save at the foot of what it saves. It is still
 * a modal <dialog> underneath, so focus and Escape behave as they did.
 */
.setup-page {
	width: 100vw;
	height: 100vh;
	max-width: none;
	max-height: none;
	margin: 0;
	padding: 0;
	border: 0;
	background: var(--bg);
	color: var(--fg);
}
.setup-page[open] { display: grid; grid-template-rows: auto minmax(0, 1fr); }
.setup-page::backdrop { background: var(--bg); }

.setup-page-head {
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: 1rem;
	padding: .75rem 1.5rem;
	border-bottom: 1px solid var(--line);
	background: var(--panel);
}
.setup-page-head h2 { margin: 0; font-size: var(--text-xl); font-weight: 600; line-height: 1.2; }
.setup-page-head p { margin: .1rem 0 0; color: var(--dim); font-size: var(--text-s); }

.setup-page-body { display: grid; grid-template-columns: 16.5rem minmax(0, 1fr); min-height: 0; }

.setup-steps {
	padding: 1rem .75rem;
	border-right: 1px solid var(--line);
	background: color-mix(in srgb, var(--bg) 55%, var(--panel));
	overflow-y: auto;
}
.setup-steps ol { display: grid; gap: .15rem; margin: 0; padding: 0; list-style: none; }
.setup-step-link {
	display: grid;
	grid-template-columns: 1.6rem minmax(0, 1fr);
	align-items: center;
	gap: .65rem;
	width: 100%;
	min-height: 0;
	padding: .5rem .6rem;
	border: 0;
	border-radius: var(--radius);
	background: transparent;
	text-align: left;
	white-space: normal;
}
.setup-step-link:hover:not(:disabled) { background: var(--hover); }
.setup-step-link[aria-current="step"] { background: var(--panel); box-shadow: 0 1px 2px rgb(20 30 25 / 10%); }
.setup-step-number {
	display: grid;
	place-items: center;
	width: 1.6rem;
	height: 1.6rem;
	border: 1px solid var(--line);
	border-radius: 50%;
	color: var(--dim);
	font-size: var(--text-s);
	font-weight: 600;
}
.setup-step-link.state-done .setup-step-number { border-color: transparent; color: var(--good); background: var(--accent-wash); }
.setup-step-link.state-default .setup-step-number { border-color: transparent; color: var(--good); background: var(--accent-wash); }
.setup-step-link.state-need .setup-step-number { border-color: transparent; color: var(--review); background: var(--review-wash); }
.setup-step-link[aria-current="step"] .setup-step-number { border-color: var(--accent); color: #fff; background: var(--accent); }
.setup-step-words { display: grid; min-width: 0; }
.setup-step-name { font-size: var(--text-m); font-weight: 600; }
.setup-step-summary { overflow: hidden; color: var(--dim); font-size: var(--text-s); white-space: nowrap; text-overflow: ellipsis; }
.setup-step-link.state-need .setup-step-summary { color: var(--review); }

.setup-step-pane { min-height: 0; overflow-y: auto; scrollbar-gutter: stable; }
.setup-step {
	display: grid;
	grid-template-rows: auto minmax(0, 1fr) auto;
	width: 100%;
	max-width: 62rem;
	min-height: 100%;
	margin: 0 auto;
	padding: 1.5rem 2rem 0;
}
.setup-step-head { margin-bottom: 1.25rem; }
.setup-step-head h2, .setup-step-head h3 { margin: 0; font-size: var(--text-xl); font-weight: 600; line-height: 1.25; }
.setup-step-counter { margin: 0 0 .15rem; color: var(--dim); font-size: var(--text-s); }
.setup-step-lead { max-width: 68ch; margin: .35rem 0 0; color: var(--dim); }
.setup-step-content { display: grid; align-content: start; gap: 1rem; padding-bottom: 1.5rem; }
/* The foot stays in view: Save belongs to what is on screen. */
.setup-step-foot {
	position: sticky;
	bottom: 0;
	display: grid;
	gap: .5rem;
	padding: .75rem 0 1rem;
	border-top: 1px solid var(--line);
	background: var(--bg);
}
.setup-step-foot .buttons { display: flex; justify-content: flex-end; gap: .5rem; }
.setup-step-foot .buttons > :first-child:not(:only-child) { margin-right: auto; }
.setup-step-foot .primary { color: #fff; border-color: var(--accent-strong); background: var(--accent); }
.setup-step-foot .primary:hover:not(:disabled) { background: var(--accent-strong); }
.setup-feedback:empty { display: none; }

/* Inside a step, a group is a sheet on the ground, not a box inside a box. */
.setup-step-content .setup-section { gap: .75rem; padding: 1rem 1.1rem; border-radius: var(--radius); background: var(--panel); }
/* A card's title reads like a field's name, small and quiet; the values in
   the card are what stand out (as Site location and Snow zone do). */
.setup-step-content .setup-section h3 { color: var(--dim); font-size: var(--text-s); font-weight: 500; }
/* The House step's roof and stories: one sheet each, top to bottom. */
.house-profile.as-cards { gap: .75rem; }
.house-profile.as-cards > .profile-row { padding: 1rem 1.1rem; border: 1px solid var(--line); border-radius: var(--radius); background: var(--panel); }
.setup-pair { display: grid; grid-template-columns: repeat(auto-fit, minmax(16rem, 1fr)); gap: .6rem 1.5rem; }
.setup-pair .setup-field { grid-template-columns: 5.5rem minmax(0, 1fr); }

/* One step alone, opened over the design from Properties. */
.setup-step-dialog {
	width: min(56rem, calc(100vw - 2rem));
	max-height: 90vh;
	scrollbar-gutter: stable;
	padding: 0;
	border: 1px solid var(--line);
	border-radius: var(--radius);
	background: var(--bg);
	color: var(--fg);
	box-shadow: var(--shadow-float);
}
.setup-step-dialog .setup-step { padding: 1.25rem 1.5rem 0; }

/* What the tables give for the site, as a row of small facts. */
.setup-facts { display: grid; grid-template-columns: repeat(auto-fit, minmax(13rem, 1fr)); gap: .75rem; }
.setup-fact { display: grid; align-content: start; gap: .15rem; padding: .7rem .85rem; border: 1px solid var(--line); border-radius: var(--radius); background: var(--panel); }
.setup-fact-label { color: var(--dim); font-size: var(--text-s); font-weight: 500; }
.setup-fact-value { font-size: var(--text-l); font-weight: 600; }
.setup-fact-value.is-long { font-size: var(--text-m); font-weight: 500; }

/*
 * A delegated decision reads value first: what the engine applies, a chip
 * saying where it came from, and Change. The choices open beneath, the
 * default first; who stated a value is asked only once one is picked.
 */
.decision-field {
	display: grid;
	gap: .5rem;
	min-width: 0;
	margin: 0;
	padding: 1rem 1.1rem;
	border: 1px solid var(--line);
	border-radius: var(--radius);
	background: var(--panel);
}
/* A floated legend sits inside the sheet like any other heading. */
.decision-field > legend { float: left; width: 100%; padding: 0; color: var(--dim); font-size: var(--text-s); font-weight: 500; }
.decision-field > legend + * { clear: both; }
.decision-current { display: flex; flex-wrap: wrap; align-items: center; gap: .35rem .75rem; }
.decision-value { font-size: var(--text-l); font-weight: 600; }
.decision-editor { display: grid; gap: .75rem; padding-top: .25rem; }
.decision-editor[hidden], .decision-source[hidden] { display: none; }
.decision-status:empty { display: none; }
.decision-status[data-resolution="REVIEW_REQUIRED"] { color: var(--review); font-weight: 500; }
.decision-source { display: flex; flex-wrap: wrap; gap: .6rem 1.5rem; }
.decision-source .setup-field { grid-template-columns: auto auto; }

.chip { display: inline-flex; align-items: center; padding: .05rem .55rem; border-radius: 999px; font-size: var(--text-s); font-weight: 500; white-space: nowrap; }
.chip-default { color: var(--dim-band); background: var(--group-bg); }
.chip-set { color: var(--accent-strong); background: var(--accent-wash); }
.chip-need { color: var(--review); background: var(--review-wash); }
.chip-changed { color: var(--accent-strong); background: var(--sel); }

.link-button {
	min-height: 0;
	padding: 0 .15rem;
	border: 0;
	background: none;
	color: var(--accent);
	font-weight: 500;
	text-decoration: underline;
	text-underline-offset: 2px;
}
.link-button:hover:not(:disabled) { color: var(--accent-strong); }

.choice-list { display: grid; gap: .4rem; }
.choice {
	display: grid;
	grid-template-columns: auto minmax(0, 1fr);
	align-items: start;
	gap: .65rem;
	padding: .55rem .75rem;
	border: 1px solid var(--line);
	border-radius: var(--radius);
	background: var(--control);
	cursor: pointer;
}
.choice:hover { border-color: var(--accent); }
.choice:has(input:checked) { border-color: var(--accent); background: var(--accent-wash); }
.choice input { margin: .2rem 0 0; accent-color: var(--accent); }
.choice small { display: block; color: var(--dim); }

/* Inside the profile a field's label sits above it: four roof fields share a
   line, and a label column beside each would leave no room for the value. */
.setup-step-content .profile-fields:not([hidden]) { display: flex; flex-wrap: wrap; align-items: start; gap: .6rem 1.5rem; }
.setup-step-content .setup-advanced > summary { flex-basis: 100%; }
.setup-step-content .profile-fields .setup-field { grid-template-columns: minmax(0, max-content); gap: .25rem; }
.setup-step-content .setup-impact { padding: 0; border: 0; background: none; }

@media (max-width: 760px) {
	.setup-page-head { padding: .6rem 1rem; }
	.setup-page-body { grid-template-columns: 1fr; grid-template-rows: auto minmax(0, 1fr); }
	.setup-steps { padding: .5rem 1rem; border-right: 0; border-bottom: 1px solid var(--line); overflow-x: auto; }
	.setup-steps ol { grid-auto-flow: column; grid-auto-columns: max-content; }
	.setup-step-summary { display: none; }
	.setup-step { padding: 1rem 1rem 0; }
	.setup-field { grid-template-columns: 1fr; }
	.setup-step-content .attic-floor-fields:not([hidden]) { flex-wrap: wrap; }
	.setup-step-content .attic-floor-fields .setup-field { flex: 1 1 12rem; }
}

/* ---------------------------------------------------------- Rotate hint */
/* Only a touch device held upright sees it (js/boot/handheld.js sets
   .is-handheld); a desktop, a monitor turned upright included, never does. */
.rotate-hint { display: none; }
@media (orientation: portrait) {
	html.is-handheld:not(.portrait-ok) .rotate-hint {
		position: fixed;
		inset: 0;
		z-index: 2000;
		display: grid;
		place-content: center;
		justify-items: center;
		gap: 1.2rem;
		padding: 3rem;
		background: var(--bg);
		color: var(--fg);
		text-align: center;
		font-size: 1.25rem;
	}
	/* A phone shows the 1024 px layout scaled down: the hint is sized for the
	   screen it is seen on, not for the layout. */
	html.is-handheld.is-scaled:not(.portrait-ok) .rotate-hint { font-size: 2.6rem; }
	html.is-handheld:not(.portrait-ok) body { overflow: hidden; }
}
.rotate-hint svg { width: 9rem; height: 9rem; fill: none; stroke: var(--accent); stroke-width: 2.5; stroke-linecap: round; stroke-linejoin: round; }
.rotate-hint h2 { margin: 0; font-size: 1.3em; }
.rotate-hint p { max-width: 24em; margin: 0; color: var(--dim); }
.rotate-hint button { min-height: 2.6em; padding: 0 1.2em; font-size: 1em; }
.rotate-hint .primary { color: #fff; border-color: var(--accent-strong); background: var(--accent); }
.rotate-hint .link-button { border: 0; background: none; color: var(--accent); text-decoration: underline; }

/* --------------------------------------------------------------- Site map */

.site-map { display: grid; gap: .4rem; margin: .25rem 0 .5rem; }
.site-map-canvas {
	/* Leaflet stacks its panes at z-index 400-1000: kept inside the map, they
	   cannot draw over the step's sticky Save bar as the page scrolls. */
	isolation: isolate;
	height: clamp(16rem, 42vh, 26rem);
	border: 1px solid var(--line);
	border-radius: var(--radius);
	background: var(--group-bg);
	font: inherit;
	cursor: crosshair;
}
.site-map-canvas.is-unavailable { display: grid; place-items: center; height: auto; padding: 1.5rem; color: var(--dim); cursor: default; }
.site-map-caption { display: flex; flex-wrap: wrap; align-items: baseline; justify-content: space-between; gap: .25rem 1rem; }
.site-map-message[data-state="error"] { color: var(--review); font-weight: 500; }
.site-map-message:empty { display: none; }
.site-map-caption:has(> .site-map-message:empty):has(> button[hidden]) { display: none; }

/* A round "?" by a label; its hint floats above the map and the fields. */
.help-tip { position: relative; display: inline-flex; flex: none; margin-left: .4rem; }
.help-tip-button {
	display: inline-grid;
	place-items: center;
	width: 1.15rem;
	min-height: 0;
	height: 1.15rem;
	padding: 0;
	border: 1px solid var(--line);
	border-radius: 50%;
	background: var(--bg);
	color: var(--dim);
	font-size: .75rem;
	font-weight: 600;
	line-height: 1;
	cursor: help;
}
.help-tip-button:hover, .help-tip-button[aria-expanded="true"] { color: var(--accent-strong); border-color: var(--accent); }
.help-tip-bubble {
	position: absolute;
	top: calc(100% + .4rem);
	left: -.5rem;
	z-index: 1100;
	width: max-content;
	max-width: min(22rem, 70vw);
	padding: .55rem .7rem;
	border: 1px solid var(--line);
	border-radius: var(--radius);
	background: var(--bg);
	color: var(--fg);
	box-shadow: var(--shadow-float);
	font-size: var(--text-s);
	font-weight: 400;
	line-height: 1.4;
}
.help-tip-bubble[hidden] { display: none; }
/* Leaflet sets marker colours as attributes; the tokens win from CSS. */
.site-map .site-map-pin { fill: var(--accent); stroke: #fff; filter: drop-shadow(0 1px 2px rgb(0 0 0 / 40%)); }
.site-map .site-map-centre { fill: #fff; stroke: var(--fg); }
.site-map .leaflet-control-attribution { font-size: var(--text-s); }
.site-map .leaflet-container { font-family: inherit; }

/* Render ▸ Render (phase C): the picture on the left at its own aspect, the
   settings in a rail on the right. */
.render-panel-dialog { width: min(96vw, 110rem); }
.render-panel-dialog[open] { display: grid; grid-template-rows: auto minmax(0, 1fr) auto; }
.render-body { display: grid; grid-template-columns: minmax(0, 1fr) 17rem; min-height: 0; }
.render-stage { display: grid; place-items: center; min-width: 0; min-height: 0; padding: .6rem; background: var(--view-bg); }
.render-stage canvas { max-width: 100%; max-height: 100%; width: auto; height: auto; box-shadow: var(--shadow-float); }
.render-rail { display: grid; align-content: start; gap: .7rem; padding: .8rem .9rem; overflow-y: auto; border-left: 1px solid var(--line); }
.render-rail .setup-field { grid-template-columns: 1fr; gap: .25rem; }
.render-rail .setup-field[hidden], .render-rail .setup-hint[hidden] { display: none; }
.render-rail input[type="range"] { width: 100%; }
.render-rail .help-tip-bubble { max-width: 12.5rem; }
@media (max-width: 52rem) { .render-body { grid-template-columns: 1fr; grid-template-rows: minmax(0, 1fr) auto; } }
