/* =========================================================================
   MyPCB House — homepage: "The Build Line"
   Loaded only on the front page.

   The page is one circuit. A copper trace runs down the whole thing and
   every section hangs off it at a numbered solder joint. Scrolling reads
   as following a track from "I need a project" to "this is in my cart".

   The metaphor is load-bearing, not decoration: a student who arrives here
   does not know what to search for, so the numbered track walks them
   through the decision instead of handing them a search box and hoping.
   ========================================================================= */

/* ---------- 1. The trace ------------------------------------------------ */

.buildline {
	position: relative;
	--trace-x: 20px;         /* where the trace sits on a phone */
	--joint: 40px;           /* solder joint diameter */
}

/* The trace itself. One continuous copper line, drawn behind everything,
   fading in at the top and out at the bottom so it reads as part of a
   larger board rather than a stray border. */
.buildline::before {
	content: "";
	position: absolute;
	top: 0;
	bottom: 0;
	inset-inline-start: var(--trace-x);
	width: 2px;
	background: linear-gradient(
		180deg,
		transparent 0,
		var(--c-copper-dim) 6%,
		var(--c-copper-dim) 88%,
		transparent 100%
	);
	opacity: .35;
	pointer-events: none;
	z-index: 0;
}

@media (min-width: 900px) {
	.buildline { --trace-x: max(28px, calc(50% - var(--wrap) / 2 + 26px)); }
}

/* Every section paints above the trace, except where a joint punches through. */
.buildline > * { position: relative; z-index: 1; }

/* ---------- 1b. Current on the trace -------------------------------------

   A second, brighter copper line sits on top of the dull one and grows down
   the page as the visitor scrolls, as if current were flowing along the
   track towards the next joint. It is a scroll-driven animation, so there is
   no script and nothing runs on the main thread. Browsers without
   animation-timeline simply show the dull trace, which is the old page. */
@supports (animation-timeline: scroll()) {
	.buildline::after {
		content: "";
		position: absolute;
		top: 0;
		bottom: 0;
		inset-inline-start: var(--trace-x);
		width: 2px;
		background: linear-gradient(180deg, transparent 0, var(--c-copper) 4%, var(--c-copper) 96%, transparent);
		box-shadow: 0 0 10px 0 color-mix(in oklab, var(--c-copper) 60%, transparent);
		transform-origin: 50% 0;
		pointer-events: none;
		z-index: 0;
		animation: current-flow linear both;
		animation-timeline: scroll(root block);
	}
	@keyframes current-flow {
		from { transform: scaleY(0); }
		to   { transform: scaleY(1); }
	}

	/* Each section rises into place as it reaches the reader. Short and
	   small: it should feel like the page settling, not a show. */
	.buildline > .node,
	.buildline > .closer {
		animation: node-in linear both;
		animation-timeline: view();
		animation-range: entry 0% entry 35%;
	}
	@keyframes node-in {
		from { opacity: 0; transform: translateY(28px); }
	}
}

/* The joints light up once current has reached them — copper ring glows. */
.node-head__joint { transition: box-shadow .4s var(--ease); }

/* ---------- 2. Shared node furniture ------------------------------------ */

.node { padding-block: var(--sp-6); }
@media (min-width: 900px) { .node { padding-block: var(--sp-7); } }

.node-head {
	display: grid;
	grid-template-columns: var(--joint) 1fr;
	align-items: center;
	gap: var(--sp-3);
	margin-bottom: var(--sp-5);
	/* Pull the joint out of the wrap so it lands exactly on the trace. */
	margin-inline-start: calc(var(--sp-4) * -1);
	padding-inline-start: 0;
}
@media (min-width: 900px) {
	.node-head {
		grid-template-columns: var(--joint) 1fr auto;
		gap: var(--sp-4);
		margin-inline-start: calc(var(--sp-5) * -1);
	}
}

/* The solder joint: a copper ring with the node number inside. */
.node-head__joint {
	display: grid;
	place-items: center;
	width: var(--joint);
	height: var(--joint);
	border-radius: var(--r-full);
	background: var(--c-bg);
	border: 2px solid var(--c-copper);
	box-shadow: 0 0 0 5px var(--c-bg), 0 0 18px -4px color-mix(in oklab, var(--c-copper) 60%, transparent);
}
.node-head__num {
	font-family: var(--f-mono);
	font-size: .8rem;
	font-weight: 700;
	color: var(--c-copper);
	letter-spacing: -.02em;
}

.node-head__text { min-width: 0; }
.node-head__title {
	margin: 0;
	font-size: clamp(1.35rem, 5vw, 2.1rem);
	letter-spacing: -.03em;
}
.node-head__tagline {
	margin: var(--sp-1) 0 0;
	color: var(--c-text-dim);
	font-size: .9rem;
	line-height: 1.45;
}

