/* =========================================================================
   MyPCB House — core design system
   "Workbench": a dark PCB board, copper traces, and one bright solder-green
   accent for anything you can tap. Light mode is a clean bench top.
   Mobile is the default. Desktop rules are added on top with min-width.
   ========================================================================= */

/* ---------- 0. Type faces ----------------------------------------------- */

/* Two faces, both self-hosted, both variable, about 115 KB together.

   Bricolage Grotesque carries the headings. It has ink traps and slightly
   uneven, hand-cut terminals — it reads as made by somebody, which is the
   whole brief, where a neutral grotesque reads as a template.

   JetBrains Mono carries everything that is a reading off an instrument:
   prices, part codes, counts, the silkscreen labels. It was always named in
   --f-mono but never loaded, so every visitor got whatever monospace their
   system had.

   The latin-ext files hold the rupee sign (U+20B9). unicode-range means a
   browser only fetches them when a ₹ is on the page — which is every page. */
@font-face {
	font-family: "Bricolage Grotesque";
	src: url("../fonts/bricolage-latin-var.woff2") format("woff2");
	font-weight: 200 800;
	font-style: normal;
	font-display: swap;
	unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
	font-family: "Bricolage Grotesque";
	src: url("../fonts/bricolage-latinext-var.woff2") format("woff2");
	font-weight: 200 800;
	font-style: normal;
	font-display: swap;
	unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+1E00-1E9F, U+1EF2-1EFF, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
	font-family: "JetBrains Mono";
	src: url("../fonts/jetbrains-mono-latin-var.woff2") format("woff2");
	font-weight: 100 800;
	font-style: normal;
	font-display: swap;
	unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
	font-family: "JetBrains Mono";
	src: url("../fonts/jetbrains-mono-latinext-var.woff2") format("woff2");
	font-weight: 100 800;
	font-style: normal;
	font-display: swap;
	unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+1E00-1E9F, U+1EF2-1EFF, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

/* ---------- 1. Tokens --------------------------------------------------- */

:root {
	/* Board */
	--c-bg:          #061410;
	--c-bg-soft:     #08190f14;
	--c-surface:     #0a1f18;
	--c-surface-2:   #0e2a20;
	--c-surface-3:   #12362a;
	--c-line:        #1b4536;
	--c-line-soft:   #143528;

	/* Ink */
	--c-text:        #e4f2ec;
	--c-text-dim:    #9db8ac;
	--c-text-faint:  #6d8a7d;

	/* Accents */
	--c-accent:      #2ef2c8;   /* solder green — every tappable thing */
	--c-accent-ink:  #04140f;   /* text sitting on the accent */
	--c-accent-dim:  #1cae90;
	--c-copper:      #e09a53;   /* traces, prices, highlights */
	--c-copper-dim:  #a86c33;

	/* Status */
	--c-ok:          #35d69a;
	--c-warn:        #f0b429;
	--c-danger:      #ff6b6b;

	/* Photo plate.
	   Supplier product shots are all cut out on white. Dropped straight onto
	   a dark page they read as holes punched in the board. So every photo
	   sits on a deliberate light plate with rounded corners — the same trick
	   a real bench uses, where you put the part on a white sheet to look at
	   it. Slightly warm rather than pure white, so it sits with the copper. */
	--c-plate:       #f7f9f8;
	--c-plate-edge:  #dfe7e3;

	/* Shape */
	--r-sm: 8px;
	--r-md: 14px;
	--r-lg: 20px;
	--r-full: 999px;

	/* Depth */
	--sh-1: 0 1px 2px rgb(0 0 0 / .30);
	--sh-2: 0 6px 18px -6px rgb(0 0 0 / .45);
	--sh-3: 0 18px 44px -12px rgb(0 0 0 / .60);
	--glow: 0 0 0 1px rgb(46 242 200 / .35), 0 0 22px -6px rgb(46 242 200 / .45);

	/* ---- Rhythm -------------------------------------------------------
	   Two scales, and they do different jobs.

	   --sp-1..5 are FIXED. They are the inside of a component: the gap
	   between an icon and its label, the padding of a button. Those must not
	   move, because a 44px tap target is 44px on every screen and a 12px gap
	   that grows to 20px on a desktop just looks loose.

	   --sp-6..8 are FLUID. They are the space BETWEEN things: section
	   padding, the gap between a heading and the grid under it. Those should
	   breathe on a wide screen and tighten on a phone. Before this, they
	   stepped — 2rem below 900px and 3rem above it — and the jump at that one
	   width was most of the "spacing feels off" problem. Now they slide.

	   The clamp lower bound is what a 360px phone gets, the upper bound is
	   what a 1440px desktop gets, and the vw term joins the two smoothly, so
	   there is no width at which the page suddenly re-spaces itself. */
	--sp-1: .25rem;
	--sp-2: .5rem;
	--sp-3: .75rem;
	--sp-4: 1rem;
	--sp-5: 1.5rem;
	--sp-6: clamp(1.5rem, 1.15rem + 1.55vw, 2.25rem);
	--sp-7: clamp(2.25rem, 1.55rem + 3.1vw, 3.75rem);
	--sp-8: clamp(3rem, 1.85rem + 5.1vw, 5.5rem);

	/* The page gutter. One value, used by every container, so nothing can
	   drift out of alignment with anything else. */
	--gutter: clamp(1rem, .55rem + 2vw, 2rem);

	/* Vertical rhythm between major page sections. */
	--section: clamp(2.5rem, 1.5rem + 4.4vw, 5rem);

	/* ---- Breakpoints ---------------------------------------------------
	   There are three, and they are the only three. They cannot be written
	   as custom properties because a media query cannot read one, so they
	   are listed here as the single source of truth and repeated literally:

	     640px   a phone turns into a wide phone or a small tablet
	     900px   the bottom tab bar goes away and the desktop nav appears
	     1200px  there is room for the widest layouts

	   Everything between those is handled by intrinsic layout — auto-fit
	   grids and container queries — rather than by adding more widths. That
	   is what lets the same CSS sit correctly on a 4:3 tablet, a 21:9
	   ultrawide and a folded phone without any of them being anticipated. */

	/* Type */
	--f-sans: "Inter", "Segoe UI", system-ui, -apple-system, "Helvetica Neue", Arial, sans-serif;
	--f-display: "Bricolage Grotesque", var(--f-sans);
	--f-mono: "JetBrains Mono", ui-monospace, "SF Mono", "Cascadia Mono", Consolas, monospace;

	/* ---- The bench, by hand -------------------------------------------
	   Three small things that make a flat dark page read as a real board.

	   Grain: a 160px tile of fractal noise, a few percent opaque. Real
	   solder mask is never a perfect flat colour, and neither is a cutting
	   mat. It is an SVG, so it costs a few hundred bytes, not an image.

	   Silkscreen: the white legend printed on a board — R12, U3, J1. Used
	   for labels that name a thing rather than describe it.

	   Pads: four small copper squares at the corners of a panel, the way a
	   component footprint is drawn. Applied as background layers, so they
	   never fight a component's own ::before or ::after. */
	--grain: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='160' height='160'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.85' numOctaves='2' stitchTiles='stitch'/%3E%3CfeColorMatrix values='0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 .055 0'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");
	--c-silk:  #cfe3da;
	--c-pad:   color-mix(in oklab, var(--c-copper) 70%, transparent);
	--pads:
		linear-gradient(var(--c-pad), var(--c-pad)) top 7px left 7px / 5px 5px no-repeat,
		linear-gradient(var(--c-pad), var(--c-pad)) top 7px right 7px / 5px 5px no-repeat,
		linear-gradient(var(--c-pad), var(--c-pad)) bottom 7px left 7px / 5px 5px no-repeat,
		linear-gradient(var(--c-pad), var(--c-pad)) bottom 7px right 7px / 5px 5px no-repeat;

	/* Layout */
	--wrap: 1280px;
	--wrap-narrow: 860px;
	--header-h: 60px;
	--tabbar-h: 62px;

	/* ---- Layers --------------------------------------------------------
	   Every fixed or floating thing on the site, bottom to top, in one
	   place. Nothing in the theme writes a bare z-index above 2; it names
	   one of these. Third-party widgets (the chat bubble, the UPI payment
	   window, the photo lightbox) use their own huge numbers, which is why
	   the theme stays well under 1000: they are meant to sit on top. */
	--z-raised:  2;     /* a badge on a card */
	--z-header:  60;
	--z-buybar:  70;    /* sticky Add to cart, phones */
	--z-tray:    75;    /* compare tray */
	--z-tabbar:  80;
	--z-prompt:  90;    /* install card */
	--z-overlay: 120;   /* menu drawer, search sheet, filter drawer */
	--z-toast:   140;
	--z-top:     200;   /* skip link, page progress bar */

	/* Motion */
	--ease: cubic-bezier(.22, .61, .36, 1);
	--dur: 220ms;

	color-scheme: dark;
}

/* Light mode: bench top, not a screen. Same accents, darker for contrast. */
:root[data-mode="light"] {
	--c-bg:          #f2f6f4;
	--c-bg-soft:     #0a1f1808;
	--c-surface:     #ffffff;
	--c-surface-2:   #eef3f0;
	--c-surface-3:   #e2ebe6;
	--c-line:        #cfdcd5;
	--c-line-soft:   #e2ebe6;

	--c-text:        #06231a;
	--c-text-dim:    #4b6a5e;
	--c-text-faint:  #7b968a;

	/* These are darker than the dark-mode accents on purpose. On white,
	   #2ef2c8 reads at about 1.4:1 — invisible. #07705a clears 4.5:1 for
	   body text and 3:1 for large text, so the same brand colour stays
	   legible in sunlight without turning grey. */
	--c-accent:      #07705a;
	--c-accent-ink:  #ffffff;
	--c-accent-dim:  #055947;
	--c-copper:      #8a4e12;
	--c-copper-dim:  #6b3c0e;

	/* In light mode the page is already pale, so the plate only needs a
	   whisper of separation from the card behind it. */
	--c-plate:       #ffffff;
	--c-plate-edge:  #e6ede9;

	--sh-1: 0 1px 2px rgb(6 35 26 / .06);
	--sh-2: 0 6px 18px -8px rgb(6 35 26 / .16);
	--sh-3: 0 18px 44px -14px rgb(6 35 26 / .22);
	--glow: 0 0 0 1px rgb(10 156 125 / .35), 0 0 18px -8px rgb(10 156 125 / .5);

	/* On a pale bench the grain is ink, not light, and the silkscreen is the
	   dark legend of a white-mask board. */
	--grain: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='160' height='160'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.85' numOctaves='2' stitchTiles='stitch'/%3E%3CfeColorMatrix values='0 0 0 0 .02 0 0 0 0 .14 0 0 0 0 .1 0 0 0 .05 0'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");
	--c-silk:  #23463a;

	color-scheme: light;
}

/* Dark is the brand, not a preference. The shop opens on the workbench for
   everyone, and light mode is a deliberate choice the visitor makes with the
   toggle — usually to read the screen in sunlight. That choice is then
   remembered. So there is no prefers-color-scheme switch here on purpose. */

/* ---------- 2. Base ----------------------------------------------------- */

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

html {
	-webkit-text-size-adjust: 100%;
	scroll-behavior: smooth;
	scrollbar-gutter: stable;
}

body {
	margin: 0;
	background: var(--c-bg);
	color: var(--c-text);
	font-family: var(--f-sans);
	font-size: 16px;
	line-height: 1.6;
	-webkit-font-smoothing: antialiased;
	text-rendering: optimizeLegibility;
	overflow-wrap: break-word;

	/* Faint PCB traces. Two thin grids offset from each other, so the page
	   reads as a board without ever fighting the content. */
	background-image:
		var(--grain),
		linear-gradient(var(--c-bg-soft) 1px, transparent 1px),
		linear-gradient(90deg, var(--c-bg-soft) 1px, transparent 1px);
	background-size: 160px 160px, 48px 48px, 48px 48px;
	background-attachment: fixed;
}

body.is-locked { overflow: hidden; }

img, svg, video, canvas { max-width: 100%; height: auto; display: block; }
img { background-color: var(--c-surface-2); }

a { color: var(--c-accent); text-decoration-thickness: 1px; text-underline-offset: 3px; }
a:hover { color: var(--c-accent-dim); }

h1, h2, h3, h4 {
	margin: 0 0 var(--sp-3);
	font-family: var(--f-display);
	line-height: 1.15;
	font-weight: 700;
	letter-spacing: -.02em;
	color: var(--c-text);
	text-wrap: balance;
}
p { text-wrap: pretty; }
h1 { font-size: clamp(1.6rem, 5vw, 2.6rem); }
h2 { font-size: clamp(1.35rem, 4vw, 2rem); }
h3 { font-size: clamp(1.1rem, 3vw, 1.4rem); }
p  { margin: 0 0 var(--sp-4); }

/* Focus ring: always visible for keyboard users, never for mouse users. */
:focus-visible {
	outline: 2px solid var(--c-accent);
	outline-offset: 2px;
	border-radius: var(--r-sm);
}

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

.screen-reader-text {
	position: absolute !important;
	width: 1px; height: 1px;
	padding: 0; margin: -1px;
	overflow: hidden; clip-path: inset(50%);
	white-space: nowrap; border: 0;
}

.skip-link {
	position: absolute; top: -100px; left: var(--sp-4); z-index: var(--z-top);
	padding: var(--sp-3) var(--sp-4);
	background: var(--c-accent); color: var(--c-accent-ink);
	border-radius: var(--r-md); font-weight: 600; text-decoration: none;
}
.skip-link:focus { top: var(--sp-3); }

.icon { width: 22px; height: 22px; flex: none; }

/* ---------- 2b. Craft details --------------------------------------------

   The small marks that make the page read as a made object. Each is one
   class, used deliberately in a handful of places — on every element they
   would turn into wallpaper. */

/* Silkscreen legend: the printed label beside a part on a board. */
.silk {
	display: inline-flex;
	align-items: center;
	gap: .5em;
	color: var(--c-silk);
	font-family: var(--f-mono);
	font-size: .62rem;
	font-weight: 600;
	letter-spacing: .2em;
	line-height: 1;
	text-transform: uppercase;
	opacity: .62;
}
.silk__ref { color: var(--c-copper); opacity: 1; }

/* Fiducial: the ringed copper dot a pick-and-place machine aims by. */
.fiducial {
	display: inline-block;
	width: 14px; height: 14px;
	flex: none;
	border-radius: var(--r-full);
	background: radial-gradient(circle, var(--c-copper) 0 3px, transparent 3.5px);
	box-shadow: inset 0 0 0 1px color-mix(in oklab, var(--c-copper) 55%, transparent);
}

/* Footprint pads on a panel's corners. Additive: keeps whatever background
   colour the panel already has underneath. */
.has-pads { background: var(--pads), var(--pad-under, var(--c-surface)); }

/* ---------- 3. Layout --------------------------------------------------- */

.site {
	min-height: 100dvh;
	display: flex;
	flex-direction: column;
}

.site-main {
	flex: 1 0 auto;
	/* Leave room for the fixed bottom bar plus the iPhone home indicator. */
	padding-bottom: calc(var(--tabbar-h) + env(safe-area-inset-bottom, 0px) + var(--sp-4));
}

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

.section { padding-block: var(--section); }

@media (min-width: 900px) {
	.site-main { padding-bottom: 0; }
}

/* ---------- 3b. Intrinsic grids ------------------------------------------

   One class, no breakpoints. The grid fits as many columns as will hold the
   stated minimum and reflows itself at every width in between.

   min() is doing the real work: without it, a 260px minimum on a 320px
   screen overflows the moment padding is taken off, which is the classic
   cause of a page that scrolls sideways on a small phone.

   Use --col-min to say how narrow a column may get before one is dropped. */

.grid-auto {
	display: grid;
	gap: var(--sp-4);
	grid-template-columns: repeat(auto-fit, minmax(min(var(--col-min, 240px), 100%), 1fr));
}
@media (min-width: 900px) {
	.grid-auto { gap: var(--sp-5); }
}

/* A row of things that should stay one row and scroll sideways on a phone
   rather than wrap into a ragged two-and-a-half. */
.rail {
	display: grid;
	grid-auto-flow: column;
	grid-auto-columns: minmax(var(--rail-min, 60%), 1fr);
	gap: var(--sp-3);
	overflow-x: auto;
	overscroll-behavior-inline: contain;
	scroll-snap-type: x mandatory;
	padding-bottom: var(--sp-2);
	scrollbar-width: thin;
}
.rail > * { scroll-snap-align: start; }
@media (min-width: 640px) { .rail { --rail-min: 30%; } }
@media (min-width: 900px) {
	.rail {
		grid-auto-flow: row;
		grid-template-columns: repeat(auto-fit, minmax(min(var(--col-min, 240px), 100%), 1fr));
		overflow-x: visible;
	}
}

/* ---------- 4. Buttons -------------------------------------------------- */

.btn {
	--btn-bg: var(--c-surface-2);
	--btn-fg: var(--c-text);
	--btn-bd: var(--c-line);

	display: inline-flex;
	align-items: center;
	justify-content: center;
	gap: var(--sp-2);
	min-height: 48px;              /* thumb target */
	padding: var(--sp-3) var(--sp-5);
	border: 1px solid var(--btn-bd);
	border-radius: var(--r-md);
	background: var(--btn-bg);
	color: var(--btn-fg);
	font: inherit;
	font-weight: 600;
	line-height: 1;
	text-decoration: none;
	cursor: pointer;
	transition: transform var(--dur) var(--ease),
				background-color var(--dur) var(--ease),
				box-shadow var(--dur) var(--ease);
}
.btn:active { transform: translateY(1px) scale(.99); }
.btn:disabled, .btn[aria-disabled="true"] { opacity: .5; cursor: not-allowed; }

/* The primary button is a real key: a lit top edge, a darker skirt under it,
   and it travels down two pixels when pressed. A flat pill says "website";
   this says "switch on a bench supply". */
.btn--primary {
	--btn-bg: var(--c-accent);
	--btn-fg: var(--c-accent-ink);
	--btn-bd: transparent;
	box-shadow:
		inset 0 1px 0 rgb(255 255 255 / .35),
		0 2px 0 var(--c-accent-dim),
		var(--sh-2);
}
.btn--primary:hover { --btn-bg: color-mix(in oklab, var(--c-accent) 88%, #fff); color: var(--c-accent-ink); }
.btn--primary:active {
	transform: translateY(2px);
	box-shadow: inset 0 1px 0 rgb(255 255 255 / .25), 0 0 0 var(--c-accent-dim), var(--sh-1);
}

.btn--copper { --btn-bg: var(--c-copper); --btn-fg: #180c02; --btn-bd: transparent; }

.btn--ghost { --btn-bg: transparent; --btn-bd: var(--c-line); }
.btn--ghost:hover { --btn-bg: var(--c-surface-2); color: var(--c-text); }

.btn--sm { min-height: 38px; padding: var(--sp-2) var(--sp-4); font-size: .875rem; }
.btn--block { width: 100%; }

.icon-btn {
	position: relative;
	display: inline-flex;
	align-items: center;
	justify-content: center;
	width: 44px; height: 44px;
	flex: none;
	padding: 0;
	border: 0;
	border-radius: var(--r-md);
	background: transparent;
	color: var(--c-text);
	cursor: pointer;
	transition: background-color var(--dur) var(--ease), color var(--dur) var(--ease);
}
.icon-btn:hover { background: var(--c-surface-2); color: var(--c-accent); }

.icon-btn__badge,
.tabbar__badge {
	position: absolute;
	top: 4px; inset-inline-end: 2px;
	min-width: 18px; height: 18px;
	padding: 0 5px;
	display: grid; place-items: center;
	border-radius: var(--r-full);
	background: var(--c-copper);
	color: #180c02;
	font-size: 11px; font-weight: 700; line-height: 1;
	font-variant-numeric: tabular-nums;
}
.icon-btn__badge[hidden], .tabbar__badge[hidden] { display: none; }

/* ---------- 5. Header --------------------------------------------------- */

.site-header {
	position: sticky;
	top: 0;
	z-index: var(--z-header);
	background: color-mix(in oklab, var(--c-bg) 88%, transparent);
	backdrop-filter: saturate(1.4) blur(12px);
	border-bottom: 1px solid var(--c-line-soft);
	transition: transform var(--dur) var(--ease), box-shadow var(--dur) var(--ease);
}
.site-header.is-stuck { box-shadow: var(--sh-2); }

/* A copper trace runs along the underside of the header and fades out at
   both ends, the way a bus line leaves the edge of a board. */
.site-header::after {
	content: "";
	position: absolute;
	inset-inline: 0;
	bottom: -1px;
	height: 1px;
	background: linear-gradient(90deg, transparent, color-mix(in oklab, var(--c-copper) 55%, transparent) 18%, color-mix(in oklab, var(--c-copper) 55%, transparent) 82%, transparent);
	pointer-events: none;
}

/* Hide the header when scrolling down on a phone. It gives back 60px of
   screen, and the bottom bar still covers navigation. */
.site-header.is-hidden { transform: translateY(-100%); }
@media (min-width: 900px) { .site-header.is-hidden { transform: none; } }

.site-header__bar {
	display: flex;
	align-items: center;
	gap: var(--sp-2);
	min-height: var(--header-h);
}

.site-header__search { display: none; flex: 1; }
.site-header__actions { display: flex; align-items: center; gap: var(--sp-1); margin-inline-start: auto; }

/* Below 900px the bottom tab bar carries Search, Cart and Me. The header
   repeated all three, and four 44px buttons beside the menu and the logo did
   not fit a 390px phone — every page scrolled sideways by 21px. The header
   keeps the cart (its badge is the one people glance at) and the mode
   toggle; search and account live in the tab bar. */
@media (max-width: 899px) {
	.site-header__searchbtn,
	.site-header__actions .icon-btn--account { display: none; }
	.site-header__actions { gap: 0; }
}

@media (min-width: 900px) {
	.site-header__menu { display: none; }
	.site-header__searchbtn { display: none; }
	.site-header__search { display: block; margin-inline: var(--sp-5); max-width: 520px; }
}

.brand {
	display: inline-flex;
	align-items: center;
	gap: var(--sp-2);
	text-decoration: none;
	color: var(--c-text);
	font-weight: 800;
	letter-spacing: -.02em;
	font-size: 1.05rem;
	white-space: nowrap;
}
.brand__logo { max-height: 38px; width: auto; background: transparent; }

/* The drawn mark. It reads the theme's own colour variables, so one file is
   correct in both light and dark mode — no second image, no CSS filter. */
.brand__mark {
	width: 28px;
	height: 28px;
	flex: none;
	color: var(--c-text);
}
.brand--sm .brand__mark { width: 24px; height: 24px; }

/* The wordmark. Two weights: the name people say, then the rest. */
.brand__name {
	display: inline-flex;
	align-items: baseline;
	gap: .28em;
	letter-spacing: -.025em;
	white-space: nowrap;
}
.brand__word { font-weight: 800; }
.brand__word--light {
	font-weight: 500;
	color: var(--c-text-dim);
	letter-spacing: -.01em;
}
.brand:hover .brand__word--light { color: var(--c-text); }

/* Below about 380px the wordmark and the search button fight for the same
   row. The mark alone still identifies the shop, and the page title says the
   rest — so the second word steps out rather than everything shrinking. */
@media (max-width: 379px) {
	.site-header__bar .brand__word--light { display: none; }
}

.brand--sm { font-size: .95rem; }
.brand:hover { color: var(--c-text); }

/* Desktop nav */
.site-nav { display: none; border-top: 1px solid var(--c-line-soft); }
@media (min-width: 900px) { .site-nav { display: block; } }

.site-nav__list {
	display: flex;
	flex-wrap: wrap;
	gap: var(--sp-1);
	margin: 0; padding: 0;
	list-style: none;
}
.site-nav__list a {
	display: block;
	padding: var(--sp-3) var(--sp-3);
	color: var(--c-text-dim);
	font-size: .9rem;
	font-weight: 600;
	text-decoration: none;
	border-bottom: 2px solid transparent;
}
.site-nav__list a:hover,
.site-nav__list .current-menu-item > a,
.site-nav__list a[aria-current="page"] {
	color: var(--c-accent);
	border-bottom-color: var(--c-accent);
}

/* The Project Finder is a tool, not a department, so it does not read as one
   more category in the row. It sits at the end behind a hairline and carries
   the accent, because for a visitor who does not know what to search for it
   is the single most useful link on the site. */
.site-nav__item--tool {
	margin-inline-start: auto;
	padding-inline-start: var(--sp-4);
	border-inline-start: 1px solid var(--c-line-soft);
}
.site-nav__item--tool > a { color: var(--c-accent); }
.site-nav__item--tool > a::before {
	content: "";
	display: inline-block;
	width: 6px; height: 6px;
	margin-inline-end: 7px;
	border-radius: var(--r-full);
	background: var(--c-copper);
	vertical-align: 1px;
}

/* ---------- 6. Search form ---------------------------------------------- */

.searchform {
	position: relative;
	display: flex;
	align-items: center;
	width: 100%;
	background: var(--c-surface-2);
	border: 1px solid var(--c-line);
	border-radius: var(--r-full);
	transition: box-shadow var(--dur) var(--ease), border-color var(--dur) var(--ease);
}
.searchform:focus-within { border-color: var(--c-accent); box-shadow: var(--glow); }

.searchform__icon {
	display: grid; place-items: center;
	padding-inline-start: var(--sp-4);
	color: var(--c-text-faint);
}
.searchform__input {
	flex: 1;
	min-width: 0;
	min-height: 46px;
	padding: var(--sp-2) var(--sp-3);
	border: 0;
	background: transparent;
	color: var(--c-text);
	font: inherit;
	font-size: 16px;   /* 16px stops iOS zooming on focus */
}
.searchform__input:focus { outline: none; }
.searchform__input::placeholder { color: var(--c-text-faint); }
.searchform__input::-webkit-search-cancel-button { filter: invert(.6); }

.searchform__submit {
	display: grid; place-items: center;
	width: 40px; height: 40px;
	margin-inline-end: 3px;
	border: 0;
	border-radius: var(--r-full);
	background: var(--c-accent);
	color: var(--c-accent-ink);
	cursor: pointer;
}
.searchform__submit .icon { width: 18px; height: 18px; }

/* ---------- 7. Drawer (mobile menu) ------------------------------------- */

.drawer, .sheet { position: fixed; inset: 0; z-index: var(--z-overlay); }
.drawer[hidden], .sheet[hidden] { display: none; }

.drawer__scrim, .sheet__scrim {
	position: absolute; inset: 0;
	background: rgb(0 0 0 / .6);
	backdrop-filter: blur(2px);
	animation: fade var(--dur) var(--ease);
}

.drawer__panel {
	position: absolute;
	inset-block: 0;
	inset-inline-start: 0;
	width: min(86vw, 340px);
	display: flex;
	flex-direction: column;
	background: var(--c-surface);
	border-inline-end: 1px solid var(--c-line);
	box-shadow: var(--sh-3);
	animation: slide-in var(--dur) var(--ease);
	overflow-y: auto;
	overscroll-behavior: contain;
	padding-bottom: env(safe-area-inset-bottom, 0px);
}

.drawer__head {
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: var(--sp-3);
	padding: var(--sp-3) var(--sp-4);
	border-bottom: 1px solid var(--c-line-soft);
	position: sticky; top: 0;
	background: var(--c-surface);
}

.drawer__list, .drawer__list ul { list-style: none; margin: 0; padding: 0; }
.drawer__list a {
	display: block;
	padding: var(--sp-4);
	color: var(--c-text);
	font-weight: 600;
	text-decoration: none;
	border-bottom: 1px solid var(--c-line-soft);
}
.drawer__list a:hover { background: var(--c-surface-2); color: var(--c-accent); }
.drawer__list ul a { padding-inline-start: var(--sp-6); font-weight: 500; color: var(--c-text-dim); font-size: .925rem; }

/* ---------- 8. Search sheet --------------------------------------------- */

.sheet__panel {
	position: absolute;
	inset-inline: 0;
	top: 0;
	max-height: 100dvh;
	display: flex;
	flex-direction: column;
	background: var(--c-surface);
	border-bottom: 1px solid var(--c-line);
	box-shadow: var(--sh-3);
	animation: drop var(--dur) var(--ease);
	padding-top: env(safe-area-inset-top, 0px);
}
.sheet__head {
	display: flex;
	align-items: center;
	gap: var(--sp-2);
	padding: var(--sp-3) var(--sp-4);
}
.sheet__body {
	overflow-y: auto;
	overscroll-behavior: contain;
	padding: 0 var(--sp-4) var(--sp-4);
}

/* ---------- 8b. Live search results --------------------------------------

   These live here rather than in shop.css because the search sheet sits in
   the header of EVERY page. Keeping them in the shop stylesheet meant a
   search started from the About page rendered as a list of bare links. */

.quick-hit {
	display: grid;
	grid-template-columns: 56px 1fr;
	align-items: center;
	gap: var(--sp-3);
	padding: var(--sp-3);
	border-bottom: 1px solid var(--c-line-soft);
	text-decoration: none;
	color: var(--c-text);
	border-radius: var(--r-md);
}
.quick-hit:hover { background: var(--c-surface-2); }

/* A part found by its exact code is the answer, not a suggestion. Mark it,
   so somebody who typed a code off an invoice can see at a glance that the
   shop understood them. */
.quick-hit.is-sku-match {
	background: color-mix(in oklab, var(--c-accent) 8%, transparent);
	box-shadow: inset 3px 0 0 var(--c-accent);
}

.quick-hit__img {
	width: 56px; height: 56px;
	object-fit: contain;
	padding: 3px;
	background: var(--c-plate);
	border: 1px solid var(--c-plate-edge);
	border-radius: var(--r-sm);
	flex: none;
}
.quick-hit__body { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.quick-hit__title {
	font-weight: 600; font-size: .9rem; line-height: 1.3;
	display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden;
}

/* The part code. Monospace and tabular, because it is read character by
   character against something printed on a bag or an invoice. */
.quick-hit__sku {
	font-family: var(--f-mono);
	font-size: .68rem;
	letter-spacing: .06em;
	color: var(--c-text-faint);
}
.quick-hit.is-sku-match .quick-hit__sku { color: var(--c-accent); font-weight: 700; }

.quick-hit__price { color: var(--c-copper); font-weight: 700; font-size: .85rem; }
.quick-hit__was { color: var(--c-text-faint); font-weight: 500; margin-inline-end: 4px; }
.quick-hit__out {
	color: var(--c-danger);
	font-weight: 600;
	font-size: .72rem;
	text-transform: uppercase;
	letter-spacing: .04em;
}

/* ---------- 9. Bottom tab bar ------------------------------------------- */

.tabbar {
	position: fixed;
	inset-inline: 0;
	bottom: 0;
	z-index: var(--z-tabbar);
	display: grid;
	grid-template-columns: repeat(5, 1fr);
	background: color-mix(in oklab, var(--c-surface) 92%, transparent);
	backdrop-filter: saturate(1.4) blur(14px);
	border-top: 1px solid var(--c-line);
	padding-bottom: env(safe-area-inset-bottom, 0px);
}
@media (min-width: 900px) { .tabbar { display: none; } }

.tabbar__item {
	display: flex;
	flex-direction: column;
	align-items: center;
	justify-content: center;
	gap: 3px;
	min-height: var(--tabbar-h);
	padding: var(--sp-2) 2px;
	color: var(--c-text-faint);
	text-decoration: none;
	font-size: 11px;
	font-weight: 600;
	-webkit-tap-highlight-color: transparent;
	transition: color var(--dur) var(--ease);
}
.tabbar__item.is-active { color: var(--c-accent); }
.tabbar__item.is-active .tabbar__icon::after {
	content: "";
	position: absolute;
	inset-inline: 25%;
	top: -8px;
	height: 3px;
	border-radius: var(--r-full);
	background: var(--c-accent);
}
.tabbar__icon { position: relative; display: grid; place-items: center; }
.tabbar__label { line-height: 1; }

/* ---------- 10. Cards and lists ----------------------------------------- */

.page-head { margin-bottom: var(--sp-5); }
.page-head__title { margin-bottom: var(--sp-2); }
.page-head__desc { color: var(--c-text-dim); }

/* Was three hard-coded column counts at 1fr / 640px / 1024px. An auto-fit
   grid reaches the same three shapes and every shape in between, including
   the ones nobody thought to write a breakpoint for. */
.post-list {
	display: grid;
	gap: var(--sp-4);
	grid-template-columns: repeat(auto-fit, minmax(min(280px, 100%), 1fr));
}

.post-card {
	display: flex;
	flex-direction: column;
	background: var(--c-surface);
	border: 1px solid var(--c-line-soft);
	border-radius: var(--r-lg);
	overflow: hidden;
	transition: border-color var(--dur) var(--ease), transform var(--dur) var(--ease), box-shadow var(--dur) var(--ease);
}
.post-card:hover {
	border-color: var(--c-accent);
	transform: translateY(-2px);
	box-shadow: var(--sh-2);
}
.post-card__media { display: block; aspect-ratio: 16 / 10; overflow: hidden; }
.post-card__media img { width: 100%; height: 100%; object-fit: cover; }
.post-card__body { padding: var(--sp-4); }
.post-card__title { font-size: 1.05rem; margin-bottom: var(--sp-1); }
.post-card__title a { color: var(--c-text); text-decoration: none; }
.post-card__title a:hover { color: var(--c-accent); }
.post-card__meta { color: var(--c-text-faint); font-size: .8rem; margin-bottom: var(--sp-2); font-family: var(--f-mono); }
.post-card__excerpt { color: var(--c-text-dim); font-size: .925rem; margin: 0; }

/* ---------- 10b. Long-form content -------------------------------------- */

/* Everything an editor can produce from the WordPress editor, plus whatever
   the old builder pages leave behind. It has to look right without anyone
   touching the markup, because there are 26 pages of it. */

.entry-content { color: var(--c-text-dim); font-size: 1rem; line-height: 1.7; }
.entry-content > * + * { margin-top: var(--sp-4); }

.entry-content h1,
.entry-content h2,
.entry-content h3,
.entry-content h4 { color: var(--c-text); margin-top: var(--sp-6); }
.entry-content h2 { font-size: clamp(1.25rem, 3.6vw, 1.65rem); }
.entry-content h3 { font-size: clamp(1.05rem, 3vw, 1.3rem); }
.entry-content h4 { font-size: 1rem; }

.entry-content a { text-decoration: underline; }

.entry-content ul,
.entry-content ol { padding-inline-start: var(--sp-5); }
.entry-content li + li { margin-top: var(--sp-2); }
.entry-content ul { list-style: none; padding-inline-start: var(--sp-4); }
.entry-content ul > li { position: relative; }

/* A WooCommerce product grid embedded in page content is a <ul>, and it
   must not inherit the prose bullets or the text indent. */
.entry-content ul.products { padding-inline-start: 0; }
.entry-content ul.products > li { position: relative; }
.entry-content ul.products > li::before { content: none; }
.entry-content ul.products > li + li { margin-top: 0; }

/* Solder-dot bullets, to stay on theme without an image. */
.entry-content ul:not(.products) > li::before {
	content: "";
	position: absolute;
	inset-inline-start: calc(var(--sp-4) * -1);
	top: .62em;
	width: 6px; height: 6px;
	border-radius: var(--r-full);
	background: var(--c-copper);
}
.entry-content ol > li::marker { color: var(--c-copper); font-family: var(--f-mono); }

.entry-content img,
.entry-content video { border-radius: var(--r-md); height: auto; }
.entry-content figure { margin: var(--sp-5) 0; }
.entry-content figcaption {
	margin-top: var(--sp-2);
	color: var(--c-text-faint);
	font-size: .8rem;
	text-align: center;
}

.entry-content blockquote {
	margin: var(--sp-5) 0;
	padding: var(--sp-3) var(--sp-4);
	border-inline-start: 3px solid var(--c-accent);
	background: var(--c-surface);
	border-radius: 0 var(--r-md) var(--r-md) 0;
	font-size: 1.05rem;
}
.entry-content blockquote p:last-child { margin-bottom: 0; }

.entry-content code {
	padding: 2px 6px;
	background: var(--c-surface-2);
	border: 1px solid var(--c-line);
	border-radius: 5px;
	font-family: var(--f-mono);
	font-size: .86em;
	color: var(--c-accent);
}
.entry-content pre {
	overflow-x: auto;
	padding: var(--sp-4);
	background: var(--c-surface);
	border: 1px solid var(--c-line);
	border-radius: var(--r-md);
	font-family: var(--f-mono);
	font-size: .85rem;
	line-height: 1.55;
}
.entry-content pre code { padding: 0; background: none; border: 0; color: inherit; }

/* Tables scroll inside their own box rather than pushing the page sideways. */
.entry-content table {
	display: block;
	width: 100%;
	overflow-x: auto;
	border-collapse: collapse;
	font-size: .9rem;
}
.entry-content th,
.entry-content td {
	padding: var(--sp-3);
	text-align: start;
	border: 1px solid var(--c-line-soft);
}
.entry-content th { background: var(--c-surface-2); color: var(--c-text); font-weight: 600; }

.entry-content hr {
	margin: var(--sp-6) 0;
	border: 0;
	border-top: 1px dashed var(--c-line);
}

.entry-content iframe,
.entry-content embed,
.entry-content object {
	max-width: 100%;
	border-radius: var(--r-md);
}
/* Videos keep their shape instead of collapsing to a sliver. */
.entry-content iframe[src*="youtube"],
.entry-content iframe[src*="vimeo"] { width: 100%; aspect-ratio: 16 / 9; height: auto; }

.entry__meta {
	margin: 0 0 var(--sp-2);
	color: var(--c-text-faint);
	font-family: var(--f-mono);
	font-size: .75rem;
}
.entry__meta a { color: var(--c-text-faint); text-decoration: none; }
.entry__meta a:hover { color: var(--c-accent); }
.entry__sep { margin-inline: var(--sp-2); }

.entry__media { margin: 0 0 var(--sp-5); }
.entry__media img { width: 100%; border-radius: var(--r-lg); }

.entry__tags { display: flex; flex-wrap: wrap; gap: var(--sp-2); list-style: none; margin: var(--sp-5) 0 0; padding: 0; }
.entry__tags a {
	display: inline-block;
	padding: 4px var(--sp-3);
	border: 1px solid var(--c-line);
	border-radius: var(--r-full);
	color: var(--c-text-dim);
	font-size: .78rem;
	text-decoration: none;
}
.entry__tags a:hover { border-color: var(--c-accent); color: var(--c-accent); }

.post-nav { margin-top: var(--sp-6); padding-top: var(--sp-4); border-top: 1px solid var(--c-line-soft); }
.post-nav .nav-links { display: grid; gap: var(--sp-3); }
@media (min-width: 640px) { .post-nav .nav-links { grid-template-columns: 1fr 1fr; } }
.post-nav a { color: var(--c-text); text-decoration: none; font-weight: 600; font-size: .925rem; }
.post-nav a:hover { color: var(--c-accent); }
.post-nav__dir {
	display: block;
	color: var(--c-text-faint);
	font-family: var(--f-mono);
	font-size: .68rem;
	letter-spacing: .12em;
	text-transform: uppercase;
	margin-bottom: 2px;
}
.post-nav .nav-next { text-align: end; }

/* ---------- 11. Empty states -------------------------------------------- */

.empty { text-align: center; padding-block: var(--sp-6); }
.empty--lg { padding-block: var(--sp-8); }
.empty__icon { width: 56px; height: 56px; margin-inline: auto; color: var(--c-accent); opacity: .8; }
.empty__code {
	font-family: var(--f-mono);
	font-size: clamp(3rem, 14vw, 5rem);
	font-weight: 700;
	color: var(--c-copper);
	margin: var(--sp-3) 0 0;
	line-height: 1;
}
.empty__title { margin-top: var(--sp-4); }
.empty__text { color: var(--c-text-dim); max-width: 46ch; margin-inline: auto; }
.empty .searchform { max-width: 460px; margin: var(--sp-5) auto; }
.empty__actions { display: flex; flex-wrap: wrap; gap: var(--sp-3); justify-content: center; }

/* ---------- 12. Pagination ---------------------------------------------- */

.pagination { margin-top: var(--sp-6); }
.pagination .nav-links { display: flex; flex-wrap: wrap; gap: var(--sp-2); justify-content: center; }
.pagination .page-numbers {
	display: grid; place-items: center;
	min-width: 44px; min-height: 44px;
	padding: 0 var(--sp-3);
	border: 1px solid var(--c-line);
	border-radius: var(--r-md);
	color: var(--c-text-dim);
	text-decoration: none;
	font-weight: 600;
}
.pagination .page-numbers:hover { border-color: var(--c-accent); color: var(--c-accent); }
.pagination .page-numbers.current {
	background: var(--c-accent);
	border-color: var(--c-accent);
	color: var(--c-accent-ink);
}

/* ---------- 13. Footer -------------------------------------------------- */

.site-footer {
	margin-top: var(--sp-7);
	background: var(--c-surface);
	border-top: 1px solid var(--c-line);
	padding-block: var(--sp-6);
	/* Clear the fixed tab bar on phones. */
	padding-bottom: calc(var(--tabbar-h) + env(safe-area-inset-bottom, 0px) + var(--sp-5));
}
@media (min-width: 900px) { .site-footer { padding-bottom: var(--sp-6); } }

.site-footer__widgets {
	display: grid;
	gap: var(--sp-5);
	grid-template-columns: repeat(auto-fit, minmax(min(260px, 100%), 1fr));
	padding-bottom: var(--sp-5);
	margin-bottom: var(--sp-5);
	border-bottom: 1px solid var(--c-line-soft);
}

/* The brand column is wider than the three link columns — the address and
   the email are what a hesitant buyer actually came down here to find.
   Below the breakpoint the columns find their own width. */
.site-footer__cols {
	display: grid;
	gap: var(--sp-5);
	grid-template-columns: repeat(auto-fit, minmax(min(220px, 100%), 1fr));
}
@media (min-width: 1200px) {
	.site-footer__cols { grid-template-columns: 1.6fr 1fr 1fr 1fr; gap: var(--sp-6); }
}

.footer-col { min-width: 0; }
.footer-col__title {
	margin: 0 0 var(--sp-3);
	font-size: .78rem;
	font-weight: 700;
	letter-spacing: .1em;
	text-transform: uppercase;
	color: var(--c-text-faint);
}
.footer-col--brand .brand { margin-bottom: var(--sp-3); }
.footer-col__blurb {
	margin: 0 0 var(--sp-3);
	color: var(--c-text-dim);
	font-size: .875rem;
	line-height: 1.55;
	max-width: 42ch;
}
.footer-col__address {
	margin: 0 0 var(--sp-2);
	color: var(--c-text-dim);
	font-size: .825rem;
	font-style: normal;
	line-height: 1.5;
	max-width: 34ch;
}
.footer-col__email {
	display: inline-flex;
	align-items: center;
	min-height: 32px;
	color: var(--c-accent);
	font-family: var(--f-mono);
	font-size: .825rem;
	text-decoration: none;
	word-break: break-all;
}
.footer-col__email:hover { text-decoration: underline; }

/* Standalone links get a 32px tall hit area even though the text is
   smaller. WCAG 2.5.8 asks for 24px minimum; a thumb on a bus wants more.
   The exception is a link inside a sentence, which is left alone. */
.footer-links { list-style: none; margin: 0; padding: 0; display: grid; gap: 2px; }
.footer-links a {
	display: inline-flex;
	align-items: center;
	min-height: 32px;
	color: var(--c-text-dim);
	font-size: .875rem;
	text-decoration: none;
	transition: color var(--dur) var(--ease), transform var(--dur) var(--ease);
}
.footer-links a:hover { color: var(--c-accent); transform: translateX(2px); }

.site-footer__trust {
	display: grid;
	gap: var(--sp-3);
	margin-top: var(--sp-6);
	padding-top: var(--sp-5);
	border-top: 1px solid var(--c-line-soft);
}
@media (min-width: 640px) { .site-footer__trust { grid-auto-flow: column; justify-content: space-between; } }

.trust {
	display: flex;
	align-items: center;
	gap: var(--sp-2);
	margin: 0;
	color: var(--c-text-dim);
	font-size: .875rem;
	font-weight: 600;
}
.trust .icon { color: var(--c-copper); width: 20px; height: 20px; }

.widget__title {
	margin-bottom: var(--sp-3);
	font-size: .78rem;
	text-transform: uppercase;
	letter-spacing: .1em;
	color: var(--c-text-faint);
}
.widget ul { list-style: none; margin: 0; padding: 0; }
.widget li { margin-bottom: var(--sp-2); }
.widget a { color: var(--c-text-dim); text-decoration: none; font-size: .925rem; }
.widget a:hover { color: var(--c-accent); }

/* WooCommerce product-list widgets (recent, featured, on-sale, mini-cart).
   A shop owner will drop these anywhere, so they have to look right
   wherever they land — not just where the theme happens to expect them. */
.product_list_widget { display: grid; gap: var(--sp-1); }
.product_list_widget li {
	display: grid;
	grid-template-columns: 52px 1fr;
	align-items: center;
	gap: var(--sp-3);
	margin: 0;
	padding: var(--sp-2) 0;
	border-bottom: 1px solid var(--c-line-soft);
}
.product_list_widget li:last-child { border-bottom: 0; }

.product_list_widget li > a {
	display: contents;      /* the image and the title each take a grid cell */
	color: var(--c-text);
	font-weight: 600;
	font-size: .85rem;
	line-height: 1.3;
}
.product_list_widget img {
	grid-row: span 2;
	width: 52px; height: 52px;
	object-fit: contain;
	padding: 4px;
	background: var(--c-plate);
	border: 1px solid var(--c-plate-edge);
	border-radius: var(--r-sm);
}
.product_list_widget .product-title {
	display: -webkit-box;
	-webkit-line-clamp: 2;
	-webkit-box-orient: vertical;
	overflow: hidden;
}
.product_list_widget li > a:hover .product-title { color: var(--c-accent); }

.product_list_widget .amount,
.product_list_widget .woocommerce-Price-amount {
	grid-column: 2;
	color: var(--c-copper);
	font-family: var(--f-mono);
	font-size: .82rem;
	font-weight: 700;
	font-variant-numeric: tabular-nums;
}
.product_list_widget del,
.product_list_widget del .amount { color: var(--c-text-faint); font-weight: 500; }
.product_list_widget ins { text-decoration: none; }
.product_list_widget .star-rating { grid-column: 2; font-size: .7rem; color: var(--c-copper); }

.site-footer__base {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	justify-content: space-between;
	gap: var(--sp-3);
	margin-top: var(--sp-5);
	padding-top: var(--sp-4);
	border-top: 1px solid var(--c-line-soft);
}
.copyright { margin: 0; color: var(--c-text-faint); font-size: .85rem; }

/* The board mark: what is printed on the back of every real PCB — a part
   number, a revision, and where it was made. */
.boardmark {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: var(--sp-2) var(--sp-3);
	width: 100%;
	margin-top: var(--sp-3);
	padding-top: var(--sp-3);
	border-top: 1px dashed var(--c-line-soft);
}

.site-footer { background: var(--grain), var(--c-surface); background-size: 160px 160px, auto; }
.legal-nav__list { display: flex; flex-wrap: wrap; gap: var(--sp-3); list-style: none; margin: 0; padding: 0; }
.legal-nav__list a {
	display: inline-flex;
	align-items: center;
	min-height: 32px;
	color: var(--c-text-faint);
	font-size: .85rem;
	text-decoration: none;
}
.legal-nav__list a:hover { color: var(--c-accent); }

/* ---------- 14. Mode toggle --------------------------------------------- */

.mode-toggle {
	position: relative;
	display: inline-grid;
	place-items: center;
	width: 44px; height: 44px;
	border: 0; padding: 0;
	background: transparent;
	color: var(--c-text-dim);
	border-radius: var(--r-md);
	cursor: pointer;
}
.mode-toggle:hover { background: var(--c-surface-2); color: var(--c-copper); }
.mode-toggle .icon { grid-area: 1 / 1; transition: opacity var(--dur) var(--ease), transform var(--dur) var(--ease); }
.mode-toggle__sun  { opacity: 0; transform: rotate(-90deg) scale(.6); }
.mode-toggle__moon { opacity: 1; transform: none; }
:root[data-mode="light"] .mode-toggle__sun  { opacity: 1; transform: none; }
:root[data-mode="light"] .mode-toggle__moon { opacity: 0; transform: rotate(90deg) scale(.6); }

/* ---------- 15. Install prompt and toast -------------------------------- */

.install-prompt {
	position: fixed;
	z-index: var(--z-prompt);
	inset-inline: var(--sp-3);
	bottom: calc(var(--tabbar-h) + env(safe-area-inset-bottom, 0px) + var(--sp-3));
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	justify-content: space-between;
	gap: var(--sp-3);
	padding: var(--sp-3) var(--sp-4);
	background: var(--c-surface-2);
	border: 1px solid var(--c-accent);
	border-radius: var(--r-lg);
	box-shadow: var(--sh-3);
	animation: rise var(--dur) var(--ease);
}
.install-prompt[hidden] { display: none; }
@media (min-width: 900px) {
	.install-prompt { inset-inline: auto var(--sp-5); bottom: var(--sp-5); max-width: 420px; }
}
.install-prompt__text {
	display: flex; align-items: center; gap: var(--sp-2);
	margin: 0; font-weight: 600; font-size: .925rem;
}
.install-prompt__text .icon { color: var(--c-accent); }
.install-prompt__actions { display: flex; gap: var(--sp-2); margin-inline-start: auto; }

.toast {
	position: fixed;
	z-index: var(--z-toast);
	inset-inline: 0;
	bottom: calc(var(--tabbar-h) + env(safe-area-inset-bottom, 0px) + var(--sp-4));
	width: max-content;
	max-width: calc(100vw - var(--sp-6));
	margin-inline: auto;
	padding: var(--sp-3) var(--sp-5);
	background: var(--c-surface-3);
	border: 1px solid var(--c-line);
	border-radius: var(--r-full);
	box-shadow: var(--sh-3);
	font-weight: 600; font-size: .9rem;
	animation: rise var(--dur) var(--ease);
}
.toast[hidden] { display: none; }
.toast.is-error { border-color: var(--c-danger); color: var(--c-danger); }
.toast.is-ok { border-color: var(--c-ok); }
@media (min-width: 900px) { .toast { bottom: var(--sp-5); } }

/* ---------- 16. Motion -------------------------------------------------- */

@keyframes fade     { from { opacity: 0; } }
@keyframes slide-in { from { transform: translateX(-100%); } }
@keyframes drop     { from { transform: translateY(-12px); opacity: 0; } }
@keyframes rise     { from { transform: translateY(12px); opacity: 0; } }

/* ---------- 16b. Page transitions ---------------------------------------

   This one line is what stops the white flash between pages. The browser
   snapshots the page being left, snapshots the page being arrived at, and
   animates between them — with no framework, no router, and no risk to the
   checkout, because these are still ordinary full page loads underneath.

   inc/navigation.php pairs the product photograph across the two pages so it
   grows out of the card rather than dissolving. Everything else cross-fades.

   A browser that does not support it ignores the rule and navigates
   normally, which is exactly the old behaviour. */

/* Cross-document, for the browsers where it works. Kept because it costs one
   line and it is the better mechanism where it is available — no JavaScript
   runs at all. Where it does not fire, the router in nav.js does the same job
   with a same-document transition instead, and this rule simply does nothing. */
@view-transition { navigation: auto; }

/* ---------- Soft navigation ---------------------------------------------

   The progress bar only appears if a page takes longer than 180 ms to
   arrive. With the page cache warm it is never seen. On a bad mobile
   connection it is the only thing telling the visitor the tap registered. */

.nav-progress {
	position: fixed;
	inset-block-start: 0;
	inset-inline: 0;
	z-index: var(--z-top);
	height: 3px;
	background: var(--c-accent);
	transform: scaleX(0);
	transform-origin: 0 50%;
	opacity: 0;
	pointer-events: none;
	box-shadow: 0 0 12px -2px var(--c-accent);
}
.nav-progress.is-active {
	opacity: 1;
	/* Creeps towards 90% and waits there. It never reaches the end on its
	   own, because the end is the page arriving. */
	animation: nav-progress 8s cubic-bezier(.1, .8, .3, 1) forwards;
}
@keyframes nav-progress {
	0%   { transform: scaleX(0); }
	40%  { transform: scaleX(.6); }
	100% { transform: scaleX(.92); }
}

/* The header and the bottom bar are the same object on both pages, so they
   must not be part of the cross-fade — naming them makes the browser carry
   them across untouched, and the page appears to move underneath them. */
.site-header { view-transition-name: mypcb-header; }
.tabbar      { view-transition-name: mypcb-tabbar; }

/* Short, and weighted towards the incoming page. A long page transition
   makes a fast site feel slow, which would undo the point of it. */
::view-transition-old(root) {
	animation: vt-out 90ms cubic-bezier(.4, 0, 1, 1) both;
}
::view-transition-new(root) {
	animation: vt-in 220ms var(--ease) both;
}

@keyframes vt-out { to   { opacity: 0; } }
@keyframes vt-in  { from { opacity: 0; transform: translateY(8px); } }

/* The paired product photograph. Let the browser morph the box and keep the
   picture crisp while it does. */
::view-transition-group(mypcb-product-hero) {
	animation-duration: 320ms;
	animation-timing-function: var(--ease);
}
::view-transition-old(mypcb-product-hero),
::view-transition-new(mypcb-product-hero) {
	/* Neither snapshot should fade; the shape change is the whole effect. */
	mix-blend-mode: normal;
	height: 100%;
	object-fit: contain;
}

/* Respect the visitor's system setting. Movement can cause nausea. */
@media (prefers-reduced-motion: reduce) {
	html { scroll-behavior: auto; }
	*, *::before, *::after {
		animation-duration: .01ms !important;
		animation-iteration-count: 1 !important;
		transition-duration: .01ms !important;
	}

	/* A view transition animates on the pseudo-elements, which the blanket
	   rule above does not reach. Turn the whole thing off rather than
	   speeding it up: an instant cut is what somebody asking for reduced
	   motion actually wants. */
	::view-transition-group(*),
	::view-transition-old(*),
	::view-transition-new(*) {
		animation: none !important;
	}
}

/* ---------- 17. Print --------------------------------------------------- */

@media print {
	.site-header, .tabbar, .site-footer, .install-prompt, .toast, .drawer, .sheet { display: none !important; }
	body { background: #fff; color: #000; }
}

/* The logo is a link home, so it gets a full tap height like the icons
   around it, not just the height of its text. */
.brand { min-height: 44px; }

/* Page titles on the editorial pages carry the homepage's signature: a
   short copper trace under the words that ends in a solder pad. */
.page-head { margin-bottom: var(--sp-6); }
.page-head__title {
	position: relative;
	display: inline-block;
	padding-bottom: .3em;
	font-size: clamp(2rem, 6vw, 3.2rem);
	font-weight: 800;
	letter-spacing: -.04em;
}
.page-head__title::after {
	content: "";
	position: absolute;
	left: 0;
	bottom: 0;
	width: min(140px, 60%);
	height: 3px;
	border-radius: var(--r-full);
	background: linear-gradient(90deg, var(--c-copper), var(--c-copper) calc(100% - 12px), transparent calc(100% - 12px));
}
.page-head__title::before {
	content: "";
	position: absolute;
	left: calc(min(140px, 60%) - 9px);
	bottom: -3px;
	width: 9px; height: 9px;
	border-radius: var(--r-full);
	background: var(--c-copper);
}

.empty__photo {
	width: min(100%, 520px);
	height: auto;
	margin: 0 auto var(--sp-4);
	aspect-ratio: 3 / 2;
	object-fit: cover;
	border-radius: var(--r-lg);
	border: 1px solid var(--c-line);
	box-shadow: var(--sh-3);
}
/* With a photograph on top, the big empty-state padding was a second gap
   stacked on the section's own. */
.empty--lg:has(.empty__photo) { padding-top: 0; }
.empty__photo + .empty__code { margin-top: 0; }
/* Prose links are underlined; a button that happens to sit inside prose is
   still a button. */
.entry-content .btn,
.entry-content a.button { text-decoration: none; }

/* ---------- Signed in as an administrator ---------------------------------

   WordPress draws its admin bar above the page for logged-in staff: fixed
   and 32px tall on a desktop, 46px below 783px, and scrolling with the page
   below 601px. The site header is sticky at top: 0, so it slid underneath
   the bar and lost its top edge — the logo, search and cart. It now sticks
   below the bar instead. Customers never see the bar. */
.admin-bar .site-header { top: 32px; }
.admin-bar .acct-nav { top: calc(var(--header-h) + 32px); }
@media (max-width: 782px) {
	.admin-bar .site-header { top: 46px; }
	.admin-bar .acct-nav { top: calc(var(--header-h) + 46px); }
}
@media (max-width: 600px) {
	.admin-bar .site-header { top: 0; }
	.admin-bar .acct-nav { top: var(--header-h); }
}
