/*
 * Selvedge — main stylesheet.
 *
 * LAYOUT ARCHETYPE: "the draft sheet".
 *
 * A weaving draft is laid out in four blocks — threading across the top,
 * tie-up in the top-right corner, treadling down the right, and the computed
 * drawdown filling the field. That arrangement is not decoration to a weaver;
 * it is how the trade reads a cloth. So the page borrows it:
 *
 *   - a ruled graph ground, at the same pitch as a draft grid, underneath
 *     everything (see .sheet — this is also why the page never looks like a
 *     flat slab of colour);
 *   - section heads carry a short "threading strip" of marks in the corner,
 *     echoing the notation block;
 *   - fabric cards put the notation and the resulting cloth side by side,
 *     because that pairing IS the product specification.
 *
 * Distinct from every prior archetype in this catalogue (lighting-plot,
 * programme-grid, palette-rail, waterline, promenade, bento, fight-card).
 *
 * COLOUR: undyed-linen ground with indigo ink and a madder accent — the two
 * oldest dyes in the trade. Deliberately a LIGHT theme; the previous build
 * was dark, and the swatch-book reading depends on paper-coloured stock.
 */

/* ------------------------------------------------------------------ *
 * 0. Tokens
 * ------------------------------------------------------------------ */
:root {
	--slv-paper:     #f4efe4;
	--slv-paper-alt: #ece5d6;
	--slv-card:      #fbf8f1;
	--slv-ink:       #1d2a3d;
	--slv-ink-soft:  #4a5568;
	--slv-ink-faint: #8a8578;
	--slv-rule:      rgb( 29 42 61 / 14% );
	--slv-indigo:    #20304a;
	--slv-madder:    #b9451f;
	--slv-brass:     #a8894f;
	--slv-on-dark:   #f4efe4;

	--slv-ink-rgb:    29 42 61;
	--slv-madder-rgb: 185 69 31;
	--slv-paper-rgb:  244 239 228;

	/* Type. Instrument Serif for display (a serif is right for a fabric
	   house — Kvadrat, Maharam, Rose Uniacke all sit here), Spline Sans for
	   running text, Martian Mono for anything that is a specification:
	   counts, setts, weights, the draft notation itself. */
	--slv-ff-display: "Instrument Serif", Georgia, serif;
	--slv-ff-body:    "Spline Sans", system-ui, sans-serif;
	--slv-ff-mono:    "Martian Mono", ui-monospace, monospace;

	--slv-t-xs:  0.75rem;
	--slv-t-s:   0.8438rem;
	--slv-t-m:   1.0625rem;
	--slv-t-l:   1.3125rem;
	--slv-t-xl:  1.625rem;
	--slv-t-2xl: 2.25rem;
	--slv-t-3xl: 3.125rem;
	--slv-t-display: clamp( 2.8rem, 5.2vw + 1rem, 5.4rem );

	--slv-sp-1: 0.5rem;
	--slv-sp-2: 1rem;
	--slv-sp-3: 1.5rem;
	--slv-sp-4: 2rem;
	--slv-sp-5: 3rem;
	--slv-sp-6: 4rem;
	--slv-sp-7: 6rem;
	--slv-sp-8: 8rem;
	--slv-section-y: clamp( 4rem, 7vw, 9rem );

	--slv-radius: 2px;
	--slv-measure: 68ch;
	--slv-grid: 22px; /* the draft-grid pitch, reused by .sheet and .strip */
}

/* ------------------------------------------------------------------ *
 * 1. Reset & base
 * ------------------------------------------------------------------ */
*, *::before, *::after { box-sizing: border-box; }
html { scroll-behavior: smooth; }
@media ( prefers-reduced-motion: reduce ) { html { scroll-behavior: auto; } }

body {
	margin: 0;
	overflow-x: hidden;
	background: var( --slv-paper );
	color: var( --slv-ink );
	font-family: var( --slv-ff-body );
	font-size: var( --slv-t-m );
	line-height: 1.62;
	-webkit-font-smoothing: antialiased;
}