.node-head__link {
	display: inline-flex;
	align-items: center;
	gap: 4px;
	min-height: 32px;   /* a real tap target, not just a line of text */
	grid-column: 2;
	justify-self: start;
	margin-top: var(--sp-2);
	color: var(--c-accent);
	font-weight: 600;
	font-size: .875rem;
	text-decoration: none;
	white-space: nowrap;
}
@media (min-width: 900px) {
	.node-head__link { grid-column: 3; justify-self: end; margin-top: 0; }
}
.node-head__link .icon { width: 15px; height: 15px; transition: transform var(--dur) var(--ease); }
.node-head__link:hover .icon { transform: translateX(3px); }

/* ---------- 3. Hero ----------------------------------------------------- */

/* Two columns that argue the same point from opposite ends: the claim and
   the job card on the left, the proof on the right. Nothing is centred,
   because a centred stack of headline / subhead / two buttons is the one
   layout every shop already has. */

.hero {
	position: relative;
	isolation: isolate;
	overflow: hidden;
	background: var(--c-bg);
	border-bottom: 1px solid var(--c-line);
}

/* The photograph of the bench.
 *
 * On a phone it is a banner across the top that fades into the board below
 * it, and the words sit underneath on clean ground — text laid over a busy
 * photograph of components is unreadable at 360px.
 *
 * From 900px it fills the whole hero. The frame was composed with its left
 * 45% empty mat, and a gradient deepens that side further, so the headline
 * and the job card sit on calm ground while the kit fills the right. */