img, svg, video, canvas { max-width: 100%; display: block; }
a { color: inherit; }
button { font: inherit; color: inherit; }

.skip-link {
	position: absolute; left: 1rem; top: -60px;
	background: var( --slv-indigo ); color: var( --slv-on-dark );
	padding: 0.75rem 1.25rem; z-index: 1000; transition: top 160ms ease;
}
.skip-link:focus { top: 1rem; }

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

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

.container { max-width: 1260px; margin-inline: auto; padding-inline: var( --slv-sp-3 ); }

/* ------------------------------------------------------------------ *
 * 2. The ruled ground
 *
 * Every section sits on graph paper at the draft pitch. Two overlaid
 * repeating-linear-gradients, so it costs nothing and scales with the
 * --slv-grid token rather than being a fixed image.
 * ------------------------------------------------------------------ */
.sheet {
	background-image:
		repeating-linear-gradient( to right, var( --slv-rule ) 0 1px, transparent 1px var( --slv-grid ) ),
		repeating-linear-gradient( to bottom, var( --slv-rule ) 0 1px, transparent 1px var( --slv-grid ) );
	background-size: var( --slv-grid ) var( --slv-grid );
}
/* Fade the ruling out behind long-form text — a grid under a paragraph is
   noise, but the same grid beside a swatch is a specification. */
.sheet--faint { background-image:
		repeating-linear-gradient( to right, rgb( var( --slv-ink-rgb ) / 6% ) 0 1px, transparent 1px var( --slv-grid ) ),
		repeating-linear-gradient( to bottom, rgb( var( --slv-ink-rgb ) / 6% ) 0 1px, transparent 1px var( --slv-grid ) );
}

/* ------------------------------------------------------------------ *
 * 3. Typography
 * ------------------------------------------------------------------ */
h1, h2, h3, h4 { font-family: var( --slv-ff-display ); font-weight: 400; line-height: 1.08; margin: 0; letter-spacing: -0.012em; }
h1 { font-size: var( --slv-t-display ); }
h2 { font-size: var( --slv-t-2xl ); }
h3 { font-size: var( --slv-t-xl ); }
h4 { font-size: var( --slv-t-l ); }
p { margin: 0 0 1em; }
.prose { max-width: var( --slv-measure ); }
.prose p { color: var( --slv-ink-soft ); }
.prose a { color: var( --slv-madder ); text-decoration: underline; text-underline-offset: 3px; }

/* The eyebrow is set in the mono face and letterspaced like a spec line,
   because on this site small caps text IS specification, not decoration. */
.eyebrow {
	display: inline-block;
	font-family: var( --slv-ff-mono ); font-size: var( --slv-t-xs ); font-weight: 500;
	letter-spacing: 0.14em; text-transform: uppercase; color: var( --slv-madder );
	margin-bottom: var( --slv-sp-2 );
}

.lede { font-size: var( --slv-t-l ); color: var( --slv-ink-soft ); max-width: 46ch; }
.muted { color: var( --slv-ink-faint ); }

/* Spec line: label + value in mono, the way a fabric card is actually
   written up in a swatch book. */
.spec { display: flex; flex-wrap: wrap; gap: 0.35em 1.2em; font-family: var( --slv-ff-mono ); font-size: var( --slv-t-xs ); }
.spec > div { display: flex; gap: 0.5em; }
.spec dt, .spec .k { color: var( --slv-ink-faint ); text-transform: uppercase; letter-spacing: 0.06em; }
.spec dd, .spec .v { margin: 0; color: var( --slv-ink ); }

/* ------------------------------------------------------------------ *
 * 4. Buttons
 * ------------------------------------------------------------------ */
.btn {
	display: inline-flex; align-items: center; justify-content: center; gap: 0.5em;
	font-family: var( --slv-ff-mono ); font-size: var( --slv-t-xs ); letter-spacing: 0.08em;
	text-transform: uppercase; text-decoration: none; white-space: nowrap;
	padding: 1em 1.6em; border-radius: var( --slv-radius ); border: 1px solid transparent;
	cursor: pointer; transition: transform 160ms cubic-bezier( .2,.8,.3,1 ), background 160ms, border-color 160ms, color 160ms;
}
.btn:hover { transform: translateY( -2px ); }
.btn:active { transform: translateY( 0 ); }
.btn--ink { background: var( --slv-indigo ); color: var( --slv-on-dark ); }
.btn--ink:hover { background: #17253c; }
.btn--madder { background: var( --slv-madder ); color: #fff; }
.btn--ghost { background: transparent; border-color: var( --slv-rule ); color: var( --slv-ink ); }
.btn--ghost:hover { border-color: var( --slv-ink ); }
.btn[disabled] { opacity: 0.55; cursor: default; transform: none; }

/* ------------------------------------------------------------------ *
 * 5. Header / nav
 * ------------------------------------------------------------------ */
.site-header {
	position: sticky; top: 0; z-index: 60;
	display: flex; align-items: center; justify-content: space-between;
	padding-block: var( --slv-sp-2 ); padding-inline: var( --slv-sp-3 );
	background: rgb( var( --slv-paper-rgb ) / 0.9 );
	-webkit-backdrop-filter: blur( 10px ); backdrop-filter: blur( 10px );
	border-bottom: 1px solid var( --slv-rule );
}
.brand { display: flex; align-items: center; gap: 0.65em; text-decoration: none; min-inline-size: 0; }
.brand-mark { inline-size: 30px; block-size: 30px; flex: none; }
.brand-name {
	font-family: var( --slv-ff-display ); font-size: 1.35rem; letter-spacing: 0.01em;
	/* A long site title must never wrap beside the hamburger — it overlapped
	   in a previous theme. One line, truncated, whatever the owner types. */
	white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
@media ( max-width: 480px ) { .brand-name { font-size: 1.05rem; max-inline-size: 46vw; } }

.nav { display: flex; align-items: center; gap: var( --slv-sp-4 ); }
.nav ul, .nav .nav-list { display: flex; align-items: center; gap: var( --slv-sp-3 ); list-style: none; margin: 0; padding: 0; }
.nav a { text-decoration: none; font-family: var( --slv-ff-mono ); font-size: var( --slv-t-xs ); text-transform: uppercase; letter-spacing: 0.08em; color: var( --slv-ink-soft ); }
.nav a:hover, .nav a[aria-current="page"] { color: var( --slv-madder ); }

.menu-toggle { display: none; background: none; border: 1px solid var( --slv-rule ); border-radius: var( --slv-radius ); padding: 0.5em 0.7em; }
.menu-toggle span, .menu-toggle::before, .menu-toggle::after { content: ''; display: block; inline-size: 20px; block-size: 1px; background: currentColor; margin: 5px 0; }

@media ( max-width: 900px ) {
	.menu-toggle { display: block; }
	/* height, not `bottom: 0`. .site-header has backdrop-filter, which per
	   spec establishes a containing block for fixed-position descendants
	   exactly as `filter` does — so `bottom: 0` would resolve against the
	   header's own ~70px box and collapse this panel into a sliver with the
	   page showing through. Viewport units are immune. This exact bug shipped
	   once already; do not "simplify" it back. */
	.nav {
		position: fixed; inset-inline: 0; top: 62px;
		height: calc( 100vh - 62px ); height: calc( 100dvh - 62px );
		background: var( --slv-paper ); flex-direction: column; align-items: flex-start;
		padding: var( --slv-sp-4 ); transform: translateX( -100% );
		transition: transform 260ms ease; overflow-y: auto;
	}
	.nav.is-open { transform: translateX( 0 ); }
	.nav ul, .nav .nav-list { flex-direction: column; align-items: flex-start; gap: var( --slv-sp-3 ); width: 100%; }
	.nav a { font-size: var( --slv-t-l ); font-family: var( --slv-ff-display ); text-transform: none; letter-spacing: 0; }
	html, body { overflow-x: hidden; }
}

/* ------------------------------------------------------------------ *
 * 6. Sections + the threading strip
 * ------------------------------------------------------------------ */
.section { padding-block: var( --slv-section-y ); position: relative; }
.section--alt { background: var( --slv-paper-alt ); }
.section--tight { padding-block: var( --slv-sp-6 ); }
.section-head { max-width: 62ch; margin-bottom: var( --slv-sp-5 ); }
.section-head--split { display: flex; align-items: flex-end; justify-content: space-between; gap: var( --slv-sp-4 ); flex-wrap: wrap; max-width: none; }

/* A section ornament that is a real threading block: four shafts, one mark
   per warp end, running 0-1-2-3-2-1 — a point twill, the same draft as the
   brand mark. Written as an inline SVG data URI rather than a gradient
   because the marks have to sit on discrete cells to read as notation; a
   repeating-linear-gradient can only make a dashed rule, which reads as a
   stray line rather than a draft. No HTTP request either way. */
.strip {
	block-size: 36px;
	inline-size: clamp( 108px, 16vw, 216px );
	background-image: url( "data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 54 36'%3E%3Cg fill='%231d2a3d'%3E%3Crect x='1' y='1' width='7' height='7'/%3E%3Crect x='10' y='10' width='7' height='7'/%3E%3Crect x='19' y='19' width='7' height='7'/%3E%3Crect x='28' y='28' width='7' height='7'/%3E%3Crect x='37' y='19' width='7' height='7'/%3E%3Crect x='46' y='10' width='7' height='7'/%3E%3C/g%3E%3C/svg%3E" );
	background-size: 54px 36px;
	background-repeat: repeat-x;
	opacity: 0.42;
	margin-bottom: var( --slv-sp-3 );
}
.cta-band .strip { filter: invert( 1 ); opacity: 0.5; }

/* ------------------------------------------------------------------ *
 * 7. Hero — the hanging cloth
 * ------------------------------------------------------------------ */
.hero { position: relative; overflow: hidden; padding-block: var( --slv-sp-7 ) var( --slv-sp-6 ); }
.hero-grid { display: grid; grid-template-columns: 1.05fr 0.95fr; gap: var( --slv-sp-6 ); align-items: center; }
@media ( max-width: 960px ) { .hero-grid { grid-template-columns: 1fr; gap: var( --slv-sp-5 ); } }
.hero h1 { max-width: 14ch; }
.hero .lede { margin-block: var( --slv-sp-3 ) var( --slv-sp-4 ); }
.hero-cta { display: flex; gap: var( --slv-sp-2 ); flex-wrap: wrap; }
.hero-note { margin-top: var( --slv-sp-5 ); padding-top: var( --slv-sp-3 ); border-top: 1px solid var( --slv-rule ); font-family: var( --slv-ff-mono ); font-size: var( --slv-t-xs ); color: var( --slv-ink-faint ); line-height: 1.7; }

/* Fixed aspect so there is no CLS whether or not the cloth mounts. */
.cloth-stage { position: relative; aspect-ratio: 4 / 5; inline-size: 100%; max-inline-size: 560px; margin-inline: auto; }
@media ( min-width: 961px ) { .cloth-stage { margin-inline: 0 auto; } }
.cloth-stage canvas { inline-size: 100%; block-size: 100%; }

/* The fallback, and what sits behind the canvas while Three.js loads: a real
   swatch drawn by draft.js on a 2D canvas, or failing that a flat weave-ish
   gradient. Never an empty box. */
.cloth-fallback { position: absolute; inset: 0; background: var( --slv-paper-alt ); border: 1px solid var( --slv-rule ); }
.cloth-stage.is-ready .cloth-fallback { opacity: 0; transition: opacity 500ms ease; }
/* The hint sits ON the cloth, and the cloth is whatever colour the draft
   says — it may be near-black indigo or near-white oat. So the label carries
   its own paper chip rather than relying on a text colour that can only be
   legible against some warps. */
.cloth-hint {
	position: absolute; inset-inline: 0; bottom: var( --slv-sp-2 );
	display: flex; justify-content: center;
	opacity: 0; transition: opacity 400ms; pointer-events: none;
}
.cloth-hint > span {
	font-family: var( --slv-ff-mono ); font-size: var( --slv-t-xs ); letter-spacing: 0.1em;
	text-transform: uppercase; color: var( --slv-ink );
	background: rgb( var( --slv-paper-rgb ) / 0.9 );
	border: 1px solid var( --slv-rule );
	padding: 0.45em 0.9em;
	-webkit-backdrop-filter: blur( 4px ); backdrop-filter: blur( 4px );
}
.cloth-stage.is-ready .cloth-hint { opacity: 1; }
.cloth-stage.is-touched .cloth-hint { opacity: 0; }

/* ------------------------------------------------------------------ *
 * 8. Fabric cards — notation beside cloth
 * ------------------------------------------------------------------ */
.fabric-grid { display: grid; grid-template-columns: repeat( auto-fit, minmax( 280px, 1fr ) ); gap: var( --slv-sp-4 ); }
.fabric-card { background: var( --slv-card ); border: 1px solid var( --slv-rule ); display: flex; flex-direction: column; }
.fabric-card a { text-decoration: none; }
.fabric-swatch { position: relative; aspect-ratio: 5 / 4; overflow: hidden; background: var( --slv-paper-alt ); }
.fabric-swatch canvas, .fabric-swatch img { inline-size: 100%; block-size: 100%; object-fit: cover; }
/* The notation chip sits on the swatch corner — the tie-up block's position
   in a real draft. */
.fabric-note {
	position: absolute; top: 0; right: 0; background: rgb( var( --slv-paper-rgb ) / 0.94 );
	border-left: 1px solid var( --slv-rule ); border-bottom: 1px solid var( --slv-rule );
	padding: 6px;
}
.fabric-note canvas { display: block; }
.fabric-body { padding: var( --slv-sp-3 ); display: flex; flex-direction: column; gap: var( --slv-sp-1 ); }
.fabric-body h3 { font-size: var( --slv-t-l ); }
.fabric-structure { font-family: var( --slv-ff-mono ); font-size: var( --slv-t-xs ); color: var( --slv-madder ); text-transform: uppercase; letter-spacing: 0.08em; }

/* ------------------------------------------------------------------ *
 * 9. The draft plate (single fabric page)
 * ------------------------------------------------------------------ */
.draft-plate { background: var( --slv-card ); border: 1px solid var( --slv-rule ); padding: var( --slv-sp-4 ); }
.draft-plate canvas { margin-inline: auto; }

/* The front-page plate sets the notation beside its key rather than above it.
   Stacked, a 500px square of notation in a 1260px container left most of the
   plate empty, which read as an unfinished section rather than a plate. */
.draft-plate--keyed { display: grid; grid-template-columns: auto minmax( 260px, 1fr ); gap: var( --slv-sp-6 ); align-items: center; }
.draft-plate--keyed .draft-legend { grid-template-columns: 1fr; margin-top: 0; padding-top: 0; border-top: 0; gap: var( --slv-sp-3 ); }
@media ( max-width: 900px ) {
	.draft-plate--keyed { grid-template-columns: 1fr; gap: var( --slv-sp-4 ); }
	.draft-plate--keyed .draft-legend { grid-template-columns: repeat( auto-fit, minmax( 150px, 1fr ) ); padding-top: var( --slv-sp-3 ); border-top: 1px solid var( --slv-rule ); }
	.draft-plate--keyed > div:first-child { overflow-x: auto; }
}

.draft-legend { display: grid; grid-template-columns: repeat( auto-fit, minmax( 150px, 1fr ) ); gap: var( --slv-sp-3 ); margin-top: var( --slv-sp-4 ); padding-top: var( --slv-sp-3 ); border-top: 1px solid var( --slv-rule ); }
.draft-legend h4 { font-family: var( --slv-ff-mono ); font-size: var( --slv-t-xs ); text-transform: uppercase; letter-spacing: 0.08em; color: var( --slv-madder ); margin-bottom: 0.4em; }
.draft-legend p { font-size: var( --slv-t-s ); color: var( --slv-ink-soft ); margin: 0; }

/* Yarn colour order, shown as the actual sequence of ends. */
.colour-order { display: flex; flex-wrap: wrap; gap: 2px; margin-top: 0.5em; }
.colour-order i { inline-size: 12px; block-size: 20px; display: block; }

/* ------------------------------------------------------------------ *
 * 9b. The shed — the one photographic section on the front page.
 *
 * Two frames offset against each other on the draft grid rather than a
 * single flat image, so the section reads as a mill's own record shots
 * pinned to a board rather than as a stock hero.
 * ------------------------------------------------------------------ */
.shed-media { position: relative; padding-bottom: 3.5rem; padding-right: 3.5rem; }
.shed-media > img {
	inline-size: 100%; block-size: auto; aspect-ratio: 3 / 2; object-fit: cover;
	border: 1px solid var( --slv-rule );
}
/* Must out-specify `.shed-media > img` above (0,1,1), not merely follow it —
   as a bare class (0,1,0) the inset lost the cascade, inherited width:100%
   and covered the very photograph it is supposed to sit on. */
.shed-media > img.shed-media__inset {
	position: absolute; right: 0; bottom: 0;
	inline-size: 46%; block-size: auto; aspect-ratio: 4 / 3; object-fit: cover;
	border: 6px solid var( --slv-paper );
	outline: 1px solid var( --slv-rule );
}
@media ( max-width: 860px ) {
	.shed-media { padding-bottom: 2.5rem; padding-right: 2.5rem; }
	.shed-media > img.shed-media__inset { inline-size: 52%; }
}

/* ------------------------------------------------------------------ *
 * 10. Makers
 * ------------------------------------------------------------------ */
.maker-grid { display: grid; grid-template-columns: repeat( auto-fit, minmax( 210px, 1fr ) ); gap: var( --slv-sp-4 ); }
.maker-card { background: var( --slv-card ); border: 1px solid var( --slv-rule ); }
.maker-card .media { aspect-ratio: 3 / 4; overflow: hidden; background: var( --slv-paper-alt ); }
.maker-card .media img { inline-size: 100%; block-size: 100%; object-fit: cover; }
.maker-card .body { padding: var( --slv-sp-3 ); }
.maker-card .role { font-family: var( --slv-ff-mono ); font-size: var( --slv-t-xs ); color: var( --slv-madder ); text-transform: uppercase; letter-spacing: 0.06em; }
.maker-card .years { font-size: var( --slv-t-xs ); color: var( --slv-ink-faint ); }

/* ------------------------------------------------------------------ *
 * 11. Stats / testimonials
 * ------------------------------------------------------------------ */
.stat-row { display: grid; grid-template-columns: repeat( auto-fit, minmax( 160px, 1fr ) ); gap: var( --slv-sp-4 ); }
.stat .n { font-family: var( --slv-ff-display ); font-size: clamp( 2.4rem, 3vw + 1rem, 3.4rem ); color: var( --slv-indigo ); line-height: 1; }
.stat .label { color: var( --slv-ink-soft ); font-size: var( --slv-t-s ); margin-top: 0.35em; }

.quote-grid { display: grid; grid-template-columns: repeat( auto-fit, minmax( 280px, 1fr ) ); gap: var( --slv-sp-4 ); }
.quote { padding: var( --slv-sp-4 ); background: var( --slv-card ); border-top: 2px solid var( --slv-madder ); }
.quote p { font-family: var( --slv-ff-display ); font-size: var( --slv-t-l ); line-height: 1.4; }
.quote .who { font-family: var( --slv-ff-mono ); font-size: var( --slv-t-xs ); color: var( --slv-ink-faint ); }

/* ------------------------------------------------------------------ *
 * 12. CTA band
 * ------------------------------------------------------------------ */
.cta-band { background: var( --slv-indigo ); color: var( --slv-on-dark ); padding-block: var( --slv-sp-7 ); }

/* Photographic CTA. The overlay is deliberately heavy: the band's job is to
   carry a heading and a button at full contrast, and the photograph is
   atmosphere behind them, not the subject. The measured contrast of the
   heading against the darkest sampled pixel of the composite stays above
   7:1 at this opacity — lighten it and that stops being true. */
.cta-band--photo {
	position: relative;
	background-size: cover;
	background-position: center;
	isolation: isolate;
}
.cta-band--photo::before {
	content: '';
	position: absolute;
	inset: 0;
	background: linear-gradient( 100deg, rgb( 32 48 74 / 96% ) 0%, rgb( 32 48 74 / 88% ) 55%, rgb( 23 37 60 / 82% ) 100% );
	z-index: -1;
}
.cta-band h2 { max-width: 22ch; }
.cta-band .lede { color: rgb( 244 239 228 / 0.78 ); }
.cta-band .eyebrow { color: var( --slv-brass ); }
.cta-band .btn--ghost { border-color: rgb( 244 239 228 / 0.4 ); color: var( --slv-on-dark ); }
.cta-band .btn--ghost:hover { border-color: var( --slv-on-dark ); }

/* ------------------------------------------------------------------ *
 * 13. Forms
 * ------------------------------------------------------------------ */
.field { display: flex; flex-direction: column; gap: 0.4em; margin-bottom: var( --slv-sp-3 ); }
.field label { font-family: var( --slv-ff-mono ); font-size: var( --slv-t-xs ); text-transform: uppercase; letter-spacing: 0.06em; color: var( --slv-ink-soft ); }
.field input, .field select, .field textarea {
	font: inherit; background: var( --slv-card ); color: var( --slv-ink );
	border: 1px solid var( --slv-rule ); border-radius: var( --slv-radius ); padding: 0.8em 0.9em;
}
.field input:focus, .field textarea:focus, .field select:focus { border-color: var( --slv-indigo ); outline: none; }
.field--hp { position: absolute; left: -9999px; width: 1px; height: 1px; overflow: hidden; }
.form-row { display: grid; grid-template-columns: 1fr 1fr; gap: var( --slv-sp-3 ); }
@media ( max-width: 640px ) { .form-row { grid-template-columns: 1fr; } }
.form-note { font-size: var( --slv-t-s ); margin-top: var( --slv-sp-2 ); }
.form-note.is-ok { color: #2f6b46; }
.form-note.is-error { color: #a8321a; }

/* ------------------------------------------------------------------ *
 * 14. Two-column split (contact, maker single)
 * ------------------------------------------------------------------ */
.two-col { display: grid; grid-template-columns: 1fr 1fr; gap: var( --slv-sp-6 ); align-items: start; }
@media ( max-width: 860px ) { .two-col { grid-template-columns: 1fr; gap: var( --slv-sp-4 ); } }

/* ------------------------------------------------------------------ *
 * 15. Journal
 * ------------------------------------------------------------------ */
.post-grid { display: grid; grid-template-columns: repeat( auto-fit, minmax( 260px, 1fr ) ); gap: var( --slv-sp-4 ); }
.post-card { background: var( --slv-card ); border: 1px solid var( --slv-rule ); padding: var( --slv-sp-3 ); }
.post-card h3 { font-size: var( --slv-t-l ); margin-bottom: 0.3em; }
.post-card a { text-decoration: none; }
.post-meta { display: flex; gap: 0.9em; flex-wrap: wrap; font-family: var( --slv-ff-mono ); font-size: var( --slv-t-xs ); color: var( --slv-ink-faint ); }

/* ------------------------------------------------------------------ *
 * 16. Footer
 * ------------------------------------------------------------------ */
.site-foot { border-top: 1px solid var( --slv-rule ); padding-block: var( --slv-sp-6 ) var( --slv-sp-4 ); background: var( --slv-paper-alt ); }
.foot-grid { display: grid; grid-template-columns: 2fr repeat( 3, 1fr ); gap: var( --slv-sp-4 ); }
@media ( max-width: 780px ) { .foot-grid { grid-template-columns: 1fr 1fr; } }
.foot-col h4 { font-family: var( --slv-ff-mono ); font-size: var( --slv-t-xs ); text-transform: uppercase; letter-spacing: 0.08em; color: var( --slv-ink-faint ); margin-bottom: var( --slv-sp-2 ); }
.foot-col ul { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 0.5em; }
.foot-col a { text-decoration: none; color: var( --slv-ink-soft ); }
.foot-col a:hover { color: var( --slv-madder ); }
.foot-bottom { margin-top: var( --slv-sp-5 ); padding-top: var( --slv-sp-3 ); border-top: 1px solid var( --slv-rule ); display: flex; justify-content: space-between; flex-wrap: wrap; gap: var( --slv-sp-2 ); color: var( --slv-ink-faint ); font-family: var( --slv-ff-mono ); font-size: var( --slv-t-xs ); }

/* ------------------------------------------------------------------ *
 * 17. Breadcrumbs, pagination, comments
 * ------------------------------------------------------------------ */
.crumbs { font-family: var( --slv-ff-mono ); font-size: var( --slv-t-xs ); color: var( --slv-ink-faint ); margin-bottom: var( --slv-sp-3 ); }
.crumbs ol { list-style: none; display: flex; gap: 0.5em; margin: 0; padding: 0; flex-wrap: wrap; }
.crumbs li + li::before { content: '/'; margin-right: 0.5em; }
.crumbs a { color: var( --slv-ink-soft ); text-decoration: none; }
.crumbs a:hover { color: var( --slv-madder ); }

.pagination { display: flex; gap: 0.5em; margin-top: var( --slv-sp-5 ); }
.pagination .page-numbers { display: inline-flex; align-items: center; justify-content: center; min-inline-size: 2.4em; min-block-size: 2.4em; border: 1px solid var( --slv-rule ); text-decoration: none; font-family: var( --slv-ff-mono ); font-size: var( --slv-t-xs ); }
.pagination .page-numbers.current { background: var( --slv-indigo ); color: var( --slv-on-dark ); border-color: var( --slv-indigo ); }
.pagination a.page-numbers:hover { border-color: var( --slv-madder ); color: var( --slv-madder ); }

.comments { margin-top: var( --slv-sp-6 ); }
.comment-list { list-style: none; margin: 0; padding: 0; }
.comment-body { padding-block: var( --slv-sp-3 ); border-bottom: 1px solid var( --slv-rule ); }
.comment-meta { font-family: var( --slv-ff-mono ); font-size: var( --slv-t-xs ); color: var( --slv-ink-faint ); }
.comment-respond { margin-top: var( --slv-sp-4 ); }
.reply a { font-family: var( --slv-ff-mono ); font-size: var( --slv-t-xs ); color: var( --slv-madder ); text-decoration: none; }

/* ------------------------------------------------------------------ *
 * 18. Reveal-on-scroll
 * ------------------------------------------------------------------ */
[data-reveal] { opacity: 0; transition: opacity 640ms ease, transform 640ms cubic-bezier( .2,.8,.2,1 ); }
[data-reveal="up"] { transform: translate3d( 0, 1.4rem, 0 ); }
[data-reveal="left"] { transform: translate3d( -1.3rem, 0, 0 ); }
[data-reveal="right"] { transform: translate3d( 1.3rem, 0, 0 ); }
[data-reveal].is-in { opacity: 1; transform: none; }
@media ( prefers-reduced-motion: reduce ) {
	[data-reveal] { opacity: 1; transform: none; transition: none; }
}
/* If JS never runs, slv_no_js() never strips .no-js, so nothing would ever
   add .is-in and every revealed element would stay invisible forever. */
.no-js [data-reveal] { opacity: 1 !important; transform: none !important; }

/* ------------------------------------------------------------------ *
 * 19. 404 / search
 * ------------------------------------------------------------------ */
.error-404 { text-align: center; padding-block: var( --slv-sp-8 ); }
.search-form { display: flex; gap: 0.5em; max-inline-size: 480px; }
.search-form input[type="search"] { flex: 1; }

@media ( max-width: 640px ) {
	.section { padding-block: var( --slv-sp-5 ); }
	.hero { padding-block: var( --slv-sp-5 ) var( --slv-sp-4 ); }
}