.hero__photo {
	display: block;
	width: 100%;
	aspect-ratio: 16 / 9;
	object-fit: cover;
	object-position: 78% 40%;
	background: var(--c-bg);
	-webkit-mask-image: linear-gradient(180deg, #000 55%, transparent);
	mask-image: linear-gradient(180deg, #000 55%, transparent);
	margin-bottom: calc(var(--sp-7) * -1);
}
@media (min-width: 900px) {
	.hero__photo {
		position: absolute;
		inset: 0;
		z-index: -2;
		height: 100%;
		aspect-ratio: auto;
		margin: 0;
		object-position: 60% 50%;
		-webkit-mask-image: none;
		mask-image: none;
	}
	.hero::before {
		content: "";
		position: absolute;
		inset: 0;
		z-index: -1;
		background:
			linear-gradient(90deg, var(--c-bg) 0%, color-mix(in oklab, var(--c-bg) 88%, transparent) 34%, color-mix(in oklab, var(--c-bg) 25%, transparent) 60%, transparent 78%),
			linear-gradient(0deg, color-mix(in oklab, var(--c-bg) 70%, transparent), transparent 30%);
	}
	.hero__grid { min-height: clamp(560px, 78vh, 740px); }
}

/* Two fiducials, diagonal corners, as on any board meant to be assembled
   by a machine. They frame the hero without a border. */
.hero__fid { position: absolute; z-index: 1; display: none; }
@media (min-width: 900px) {
	.hero__fid { display: block; }
	.hero__fid--a { top: var(--sp-5); left: max(var(--gutter), calc(50% - var(--wrap) / 2 + var(--gutter))); }
	.hero__fid--b { bottom: var(--sp-5); right: max(var(--gutter), calc(50% - var(--wrap) / 2 + var(--gutter))); }
}

/* Perfboard, not "tech lines". A square grid of drilled pads is what the
   back of a prototype actually looks like, and it reads as texture rather
   than as a pattern competing with the type. */
.hero__perf {
	position: absolute;
	inset: 0;
	z-index: 0;
	pointer-events: none;
	background-image:
		radial-gradient(circle, color-mix(in oklab, var(--c-copper) 55%, transparent) 1.5px, transparent 1.6px),
		radial-gradient(140% 120% at 88% 8%, color-mix(in oklab, var(--c-accent) 13%, transparent), transparent 55%);
	background-size: 26px 26px, auto;
	/* Only over the empty mat on the left now, where it reads as the
	   drilled holes of a perfboard rather than as noise over the photo. */
	mask-image: linear-gradient(90deg, #000 0%, transparent 42%);
	-webkit-mask-image: linear-gradient(90deg, #000 0%, transparent 42%);
	opacity: .32;
}

.hero__grid {
	position: relative;
	z-index: 1;
	display: grid;
	gap: var(--sp-6);
	padding-block: var(--sp-6) var(--sp-7);
	align-items: center;
}
@media (min-width: 900px) {
	.hero__grid {
		grid-template-columns: minmax(0, 580px);
		padding-block: var(--sp-7) var(--sp-8);
	}
}

.hero__pitch { min-width: 0; }

/* Facts, not a marketing capsule. Set as a mono strip with a live LED. */
.hero__meta {
	display: flex;
	align-items: center;
	gap: var(--sp-2);
	margin: 0 0 var(--sp-4);
	color: var(--c-text-faint);
	font-family: var(--f-mono);
	font-size: .68rem;
	letter-spacing: .12em;
	line-height: 1.3;
}
.hero__led {
	width: 7px; height: 7px;
	flex: none;
	border-radius: var(--r-full);
	background: var(--c-accent);
	box-shadow: 0 0 9px var(--c-accent);
	animation: led 2.6s ease-in-out infinite;
}
@keyframes led { 0%, 100% { opacity: 1; } 50% { opacity: .2; } }

.hero__title {
	margin: 0 0 var(--sp-4);
	font-size: clamp(2.6rem, 8.6vw, 5rem);
	line-height: .92;
	letter-spacing: -.045em;
	font-weight: 800;
	font-variation-settings: "wdth" 90;
}
.hero__title-a { display: block; color: var(--c-text); }

/* The payoff line is underscored by a copper trace that terminates in a
   pad — the sentence is literally wired up. */
.hero__title-b {
	display: inline-block;
	position: relative;
	color: var(--c-accent);
	/* A faint solder glow — light thrown onto the mat, not a neon sign. */
	text-shadow: 0 0 42px color-mix(in oklab, var(--c-accent) 35%, transparent);
	padding-bottom: .12em;
}
.hero__title-b::after {
	content: "";
	position: absolute;
	left: 0; right: .34em;
	bottom: 0;
	height: 3px;
	background: var(--c-copper);
	border-radius: var(--r-full);
}
.hero__title-b::before {
	content: "";
	position: absolute;
	right: 0; bottom: -3px;
	width: 9px; height: 9px;
	border-radius: var(--r-full);
	background: var(--c-copper);
}

.hero__lead {
	max-width: 46ch;
	margin: 0 0 var(--sp-5);
	color: var(--c-text-dim);
	font-size: clamp(.95rem, 2.4vw, 1.08rem);
	line-height: 1.55;
}

.btn--lg { min-height: 54px; padding-inline: var(--sp-5); font-size: 1rem; }

/* ---------- 3b. The job card -------------------------------------------- */

/* Styled as the paper docket a workshop clips to a job: ruled rows, a
   number in the corner, monospace throughout. It is the Project Finder,
   moved to the top of the page because "which kit do I need" is the
   question people actually arrive with. */
.jobcard {
	/* A container, so the rows below respond to the width of the card. The
	   card sits in the hero column, which is roughly half the window on a
	   desktop and all of it on a phone — so window width was never the right
	   question to ask. */
	container-type: inline-size;
	container-name: jobcard;

	max-width: 520px;
	background: var(--c-bg);
	border: 1px solid var(--c-line);
	border-radius: var(--r-md);
	box-shadow: var(--sh-2);
	overflow: hidden;
}

.jobcard__head {
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: var(--sp-3);
	padding: var(--sp-2) var(--sp-4);
	background: var(--c-surface-2);
	border-bottom: 1px solid var(--c-line);
}
.jobcard__title {
	color: var(--c-text-faint);
	font-family: var(--f-mono);
	font-size: .66rem;
	font-weight: 700;
	letter-spacing: .2em;
	text-transform: uppercase;
}
.jobcard__no {
	color: var(--c-copper);
	font-family: var(--f-mono);
	font-size: .72rem;
	font-variant-numeric: tabular-nums;
}

.jobcard__row {
	display: grid;
	gap: var(--sp-2);
	padding: var(--sp-3) var(--sp-4);
	border-bottom: 1px dashed var(--c-line-soft);
}
@container jobcard (min-width: 380px) {
	.jobcard__row { grid-template-columns: 62px 1fr; align-items: center; gap: var(--sp-3); }
}
.jobcard__label {
	color: var(--c-text-faint);
	font-family: var(--f-mono);
	font-size: .64rem;
	font-weight: 700;
	letter-spacing: .14em;
	text-transform: uppercase;
}
.jobcard__opts { display: flex; flex-wrap: wrap; gap: 6px; }

.opt {
	min-height: 36px;
	padding: 0 var(--sp-3);
	background: transparent;
	border: 1px solid var(--c-line);
	border-radius: var(--r-sm);
	color: var(--c-text-dim);
	font: inherit;
	font-size: .8rem;
	font-weight: 600;
	line-height: 1;
	cursor: pointer;
	transition: border-color var(--dur) var(--ease),
				background-color var(--dur) var(--ease),
				color var(--dur) var(--ease);
}
.opt--num { font-family: var(--f-mono); font-size: .74rem; }
.opt:hover { border-color: var(--c-accent); color: var(--c-text); }
.opt[aria-pressed="true"] {
	background: var(--c-accent);
	border-color: var(--c-accent);
	color: var(--c-accent-ink);
}

.jobcard__foot {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: var(--sp-3);
	padding: var(--sp-3) var(--sp-4);
}
.jobcard__go { flex: 0 0 auto; }
.jobcard__go .icon { width: 16px; height: 16px; }
.jobcard__readout {
	flex: 1 1 auto;
	margin: 0;
	min-width: 0;
	color: var(--c-text-faint);
	font-family: var(--f-mono);
	font-size: .7rem;
	line-height: 1.35;
}

/* ---------- 3c. The exploded kit ---------------------------------------- */

/* Five real products at real prices, wired to one node. It draws the
   headline rather than repeating it, and every part is a live link. */
.kit { margin: 0; min-width: 0; }

.kit__stage {
	position: relative;
	aspect-ratio: 1;
	max-width: 560px;
	margin-inline: auto;
	width: 100%;
}

.kit__wires {
	position: absolute;
	inset: 0;
	width: 100%; height: 100%;
	overflow: visible;
}
/* vector-effect keeps the stroke a real 1.5px even though the viewBox is
   stretched to a square, so the wires never go hairline or fat. */
.kit__wires line {
	stroke: var(--c-copper);
	stroke-width: 1.5;
	stroke-linecap: round;
	stroke-dasharray: 5 5;
	opacity: .75;
	vector-effect: non-scaling-stroke;
	animation: wire-crawl 3s linear infinite;
}
@keyframes wire-crawl { to { stroke-dashoffset: -20; } }

.part {
	position: absolute;
	left: var(--x);
	top: var(--y);
	transform: translate(-50%, -50%);
	display: grid;
	justify-items: center;
	gap: 5px;
	width: clamp(84px, 23%, 128px);
	text-decoration: none;
	color: var(--c-text);
	/* Each part settles in turn, so the kit reads as being laid out. */
	animation: part-settle .5s var(--ease) backwards;
	animation-delay: calc(var(--i) * 90ms + 120ms);
}
@keyframes part-settle {
	from { opacity: 0; transform: translate(-50%, -50%) scale(.86); }
}

.part__plate {
	display: block;
	width: 100%;
	aspect-ratio: 1;
	padding: 8px;
	background: var(--c-plate);
	border: 1px solid var(--c-plate-edge);
	border-radius: var(--r-md);
	box-shadow: var(--sh-2);
	transition: transform var(--dur) var(--ease), box-shadow var(--dur) var(--ease);
}
.part__plate img { width: 100%; height: 100%; object-fit: contain; background: transparent; }
.part:hover .part__plate { transform: translateY(-4px) scale(1.05); box-shadow: var(--sh-3); }

.part__tag { display: grid; justify-items: center; gap: 1px; text-align: center; }
.part__role {
	color: var(--c-text-faint);
	font-family: var(--f-mono);
	font-size: .58rem;
	letter-spacing: .1em;
	text-transform: uppercase;
	white-space: nowrap;
}
.part__price {
	color: var(--c-copper);
	font-family: var(--f-mono);
	font-size: .72rem;
	font-weight: 700;
	font-variant-numeric: tabular-nums;
}
.part__price del { display: none; }   /* the hero shows one number only */

/* The node every wire runs to: the box itself. */
.kit__node {
	position: absolute;
	left: 50%; top: 50%;
	transform: translate(-50%, -50%);
	display: grid;
	justify-items: center;
	gap: 1px;
	width: clamp(96px, 26%, 138px);
	aspect-ratio: 1;
	align-content: center;
	border-radius: var(--r-full);
	background: var(--c-bg);
	border: 2px dashed var(--c-accent);
	box-shadow: 0 0 0 8px var(--c-bg), var(--sh-3);
}
.kit__node-count {
	color: var(--c-accent);
	font-family: var(--f-mono);
	font-size: clamp(1.5rem, 4.6vw, 2.1rem);
	font-weight: 700;
	line-height: 1;
}
.kit__node-label {
	color: var(--c-text-faint);
	font-family: var(--f-mono);
	font-size: .58rem;
	letter-spacing: .18em;
	text-transform: uppercase;
}
.kit__node-total {
	margin-top: 3px;
	color: var(--c-copper);
	font-family: var(--f-mono);
	font-size: .78rem;
	font-weight: 700;
	font-variant-numeric: tabular-nums;
}
.kit__node-total del { display: none; }

.kit__cap {
	margin: var(--sp-4) 0 0;
	color: var(--c-text-faint);
	font-size: .72rem;
	line-height: 1.45;
	text-align: center;
}

/* On a narrow phone the exploded diagram would collapse into a pile of
   overlapping stamps. Below 600px the wires are dropped and the same parts
   are laid out honestly: the box first, then the contents beneath it. */
@media (max-width: 639px) {
	.kit__stage {
		aspect-ratio: auto;
		display: flex;
		flex-wrap: wrap;
		justify-content: center;
		align-items: flex-start;
		gap: var(--sp-3);
	}
	.kit__wires { display: none; }

	.kit__node {
		position: static;
		transform: none;
		order: -1;
		flex: 0 0 auto;
		width: 122px;
		margin-bottom: var(--sp-1);
		box-shadow: none;
	}

	.part {
		position: static;
		transform: none;
		flex: 0 0 auto;
		width: 84px;
		animation: none;
	}
	.part:hover .part__plate { transform: none; }
}

/* ---------- 3d. Node 01 — what is in the box ----------------------------- */

/* The bill of materials on the left, the exploded diagram on the right: the
   same five parts told twice, once as a list you can read and once as a
   drawing you can see. */
.kitnode { display: grid; gap: var(--sp-6); align-items: center; }
@media (min-width: 900px) {
	.kitnode { grid-template-columns: minmax(0, .9fr) minmax(0, 1.1fr); gap: var(--sp-7); }
}
.kitnode__text { min-width: 0; }

.kitbom {
	margin: 0 0 var(--sp-5);
	padding: var(--sp-2) var(--sp-4);
	list-style: none;
	--pad-under: var(--c-surface);
	background: var(--pads), var(--grain), var(--c-surface);
	border: 1px solid var(--c-line);
	border-radius: var(--r-md);
	box-shadow: var(--sh-2);
}
.kitbom__row {
	display: grid;
	grid-template-columns: 2.4rem minmax(0, 1fr) auto;
	align-items: baseline;
	gap: var(--sp-3);
	padding-block: var(--sp-3);
	border-bottom: 1px dashed var(--c-line-soft);
}
.kitbom__ref {
	color: var(--c-copper);
	font-family: var(--f-mono);
	font-size: .78rem;
	font-weight: 700;
}
.kitbom__name {
	min-width: 0;
	color: var(--c-text);
	font-size: .9rem;
	font-weight: 600;
	line-height: 1.35;
	text-decoration: none;
	overflow-wrap: anywhere;
}
a.kitbom__name:hover { color: var(--c-accent); }
.kitbom__role {
	display: block;
	color: var(--c-text-faint);
	font-family: var(--f-mono);
	font-size: .6rem;
	font-weight: 600;
	letter-spacing: .14em;
	text-transform: uppercase;
}
.kitbom__price {
	color: var(--c-copper);
	font-family: var(--f-mono);
	font-size: .85rem;
	font-weight: 700;
	font-variant-numeric: tabular-nums;
	white-space: nowrap;
}
.kitbom__price del { display: none; }
.kitbom__row--total { border-bottom: 0; border-top: 1px solid var(--c-line); margin-top: -1px; }
.kitbom__row--total .kitbom__name { font-family: var(--f-display); font-size: 1rem; font-weight: 700; }
.kitbom__row--total .kitbom__price { font-size: 1.05rem; }

.kitnode__more .icon { width: 16px; height: 16px; }

/* ---------- 3e. Silkscreen beside every joint ---------------------------- */

.node-head__silk { margin-bottom: var(--sp-2); }
.node-head__trace {
	display: inline-block;
	width: 42px;
	height: 1px;
	background: linear-gradient(90deg, var(--c-copper), transparent);
	opacity: .7;
}
.node-head__title { font-family: var(--f-display); font-weight: 750; }

/* ---------- 4. Trust rail ------------------------------------------------ */

.trustbar {
	background: var(--c-surface-2);
	border-bottom: 1px solid var(--c-line);
}
.trustbar__inner {
	display: grid;
	gap: var(--sp-3);
	padding-block: var(--sp-4);
}
/* Three promises. auto-fit puts them on one line the moment there is room
   for three readable columns, which happens somewhere around 700px on a
   tablet in portrait and immediately on anything wider. */
.trustbar__inner { grid-template-columns: repeat(auto-fit, minmax(min(230px, 100%), 1fr)); }
@media (min-width: 640px) { .trustbar__inner { gap: var(--sp-5); } }

.trustbar__item {
	display: flex;
	align-items: center;
	gap: var(--sp-3);
	margin: 0;
	color: var(--c-text-dim);
	font-size: .82rem;
	line-height: 1.4;
}
.trustbar__icon {
	display: grid;
	place-items: center;
	width: 38px; height: 38px;
	flex: none;
	border-radius: var(--r-md);
	background: var(--c-bg);
	border: 1px solid var(--c-line);
	color: var(--c-copper);
}
.trustbar__item strong { display: block; color: var(--c-text); font-size: .9rem; }

/* ---------- 5. Node 01 — the picker ------------------------------------- */

.picker { margin-bottom: var(--sp-4); }
.picker:last-child { margin-bottom: 0; }

.picker__label {
	display: flex;
	align-items: center;
	gap: var(--sp-2);
	margin: 0 0 var(--sp-3);
	color: var(--c-text-faint);
	font-size: .72rem;
	font-weight: 700;
	letter-spacing: .12em;
	text-transform: uppercase;
}
.picker__step {
	display: grid;
	place-items: center;
	width: 22px; height: 22px;
	flex: none;
	border-radius: var(--r-sm);
	background: var(--c-surface-3);
	border: 1px solid var(--c-line);
	color: var(--c-accent);
	font-family: var(--f-mono);
	font-size: .7rem;
	letter-spacing: 0;
}

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

.chip {
	display: flex;
	align-items: center;
	gap: var(--sp-3);
	min-height: 56px;
	padding: var(--sp-2) var(--sp-4);
	background: var(--c-surface);
	border: 1px solid var(--c-line);
	border-radius: var(--r-md);
	color: var(--c-text);
	text-decoration: none;
	transition: border-color var(--dur) var(--ease),
				background-color var(--dur) var(--ease),
				transform var(--dur) var(--ease);
}
.chip:hover {
	border-color: var(--c-accent);
	background: var(--c-surface-2);
	color: var(--c-text);
	transform: translateY(-2px);
}
.chip .icon { width: 19px; height: 19px; color: var(--c-accent); flex: none; }
.chip__text { display: flex; flex-direction: column; gap: 1px; }
.chip__name { font-weight: 600; font-size: .875rem; line-height: 1.2; }
.chip__meta {
	color: var(--c-text-faint);
	font-family: var(--f-mono);
	font-size: .68rem;
	letter-spacing: .02em;
}
.chip__amount { font-weight: 700; font-size: .95rem; color: var(--c-copper); font-variant-numeric: tabular-nums; }

.chip--budget {
	flex-direction: column;
	align-items: flex-start;
	justify-content: center;
	gap: 0;
	min-height: 62px;
	min-width: 116px;
}
.chip--budget:hover { border-color: var(--c-copper); }

/* On a phone the chips scroll sideways rather than stack six rows deep. */
@media (max-width: 639px) {
	.chips {
		flex-wrap: nowrap;
		overflow-x: auto;
		scroll-snap-type: x proximity;
		margin-inline: calc(var(--sp-4) * -1);
		padding: 2px var(--sp-4) var(--sp-3);
		scrollbar-width: none;
	}
	.chips::-webkit-scrollbar { display: none; }
	.chip { flex: none; scroll-snap-align: start; }
}

/* ---------- 6. Node 02 — parts drawers ---------------------------------- */

/* Categories drawn as the labelled bins on a component cabinet: a pull
   handle at the top, the part inside, and a printed label strip below. */
.drawers {
	display: grid;
	/* Matched to the product grid on purpose: a drawer tile and a product
	   card are the same size object, and when the two grids used different
	   column counts at the same window width the page read as two designs
	   stacked on each other. */
	grid-template-columns: repeat(auto-fill, minmax(min(158px, 100%), 1fr));
	gap: var(--sp-3);
	margin: 0;
	padding: 0;
	list-style: none;
}
@media (min-width: 640px) {
	.drawers {
		grid-template-columns: repeat(auto-fill, minmax(min(215px, 100%), 1fr));
		gap: var(--sp-4);
	}
}

.drawer-tile > a {
	position: relative;
	display: flex;
	flex-direction: column;
	height: 100%;
	background: var(--c-surface);
	border: 1px solid var(--c-line);
	border-radius: var(--r-md);
	overflow: hidden;
	text-decoration: none;
	color: var(--c-text);
	transition: border-color var(--dur) var(--ease),
				transform var(--dur) var(--ease),
				box-shadow var(--dur) var(--ease);
}
.drawer-tile > a:hover {
	border-color: var(--c-accent);
	/* The drawer slides open a little. */
	transform: translateY(-4px);
	box-shadow: var(--sh-3);
}

/* The metal pull handle. */
.drawer-tile__pull {
	display: block;
	width: 34px;
	height: 4px;
	margin: var(--sp-3) auto 0;
	border-radius: var(--r-full);
	background: var(--c-line);
	transition: background-color var(--dur) var(--ease), width var(--dur) var(--ease);
}
.drawer-tile > a:hover .drawer-tile__pull { background: var(--c-accent); width: 46px; }

.drawer-tile__media {
	display: grid;
	place-items: center;
	aspect-ratio: 5 / 4;
	padding: var(--sp-2) var(--sp-2) 0;
	overflow: hidden;
}
.drawer-tile__media img {
	width: 100%; height: 100%;
	object-fit: contain;
	padding: var(--sp-3);
	background: var(--c-plate);
	border: 1px solid var(--c-plate-edge);
	border-radius: var(--r-sm);
}
.drawer-tile__fallback { width: 42px; height: 42px; color: var(--c-accent); opacity: .5; }

/* A photographed drawer: the bench shot fills the bin edge to edge, and
   the pull handle sits on top of it like the real metal tab. */
.drawer-tile--photo .drawer-tile__pull {
	position: absolute;
	top: var(--sp-3);
	left: 50%;
	z-index: 1;
	margin: 0;
	transform: translateX(-50%);
	background: color-mix(in oklab, var(--c-silk) 55%, transparent);
	box-shadow: 0 1px 2px rgb(0 0 0 / .5);
}
.drawer-tile--photo .drawer-tile__media { padding: 0; aspect-ratio: 1; }
.drawer-tile--photo .drawer-tile__media img {
	padding: 0;
	border: 0;
	border-radius: 0;
	object-fit: cover;
	background: var(--c-bg);
	transition: transform .6s var(--ease);
}
.drawer-tile--photo > a:hover .drawer-tile__media img { transform: scale(1.05); }
@media (prefers-reduced-motion: reduce) {
	.drawer-tile--photo > a:hover .drawer-tile__media img { transform: none; }
}

/* The printed label strip along the bottom of the bin. */
.drawer-tile__label {
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: var(--sp-2);
	margin-top: auto;
	padding: var(--sp-3);
	background: var(--c-surface-2);
	border-top: 1px dashed var(--c-line);
}
.drawer-tile__name {
	font-weight: 700;
	font-size: .8rem;
	line-height: 1.25;
	text-transform: capitalize;
	display: -webkit-box;
	-webkit-line-clamp: 2;
	-webkit-box-orient: vertical;
	overflow: hidden;
}
.drawer-tile__count {
	flex: none;
	color: var(--c-copper);
	font-family: var(--f-mono);
	font-size: .95rem;
	font-weight: 700;
	line-height: 1;
	text-align: end;
}
.drawer-tile__count small {
	display: block;
	color: var(--c-text-faint);
	font-size: .58rem;
	font-weight: 500;
	letter-spacing: .06em;
	text-transform: uppercase;
}

/* ---------- 7. Nodes 03–05 — the shelves -------------------------------- */

/* A sideways swipe on a phone; a five-up grid on a wide screen. This
   overrides ul.products from shop.css on purpose. */
ul.products.products--rail {
	display: flex;
	grid-template-columns: none;
	gap: var(--sp-3);
	overflow-x: auto;
	scroll-snap-type: x proximity;
	scroll-padding-inline: var(--sp-4);
	margin-inline: calc(var(--sp-4) * -1);
	padding: 2px var(--sp-4) var(--sp-4);
	scrollbar-width: thin;
	scrollbar-color: var(--c-line) transparent;
	overscroll-behavior-x: contain;
}
ul.products.products--rail::-webkit-scrollbar { height: 5px; }
ul.products.products--rail::-webkit-scrollbar-thumb { background: var(--c-line); border-radius: var(--r-full); }

ul.products.products--rail li.product {
	flex: 0 0 auto;
	width: 47vw;
	max-width: 232px;
	scroll-snap-align: start;
}

.rail-hint {
	display: flex;
	align-items: center;
	justify-content: flex-end;
	gap: 2px;
	margin: 0;
	color: var(--c-text-faint);
	font-size: .7rem;
	letter-spacing: .08em;
	text-transform: uppercase;
}
.rail-hint .icon { width: 13px; height: 13px; animation: nudge 1.8s ease-in-out infinite; }
@keyframes nudge { 0%, 100% { transform: translateX(0); } 50% { transform: translateX(4px); } }

@media (min-width: 900px) {
	ul.products.products--rail {
		display: grid;
		grid-template-columns: repeat(5, minmax(0, 1fr));
		gap: var(--sp-4);
		overflow: visible;
		margin-inline: 0;
		padding-inline: 0;
	}
	ul.products.products--rail li.product { width: auto; max-width: none; }
	/* The fifth column only earns its place on a wide screen. */
	ul.products.products--rail li.product:nth-child(n + 6) { display: none; }
	.rail-hint { display: none; }
}

/* ---------- 8. Node 06 — the three steps -------------------------------- */

.steps {
	display: grid;
	gap: var(--sp-5);
	margin: var(--sp-4) 0 0;
	padding: 0;
	list-style: none;
}
.steps { grid-template-columns: repeat(auto-fit, minmax(min(260px, 100%), 1fr)); }
@media (min-width: 640px) { .steps { gap: var(--sp-4); } }

.step {
	position: relative;
	padding: var(--sp-6) var(--sp-4) var(--sp-4);
	background: var(--c-surface);
	border: 1px solid var(--c-line);
	border-radius: var(--r-lg);
}

/* Each step is soldered to its own pad. */
.step__joint {
	position: absolute;
	top: calc(var(--sp-4) * -1);
	inset-inline-start: var(--sp-4);
	display: grid;
	place-items: center;
	width: 42px; height: 42px;
	background: var(--c-accent);
	color: var(--c-accent-ink);
	border: 3px solid var(--c-bg);
	border-radius: var(--r-full);
	font-family: var(--f-mono);
	font-weight: 700;
	font-size: 1.05rem;
	box-shadow: 0 0 22px -6px color-mix(in oklab, var(--c-accent) 70%, transparent);
}
.step__title { margin: 0 0 var(--sp-2); font-size: 1.05rem; letter-spacing: -.02em; }
.step__text { margin: 0; color: var(--c-text-dim); font-size: .9rem; line-height: 1.5; }

/* A step with a photograph: the picture is the top of the card, and the
   numbered joint sits on its lower edge, soldered across the seam. */
.step--photo { padding-top: 0; overflow: hidden; }
.step__photo {
	display: block;
	width: calc(100% + var(--sp-4) * 2);
	max-width: none;
	margin: 0 calc(var(--sp-4) * -1) var(--sp-6);
	aspect-ratio: 3 / 2;
	object-fit: cover;
	background: var(--c-bg);
	border-bottom: 1px solid var(--c-line);
}
.step--photo .step__joint { top: auto; margin-top: calc(-21px - var(--sp-6)); position: relative; inset-inline-start: 0; margin-bottom: var(--sp-3); }
.step { background: var(--pads), var(--c-surface); }

/* ---------- 9. The close ------------------------------------------------ */

.closer {
	position: relative;
	margin-top: var(--sp-6);
	padding-block: var(--sp-7);
	background:
		radial-gradient(90% 120% at 50% 120%, color-mix(in oklab, var(--c-accent) 15%, transparent), transparent 65%),
		var(--c-surface);
	border-top: 1px solid var(--c-line);
}
.closer__inner { text-align: center; }

/* With a photograph the close becomes a wide, low bench at dusk, darkened
   in the middle so the question and the two buttons stay the brightest
   thing in the frame. */
.closer--photo { overflow: hidden; isolation: isolate; padding-block: var(--sp-8); }
.closer__photo {
	position: absolute;
	inset: 0;
	z-index: -2;
	width: 100%;
	height: 100%;
	object-fit: cover;
	opacity: .9;
}
.closer--photo::before {
	content: "";
	position: absolute;
	inset: 0;
	z-index: -1;
	background:
		radial-gradient(60% 75% at 50% 50%, color-mix(in oklab, var(--c-bg) 86%, transparent), color-mix(in oklab, var(--c-bg) 45%, transparent) 75%),
		linear-gradient(180deg, var(--c-bg), transparent 22%, transparent 78%, var(--c-bg));
}

/* The trace terminates here, in a single bright pad. */
.closer__joint {
	display: block;
	width: 14px; height: 14px;
	margin: 0 auto var(--sp-5);
	border-radius: var(--r-full);
	background: var(--c-accent);
	box-shadow: 0 0 0 6px color-mix(in oklab, var(--c-accent) 18%, transparent),
				0 0 26px -2px var(--c-accent);
}

.closer__title { margin: 0 0 var(--sp-3); font-size: clamp(1.5rem, 6vw, 2.4rem); letter-spacing: -.03em; }
.closer__text {
	max-width: 54ch;
	margin: 0 auto var(--sp-5);
	color: var(--c-text-dim);
	font-size: clamp(.925rem, 2.5vw, 1.05rem);
	line-height: 1.55;
}
.closer__actions { display: flex; flex-wrap: wrap; gap: var(--sp-3); justify-content: center; }
.closer__actions .btn { flex: 1 1 190px; max-width: 260px; }

/* ---------- 10. Editor content ------------------------------------------ */

.entry-content > * { max-width: 100%; }
.entry-content img { border-radius: var(--r-md); }

/* ---------- 11. Motion opt-out ------------------------------------------ */

/* The LED, the parts settling in and the swipe nudge are all ambient. If
   the visitor asked their system to stop movement, they stop dead. */
@media (prefers-reduced-motion: reduce) {
	.buildline::after { animation: none; transform: none; opacity: .5; }
	.buildline > .node, .buildline > .closer { animation: none; }
	.hero__led { animation: none; }
	.part { animation: none; }
	.kit__wires line { animation: none; }
	.part:hover .part__plate { transform: none; }
	.rail-hint .icon { animation: none; }
	.drawer-tile > a:hover { transform: none; }
	.chip:hover { transform: none; }
}

/* The node heading above already says this, so the caption stays for
   screen readers (it labels the figure) but is not printed twice. */
.kitnode .kit__cap {
	position: absolute; width: 1px; height: 1px; margin: -1px; padding: 0;
	overflow: hidden; clip-path: inset(50%); white-space: nowrap;
}

@media print {
	.buildline::after { display: none; }
	.buildline > .node, .buildline > .closer { animation: none !important; opacity: 1 !important; transform: none !important; }
}

/* The close already ends the page in its own full-width band, so the
   footer's usual top margin only left an empty strip between the two. */
.home .site-footer { margin-top: 0; }
