/*
 * Lapland Reveal v5 — design system
 *
 * The idea: it is the night before, the aurora is out, and the light is coming from
 * lanterns rather than the sky. Midnight-blue ground, gilded rules and filigree,
 * candle-gold type, postbox red for actions, snow along the top edge.
 *
 * v5 is v4's structure with v4's mistake corrected. v4 built the ground out of a
 * spruce black-green, which meant the aurora had nothing to glow against and the red
 * and gold had nothing to be warm against — every colour was competing on the same
 * temperature. Here the entire ground is cold, and gold, candle and postbox red are
 * the only warm things on the page. They therefore read as light rather than as
 * decoration, and the aurora is free to be the one saturated thing in the frame.
 *
 * The token names are v4's throughout. Sections 8–13 restyle a thousand declarations
 * of inherited page markup against those names; re-pointing the values is a palette
 * change, renaming them would have been a rewrite.
 *
 * This is the ornate, dark, gold-on-blue theme. v3 is the light postal one and v2 the
 * earlier cinematic one; they share no visual vocabulary on purpose, and none of
 * them loads a line of another's code.
 *
 * Ornament policy: every illustrated ornament — lantern, corner filigree, snow edge,
 * wax seal, frame — is a background image behind a custom property with a drawn CSS
 * fallback underneath it. A missing art file degrades to the fallback rather than to a
 * broken box, so the theme is previewable before any of the art in
 * assets/images/ornaments/PROMPTS.md has been generated.
 *
 * The twelve published pages still carry markup written for the earlier themes
 * (.section--night, .media-frame, .ticket, .article-hero and so on). Section 12
 * restyles every one of those into this language, so nothing has to be re-authored.
 *
 * Contents
 *   1  Tokens and fonts
 *   2  Reset and base
 *   3  Typography
 *   4  Layout: wrap, section, paper
 *   5  Postal furniture: stripes, postmarks, stamps, seals
 *   6  Buttons and forms
 *   7  Masthead and navigation
 *   8  The letter hero
 *   9  Guide modules
 *  10  Product ladder, demo, FAQ, related
 *  11  Postbox call to action and footer
 *  12  Inherited page markup
 *  13  WooCommerce
 *  14  Accessibility and motion
 *  15  Ornament layer — gilding, lanterns, snow, aurora
 *  16  Hero plates — one rendered night photograph per page
 */

/* -------------------------------------------------------- 1 Tokens and fonts */

@font-face {
	font-family: "Fraunces";
	src: url("../fonts/fraunces.woff2") format("woff2-variations");
	font-weight: 300 900;
	font-style: normal;
	font-display: swap;
}

@font-face {
	font-family: "Nunito";
	src: url("../fonts/nunito.woff2") format("woff2-variations");
	font-weight: 300 900;
	font-style: normal;
	font-display: swap;
}

@font-face {
	font-family: "Courier Prime";
	src: url("../fonts/courier-prime-400.woff2") format("woff2");
	font-weight: 400;
	font-style: normal;
	font-display: swap;
}

@font-face {
	font-family: "Courier Prime";
	src: url("../fonts/courier-prime-700.woff2") format("woff2");
	font-weight: 700;
	font-style: normal;
	font-display: swap;
}

:root {
	/*
	 * Ground: midnight blue, and cold all the way down. v4 used a spruce black-green
	 * here, which was the mistake the whole of v5 exists to correct — you cannot make
	 * an aurora glow green against a green ground, and you cannot make a red ticket
	 * read as *lit* when the surface behind it is already warm-ish. Everything below
	 * the aurora is now blue, so the two warm things on the page (gold, postbox red)
	 * are the only warm things, and therefore the focus.
	 *
	 * The names are v4's on purpose. Sections 8–13 restyle a thousand declarations of
	 * inherited page markup against these names; re-pointing the values is a palette
	 * change, renaming them would be a rewrite.
	 */
	--night: #0a1430;
	--night-deep: #050b1c;
	--pine: #12204a;
	--pine-lift: #182a5c;
	--panel: #16244e;
	--panel-lift: #1d2e60;

	/* Gilding. Three stops, because a single gold reads flat on a dark ground. */
	--gold: #d8ab5c;
	--gold-bright: #f2d69a;
	--gold-deep: #8a6522;
	--candle: #ffcf85;

	--postbox: #a5121b;
	--berry: #7d0d14;
	--ember: #c8323c;

	/*
	 * Snow, where v4 had parchment and cream. Same four roles, but cool — snow in
	 * shade is blue-lilac, and only the lit crest is white. A warm cream on this
	 * ground reads as dirty beige, which is what forced the change.
	 */
	--parchment: #dde5f7;
	--cream: #eaf0ff;
	--ink: #eef3ff;
	--ink-soft: #b9c6e6;
	--snow: #ffffff;

	/*
	 * Aurora. Emissive only — these three may appear in a gradient, a glow, a blur,
	 * or a hairline, and nowhere else. Never a fill, never body text, never a button.
	 * That single restriction is the difference between a sky and a Christmas jumper.
	 */
	--aurora-teal: #2ee6c0;
	--aurora-green: #34d17a;
	--aurora-violet: #7b53d6;

	/*
	 * The hero scrim: what makes a headline legible over a photograph. Ramped from the
	 * left because every hero on the site sets its copy left, plus a fade at the foot
	 * so the plate dissolves into the page rather than ending on a line.
	 */
	--hero-scrim:
		linear-gradient(100deg, rgba(5, 11, 28, 0.92) 0%, rgba(5, 11, 28, 0.72) 38%, rgba(5, 11, 28, 0.18) 72%, transparent 100%),
		linear-gradient(0deg, var(--night) 0%, transparent 42%);

	/*
	 * Aliases for the vocabulary the inherited rules were written against. The light
	 * theme's paper names still appear all through sections 8–13; rather than rewrite
	 * a thousand declarations, each name is re-pointed at its night equivalent, so a
	 * rule that asked for "parchment" gets the surface that plays that role here.
	 */
	--paper: var(--panel);
	--parchment-deep: var(--panel-lift);
	--kraft: var(--pine);
	--kraft-line: var(--rule);
	--spruce: var(--pine);

	--surface: var(--night);
	--text: var(--ink);
	--text-muted: var(--ink-soft);
	--rule: rgba(216, 171, 92, 0.34);
	--rule-soft: rgba(216, 171, 92, 0.18);

	--font-display: "Fraunces", "Iowan Old Style", Georgia, serif;
	--font-body: "Nunito", -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
	--font-postal: "Courier Prime", ui-monospace, "Courier New", monospace;

	--step--1: clamp(0.84rem, 0.81rem + 0.14vw, 0.92rem);
	--step-0: clamp(1rem, 0.96rem + 0.2vw, 1.09rem);
	--step-1: clamp(1.12rem, 1.06rem + 0.3vw, 1.3rem);
	--step-2: clamp(1.4rem, 1.26rem + 0.7vw, 1.85rem);
	--step-3: clamp(1.75rem, 1.5rem + 1.25vw, 2.7rem);
	--step-4: clamp(2.1rem, 1.55rem + 2.6vw, 4rem);
	--step-article: clamp(1.04rem, 1rem + 0.22vw, 1.17rem);

	--space-2xs: 0.5rem;
	--space-xs: 0.75rem;
	--space-s: 1.15rem;
	--space-m: 1.75rem;
	--space-l: 2.6rem;
	--space-xl: clamp(2.75rem, 5.5vw, 4.5rem);
	--space-2xl: clamp(3.5rem, 8vw, 6rem);

	--measure: 58ch;
	--wide: 1160px;
	--gutter: clamp(1.15rem, 5vw, 2.75rem);

	/*
	 * Corner softening — ONE KNOB.
	 *
	 * Every non-circular radius in the theme derives from --radius-base, so the whole
	 * site's corner treatment moves together from this single line. v4 was effectively
	 * square at 3px; v5 softens to 10px, which reads warmer and less clinical against
	 * the ornate gilding without going anywhere near a rounded-app look.
	 *
	 * TO REVERT to v4's near-square corners: set --radius-base to 3px. That is the
	 * whole reversal — nothing else needs touching.
	 *
	 * Deliberately NOT derived from this: `border-radius: 50%` (seals, play buttons,
	 * bullets — those are circles, not soft rectangles) and `999px` (the pill on the
	 * contents strip). Both should stay as they are at any base value.
	 */
	/*
	 * How far the CSS sky reaches down the document. It exists to light the masthead —
	 * the crown, the lanterns and the wordmark would be flat on plain navy. It must
	 * fade out before the hero ends, or it reappears underneath as a second aurora
	 * competing with the plate's. Masthead runs ~375px on desktop; this clears it and
	 * is gone well above a hero's foot.
	 */
	--sky-height: 620px;

	--radius-base: 10px;

	--radius-sm: calc(var(--radius-base) * 0.5);
	--radius: var(--radius-base);
	--radius-lg: calc(var(--radius-base) * 1.6);

	/*
	 * Shadows on a dark ground do almost no work, so depth is carried by a gilded
	 * hairline and a warm glow instead. Both are here so a card can use either.
	 */
	--shadow-paper: 0 1px 2px rgba(0, 0, 0, 0.5), 0 14px 30px -18px rgba(0, 0, 0, 0.8);
	--shadow-lift: 0 2px 6px rgba(0, 0, 0, 0.55), 0 30px 60px -28px rgba(0, 0, 0, 0.95);
	--glow-gold: 0 0 0 1px rgba(216, 171, 92, 0.28), 0 0 34px -8px rgba(255, 207, 133, 0.35);
	--glow-candle: 0 0 60px -12px rgba(255, 207, 133, 0.45);

	--bar-height: 3.6rem;
	/*
	 * The height of the contents strip once it collapses to a row of pills and sticks
	 * under the bar on small screens. Only used to keep anchor targets clear of it.
	 */
	--toc-height: 3.2rem;
	--ease: cubic-bezier(0.2, 0.7, 0.3, 1);

	/*
	 * Fibre. On the light theme this was paper grain; here it is the faint film of
	 * snow-static over a night photograph. It must stay near-invisible — anything
	 * heavier turns the spruce grey.
	 */
	--fibre: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='160' height='160'%3E%3Cfilter id='f'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.8' numOctaves='4'/%3E%3C/filter%3E%3Crect width='160' height='160' filter='url(%23f)' opacity='0.05'/%3E%3C/svg%3E");

	/*
	 * Aurora. Drawn in CSS so the theme has a sky before any art exists; the generated
	 * plate in section 15 layers over the top when it is present.
	 */
	--aurora:
		radial-gradient(64% 30% at 12% 2%, rgba(46, 230, 192, 0.30), transparent 66%),
		radial-gradient(52% 26% at 40% 0%, rgba(52, 209, 122, 0.22), transparent 64%),
		radial-gradient(58% 34% at 82% 4%, rgba(123, 83, 214, 0.24), transparent 66%),
		radial-gradient(120% 44% at 50% 0%, rgba(46, 230, 192, 0.10), transparent 60%),
		radial-gradient(90% 60% at 50% 100%, rgba(18, 32, 74, 0.9), transparent 70%);

	/*
	 * The star field. Two sizes at different densities so it does not read as a grid,
	 * fixed to the viewport with the sky. Pure white at low alpha — a warm star on a
	 * cold sky looks like dust on the lens.
	 */
	--stars:
		radial-gradient(1px 1px at 8% 12%, rgba(255, 255, 255, 0.9), transparent),
		radial-gradient(1px 1px at 23% 34%, rgba(255, 255, 255, 0.55), transparent),
		radial-gradient(1.5px 1.5px at 41% 8%, rgba(255, 255, 255, 0.8), transparent),
		radial-gradient(1px 1px at 57% 26%, rgba(255, 255, 255, 0.5), transparent),
		radial-gradient(1px 1px at 72% 16%, rgba(255, 255, 255, 0.75), transparent),
		radial-gradient(1.5px 1.5px at 88% 30%, rgba(255, 255, 255, 0.65), transparent),
		radial-gradient(1px 1px at 94% 6%, rgba(255, 255, 255, 0.5), transparent),
		radial-gradient(1px 1px at 33% 52%, rgba(255, 255, 255, 0.4), transparent),
		radial-gradient(1px 1px at 64% 46%, rgba(255, 255, 255, 0.35), transparent);

	/*
	 * Ornament art. Each is set to `none` here and switched on in section 15 only
	 * when the corresponding file has been generated — see the note there.
	 */
	--art-ornaments: url("../images/ornaments/");
}

/* --------------------------------------------------------- 2 Reset and base */

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

html {
	-webkit-text-size-adjust: 100%;
	scroll-behavior: smooth;
	scroll-padding-top: calc(var(--bar-height) + 1rem);
}

body {
	margin: 0;
	background-color: var(--surface);
	background-image: var(--fibre);
	background-size: 160px 160px;
	color: var(--text);
	font-family: var(--font-body);
	font-size: var(--step-0);
	line-height: 1.7;
	-webkit-font-smoothing: antialiased;
	overflow-x: hidden;
}

img,
picture,
video,
svg {
	max-width: 100%;
	height: auto;
	display: block;
}

button,
input,
select,
textarea {
	font: inherit;
	color: inherit;
}

a {
	color: var(--gold);
	text-underline-offset: 0.16em;
	text-decoration-thickness: 1px;
	transition: color 150ms var(--ease);
}

a:hover {
	color: var(--berry);
}

hr {
	border: 0;
	border-top: 1px solid var(--rule);
	margin: var(--space-l) 0;
}

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

/* ------------------------------------------------------------ 3 Typography */

h1,
h2,
h3,
h4 {
	font-family: var(--font-display);
	font-weight: 700;
	line-height: 1.1;
	color: var(--parchment);
	margin: 0 0 var(--space-s);
	text-wrap: balance;
	font-variation-settings: "SOFT" 20, "WONK" 1;
}

h1 { font-size: var(--step-4); }
h2 { font-size: var(--step-3); }
h3 { font-size: var(--step-2); line-height: 1.2; }
h4 { font-size: var(--step-1); }

p {
	margin: 0 0 var(--space-s);
	text-wrap: pretty;
}

p:last-child {
	margin-bottom: 0;
}

small,
.fine-print {
	font-size: var(--step--1);
	color: var(--text-muted);
}

/* Eyebrows are typed, not set — they read as postal annotations. */
.eyebrow {
	font-family: var(--font-postal);
	font-size: 0.76rem;
	font-weight: 700;
	letter-spacing: 0.18em;
	text-transform: uppercase;
	color: var(--gold);
	margin: 0 0 var(--space-xs);
	display: flex;
	align-items: center;
	gap: 0.6rem;
}

.eyebrow::after {
	content: "";
	flex: 1;
	height: 1px;
	background: repeating-linear-gradient(90deg, var(--rule) 0 4px, transparent 4px 8px);
}

.eyebrow--light {
	color: var(--candle);
}

.eyebrow--light::after {
	background: repeating-linear-gradient(90deg, rgba(255, 255, 255, 0.4) 0 4px, transparent 4px 8px);
}

.lede {
	font-size: var(--step-1);
	line-height: 1.55;
	color: var(--text-muted);
	max-width: 48ch;
}

.section__title {
	margin-bottom: var(--space-m);
}

.section__title--light {
	color: var(--parchment);
}

/* ------------------------------------------------- 4 Layout: wrap, section */

/* .section__inner is the container class the published pages already use. */
.wrap,
.section__inner {
	width: min(100% - (var(--gutter) * 2), var(--wide));
	margin-inline: auto;
}

.wrap--narrow,
.section__inner--narrow {
	width: min(100% - (var(--gutter) * 2), var(--measure));
}

.wrap + .wrap,
.section__inner + .section__inner {
	margin-top: var(--space-xl);
}

.section {
	padding: var(--space-2xl) 0;
	position: relative;
}

.section--kraft,
.guide-section--kraft {
	background-color: var(--kraft);
	background-image: var(--fibre);
	background-size: 160px 160px;
	border-block: 1px solid var(--kraft-line);
}

.section--pine {
	background-color: var(--spruce);
	background-image:
		radial-gradient(circle at 20% 0%, rgba(243, 201, 105, 0.14), transparent 55%),
		var(--fibre);
	background-size: auto, 160px 160px;
	color: var(--parchment);
}

.section--pine h2,
.section--pine h3,
.section--pine .section__title {
	color: var(--parchment);
}

.section--pine p {
	color: rgba(238, 243, 255, 0.82);
}

/* Paper: the base surface for every card in the theme. */
.paper {
	position: relative;
	background: var(--paper);
	border: 1px solid var(--rule-soft);
	border-radius: var(--radius);
	box-shadow: var(--shadow-paper);
	padding: clamp(1.3rem, 3vw, 1.9rem);
}

.card-grid {
	display: grid;
	gap: clamp(1.1rem, 2.4vw, 1.7rem);
	grid-template-columns: repeat(auto-fit, minmax(min(100%, 16.5rem), 1fr));
	margin-top: var(--space-l);
}

.card-grid--two {
	grid-template-columns: repeat(auto-fit, minmax(min(100%, 22rem), 1fr));
}

.button-row {
	display: flex;
	flex-wrap: wrap;
	gap: var(--space-xs) var(--space-s);
	align-items: center;
	margin-top: var(--space-m);
}

.table-scroll {
	overflow-x: auto;
	margin: var(--space-m) 0;
}

/* ------------------------------------------------------ 5 Postal furniture */

.airmail-stripe {
	height: 8px;
	background: repeating-linear-gradient(
		45deg,
		var(--postbox) 0 12px,
		var(--parchment) 12px 24px,
		var(--spruce) 24px 36px,
		var(--parchment) 36px 48px
	);
}

/* Circular postmark, rubber-stamped slightly off true. */
.postmark {
	display: grid;
	place-content: center;
	width: 6.5rem;
	height: 6.5rem;
	border: 2px solid var(--postbox);
	border-radius: 50%;
	color: var(--gold);
	font-family: var(--font-postal);
	font-size: 0.58rem;
	letter-spacing: 0.12em;
	text-transform: uppercase;
	text-align: center;
	line-height: 1.5;
	transform: rotate(-8deg);
	opacity: 0.75;
	box-shadow: inset 0 0 0 1px var(--postbox);
}

.postmark-chip {
	display: inline-flex;
	align-items: center;
	font-family: var(--font-postal);
	font-size: 0.62rem;
	font-weight: 700;
	letter-spacing: 0.14em;
	text-transform: uppercase;
	padding: 0.2rem 0.55rem;
	border: 1px solid currentColor;
	border-radius: var(--radius-sm);
	color: var(--gold);
}

.postmark-chip--posted {
	color: var(--candle);
}

/* Wax seal. */
.wax-seal {
	position: absolute;
	right: 1.1rem;
	bottom: 1.1rem;
	display: grid;
	place-content: center;
	width: 3rem;
	height: 3rem;
	border-radius: 50%;
	background: radial-gradient(circle at 35% 30%, #c8323c, var(--berry) 60%, #6d0f18);
	color: rgba(255, 255, 255, 0.85);
	font-family: var(--font-postal);
	font-size: 0.7rem;
	font-weight: 700;
	letter-spacing: 0.06em;
	box-shadow: inset 0 -2px 4px rgba(0, 0, 0, 0.35), 0 3px 6px rgba(0, 0, 0, 0.28);
	transform: rotate(-6deg);
}

/* A perforated stamp edge, cut with a repeating radial mask. */
.stamp-edge {
	--perf: 7px;
	padding: calc(var(--perf) * 1.4);
	background: var(--paper);
	filter: drop-shadow(0 8px 18px rgba(0, 0, 0, 0.18));
	-webkit-mask:
		radial-gradient(circle at 50% 0, transparent var(--perf), #000 calc(var(--perf) + 0.5px)) 50% 0 / calc(var(--perf) * 2.4) 100% repeat-x,
		radial-gradient(circle at 50% 100%, transparent var(--perf), #000 calc(var(--perf) + 0.5px)) 50% 100% / calc(var(--perf) * 2.4) 100% repeat-x,
		radial-gradient(circle at 0 50%, transparent var(--perf), #000 calc(var(--perf) + 0.5px)) 0 50% / 100% calc(var(--perf) * 2.4) repeat-y,
		radial-gradient(circle at 100% 50%, transparent var(--perf), #000 calc(var(--perf) + 0.5px)) 100% 50% / 100% calc(var(--perf) * 2.4) repeat-y,
		linear-gradient(#000 0 0) padding-box;
	mask:
		radial-gradient(circle at 50% 0, transparent var(--perf), #000 calc(var(--perf) + 0.5px)) 50% 0 / calc(var(--perf) * 2.4) 100% repeat-x,
		radial-gradient(circle at 50% 100%, transparent var(--perf), #000 calc(var(--perf) + 0.5px)) 50% 100% / calc(var(--perf) * 2.4) 100% repeat-x,
		radial-gradient(circle at 0 50%, transparent var(--perf), #000 calc(var(--perf) + 0.5px)) 0 50% / 100% calc(var(--perf) * 2.4) repeat-y,
		radial-gradient(circle at 100% 50%, transparent var(--perf), #000 calc(var(--perf) + 0.5px)) 100% 50% / 100% calc(var(--perf) * 2.4) repeat-y,
		linear-gradient(#000 0 0) padding-box;
}

/* ---------------------------------------------------- 6 Buttons and forms */

.button,
.wp-block-button__link,
.woocommerce a.button,
.woocommerce button.button,
.woocommerce input.button,
.woocommerce #respond input#submit {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	gap: 0.5em;
	padding: 0.9rem 1.7rem;
	background: var(--postbox);
	color: var(--snow);
	font-family: var(--font-postal);
	font-size: 0.82rem;
	font-weight: 700;
	letter-spacing: 0.1em;
	text-transform: uppercase;
	text-decoration: none;
	border: 1px solid var(--berry);
	border-radius: var(--radius);
	cursor: pointer;
	/*
	 * The label is all-caps in a monospace face, so the line box carries descender
	 * room that no glyph ever uses and the text reads as sitting high with a gap
	 * beneath it. Trimming the leading to 1 and biasing the block padding down by a
	 * hair centres the cap-height rather than the em box.
	 */
	line-height: 1;
	padding-block: 1rem 0.86rem;
	text-align: center;
	box-shadow: 0 2px 0 var(--berry);
	transition: background-color 150ms var(--ease), transform 150ms var(--ease), box-shadow 150ms var(--ease);
}

.button:hover,
.wp-block-button__link:hover,
.woocommerce a.button:hover,
.woocommerce button.button:hover {
	background: var(--berry);
	color: var(--snow);
	transform: translateY(-1px);
	box-shadow: 0 3px 0 #6d0f18;
}

.button:active {
	transform: translateY(1px);
	box-shadow: 0 1px 0 var(--berry);
}

.button--outline,
.button--ghost {
	background: transparent;
	color: var(--gold);
	border-color: currentColor;
	box-shadow: none;
}

.button--outline:hover,
.button--ghost:hover {
	background: rgba(179, 30, 40, 0.08);
	color: var(--berry);
	box-shadow: none;
}

/*
 * Pale outline buttons belong only on the dark surfaces. The hero is parchment in
 * this theme, so a hero ghost button keeps the red outline — light on light would
 * be invisible.
 */
.section--pine .button--outline,
.section--pine .button--ghost,
.section--night .button--ghost,
.section--night .button--outline,
.postbox-cta .button--outline {
	color: var(--parchment);
	border-color: rgba(238, 243, 255, 0.6);
}

.section--pine .button--outline:hover,
.section--pine .button--ghost:hover,
.section--night .button--ghost:hover,
.postbox-cta .button--outline:hover {
	background: rgba(238, 243, 255, 0.16);
	color: var(--snow);
}

.button--block {
	width: 100%;
}

.button--compact {
	/* Same downward bias as the full-size button, scaled to the smaller box. */
	padding: 0.7rem 1rem 0.56rem;
	font-size: 0.72rem;
	letter-spacing: 0.07em;
}

.link-button {
	background: none;
	border: 0;
	padding: 0;
	color: var(--gold);
	font: inherit;
	text-decoration: underline;
	text-underline-offset: 0.16em;
	cursor: pointer;
}

.field {
	display: grid;
	gap: 0.35rem;
	margin-bottom: var(--space-s);
}

.field label {
	font-family: var(--font-postal);
	font-size: 0.72rem;
	font-weight: 700;
	letter-spacing: 0.1em;
	text-transform: uppercase;
	color: var(--text-muted);
}

.field input,
.field select,
.field textarea {
	padding: 0.75rem 0.9rem;
	border: 1px solid var(--rule);
	border-radius: var(--radius);
	background: var(--paper);
	color: var(--ink);
	width: 100%;
}

.field input:focus-visible {
	outline: 2px solid var(--postbox);
	outline-offset: 2px;
}

.ticks,
.tick-list {
	list-style: none;
	margin: 0 0 var(--space-m);
	padding: 0;
	display: grid;
	gap: 0.5rem;
}

.ticks li,
.tick-list li {
	position: relative;
	padding-left: 1.6rem;
	font-size: var(--step--1);
	line-height: 1.55;
}

/* A tick, not a cross — on a list of what you get, ✕ reads as an exclusion. */
.ticks li::before,
.tick-list li::before {
	content: "";
	position: absolute;
	left: 0.1rem;
	top: 0.42em;
	width: 0.6rem;
	height: 0.32rem;
	border-left: 2px solid var(--postbox);
	border-bottom: 2px solid var(--postbox);
	transform: rotate(-45deg);
}

.section--pine .ticks li::before,
.section--night .tick-list li::before {
	border-color: var(--candle);
}

/* ------------------------------------------ 7 Masthead and navigation */

.announcement {
	background: var(--spruce);
	color: var(--parchment);
	text-align: center;
	font-family: var(--font-postal);
	font-size: 0.78rem;
	letter-spacing: 0.06em;
	padding: 0.5rem var(--gutter);
}

.announcement p {
	margin: 0;
}

.masthead__full {
	padding: var(--space-m) 0 var(--space-s);
	border-bottom: 1px solid var(--rule-soft);
	background: var(--parchment);
}

.masthead__inner {
	display: flex;
	align-items: center;
	justify-content: center;
	gap: var(--space-m);
	position: relative;
}

.wordmark {
	display: grid;
	justify-items: center;
	gap: 0.15rem;
	text-decoration: none;
	color: var(--parchment);
	text-align: center;
}

.wordmark__rule {
	width: 3.5rem;
	height: 2px;
	background: var(--gold);
	margin-bottom: 0.35rem;
}

.wordmark__name {
	font-family: var(--font-display);
	font-size: clamp(1.65rem, 1.1rem + 2.2vw, 2.9rem);
	font-weight: 800;
	line-height: 1;
	letter-spacing: -0.01em;
	font-variation-settings: "SOFT" 30, "WONK" 1;
}

.wordmark__tagline {
	font-family: var(--font-postal);
	font-size: 0.66rem;
	letter-spacing: 0.3em;
	text-transform: uppercase;
	color: var(--gold);
	/*
	 * The wordmark sets line-height 1, so its descenders reach the bottom of their
	 * box and the grid gap alone leaves the tagline crowding the name. This buys
	 * the breathing room back without loosening the gap above the rule.
	 */
	margin-top: 0.5rem;
}

.masthead__postmark {
	position: absolute;
	right: 0;
	top: 50%;
	transform: translateY(-50%) rotate(-9deg);
	display: none;
	place-content: center;
	width: 6rem;
	height: 6rem;
	border: 2px solid var(--postbox);
	border-radius: 50%;
	color: var(--gold);
	font-family: var(--font-postal);
	font-size: 0.54rem;
	letter-spacing: 0.1em;
	text-transform: uppercase;
	text-align: center;
	line-height: 1.6;
	opacity: 0.6;
}

.masthead__postmark-mid {
	font-size: 0.72rem;
	font-weight: 700;
	display: block;
	border-block: 1px solid currentColor;
	padding: 0.1rem 0;
	margin: 0.12rem 0;
}

@media (min-width: 56em) {
	.masthead__postmark {
		display: grid;
	}
}

.masthead__bar {
	position: sticky;
	top: 0;
	z-index: 50;
	background: var(--parchment);
	border-bottom: 1px solid var(--rule);
	transition: box-shadow 200ms var(--ease);
}

.masthead__bar.is-stuck {
	box-shadow: 0 8px 24px -20px rgba(0, 0, 0, 0.8);
}

.masthead__bar-inner {
	min-height: var(--bar-height);
	display: flex;
	align-items: center;
	gap: var(--space-s);
}

.masthead__mini {
	font-family: var(--font-display);
	font-weight: 800;
	font-size: 1rem;
	color: var(--parchment);
	text-decoration: none;
	white-space: nowrap;
	opacity: 0;
	transform: translateY(4px);
	transition: opacity 200ms var(--ease), transform 200ms var(--ease);
	pointer-events: none;
	max-width: 0;
	overflow: hidden;
}

.masthead__bar.is-stuck .masthead__mini {
	opacity: 1;
	transform: none;
	pointer-events: auto;
	max-width: 14rem;
	margin-right: var(--space-s);
}

.site-nav__list,
.site-nav ul {
	display: flex;
	align-items: center;
	gap: clamp(0.9rem, 2vw, 1.8rem);
	list-style: none;
	margin: 0 auto 0 0;
	padding: 0;
}

.site-nav li a {
	font-family: var(--font-postal);
	font-size: 0.78rem;
	font-weight: 700;
	letter-spacing: 0.06em;
	text-transform: uppercase;
	color: var(--parchment);
	text-decoration: none;
	padding: 0.35rem 0;
	position: relative;
	white-space: nowrap;
}

.site-nav li a::after {
	content: "";
	position: absolute;
	inset-inline: 0;
	bottom: 0;
	height: 2px;
	background: var(--postbox);
	transform: scaleX(0);
	transform-origin: left;
	transition: transform 180ms var(--ease);
}

.site-nav li a:hover::after,
.site-nav .is-current a::after,
.site-nav .current-menu-item a::after {
	transform: scaleX(1);
}

/*
 * Submenus. The parent item pairs its link with a script-injected toggle button:
 * hover alone would strand keyboard and touch users, and the "Lapland Guides"
 * parent points at "#", so its link is not a destination on any device.
 */
.site-nav .menu-item-has-children {
	position: relative;
}

.site-nav__parent {
	display: flex;
	align-items: center;
	gap: 0.3rem;
}

/*
 * The toggle matches the link's own box exactly — same vertical padding, same
 * line-height — so a parent item is the same height as its flat siblings.
 */
.site-nav__sub-toggle {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	width: 1.1rem;
	padding: 0.35rem 0;
	background: transparent;
	border: 0;
	color: var(--parchment);
	cursor: pointer;
	font-size: 0.78rem;
	line-height: 1.2;
}

.site-nav__sub-toggle svg {
	width: 0.6rem;
	height: 0.6rem;
	transition: transform 180ms var(--ease);
}

.site-nav__sub-toggle[aria-expanded="true"] svg {
	transform: rotate(180deg);
}

.site-nav .sub-menu li a::after {
	display: none;
}

.site-nav__action {
	display: none;
}

.masthead__action {
	flex: none;
	white-space: nowrap;
}

.cta-short {
	display: none;
}

.menu-toggle {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	width: 2.6rem;
	height: 2.6rem;
	background: transparent;
	border: 1px solid rgba(216, 171, 92, 0.5);
	border-radius: var(--radius);
	cursor: pointer;
}

.menu-toggle__bars {
	display: grid;
	gap: 4px;
	width: 17px;
}

/*
 * Gold, not spruce. The bars were drawn in the same dark green the header now sits on,
 * so the control was very nearly invisible against its own background.
 */
.menu-toggle__bars span {
	height: 2px;
	background: var(--gold);
	transition: transform 180ms var(--ease), opacity 180ms var(--ease);
}

body.menu-open .menu-toggle__bars span:nth-child(1) { transform: translateY(6px) rotate(45deg); }
body.menu-open .menu-toggle__bars span:nth-child(2) { opacity: 0; }
body.menu-open .menu-toggle__bars span:nth-child(3) { transform: translateY(-6px) rotate(-45deg); }

@media (max-width: 61.99em) {
	/*
	 * The shared clamp bottoms out at 1.65rem well before phone widths, so the
	 * wordmark arrived at its smallest size on the screens with the most vertical
	 * room to spare. Small screens get their own curve: a higher floor, and a
	 * steeper slope so it grows through the tablet range instead of sitting flat.
	 */
	.wordmark__name {
		font-size: clamp(1.95rem, 1.2rem + 3.6vw, 2.9rem);
	}

	.site-nav {
		position: fixed;
		inset: 0;
		background: var(--parchment);
		background-image: var(--fibre);
		background-size: 160px 160px;
		display: grid;
		/*
		 * Start, not centre. Centring left a deep gap above the first link, and it got
		 * worse as the guides accordion opened and pushed the block further down. The
		 * top padding clears the bar the close X sits in, so the menu begins directly
		 * under it whether or not a submenu is expanded.
		 */
		align-content: start;
		justify-items: start;
		gap: var(--space-s);
		padding: calc(var(--bar-height) + var(--space-s)) var(--gutter) var(--space-2xl);
		opacity: 0;
		visibility: hidden;
		transform: translateY(-0.75rem);
		transition: opacity 220ms var(--ease), transform 220ms var(--ease), visibility 220ms;
		overflow-y: auto;
		z-index: 60;
	}

	.site-nav.is-open {
		opacity: 1;
		visibility: visible;
		transform: none;
	}

	.site-nav__list,
	.site-nav ul {
		flex-direction: column;
		align-items: flex-start;
		gap: var(--space-s);
		margin: 0;
	}

	.site-nav li a {
		font-family: var(--font-display);
		font-size: var(--step-2);
		font-weight: 700;
		letter-spacing: 0;
		text-transform: none;
	}

	/* An in-flow accordion on small screens rather than an overlay panel. */
	.site-nav .sub-menu {
		display: none;
		flex-direction: column;
		align-items: flex-start;
		gap: var(--space-2xs);
		margin: var(--space-2xs) 0 0;
		padding: 0 0 0 var(--space-s);
		border-left: 1px solid var(--rule);
	}

	.site-nav .menu-item-has-children.is-open > .sub-menu {
		display: flex;
	}

	/*
	 * Children read smaller than their parent. `--step-0` was larger than the 0.74rem
	 * the top-level links settle at, and because this selector is more specific than
	 * the `.site-nav li a` rule that sets that size, the submenu won on the cascade and
	 * the guide titles came out bigger than the section they sit under.
	 */
	.site-nav .sub-menu li a {
		font-size: 0.66rem;
		font-weight: 500;
	}

	.site-nav__sub-toggle {
		width: 2.2rem;
		height: 2.2rem;
	}

	.site-nav__sub-toggle svg {
		width: 0.8rem;
		height: 0.8rem;
	}

	.site-nav__action {
		display: block;
		width: 100%;
		margin-top: var(--space-s);
	}

	/*
	 * The nav is taken out of flow on small screens, so it no longer supplies the
	 * automatic margin that pushes the action right. The action does it itself.
	 */
	.masthead__action {
		margin-left: auto;
		order: 3;
	}

	/*
	 * The mini wordmark is a scroll affordance on desktop, revealed only once the
	 * bar sticks. On small screens the bar would otherwise open with a wide empty
	 * left edge, so the wordmark is shown from the start and the burger sits with
	 * it rather than drifting off alone on the right.
	 */
	.masthead__mini {
		opacity: 1;
		transform: none;
		pointer-events: auto;
		max-width: 14rem;
		order: 1;
	}

	.menu-toggle {
		order: 2;
	}

	/*
	 * The menu row cost a full bar of vertical space at the top of every page on the
	 * screens with the least of it, for a nav that is behind a burger anyway. Below
	 * 62em it is lifted out of the flow entirely and kept hidden until the page
	 * scrolls, so the masthead opens straight onto the wordmark and the crown, and the
	 * bar returns as a compact sticky title + burger once you are past the header.
	 *
	 * `visibility` rather than `display`, so that showing it is a transition rather
	 * than a jump, and so it costs no layout at any point. Note it must not gain a
	 * transform or filter to do this: `.site-nav` inside it is `position: fixed`, and
	 * either property would make the bar its containing block and strand the overlay.
	 */
	.masthead__bar {
		position: fixed;
		top: 0;
		left: 0;
		right: 0;
		transition: opacity 200ms var(--ease), visibility 200ms var(--ease);
	}

	/*
	 * Written as `:not(.is-stuck)` rather than as a base rule plus an `.is-stuck`
	 * override, so the hidden and shown states are mutually exclusive selectors of
	 * equal specificity that can never fight. `body.menu-open` then re-shows it while
	 * the menu is open, so the X stays reachable at any scroll position.
	 */
	.masthead__bar:not(.is-stuck) {
		visibility: hidden;
		opacity: 0;
	}

	body.menu-open .masthead__bar:not(.is-stuck) {
		visibility: visible;
		opacity: 1;
	}

	/*
	 * The open menu must keep a way out. The overlay is `z-index: 60` inside the bar's
	 * own stacking context, so the burger is lifted above it — without this it is
	 * painted underneath the panel and the X cannot be tapped, which on a phone (no
	 * Escape key) leaves following a link as the only way to close the menu.
	 */
	.menu-toggle {
		position: relative;
		z-index: 70;
	}

	/*
	 * The masthead's own burger, under the tagline. It is the only one on screen until
	 * the bar sticks, and it is hidden while the menu is open so that the X in the bar
	 * is the single close control rather than two burgers in different places.
	 */
	.menu-toggle--header {
		margin-top: var(--space-xs);
	}

	body.menu-open .menu-toggle--header {
		visibility: hidden;
	}

	/* The nav panel carries its own full-width CTA, so the bar can drop it. */
	@media (max-width: 23.4375em) {
		.masthead__action {
			display: none;
		}
	}

	body.menu-open {
		overflow: hidden;
	}
}

@media (min-width: 62em) {
	.menu-toggle {
		display: none;
	}

	/* A dropped card on pointer screens. */
	.site-nav .sub-menu {
		position: absolute;
		top: calc(100% + 0.6rem);
		inset-inline-start: 0;
		z-index: 70;
		display: flex;
		flex-direction: column;
		align-items: flex-start;
		gap: 0;
		min-width: 15rem;
		margin: 0;
		padding: var(--space-2xs) 0;
		background: var(--parchment);
		border: 1px solid var(--rule);
		border-radius: var(--radius);
		box-shadow: var(--shadow-paper);
		opacity: 0;
		visibility: hidden;
		transform: translateY(-0.35rem);
		transition: opacity 160ms var(--ease), transform 160ms var(--ease), visibility 160ms;
	}

	/*
	 * Hover keeps it feeling immediate for mouse users; focus-within covers tabbing
	 * straight through; is-open is what the toggle button drives.
	 */
	.site-nav .menu-item-has-children:hover > .sub-menu,
	.site-nav .menu-item-has-children:focus-within > .sub-menu,
	.site-nav .menu-item-has-children.is-open > .sub-menu {
		opacity: 1;
		visibility: visible;
		transform: none;
	}

	.site-nav .sub-menu li {
		width: 100%;
	}

	.site-nav .sub-menu li a {
		display: block;
		width: 100%;
		padding: 0.5rem var(--space-s);
		font-size: 0.74rem;
		white-space: normal;
	}

	.site-nav .sub-menu li a:hover,
	.site-nav .sub-menu li a:focus-visible {
		background: var(--parchment-deep);
	}

	/*
	 * The gap between the parent and the card would drop the hover on the way down,
	 * so it is bridged rather than removed — the card keeps its visual offset.
	 */
	.site-nav .menu-item-has-children > .sub-menu::before {
		content: "";
		position: absolute;
		inset-inline: 0;
		bottom: 100%;
		height: 0.6rem;
	}
}

@media (max-width: 30em) {
	.cta-long { display: none; }
	.cta-short { display: inline; }

	/*
	 * The tagline is a single line of widely-tracked uppercase, so it costs about
	 * 9.5px a character and a 34-character line runs out of room before 360px.
	 * Tightening the tracking keeps it on one line rather than letting it wrap and
	 * unbalance the masthead.
	 */
	.wordmark__tagline {
		font-size: 0.58rem;
		letter-spacing: 0.18em;
	}
}

/* --------------------------------------------------------- 8 The letter hero */

/*
 * The published pages open with .hero / .article-hero. Here that becomes a letter on
 * the desk: parchment, ruled margin, a stamp cut from the page's hero photograph, and
 * a postmark across it.
 */
.hero,
.article-hero {
	position: relative;
	background: var(--parchment-deep);
	background-image: var(--fibre);
	background-size: 160px 160px;
	border-bottom: 1px solid var(--rule);
	padding: var(--space-2xl) 0;
	overflow: hidden;
}

.hero::before,
.article-hero::before {
	content: "";
	position: absolute;
	inset-block: 0;
	left: 0;
	width: 3px;
	background: repeating-linear-gradient(180deg, var(--postbox) 0 10px, transparent 10px 20px);
	opacity: 0.5;
}

.hero__content,
.article-hero__inner {
	width: min(100% - (var(--gutter) * 2), var(--wide));
	margin-inline: auto;
	position: relative;
	z-index: 2;
}

.hero h1,
.article-hero h1 {
	color: var(--parchment);
	margin-bottom: var(--space-s);
}

.hero .lede,
.article-hero .lede {
	color: var(--text-muted);
}

.hero .price-note {
	margin-top: var(--space-s);
	font-family: var(--font-postal);
	font-size: var(--step--1);
	color: var(--text-muted);
}

/* The hero photograph, cut as a stamp and pinned to the right on wide screens. */
.hero::after,
.article-hero::after {
	content: "";
	position: absolute;
	right: clamp(1rem, 5vw, 4.5rem);
	top: 50%;
	width: clamp(12rem, 22vw, 19rem);
	aspect-ratio: 3 / 4;
	transform: translateY(-50%) rotate(3deg);
	background-image: var(--hero-image, var(--lr5-hero-image, none));
	background-size: cover;
	background-position: center;
	border: 10px solid var(--paper);
	box-shadow: var(--shadow-lift);
	display: none;
	z-index: 1;
}

@media (min-width: 62em) {
	.hero::after,
	.article-hero::after {
		display: block;
	}

	.hero__content > *,
	.article-hero__inner > * {
		max-width: min(100%, 34rem);
	}

	.hero__content > h1,
	.article-hero__inner > h1 {
		max-width: 17ch;
	}
}

/* Snow, only on the hero, only if motion is welcome. */
.hero .snow,
.article-hero .snow {
	position: absolute;
	inset: 0;
	pointer-events: none;
	z-index: 1;
	background-image:
		radial-gradient(2px 2px at 20% 30%, rgba(255, 255, 255, 0.9), transparent),
		radial-gradient(2px 2px at 70% 20%, rgba(255, 255, 255, 0.8), transparent),
		radial-gradient(1.5px 1.5px at 45% 70%, rgba(255, 255, 255, 0.85), transparent),
		radial-gradient(1.5px 1.5px at 85% 60%, rgba(255, 255, 255, 0.75), transparent),
		radial-gradient(2px 2px at 10% 80%, rgba(255, 255, 255, 0.8), transparent);
	background-size: 300px 300px;
	animation: lr5-snow 16s linear infinite;
	opacity: 0.7;
}

@keyframes lr5-snow {
	from { background-position: 0 -300px, 0 -300px, 0 -300px, 0 -300px, 0 -300px; }
	to { background-position: 30px 300px, -20px 300px, 15px 300px, -35px 300px, 25px 300px; }
}

/* ------------------------------------------------------- 9 Guide modules */

.guide-section {
	border-top: 1px solid var(--rule-soft);
}

.glance {
	margin: var(--space-m) 0 0;
	display: grid;
	gap: 0;
	border-top: 2px solid var(--spruce);
}

.glance__row {
	display: grid;
	gap: 0.15rem 1.5rem;
	padding: var(--space-s) 0;
	border-bottom: 1px solid var(--rule-soft);
}

@media (min-width: 44em) {
	.glance__row {
		grid-template-columns: 12rem minmax(0, 1fr);
		align-items: baseline;
	}
}

.glance dt {
	font-family: var(--font-postal);
	font-size: 0.76rem;
	font-weight: 700;
	letter-spacing: 0.12em;
	text-transform: uppercase;
	color: var(--gold);
}

.glance dd {
	margin: 0;
	color: var(--text);
}

.ledger {
	border-collapse: collapse;
	width: 100%;
	min-width: 36rem;
	background: var(--paper);
	box-shadow: var(--shadow-paper);
}

.ledger th,
.ledger td {
	text-align: left;
	padding: 0.85rem 1rem;
	border-bottom: 1px solid var(--rule-soft);
	font-size: var(--step--1);
	vertical-align: top;
}

.ledger thead th {
	font-family: var(--font-postal);
	font-size: 0.72rem;
	letter-spacing: 0.12em;
	text-transform: uppercase;
	color: var(--parchment);
	background: var(--spruce);
	border-bottom: 0;
}

.ledger tbody th {
	font-family: var(--font-display);
	font-size: var(--step-1);
	color: var(--parchment);
	white-space: nowrap;
}

.ledger tbody tr:nth-child(even) {
	background: rgba(185, 198, 230, 0.35);
}

.activity__age {
	font-family: var(--font-postal);
	font-size: 0.68rem;
	letter-spacing: 0.1em;
	text-transform: uppercase;
	color: var(--gold);
	margin-bottom: var(--space-2xs);
}

.checklist {
	display: grid;
	gap: clamp(1.1rem, 2.4vw, 1.6rem);
	grid-template-columns: repeat(auto-fit, minmax(min(100%, 18rem), 1fr));
	margin-top: var(--space-l);
}

.checklist__group h3 {
	font-size: var(--step-1);
	margin-bottom: var(--space-xs);
	padding-bottom: var(--space-2xs);
	border-bottom: 2px solid var(--gold);
}

.checklist__group ul {
	list-style: none;
	margin: 0;
	padding: 0;
	display: grid;
	gap: 0.6rem;
}

.checklist__group li {
	display: grid;
	grid-template-columns: auto minmax(0, 1fr);
	gap: 0.65rem;
	align-items: start;
	font-size: var(--step--1);
	line-height: 1.5;
}

.checklist__group input[type="checkbox"] {
	width: 1.05rem;
	height: 1.05rem;
	margin-top: 0.2rem;
	accent-color: var(--gold);
}

.checklist__group input:checked + label {
	color: var(--text-muted);
	text-decoration: line-through;
}

.checklist__note {
	margin-top: var(--space-m);
	display: flex;
	flex-wrap: wrap;
	gap: 0.6rem;
	align-items: center;
}

.bands {
	display: grid;
	gap: clamp(1.1rem, 2.4vw, 1.6rem);
	grid-template-columns: repeat(auto-fit, minmax(min(100%, 16rem), 1fr));
	margin-top: var(--space-l);
}

.band__verdict {
	font-family: var(--font-postal);
	font-size: 0.72rem;
	font-weight: 700;
	letter-spacing: 0.1em;
	text-transform: uppercase;
	color: var(--gold);
	margin-bottom: var(--space-2xs);
}

.tips {
	counter-reset: tips;
	list-style: none;
	margin: var(--space-l) 0 0;
	padding: 0;
	display: grid;
	gap: var(--space-s);
	max-width: 62ch;
}

.tips li {
	counter-increment: tips;
	position: relative;
	padding-left: 3rem;
	line-height: 1.6;
}

.tips li::before {
	content: counter(tips, decimal-leading-zero);
	position: absolute;
	left: 0;
	top: 0;
	font-family: var(--font-postal);
	font-weight: 700;
	color: var(--gold);
	border: 1px solid currentColor;
	border-radius: var(--radius-sm);
	padding: 0.05rem 0.35rem;
	font-size: 0.72rem;
}

/* ------------------------- 10 Product ladder, demo, FAQ, related */

.ladder__grid {
	display: grid;
	gap: clamp(1.5rem, 3vw, 2.25rem);
	grid-template-columns: repeat(auto-fit, minmax(min(100%, 17rem), 1fr));
	margin-top: var(--space-l);
	align-items: stretch;
}

/* One tier on sale: a single card centred, rather than stretched across the grid. */
.ladder--single .ladder__grid {
	grid-template-columns: minmax(0, 26rem);
	justify-content: center;
}

.stamp-card {
	--perf: 7px;
	position: relative;
	display: flex;
	background: var(--paper);
	filter: drop-shadow(0 10px 22px rgba(0, 0, 0, 0.35));
	-webkit-mask:
		radial-gradient(circle at 50% 0, transparent var(--perf), #000 calc(var(--perf) + 0.5px)) 50% 0 / calc(var(--perf) * 2.4) 100% repeat-x,
		radial-gradient(circle at 50% 100%, transparent var(--perf), #000 calc(var(--perf) + 0.5px)) 50% 100% / calc(var(--perf) * 2.4) 100% repeat-x,
		radial-gradient(circle at 0 50%, transparent var(--perf), #000 calc(var(--perf) + 0.5px)) 0 50% / 100% calc(var(--perf) * 2.4) repeat-y,
		radial-gradient(circle at 100% 50%, transparent var(--perf), #000 calc(var(--perf) + 0.5px)) 100% 50% / 100% calc(var(--perf) * 2.4) repeat-y,
		linear-gradient(#000 0 0) padding-box;
	mask:
		radial-gradient(circle at 50% 0, transparent var(--perf), #000 calc(var(--perf) + 0.5px)) 50% 0 / calc(var(--perf) * 2.4) 100% repeat-x,
		radial-gradient(circle at 50% 100%, transparent var(--perf), #000 calc(var(--perf) + 0.5px)) 50% 100% / calc(var(--perf) * 2.4) 100% repeat-x,
		radial-gradient(circle at 0 50%, transparent var(--perf), #000 calc(var(--perf) + 0.5px)) 0 50% / 100% calc(var(--perf) * 2.4) repeat-y,
		radial-gradient(circle at 100% 50%, transparent var(--perf), #000 calc(var(--perf) + 0.5px)) 100% 50% / 100% calc(var(--perf) * 2.4) repeat-y,
		linear-gradient(#000 0 0) padding-box;
	transition: transform 200ms var(--ease);
}

.stamp-card:hover {
	transform: translateY(-4px);
}

.stamp-card__perf {
	display: flex;
	flex-direction: column;
	width: 100%;
	padding: clamp(1.5rem, 3vw, 2rem);
	border: 2px solid var(--kraft-line);
	margin: 12px;
}

.stamp-card--featured .stamp-card__perf {
	border-color: var(--postbox);
}

.stamp-card__class {
	font-family: var(--font-postal);
	font-size: 0.68rem;
	font-weight: 700;
	letter-spacing: 0.16em;
	text-transform: uppercase;
	color: var(--gold);
}

.stamp-card__value {
	font-family: var(--font-display);
	font-size: var(--step-4);
	font-weight: 800;
	line-height: 1;
	color: var(--parchment);
	margin: 0.4rem 0 0.15rem;
}

.stamp-card__name {
	font-size: var(--step-1);
	margin-bottom: var(--space-2xs);
}

.stamp-card__tagline {
	font-size: var(--step--1);
	color: var(--text-muted);
	margin-bottom: var(--space-s);
}

.stamp-card__delivery {
	display: flex;
	align-items: center;
	gap: 0.55rem;
	flex-wrap: wrap;
	font-size: var(--step--1);
	color: var(--text-muted);
	margin-top: auto;
	margin-bottom: var(--space-s);
}

.stamp-card .postmark-chip {
	color: var(--parchment);
}

.stamp-card .postmark-chip--posted {
	color: var(--gold);
}

/*
 * Paper stays dark-on-light even when it sits on a dark section.
 *
 * The section-level text colours are set for the section's own background, and they
 * would otherwise cascade into the white stamps and wash them out. These selectors
 * carry a class more than the section rules on purpose, so the order of the file
 * cannot reintroduce the problem.
 */
.section--pine .stamp-card,
.section--night .stamp-card {
	color: var(--ink);
}

.section--pine .stamp-card h2,
.section--pine .stamp-card h3,
.section--night .stamp-card h2,
.section--night .stamp-card h3 {
	color: var(--parchment);
}

.section--pine .stamp-card p,
.section--pine .stamp-card li,
.section--night .stamp-card p,
.section--night .stamp-card li {
	color: var(--text-muted);
}

.section--pine .stamp-card .stamp-card__value,
.section--night .stamp-card .stamp-card__value {
	color: var(--parchment);
}


.section--pine .stamp-card .button--outline,
.section--night .stamp-card .button--outline {
	color: var(--gold);
	border-color: currentColor;
	background: transparent;
}

.section--pine .stamp-card .ticks li::before,
.section--night .stamp-card .ticks li::before {
	border-color: var(--postbox);
}

.section--pine .stamp-card .button--outline:hover,
.section--night .stamp-card .button--outline:hover {
	background: rgba(179, 30, 40, 0.08);
	color: var(--berry);
}

.ladder__note {
	margin-top: var(--space-l);
	font-size: var(--step--1);
	color: rgba(238, 243, 255, 0.75);
	max-width: 62ch;
}

.ladder__note a {
	color: var(--candle);
}

.demo__layout {
	display: grid;
	gap: clamp(1.75rem, 4vw, 3rem);
	align-items: start;
	margin-top: var(--space-l);
}

@media (min-width: 62em) {
	.demo__layout {
		grid-template-columns: 19rem minmax(0, 1fr);
	}
}

.demo__controls {
	position: sticky;
	top: calc(var(--bar-height) + 1rem);
}

.demo__previews {
	display: grid;
	gap: var(--space-m);
	grid-template-columns: repeat(auto-fit, minmax(min(100%, 15rem), 1fr));
}

.demo__card {
	display: grid;
	gap: var(--space-xs);
	align-content: start;
}

.demo__label {
	font-family: var(--font-postal);
	font-size: 0.66rem;
	font-weight: 700;
	letter-spacing: 0.16em;
	text-transform: uppercase;
	color: var(--gold);
}

.paper--letter {
	padding-bottom: 3.5rem;
	background-image: repeating-linear-gradient(180deg, transparent 0 27px, rgba(216, 171, 92, 0.10) 27px 28px);
}

.demo__letter,
.demo__quote {
	font-family: var(--font-display);
	font-size: var(--step-1);
	line-height: 1.5;
	margin: 0;
	color: var(--ink);
}

.demo__card figcaption {
	font-size: var(--step--1);
	color: var(--text-muted);
	border-top: 1px dashed var(--rule);
	padding-top: var(--space-xs);
}

[data-lr5-demo-name] {
	color: var(--gold);
	font-weight: 800;
	transition: background-color 350ms var(--ease);
}

.demo__card.is-updating [data-lr5-demo-name] {
	background: var(--candle);
	border-radius: var(--radius-sm);
}

.mini-ticket {
	background: var(--spruce);
	color: var(--parchment);
	border-radius: var(--radius);
	padding: var(--space-s);
	display: grid;
	gap: 0.3rem;
}

.mini-ticket__route {
	font-family: var(--font-postal);
	font-size: 0.6rem;
	letter-spacing: 0.16em;
	text-transform: uppercase;
	color: var(--candle);
}

.mini-ticket strong {
	font-family: var(--font-display);
	font-size: var(--step-2);
	font-weight: 700;
	line-height: 1.05;
	color: var(--parchment);
}

.mini-ticket__meta {
	display: flex;
	justify-content: space-between;
	gap: var(--space-xs);
	flex-wrap: wrap;
	font-size: var(--step--1);
	color: rgba(238, 243, 255, 0.75);
	border-top: 1px dashed rgba(238, 243, 255, 0.3);
	padding-top: 0.4rem;
}

/*
 * FAQ inset — ONE KNOB.
 *
 * Section 15.9 turns .faq__item into a card (panel fill, border, shadow). It was not
 * one in the light theme, where a question sitting flush left against nothing looked
 * right. Now that there is a border a few pixels to its left, flush left reads as a
 * mistake, so question and answer are inset from the card edge on every side.
 *
 * Change --faq-inset to move the text; the marker on the right tracks it automatically.
 */
.faq__list {
	--faq-inset: clamp(1.05rem, 2.2vw, 1.6rem);

	margin-top: var(--space-l);
	display: grid;
	gap: 0.6rem;
}

.faq__item summary {
	cursor: pointer;
	list-style: none;
	padding: var(--space-s) calc(var(--faq-inset) + 1.9rem) var(--space-s) var(--faq-inset);
	font-family: var(--font-display);
	font-size: var(--step-1);
	font-weight: 700;
	color: var(--parchment);
	position: relative;
}

.faq__item summary::-webkit-details-marker {
	display: none;
}

.faq__item summary::after {
	content: "+";
	position: absolute;
	right: var(--faq-inset);
	top: 50%;
	transform: translateY(-50%);
	font-family: var(--font-postal);
	font-size: 1.4rem;
	font-weight: 700;
	color: var(--gold);
	line-height: 1;
}

.faq__item[open] summary::after {
	content: "–";
}

.faq__answer {
	padding: 0 var(--faq-inset) var(--space-s);
	color: var(--text-muted);
	/* 62ch measured from the card edge; the inset eats into it, so hold the measure. */
	max-width: calc(62ch + var(--faq-inset));
}

.related__grid {
	display: grid;
	gap: clamp(1rem, 2.4vw, 1.6rem);
	grid-template-columns: repeat(auto-fit, minmax(min(100%, 15rem), 1fr));
	margin-top: var(--space-m);
}

.related__card {
	display: grid;
	gap: var(--space-xs);
	text-decoration: none;
	color: var(--ink);
	padding: 0.75rem;
	transition: transform 200ms var(--ease), box-shadow 200ms var(--ease);
}

.related__card:hover {
	transform: translateY(-3px);
	box-shadow: var(--shadow-lift);
}

.related__art {
	display: block;
	aspect-ratio: 4 / 3;
	background-size: cover;
	background-position: center;
	border: 1px solid var(--rule-soft);
}

.related__stamp {
	font-family: var(--font-postal);
	font-size: 0.64rem;
	font-weight: 700;
	letter-spacing: 0.14em;
	text-transform: uppercase;
	color: var(--gold);
}

.related__title {
	font-family: var(--font-display);
	font-size: var(--step-1);
	font-weight: 700;
	line-height: 1.2;
	color: var(--parchment);
}

/* ------------------------- 11 Postbox call to action and footer */

.postbox-cta {
	position: relative;
	background: var(--postbox);
	background-image:
		repeating-linear-gradient(45deg, rgba(0, 0, 0, 0.06) 0 18px, transparent 18px 36px),
		var(--fibre);
	background-size: auto, 160px 160px;
	color: var(--parchment);
	padding: var(--space-2xl) 0;
	border-top: 6px solid var(--spruce);
}

.postbox-cta__inner {
	display: grid;
	gap: var(--space-xl);
	align-items: center;
}

@media (min-width: 56em) {
	.postbox-cta__inner {
		grid-template-columns: minmax(0, 1.15fr) minmax(0, 0.85fr);
	}
}

.postbox-cta h2 {
	color: var(--parchment);
	font-size: var(--step-4);
}

.postbox-cta p {
	color: rgba(238, 243, 255, 0.88);
	max-width: 40ch;
}

.fine-print--light {
	color: rgba(238, 243, 255, 0.72);
}

.postbox-cta .button {
	background: var(--candle);
	color: var(--ink);
	border-color: var(--gold);
	box-shadow: 0 2px 0 var(--gold);
}

.postbox-cta .button:hover {
	background: var(--snow);
	color: var(--ink);
}

/* An envelope, drawn in CSS, addressed and stamped. */
.envelope {
	position: relative;
	aspect-ratio: 3 / 2;
	background: var(--paper);
	border: 1px solid var(--kraft-line);
	box-shadow: var(--shadow-lift);
	transform: rotate(-2deg);
	overflow: hidden;
}

.envelope::before {
	content: "";
	position: absolute;
	inset: 0 0 auto;
	height: 58%;
	background: linear-gradient(175deg, var(--parchment-deep) 0 50%, transparent 50%);
	clip-path: polygon(0 0, 100% 0, 50% 100%);
	border-bottom: 1px solid var(--kraft-line);
}

.envelope__stamp {
	position: absolute;
	top: 8%;
	right: 7%;
	display: grid;
	place-content: center;
	width: 22%;
	aspect-ratio: 3 / 4;
	background: var(--spruce);
	color: var(--candle);
	font-family: var(--font-postal);
	font-size: 0.56rem;
	font-weight: 700;
	letter-spacing: 0.06em;
	text-transform: uppercase;
	text-align: center;
	padding: 0.25rem;
	border: 3px solid var(--paper);
	outline: 1px dashed var(--kraft-line);
	z-index: 2;
}

.envelope__postmark {
	position: absolute;
	top: 12%;
	right: 30%;
	display: grid;
	place-content: center;
	width: 20%;
	aspect-ratio: 1;
	border: 2px solid var(--postbox);
	border-radius: 50%;
	color: var(--gold);
	font-family: var(--font-postal);
	font-size: 0.48rem;
	letter-spacing: 0.05em;
	text-transform: uppercase;
	text-align: center;
	transform: rotate(-12deg);
	opacity: 0.65;
	z-index: 2;
}

.envelope__address {
	position: absolute;
	left: 12%;
	bottom: 16%;
	display: grid;
	gap: 0.55rem;
	width: 45%;
	z-index: 2;
}

.envelope__address span {
	display: block;
	height: 2px;
	background: var(--rule);
}

.envelope__address span:nth-child(2) { width: 78%; }
.envelope__address span:nth-child(3) { width: 55%; }

.site-footer {
	background: var(--spruce);
	background-image: var(--fibre);
	background-size: 160px 160px;
	color: rgba(238, 243, 255, 0.82);
	padding: var(--space-2xl) 0 var(--space-l);
}

.site-footer__inner {
	display: grid;
	gap: var(--space-xl);
}

.site-footer__cols {
	display: grid;
	gap: var(--space-l);
	grid-template-columns: repeat(auto-fit, minmax(min(100%, 12rem), 1fr));
}

.site-footer__col h3 {
	font-family: var(--font-postal);
	font-size: 0.72rem;
	font-weight: 700;
	letter-spacing: 0.16em;
	text-transform: uppercase;
	color: var(--candle);
	margin-bottom: var(--space-s);
}

.site-footer__col ul {
	list-style: none;
	margin: 0;
	padding: 0;
	display: grid;
	gap: 0.5rem;
}

.site-footer__col a {
	color: rgba(238, 243, 255, 0.82);
	text-decoration: none;
	font-size: var(--step--1);
}

.site-footer__col a:hover {
	color: var(--snow);
	text-decoration: underline;
	text-underline-offset: 0.18em;
}

.site-footer__notes {
	display: grid;
	gap: 0.5rem;
	font-size: var(--step--1);
	list-style: none;
	margin: 0;
	padding: 0;
}

.site-footer__base {
	border-top: 1px solid rgba(238, 243, 255, 0.18);
	padding-top: var(--space-m);
	display: grid;
	gap: var(--space-2xs);
	font-size: var(--step--1);
}

.site-footer__mark {
	font-family: var(--font-display);
	font-size: var(--step-2);
	font-weight: 800;
	color: var(--parchment);
}

.site-footer__base p {
	margin: 0;
}

.site-footer__independence {
	max-width: 52ch;
	color: rgba(238, 243, 255, 0.62);
}

/* ------------------------------------------------ 12 Inherited page markup */

/*
 * Everything below restyles markup written for the earlier themes so the twelve
 * published pages render in this language without being re-authored.
 */

/* The dark and pale section variants become pine and kraft. */
.section--night {
	background-color: var(--spruce);
	background-image:
		radial-gradient(circle at 20% 0%, rgba(243, 201, 105, 0.14), transparent 55%),
		var(--fibre);
	background-size: auto, 160px 160px;
	color: var(--parchment);
}

.section--night h2,
.section--night h3 {
	color: var(--parchment);
}

.section--night p,
.section--night .lede {
	color: rgba(238, 243, 255, 0.82);
}

.section--night .eyebrow {
	color: var(--candle);
}

.section--night .eyebrow::after {
	background: repeating-linear-gradient(90deg, rgba(255, 255, 255, 0.35) 0 4px, transparent 4px 8px);
}

.section--night a:not(.button) {
	color: var(--candle);
}

.section--mist {
	background-color: var(--kraft);
	background-image: var(--fibre);
	background-size: 160px 160px;
	border-block: 1px solid var(--kraft-line);
}

/* The reassurance strip becomes a row of rubber stamps. */
.trust-strip,
.delivery-strip {
	background: var(--kraft);
	border-block: 1px dashed var(--kraft-line);
}

.trust-strip__inner,
.delivery-strip__inner {
	width: min(100% - (var(--gutter) * 2), var(--wide));
	margin-inline: auto;
	display: flex;
	flex-wrap: wrap;
	justify-content: center;
	gap: 0.6rem clamp(0.75rem, 3vw, 2rem);
	padding: var(--space-s) 0;
}

.trust-strip__inner span,
.delivery-strip__mark {
	font-family: var(--font-postal);
	font-size: 0.68rem;
	font-weight: 700;
	letter-spacing: 0.1em;
	text-transform: uppercase;
	color: var(--gold);
	border: 1px solid currentColor;
	border-radius: var(--radius-sm);
	padding: 0.28rem 0.6rem;
	transform: rotate(-1deg);
}

.trust-strip__inner span:nth-child(even),
.delivery-strip__mark:nth-child(even) {
	transform: rotate(1.2deg);
	color: var(--parchment);
}

/* Two-column splits. */
.split {
	display: grid;
	gap: clamp(1.75rem, 4vw, 3.25rem);
	align-items: center;
}

@media (min-width: 62em) {
	.split { grid-template-columns: 1fr 1fr; }
	.split--wide-media { grid-template-columns: 1.1fr 1fr; }
}

/* Photographs are mounted like prints, not bled to the edge. */
.media-frame {
	position: relative;
	background: var(--paper);
	padding: 0.75rem;
	border: 1px solid var(--rule-soft);
	box-shadow: var(--shadow-lift);
	transform: rotate(-1deg);
}

.media-frame img {
	width: 100%;
	aspect-ratio: 16 / 10;
	object-fit: cover;
}

.media-frame__play {
	position: absolute;
	inset: 0;
	margin: auto;
	width: 4.2rem;
	height: 4.2rem;
	border-radius: 50%;
	border: 2px solid var(--paper);
	background: var(--postbox);
	color: var(--snow);
	font-size: 1.2rem;
	cursor: pointer;
	display: grid;
	place-items: center;
	box-shadow: var(--shadow-lift);
	transition: transform 180ms var(--ease), background-color 180ms var(--ease);
}

.media-frame__play:hover {
	transform: scale(1.06);
	background: var(--berry);
}

/* Cards. */
.card {
	background: var(--paper);
	border: 1px solid var(--rule-soft);
	border-radius: var(--radius);
	box-shadow: var(--shadow-paper);
	padding: clamp(1.3rem, 3vw, 1.9rem);
	transition: transform 200ms var(--ease), box-shadow 200ms var(--ease);
}

.card:hover {
	transform: translateY(-3px);
	box-shadow: var(--shadow-lift);
}

.section--night .card,
.section--pine .card {
	background: rgba(238, 243, 255, 0.07);
	border-color: rgba(238, 243, 255, 0.2);
	color: var(--parchment);
	box-shadow: none;
}

.section--night .card h3 {
	color: var(--parchment);
}

.card__number {
	display: inline-block;
	font-family: var(--font-postal);
	font-size: 0.78rem;
	font-weight: 700;
	color: var(--gold);
	border: 1px solid currentColor;
	border-radius: var(--radius-sm);
	padding: 0.1rem 0.4rem;
	margin-bottom: var(--space-xs);
}

.section--night .card__number {
	color: var(--candle);
}

.product-card--featured {
	border-color: var(--postbox);
	box-shadow: 0 0 0 3px rgba(179, 30, 40, 0.12), var(--shadow-lift);
}

.product-price {
	display: inline-block;
	font-family: var(--font-display);
	font-size: var(--step-3);
	font-weight: 800;
	line-height: 1;
	color: var(--parchment);
	margin: 0.3rem 0 var(--space-s);
	padding: 0.25rem 0.65rem;
	background: var(--candle);
	border-radius: var(--radius-sm);
}

.price-note {
	font-size: var(--step--1);
	color: var(--text-muted);
}

/* Editorial layout. */
.article-layout {
	width: min(100% - (var(--gutter) * 2), var(--wide));
	margin-inline: auto;
	padding: var(--space-2xl) 0;
	display: grid;
	gap: clamp(1.75rem, 4vw, 3.25rem);
	align-items: start;
}

@media (min-width: 62em) {
	.article-layout {
		grid-template-columns: 14rem minmax(0, 1fr);
	}
}

.article-body {
	max-width: var(--measure);
	font-size: var(--step-article);
	line-height: 1.75;
}

.article-body > h2 {
	margin-top: var(--space-xl);
	padding-top: var(--space-s);
	border-top: 2px solid var(--gold);
}

.article-body > h2:first-child {
	margin-top: 0;
	border-top: 0;
	padding-top: 0;
}

.article-body h3 {
	margin-top: var(--space-l);
}

.article-body ul,
.article-body ol {
	margin: 0 0 var(--space-s);
	padding-left: 1.35rem;
	display: grid;
	gap: 0.45rem;
}

.article-body li::marker {
	color: var(--gold);
}

.article-body blockquote {
	margin: var(--space-l) 0;
	padding-left: var(--space-m);
	border-left: 3px solid var(--postbox);
	font-family: var(--font-display);
	font-size: var(--step-2);
	line-height: 1.35;
	color: var(--parchment);
}

/* Contents: an index card on desktop, a scrolling rail on mobile. */
.article-toc {
	position: sticky;
	top: calc(var(--bar-height) + 1rem);
	display: grid;
	gap: 0.1rem;
	align-content: start;
	background: var(--paper);
	border: 1px solid var(--rule-soft);
	box-shadow: var(--shadow-paper);
	padding: var(--space-s);
	font-size: var(--step--1);
}

.article-toc strong {
	display: block;
	font-family: var(--font-postal);
	font-size: 0.68rem;
	letter-spacing: 0.14em;
	text-transform: uppercase;
	color: var(--gold);
	border-bottom: 1px solid var(--rule-soft);
	padding-bottom: var(--space-2xs);
	margin-bottom: var(--space-2xs);
}

.article-toc a {
	color: var(--text-muted);
	text-decoration: none;
	padding: 0.28rem 0 0.28rem 0.6rem;
	line-height: 1.35;
	border-left: 2px solid transparent;
	transition: color 150ms var(--ease), border-color 150ms var(--ease);
}

.article-toc a:hover,
.article-toc a.is-active {
	color: var(--parchment);
	border-left-color: var(--postbox);
}

@media (max-width: 61.99em) {
	/*
	 * Jumping to a heading has to clear both sticky layers, not just the bar. The
	 * contents strip sticks directly beneath the bar, so on a page that has one the
	 * two stack to roughly 109px while the document's scroll padding only reserved the
	 * bar's 74px — landing every anchor about a heading's worth underneath the pills.
	 *
	 * Scoped with `:has()` so pages without a contents strip keep the smaller offset
	 * and do not jump further than they need to. Browsers without `:has()` fall back to
	 * the base scroll padding, which is the behaviour they have today.
	 */
	html:has(.article-toc) {
		scroll-padding-top: calc(var(--bar-height) + var(--toc-height) + 0.75rem);
	}

	.article-toc {
		position: sticky;
		top: var(--bar-height);
		z-index: 20;
		display: flex;
		gap: 0.5rem;
		overflow-x: auto;
		scrollbar-width: none;
		border-radius: 0;
		border-inline: 0;
		box-shadow: none;
		padding: 0.6rem var(--gutter);
		margin-inline: calc(var(--gutter) * -1);
	}

	.article-toc::-webkit-scrollbar { display: none; }
	.article-toc strong { display: none; }

	.article-toc a {
		flex: none;
		white-space: nowrap;
		border: 1px solid var(--rule);
		border-radius: 999px;
		padding: 0.3rem 0.75rem;
	}

	.article-toc a.is-active {
		border-color: var(--postbox);
		background: rgba(179, 30, 40, 0.1);
	}
}

/* Key facts and verdict panels. */
.key-facts {
	background: var(--kraft);
	border: 1px solid var(--kraft-line);
	border-left: 4px solid var(--spruce);
	border-radius: var(--radius);
	padding: clamp(1.2rem, 3vw, 1.8rem);
	margin: var(--space-l) 0;
}

.key-facts h2 {
	font-size: var(--step-2);
	margin-top: 0;
	border: 0;
	padding-top: 0;
}

.key-facts ul {
	margin-bottom: 0;
}

.verdict {
	position: relative;
	background: var(--spruce);
	color: var(--parchment);
	border-radius: var(--radius);
	padding: clamp(1.5rem, 4vw, 2.4rem);
	margin-bottom: var(--space-l);
	box-shadow: var(--shadow-lift);
}

.verdict h2 {
	color: var(--parchment);
	margin-top: 0;
	border: 0;
	padding-top: 0;
}

.verdict p {
	color: rgba(238, 243, 255, 0.85);
}

/* The in-content product panel, as a franked envelope. */
.inline-reveal {
	position: relative;
	background: var(--paper);
	border: 2px solid var(--postbox);
	border-radius: var(--radius);
	padding: clamp(1.4rem, 3.5vw, 2.2rem);
	margin: var(--space-xl) 0;
	box-shadow: var(--shadow-paper);
	overflow: hidden;
}

.inline-reveal::before {
	content: "";
	position: absolute;
	inset-block: 0;
	left: 0;
	width: 10px;
	background: repeating-linear-gradient(
		45deg,
		var(--postbox) 0 8px,
		var(--paper) 8px 16px,
		var(--spruce) 16px 24px,
		var(--paper) 24px 32px
	);
}

.inline-reveal > * {
	margin-left: 0.75rem;
}

.inline-reveal h3 {
	margin-bottom: var(--space-2xs);
}

.inline-reveal__stamp {
	position: absolute;
	top: 1rem;
	right: 1rem;
	width: 3.2rem;
	height: 4rem;
	background: var(--spruce);
	border: 3px solid var(--paper);
	outline: 1px dashed var(--kraft-line);
	display: none;
}

@media (min-width: 44em) {
	.inline-reveal__stamp { display: block; }
	.inline-reveal > * { margin-right: 5rem; }
}

/* Numbered reveal ideas. */
.idea-list {
	counter-reset: ideas;
	display: grid;
	gap: var(--space-l);
	margin: var(--space-l) 0 0;
	padding: 0;
	list-style: none;
}

.idea {
	counter-increment: ideas;
	position: relative;
	padding-left: clamp(3rem, 6vw, 4rem);
	padding-bottom: var(--space-l);
	border-bottom: 1px dashed var(--rule);
}

.idea:last-child {
	border-bottom: 0;
	padding-bottom: 0;
}

.idea::before {
	content: counter(ideas, decimal-leading-zero);
	position: absolute;
	left: 0;
	top: 0.15em;
	font-family: var(--font-postal);
	font-size: 0.85rem;
	font-weight: 700;
	color: var(--gold);
	border: 1px solid currentColor;
	border-radius: var(--radius-sm);
	padding: 0.15rem 0.4rem;
}

.idea h2,
.idea h3 {
	margin-top: 0;
	border: 0;
	padding-top: 0;
}

/* The free ticket studio. */
.ticket-studio {
	display: grid;
	gap: clamp(1.75rem, 4vw, 3rem);
	align-items: center;
}

@media (min-width: 62em) {
	.ticket-studio { grid-template-columns: 21rem minmax(0, 1fr); }
}

.ticket-controls {
	background: var(--paper);
	border: 1px solid var(--rule-soft);
	border-radius: var(--radius);
	box-shadow: var(--shadow-paper);
	padding: clamp(1.3rem, 3vw, 1.9rem);
}

.ticket-controls h2 {
	font-size: var(--step-2);
}

.ticket-controls .button {
	width: 100%;
}

.ticket-controls p {
	margin-top: var(--space-s);
	color: var(--text-muted);
}

.ticket {
	position: relative;
	background: var(--paper);
	border: 2px solid var(--spruce);
	border-radius: var(--radius);
	padding: clamp(1.4rem, 4vw, 2.2rem);
	display: grid;
	gap: var(--space-m);
	min-height: 14rem;
	box-shadow: var(--shadow-lift);
	overflow: hidden;
}

.ticket::before {
	content: "";
	position: absolute;
	inset-block: 0;
	right: 22%;
	width: 2px;
	background: repeating-linear-gradient(180deg, var(--rule) 0 6px, transparent 6px 12px);
}

/*
 * Once the studio script runs, the pass becomes a single 300 DPI canvas and the markup
 * above is replaced wholesale. The frame, padding and perforation all belong to the
 * drawn artwork now, so the container gets out of its way.
 */
.ticket--canvas {
	background: none;
	border: 0;
	padding: 0;
	min-height: 0;
	box-shadow: none;
	display: block;
}

.ticket--canvas::before {
	display: none;
}

.ticket__canvas {
	display: block;
	width: 100%;
	height: auto;
	border-radius: var(--radius);
	box-shadow: var(--shadow-lift);
}

.ticket-actions {
	display: flex;
	flex-wrap: wrap;
	gap: var(--space-2xs);
	margin-top: var(--space-s);
}

/* The print sheet only ever exists for the printer. */
.lr5-print-sheet {
	display: none;
}

/*
 * The letter studio. The drawn letter is on white paper — deliberately, since a full
 * A4 of the dark theme would be brutal on a home printer — so it is given a frame on
 * screen to stop it glaring against the spruce ground.
 */
.letter-studio {
	display: grid;
	gap: var(--space-l);
	margin: var(--space-l) 0;
}

@media (min-width: 52em) {
	.letter-studio {
		grid-template-columns: 20rem minmax(0, 1fr);
		align-items: start;
	}
}

.letter-side {
	display: grid;
	gap: var(--space-s);
	align-content: start;
}

.letter-controls {
	display: grid;
	gap: var(--space-s);
}

.letter-actions {
	display: flex;
	flex-wrap: wrap;
	gap: var(--space-2xs);
}

.letter-note small {
	color: var(--text-muted);
}

.letter-preview {
	border: 1px solid var(--rule-soft);
	border-radius: var(--radius);
	padding: var(--space-2xs);
	background: rgba(255, 255, 255, 0.06);
}

.letter__canvas {
	display: block;
	width: 100%;
	height: auto;
	border-radius: calc(var(--radius) * 0.6);
	box-shadow: var(--shadow-lift);
}

/*
 * The invitation studio — written mobile first.
 *
 * Phone-out rather than desktop-down, because that is where this page gets read. The
 * keyword peaks in the last week of November and the person it is aimed at is deciding
 * on a Saturday evening, on a phone, for a reveal tomorrow.
 *
 * Laid out the other way round the source order put the invitation itself 1,700px down
 * a 812px-tall screen — form, then four portrait thumbnails, then the buttons, and only
 * then the artefact. Two full screens below the fold, on the one page whose entire
 * proposition is that you watch it being made. So the default is a single column with
 * the preview pinned to the top and the controls scrolling underneath it.
 *
 * The chooser is a real radio group. The thumbnails are labels for those radios rather
 * than clickable divs, so it arrives keyboard-navigable and announces the selected style
 * without any of that having to be reimplemented in script.
 */
/*
 * The studio sits in its own panel, in the same paper-and-hairline language as the
 * article contents box and the key-facts panels, so it reads as part of the site rather
 * than as an application bolted into the page.
 */
.invitation-studio {
	display: block;
	margin: var(--space-l) 0;
	padding: clamp(1rem, 3vw, 1.8rem);
	background: var(--paper);
	border: 1px solid var(--rule-soft);
	border-radius: var(--radius);
	box-shadow: var(--shadow-paper);
	/* Belt and braces: nothing inside may widen the page on a phone. */
	max-width: 100%;
	overflow-x: clip;
}

/*
 * Sticky, and pinned to the *visual* viewport rather than the layout one.
 *
 * iOS sticks sticky elements to the layout viewport. Focusing an input shrinks the
 * visual viewport for the keyboard without moving the layout viewport, so a preview
 * pinned at layout-top slides off the top of the screen exactly when it matters. There
 * is no CSS-only fix, so invitation-creator.js watches window.visualViewport and keeps
 * --lr5-vv-top and --lr5-vv-h in step with it. Both have defaults here, so the rule
 * degrades to ordinary sticky if that script never runs.
 */
.invitation-preview {
	position: sticky;
	top: var(--lr5-vv-top, 0px);
	z-index: 3;
	margin-bottom: var(--space-s);
	/* Opaque: content scrolls underneath a sticky panel. */
	background: var(--night);
	border: 1px solid var(--rule);
	border-radius: var(--radius);
	padding: var(--space-2xs);
}

/*
 * Sized against the visual viewport, not vh.
 *
 * The pinned preview and an open keyboard compete for the same screen, and iOS does not
 * shrink vh when the keyboard appears — so a vh-based cap is taken off the top
 * permanently while someone is typing. --lr5-vv-h is the real visible height, kept up to
 * date by the studio script, so the invitation quietly gets smaller while the keyboard is
 * up and returns to full size when it closes. vh is the fallback if the script is absent.
 */
.invitation__canvas {
	display: block;
	width: auto;
	max-width: 100%;
	max-height: min(36vh, calc(var(--lr5-vv-h, 100vh) * 0.42));
	margin: 0 auto;
	border-radius: calc(var(--radius) * 0.6);
	box-shadow: var(--shadow-lift);
}

/* Landscape phones, and anything else short. */
@media (max-height: 34rem) {
	.invitation__canvas {
		max-height: 60vh;
	}
}

.invitation-side {
	display: grid;
	gap: var(--space-s);
	align-content: start;
}

.invitation-controls {
	display: grid;
	gap: var(--space-s);
}

.invitation-controls .field--choice {
	border: 1px solid var(--rule-soft);
	border-radius: var(--radius);
	padding: var(--space-2xs) var(--space-xs) var(--space-xs);
	margin: 0;
}

.invitation-controls legend,
.invitation-presets legend {
	font-family: var(--font-postal);
	font-size: 0.68rem;
	letter-spacing: 0.18em;
	text-transform: uppercase;
	color: var(--gold);
	padding: 0 var(--space-2xs);
}

.invitation-controls .choice {
	display: flex;
	align-items: center;
	gap: var(--space-2xs);
}

/*
 * Radios have to opt out of the shared field styling. `.field input` sets width: 100%
 * plus padding and a border for text inputs, and a radio inheriting that became a
 * full-width control that pushed its own label off the side of the screen on iOS.
 */
.invitation-controls .choice input[type="radio"] {
	flex: 0 0 auto;
	width: 1.2rem;
	height: 1.2rem;
	min-width: 1.2rem;
	padding: 0;
	border: 0;
	border-radius: 50%;
	background: none;
	accent-color: var(--gold);
}

/*
 * A comfortable thumb target, which a bare radio and its label are not — and sentence
 * case rather than the caps used for field labels, because "An Elf of the North Pole"
 * set in tracked capitals is a paragraph.
 */
.invitation-controls .choice label {
	display: flex;
	align-items: center;
	flex: 1 1 auto;
	min-width: 0;
	min-height: 2.75rem;
	font-size: 0.82rem;
	letter-spacing: 0.02em;
	text-transform: none;
	color: var(--text);
	cursor: pointer;
}

.invitation-presets {
	border: 0;
	padding: 0;
	margin: 0;
}

/*
 * A swipeable row on phones. The same four thumbnails as a two-up grid came to 635px of
 * chooser before the visitor had reached a button.
 */
.invitation-presets__grid {
	display: flex;
	gap: var(--space-2xs);
	overflow-x: auto;
	/* Keep the swipe inside the strip; without it iOS rubber-bands the whole page. */
	overscroll-behavior-x: contain;
	scroll-snap-type: x mandatory;
	-webkit-overflow-scrolling: touch;
	margin-top: var(--space-2xs);
	padding-bottom: var(--space-2xs);
}

.invitation-preset {
	position: relative;
	flex: 0 0 34%;
	scroll-snap-align: start;
}

/*
 * Visually hidden rather than display:none — a display:none radio is removed from the
 * tab order, which would leave the chooser mouse-only.
 */
.invitation-preset__input {
	position: absolute;
	width: 1px;
	height: 1px;
	opacity: 0;
	pointer-events: none;
}

.invitation-preset__label {
	display: grid;
	gap: var(--space-2xs);
	padding: var(--space-2xs);
	border: 1px solid var(--rule-soft);
	border-radius: var(--radius);
	cursor: pointer;
	transition: border-color 0.15s ease, background-color 0.15s ease;
}

.invitation-preset__input:checked + .invitation-preset__label {
	border-color: var(--gold);
	background: rgba(255, 255, 255, 0.06);
}

.invitation-preset__input:focus-visible + .invitation-preset__label {
	outline: 2px solid var(--gold);
	outline-offset: 2px;
}

.invitation-preset__thumb {
	display: block;
	width: 100%;
	height: auto;
	border-radius: calc(var(--radius) * 0.5);
}

.invitation-preset__name {
	font-family: var(--font-display);
	font-size: 0.82rem;
	line-height: 1.2;
}

/* No room for a second line of type beside a thumbnail this narrow. */
.invitation-preset__summary {
	display: none;
	font-size: 0.74rem;
	line-height: 1.3;
	color: var(--text-muted);
}

.invitation-actions {
	display: flex;
	flex-wrap: wrap;
	gap: var(--space-2xs);
}

.invitation-actions .button {
	flex: 1 1 auto;
	min-height: 2.75rem;
}

.invitation-note small {
	color: var(--text-muted);
}

/*
 * From here up it is a desk. Two columns, the preview back in the flow at full size,
 * and the chooser as a grid with room for each design's one-line description.
 */
@media (min-width: 52em) {
	.invitation-studio {
		display: grid;
		grid-template-columns: 22rem minmax(0, 1fr);
		gap: var(--space-l);
		align-items: start;
	}

	/* DOM order is preview-then-controls for the phone; put it back for the desk. */
	.invitation-side {
		order: 1;
	}

	.invitation-preview {
		order: 2;
		/* Side by side on a desk — nothing to pin against, and nothing to pin for. */
		position: static;
		min-width: 0;
		margin-bottom: 0;
		background: rgba(255, 255, 255, 0.06);
		border-color: var(--rule-soft);
	}

	.invitation-side {
		min-width: 0;
	}

	/*
	 * Capped rather than 100%. In a panel this wide an uncapped A4 canvas becomes a very
	 * tall column of paper that pushes everything else off the screen — the invitation
	 * should look like a card on a desk, not a poster.
	 */
	.invitation__canvas {
		width: auto;
		max-height: min(70vh, 34rem);
	}

	.invitation-presets__grid {
		display: grid;
		grid-template-columns: repeat(2, minmax(0, 1fr));
		gap: var(--space-xs);
		overflow: visible;
	}

	.invitation-preset {
		flex: none;
	}

	.invitation-preset__label:hover {
		border-color: var(--gold);
	}

	.invitation-preset__name {
		font-size: 0.9rem;
	}

	.invitation-preset__summary {
		display: block;
	}
}

.ticket__route {
	font-family: var(--font-postal);
	font-size: 0.68rem;
	letter-spacing: 0.2em;
	text-transform: uppercase;
	color: var(--gold);
}

.ticket__name {
	font-family: var(--font-display);
	font-size: var(--step-3);
	font-weight: 800;
	line-height: 1.05;
	color: var(--parchment);
	margin-top: 0.3rem;
	word-break: break-word;
}

.ticket__meta {
	display: grid;
	grid-template-columns: repeat(auto-fit, minmax(7rem, 1fr));
	gap: var(--space-s);
	border-top: 1px dashed var(--rule);
	padding-top: var(--space-s);
}

.ticket__meta small {
	display: block;
	font-family: var(--font-postal);
	font-size: 0.6rem;
	letter-spacing: 0.16em;
	text-transform: uppercase;
	color: var(--text-muted);
	margin-bottom: 0.15rem;
}

.ticket__meta span {
	font-weight: 700;
	color: var(--parchment);
}

/* Utility bars. */
.page-utility {
	background: var(--parchment);
	border-bottom: 1px solid var(--rule-soft);
}

.page-utility__inner {
	padding: var(--space-s) 0;
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	justify-content: space-between;
	gap: var(--space-xs) var(--space-m);
}

.breadcrumbs {
	font-family: var(--font-postal);
	font-size: 0.74rem;
	letter-spacing: 0.04em;
	color: var(--text-muted);
	display: flex;
	align-items: center;
	gap: 0.5rem;
	flex-wrap: wrap;
}

.breadcrumbs a {
	color: var(--text-muted);
}

.breadcrumbs a:hover {
	color: var(--gold);
}

.article-meta {
	display: flex;
	align-items: center;
	flex-wrap: wrap;
	gap: 0.4rem 1rem;
	font-family: var(--font-postal);
	font-size: 0.74rem;
	color: var(--text-muted);
}

.article-meta__by {
	font-weight: 700;
	color: var(--parchment);
}

.reading-progress {
	position: fixed;
	top: 0;
	left: 0;
	right: 0;
	height: 3px;
	z-index: 60;
	pointer-events: none;
}

.reading-progress span {
	display: block;
	height: 100%;
	width: 0;
	background: var(--postbox);
	transition: width 90ms linear;
}

/* --------------------------------------------------------- 13 WooCommerce */

.woocommerce .woo-reassurance {
	list-style: none;
	margin: var(--space-s) 0 0;
	padding: 0;
	display: grid;
	gap: 0.4rem;
	font-size: var(--step--1);
	color: var(--text-muted);
}

.woocommerce div.product .product_title,
.woocommerce ul.products li.product h2 {
	font-family: var(--font-display);
	color: var(--parchment);
}

.woocommerce div.product p.price,
.woocommerce ul.products li.product .price {
	color: var(--parchment);
	font-family: var(--font-display);
	font-size: var(--step-2);
}

.woocommerce-message,
.woocommerce-info {
	border-top-color: var(--postbox);
}

.woocommerce-message::before,
.woocommerce-info::before {
	color: var(--gold);
}

/* --------------------------------------- 14 Accessibility and motion */

.skip-link {
	position: absolute;
	left: -9999px;
	top: 0;
	z-index: 100;
	background: var(--postbox);
	color: var(--snow);
	padding: 0.75rem 1.25rem;
	font-weight: 700;
	text-decoration: none;
}

.skip-link:focus {
	left: 0;
}

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

:where(a, button, summary, input, select, textarea, [tabindex]):focus-visible {
	outline: 3px solid var(--postbox);
	outline-offset: 2px;
	border-radius: var(--radius-sm);
}

.section--pine :where(a, button):focus-visible,
.section--night :where(a, button):focus-visible,
.postbox-cta :where(a, button):focus-visible,
.site-footer :where(a, button):focus-visible {
	outline-color: var(--candle);
}

.video-theatre {
	position: fixed;
	inset: 0;
	z-index: 90;
	display: grid;
	place-items: center;
	background: rgba(17, 29, 64, 0.95);
	padding: var(--gutter);
}

.video-theatre video,
.video-theatre__embed {
	width: min(100%, 66rem);
	max-height: 82svh;
	border: 10px solid var(--paper);
	/* Matches the showcase frame so the same video keeps its shape when enlarged. */
	border-radius: var(--radius-lg);
	box-shadow: var(--shadow-lift);
	background: #000;
}

/* An iframe has no intrinsic ratio to size against, so it is given one. */
.video-theatre__embed {
	aspect-ratio: 16 / 9;
	height: auto;
}

.video-theatre__close {
	position: absolute;
	top: var(--gutter);
	right: var(--gutter);
	width: 2.75rem;
	height: 2.75rem;
	border-radius: 50%;
	border: 1px solid rgba(238, 243, 255, 0.5);
	background: transparent;
	color: var(--parchment);
	font-size: 1.1rem;
	cursor: pointer;
}

.video-theatre__close:hover {
	background: var(--postbox);
	border-color: var(--postbox);
	color: var(--snow);
}

@media (prefers-reduced-motion: reduce) {
	html {
		scroll-behavior: auto;
	}

	*,
	*::before,
	*::after {
		animation-duration: 0.001ms !important;
		animation-iteration-count: 1 !important;
		transition-duration: 0.001ms !important;
	}

	/* The snow is decoration; it goes entirely rather than freezing mid-fall. */
	.hero .snow,
	.article-hero .snow {
		display: none;
	}
}

@media (prefers-contrast: more) {
	:root {
		--text-muted: #cfd9f2;
		--rule: rgba(216, 171, 92, 0.6);
		--rule-soft: rgba(216, 171, 92, 0.4);
	}
}

/* ------------------------------------------------- 24 The video showcase */

/*
 * The sample video, directly under the hero. Dark surface so the frame reads as a
 * screen rather than another sheet of paper, and so it separates the hero from the
 * parchment sections below it.
 */
.video-showcase {
	background: var(--pine, #0d1730);
	background-image: var(--fibre);
	background-size: 160px 160px;
	padding: var(--space-2xl) 0;
	text-align: center;
	color: var(--parchment);
}

.video-showcase .eyebrow {
	color: var(--gold);
}

.video-showcase__title {
	font-family: var(--font-display);
	font-size: clamp(1.7rem, 1.1rem + 2.6vw, 2.6rem);
	line-height: 1.1;
	/* The eyebrow above this is gone, so the heading opens the section itself. */
	margin: 0;
	color: var(--parchment);
}

.video-showcase__lede {
	margin: 0;
	color: rgba(238, 243, 255, 0.86);
	font-size: var(--step-1);
}

.video-showcase__body {
	margin: var(--space-s) 0 0;
	color: rgba(238, 243, 255, 0.7);
}

.video-showcase__copy {
	max-width: 56ch;
	margin: var(--space-l) auto 0;
}

.video-showcase__frame {
	position: relative;
	max-width: 62rem;
	margin: var(--space-l) auto 0;
	aspect-ratio: 16 / 9;
	overflow: hidden;
	/*
	 * Softer than the theme's --radius-lg. Everything else on the site is paper,
	 * where a near-square corner is right; this one is a screen, and reads as one
	 * with a rounder corner. Kept off the sharp end so it still sits in the set.
	 */
	border-radius: var(--radius-lg);
	border: 1px solid rgba(238, 243, 255, 0.22);
	box-shadow: var(--shadow-lift);
	background: #000;
}

.video-showcase__poster,
.video-showcase__frame iframe {
	position: absolute;
	inset: 0;
	width: 100%;
	height: 100%;
	border: 0;
	object-fit: cover;
	display: block;
}

.video-showcase__play {
	position: absolute;
	inset: 0;
	display: grid;
	place-content: center;
	gap: var(--space-xs);
	justify-items: center;
	width: 100%;
	background: linear-gradient(180deg, rgba(13, 23, 48, 0.12), rgba(13, 23, 48, 0.55));
	border: 0;
	color: var(--parchment);
	cursor: pointer;
	transition: background-color 180ms var(--ease);
}

.video-showcase__play:hover,
.video-showcase__play:focus-visible {
	background: linear-gradient(180deg, rgba(13, 23, 48, 0.05), rgba(13, 23, 48, 0.42));
}

/* A wax-seal disc with a play triangle punched out of it. */
.video-showcase__play-mark {
	width: clamp(3.6rem, 8vw, 5.2rem);
	aspect-ratio: 1;
	border-radius: 50%;
	background: var(--postbox);
	border: 2px solid rgba(238, 243, 255, 0.85);
	box-shadow: 0 10px 30px -12px rgba(0, 0, 0, 0.8);
	display: grid;
	place-content: center;
	transition: transform 180ms var(--ease);
}

.video-showcase__play-mark::after {
	content: "";
	width: 0;
	height: 0;
	margin-left: 0.28em;
	border-left: 1.05rem solid var(--parchment);
	border-top: 0.66rem solid transparent;
	border-bottom: 0.66rem solid transparent;
}

.video-showcase__play:hover .video-showcase__play-mark {
	transform: scale(1.06);
}

.video-showcase__play-label {
	font-family: var(--font-postal);
	font-size: 0.72rem;
	font-weight: 700;
	letter-spacing: 0.18em;
	text-transform: uppercase;
	text-shadow: 0 1px 12px rgba(0, 0, 0, 0.6);
}

.video-showcase__action {
	margin-top: var(--space-l);
}

@media (prefers-reduced-motion: reduce) {
	.video-showcase__play-mark,
	.video-showcase__play:hover .video-showcase__play-mark {
		transition: none;
		transform: none;
	}
}

/* A media frame that became a facade plays in place; the iframe fills the frame. */
.media-frame[data-lr5-facade] {
	position: relative;
}

.media-frame[data-lr5-facade] iframe {
	display: block;
	width: 100%;
	aspect-ratio: 16 / 9;
	border: 0;
	border-radius: var(--radius-lg);
	background: #000;
}

/* ------------------- 15 Ornament layer — gilding, lanterns, snow, aurora */

/*
 * Everything below is what makes v4 v4. It is deliberately the last section, and almost
 * entirely additive: strip section 15 and the theme still renders as a legible dark
 * site. That property is what lets the illustrated art be optional.
 *
 * One change could not live here. Sections 8–13 were written for pale paper, where
 * `color: var(--spruce)` meant "heading" and `color: var(--postbox)` meant "accent" —
 * both of which disappear on a dark ground. Every `color:` use of those two tokens was
 * re-pointed to parchment and gold in place, throughout the file. Their background and
 * border uses are untouched, and are still spruce and red.
 *
 * ART HOOKS. Each ornament reads a custom property that is `none` by default. When the
 * matching file in assets/images/ornaments/ exists, switch it on by uncommenting the
 * one line in the block marked "generated art" at the end of this section. Until then
 * the CSS-drawn fallback beneath it does the job. See ornaments/PROMPTS.md for the
 * generation prompts and the exact filenames and sizes each hook expects.
 */

:root {
	--art-snow-edge: none;
	--art-lantern: none;
	--art-corner: none;
	--art-seal: none;
	--art-flourish: none;
	--art-frame: none;
	--art-aurora-plate: none;
	--art-holly: none;

	/*
	 * The drawn drift, capped at 54px. It carries icicles in its lower third and wants
	 * height to read as snow rather than as a white line, but much past this it starts
	 * to dominate the section boundary instead of decorating it.
	 */
	--snow-edge-height: clamp(36px, 5.1vw, 54px);
	--lantern-width: clamp(52px, 7vw, 104px);

	/*
	 * The two crown plates together are 3.274 times this tall in width, so the ceiling
	 * keeps them from meeting in the middle on a phone: at the 56px floor they occupy
	 * 183px, which still leaves a gap at the narrowest width worth supporting.
	 */
	--crown-height: clamp(56px, 8.5vw, 132px);
}

/* ------------------------------------------------------------ 15.1 The sky */

/*
 * The aurora is painted on a fixed pseudo-element rather than the body background so
 * it stays put while the page scrolls — the sky should not slide past the trees.
 */
/*
 * v4 fixed the sky to the viewport, which was fine when the aurora was weak. At v5's
 * strength that parks a teal bloom permanently behind the middle of a 4,000-word
 * article, and both the text and the effect suffer for it.
 *
 * So the sky is now a band anchored to the top of the *document* rather than the
 * viewport: it lights the masthead and the hero, fades out over the first screen and a
 * half, and everything below it is plain --night to read against. That is also how an
 * aurora behaves — it is in the sky, not in the room.
 *
 * `position: absolute` on a static body resolves against the initial containing block,
 * which is exactly the document-origin anchor wanted here; body does not need to become
 * a positioned ancestor for it.
 */
body::before {
	content: "";
	position: absolute;
	top: 0;
	left: 0;
	right: 0;
	height: var(--sky-height);
	z-index: -2;
	background-image: var(--art-aurora-plate), var(--stars), var(--aurora);
	background-size: cover, 900px 700px, cover;
	background-position: center top;
	background-repeat: no-repeat, repeat, no-repeat;
	/* Feathered out at the bottom so the band never ends on a visible edge. */
	-webkit-mask-image: linear-gradient(180deg, #000 0%, #000 34%, transparent 100%);
	mask-image: linear-gradient(180deg, #000 0%, #000 34%, transparent 100%);
	pointer-events: none;
}

/*
 * The stars breathe. A very slow, very small opacity drift — enough that the sky is
 * never quite the same twice, not enough to notice it happening. 90s, because anything
 * faster starts reading as a loading state rather than as weather.
 */
@media (prefers-reduced-motion: no-preference) {
	body::before {
		animation: lr5-sky 90s ease-in-out infinite;
	}
}

@keyframes lr5-sky {
	0%, 100% { opacity: 1; }
	50%      { opacity: 0.72; }
}

/* A vignette so the gilding at the edges never competes with the content. */
body::after {
	content: "";
	position: fixed;
	inset: 0;
	z-index: -1;
	background: radial-gradient(120% 80% at 50% 30%, transparent 40%, rgba(5, 11, 28, 0.75) 100%);
	pointer-events: none;
}

/* --------------------------------------------------- 15.2 Snow along an edge */

/*
 * A drift that straddles a boundary: the snow gathers on the section above and the
 * icicles hang into the section below.
 *
 * `background-size: auto 100%` is height-driven, so the drift keeps its drawn
 * proportions at every width rather than being stretched to fit. That relies on the
 * plate tiling cleanly, which the drawn one does: it is stored as the artwork followed
 * by a mirrored copy of itself, so the columns that meet when it repeats are identical
 * and there is no seam at any viewport width. Do not replace it with an unmirrored
 * strip — the original seams visibly.
 */
.snow-edge {
	position: absolute;
	left: 0;
	right: 0;
	height: var(--snow-edge-height);
	pointer-events: none;
	background-image: var(--art-snow-edge);
	background-size: auto 100%;
	background-repeat: repeat-x;
	background-position: left top;
}

.snow-edge::before {
	content: "";
	position: absolute;
	inset: 0;
	background:
		radial-gradient(14px 10px at 8% 100%, var(--snow) 60%, transparent 62%),
		radial-gradient(22px 12px at 24% 100%, var(--snow) 60%, transparent 62%),
		radial-gradient(16px 9px at 41% 100%, var(--snow) 60%, transparent 62%),
		radial-gradient(26px 13px at 58% 100%, var(--snow) 60%, transparent 62%),
		radial-gradient(18px 10px at 76% 100%, var(--snow) 60%, transparent 62%),
		radial-gradient(20px 11px at 93% 100%, var(--snow) 60%, transparent 62%),
		linear-gradient(180deg, transparent 72%, rgba(255, 255, 255, 0.85) 100%);
	opacity: 0.82;
}

/* When the drawn plate is available the CSS drift would double it up. */
.snow-edge[style*="ornaments"]::before,
:root:not([data-lr5-art="fallback"]) .snow-edge.has-art::before {
	display: none;
}

/*
 * Both variants straddle their boundary rather than sitting inside the section. The
 * drawn drift's base — where the snow rests and the icicles start — sits 64% of the way
 * down the plate, not at its middle, so that is the point pinned to the section edge:
 * 64% of the plate above the line, the icicles in the 36% below it. Centring the plate
 * instead would put a slab of solid snow below the boundary and read as embedded rather
 * than resting on it.
 *
 * No `scaleY(-1)` any more. That flip existed to turn the CSS fallback's drift upside
 * down for a top edge; flipping the drawn plate would point the icicles at the sky.
 */
.snow-edge--top {
	top: calc(var(--snow-edge-height) * -0.64);
}

.snow-edge--bottom {
	bottom: calc(var(--snow-edge-height) * -0.36);
}

/*
 * The footer drift. The same plate does duty at the top of the footer and along the
 * bottom of every hero, which is efficient but reads as a repeat once you have scrolled
 * past three of them. This hook lets the footer take a deeper, heavier drift so the page
 * ends on a floor rather than on the same trim it started with.
 *
 * Optional, like every other ornament: without the file it inherits the standard plate
 * and nothing looks broken. Render `snow-drift-deep.webp` into assets/images/ornaments/
 * and it takes over on its own.
 */
.site-footer .snow-edge--top {
	--snow-edge-height: clamp(3.2rem, 7vw, 5.4rem);
}

.site-footer .snow-edge--top::before {
	background-image: var(--art-snow-drift, var(--art-snow-edge));
}

/* ------------------------------------------------------- 15.3 Gilded rules */

/*
 * The double rule with a diamond at its centre, used to close a masthead and to open
 * a section. Pure CSS: a gradient hairline that fades at both ends, so it never
 * collides with the gutter.
 */
.gild-rule {
	position: relative;
	height: 1px;
	border: 0;
	margin: var(--space-s) 0;
	background: linear-gradient(90deg, transparent, var(--rule) 12%, var(--gold) 50%, var(--rule) 88%, transparent);
}

.gild-rule::after {
	content: "";
	position: absolute;
	left: 50%;
	top: 50%;
	width: 7px;
	height: 7px;
	background: var(--gold-bright);
	transform: translate(-50%, -50%) rotate(45deg);
	box-shadow: 0 0 10px rgba(255, 207, 133, 0.7);
}

/* The centred flourish above a section title. */
.flourish {
	display: block;
	width: clamp(120px, 22vw, 260px);
	height: 20px;
	margin: 0 auto var(--space-xs);
	background-image: var(--art-flourish);
	background-size: contain;
	background-position: center;
	background-repeat: no-repeat;
}

.flourish::before {
	content: "❋";
	display: block;
	text-align: center;
	color: var(--gold);
	font-size: 0.9rem;
	line-height: 20px;
	letter-spacing: 1.4em;
	text-indent: 1.4em;
	opacity: 0.85;
}

/* ------------------------------------------------ 15.4 Corner filigree */

/*
 * Four corner pieces on the frame that wraps the masthead. The fallback is an L of two
 * gilded hairlines, which is quiet enough to live with permanently if the drawn
 * filigree never arrives.
 */
.gild-frame {
	position: relative;
}

.gild-frame > .corner {
	position: absolute;
	width: clamp(28px, 4vw, 64px);
	height: clamp(28px, 4vw, 64px);
	background-image: var(--art-corner);
	background-size: contain;
	background-repeat: no-repeat;
	pointer-events: none;
}

.gild-frame > .corner::before {
	content: "";
	position: absolute;
	inset: 0;
	border-top: 1px solid var(--gold);
	border-left: 1px solid var(--gold);
	opacity: 0.55;
}

.corner--tl { top: 8px; left: 8px; }
.corner--tr { top: 8px; right: 8px; transform: scaleX(-1); }
.corner--bl { bottom: 8px; left: 8px; transform: scaleY(-1); }
.corner--br { bottom: 8px; right: 8px; transform: scale(-1); }

/* ------------------------------------------ 15.4b The crown along the top */

/*
 * The gilded top border of the masthead: two drawn plates, one hung in each top
 * corner, joined across the middle by a hairline. Each plate carries its own snow
 * drift, fairy lights, corner filigree and a rod that drops to a spearhead finial,
 * so this replaces both the CSS snow drift and the small corner filigree here.
 *
 * The two plates were not drawn to match, so they were reconciled when they were
 * cut (see PROMPTS.md): the right plate is scaled to 91.2% of the left so that both
 * the rail and the rod finial land on the same line, and both were cropped to a
 * shared 807px-tall canvas with the rail at y=64. What that buys is the two numbers
 * below — give both plates the same height and everything lines up on its own, at
 * any viewport width, with no per-breakpoint nudging.
 */
.gild-crown {
	position: absolute;
	top: 0;
	left: 0;
	right: 0;
	height: var(--crown-height);
	pointer-events: none;
	/*
	 * Deliberately no `z-index` here. A positioned element with a non-auto z-index
	 * forms its own blending group, which would isolate the `screen` on the plates
	 * below and render them as black boxes. Being positioned and later in the markup
	 * than the masthead background is enough to paint above it.
	 */
}

/*
 * The rail that carries across the middle. Both plates taper to a fine point at
 * their inner ends, so a hairline at the rail's own height (64/807 = 7.9% of the
 * plate) reads as one continuous rail rather than as two pieces plus a join. It
 * also means the gap between the plates on a wide screen is never empty.
 */
.gild-crown::before {
	content: "";
	position: absolute;
	left: 0;
	right: 0;
	top: calc(var(--crown-height) * 0.079);
	height: 1px;
	background: linear-gradient(90deg, rgba(216, 171, 92, 0) 0%, var(--gold) 12%, var(--gold) 88%, rgba(216, 171, 92, 0) 100%);
	opacity: 0.7;
}

/*
 * The plates are stored flattened onto black rather than with an alpha channel, and
 * composited with `screen` — black is the identity colour for screen, so the black
 * ground disappears and only the gilding and snow are added to what is behind. That
 * cut the pair from 65KB to 15KB, and it suits the art better than alpha did: these
 * are glows and fairy lights, which are physically additive, so the halos now build
 * on the spruce ground instead of veiling it.
 *
 * The tradeoff is that `screen` needs an unisolated backdrop. If an ancestor of the
 * crown ever gains a transform, filter, opacity below 1, or `isolation: isolate`, the
 * blend stops reaching the page behind it and the plates render as black boxes. As of
 * this writing the ancestors are only `.masthead__full` (position and background) and
 * `.masthead`; the transforms in this file are on `.masthead__bar` and its children,
 * which are siblings, so they are safe.
 */
.gild-crown__end {
	position: absolute;
	top: 0;
	height: 100%;
	background-repeat: no-repeat;
	background-size: auto 100%;
	mix-blend-mode: screen;
}

/*
 * Each width is the plate's own aspect ratio (755/420 and 620/420), so pairing it
 * with `background-size: auto 100%` scales the art by height alone — it is never
 * cropped or stretched, and the plates simply grow and shrink with --crown-height.
 */
.gild-crown__end--left {
	left: 0;
	width: calc(var(--crown-height) * 1.798);
	background-image: url("../images/ornaments/corner-top-left.webp");
	background-position: left top;
}

.gild-crown__end--right {
	right: 0;
	width: calc(var(--crown-height) * 1.476);
	background-image: url("../images/ornaments/corner-top-right.webp");
	background-position: right top;
}

/* ---------------------------------------------------------- 15.5 Lanterns */

/*
 * The lanterns hang from the top edge, flanking the masthead. They are decorative and
 * carry no meaning, so they are hidden from assistive technology in the template and
 * dropped entirely below the width where they would crowd the wordmark.
 */
.lantern {
	position: absolute;
	top: 0;
	width: var(--lantern-width);
	aspect-ratio: 1 / 2.4;
	background-image: var(--art-lantern);
	background-size: contain;
	background-position: top center;
	background-repeat: no-repeat;
	pointer-events: none;
	transform-origin: 50% 0;
	animation: lr5-sway 7s ease-in-out infinite alternate;
}

.lantern--left { left: clamp(0.5rem, 3vw, 3.5rem); }
.lantern--right { right: clamp(0.5rem, 3vw, 3.5rem); animation-delay: -3.5s; }

/* Fallback: a chain, a warm glass box and the glow it throws. */
.lantern::before {
	content: "";
	position: absolute;
	top: 0;
	left: 50%;
	width: 2px;
	height: 38%;
	transform: translateX(-50%);
	background: linear-gradient(180deg, var(--gold-deep), var(--gold));
}

.lantern::after {
	content: "";
	position: absolute;
	top: 38%;
	left: 50%;
	width: 68%;
	height: 46%;
	transform: translateX(-50%);
	border: 1px solid var(--gold);
	border-radius: var(--radius) var(--radius) var(--radius-lg) var(--radius-lg);
	background: linear-gradient(180deg, rgba(255, 207, 133, 0.95), rgba(216, 138, 43, 0.75));
	box-shadow: var(--glow-candle);
}

@keyframes lr5-sway {
	from { transform: rotate(-2.2deg); }
	to { transform: rotate(2.2deg); }
}

@media (max-width: 61.99em) {
	.lantern { display: none; }
}

/* ------------------------------------------------------- 15.6 The wax seal */

/*
 * The date stamp in the masthead's top right. Set as a wax medallion with a stamped
 * ring of type. The date is printed by the template, so it is always today's.
 */
.seal {
	position: relative;
	display: grid;
	place-content: center;
	gap: 0.1rem;
	width: clamp(64px, 8vw, 96px);
	aspect-ratio: 1;
	border-radius: 50%;
	text-align: center;
	color: var(--gold-bright);
	font-family: var(--font-postal);
	text-transform: uppercase;
	background-image: var(--art-seal);
	background-size: contain;
	background-repeat: no-repeat;
	background-color: var(--berry);
	box-shadow:
		inset 0 -3px 6px rgba(0, 0, 0, 0.45),
		inset 0 2px 4px rgba(255, 255, 255, 0.15),
		0 6px 18px -8px rgba(0, 0, 0, 0.9);
}

.seal::before {
	content: "";
	position: absolute;
	inset: 6px;
	border: 1px solid rgba(242, 214, 154, 0.6);
	border-radius: 50%;
}

.seal__top,
.seal__bottom {
	font-size: 0.44rem;
	letter-spacing: 0.16em;
	opacity: 0.9;
}

.seal__date {
	font-size: 0.72rem;
	font-weight: 700;
	letter-spacing: 0.06em;
}

/* ------------------------------------------- 15.7 Masthead and navigation */

.masthead__full {
	position: relative;
	background:
		linear-gradient(180deg, rgba(5, 11, 28, 0.9), rgba(10, 20, 48, 0.72));
	border-bottom: 0;
	/* Clear the crown's rail so the wordmark never rides up into the snow. */
	padding-top: calc(var(--crown-height) * 0.28);
}

.masthead__inner {
	position: relative;
	flex-direction: column;
	align-items: center;
	gap: var(--space-2xs);
	padding-block: clamp(1.2rem, 3vw, 2.2rem);
	text-align: center;
}

.wordmark {
	align-items: center;
	text-align: center;
}

/*
 * The wordmark is type by default and art when a logo file is set. `--lr5-logo` is
 * printed by the template from the Customizer setting, so swapping the lettering for
 * the drawn logo is a media-library upload, not a code change.
 */
.wordmark__name {
	background-image: linear-gradient(180deg, var(--gold-bright) 8%, var(--gold) 52%, var(--gold-deep) 96%);
	-webkit-background-clip: text;
	background-clip: text;
	color: transparent;
	font-size: clamp(2.2rem, 6.5vw, 4.4rem);
	font-weight: 600;
	letter-spacing: 0.005em;
	line-height: 1.02;
	filter: drop-shadow(0 2px 10px rgba(255, 207, 133, 0.28));
}

.wordmark--art .wordmark__name {
	display: block;
	width: min(90vw, 620px);
	height: clamp(3rem, 8vw, 5.6rem);
	background-image: var(--lr5-logo);
	background-size: contain;
	background-position: center;
	background-repeat: no-repeat;
	filter: none;
	text-indent: -9999px;
	overflow: hidden;
}

.wordmark__rule {
	display: none;
}

.wordmark__tagline {
	color: var(--gold);
	font-family: var(--font-body);
	font-size: clamp(0.62rem, 1.1vw, 0.76rem);
	letter-spacing: 0.34em;
	text-transform: uppercase;
	opacity: 0.85;
}

/* The tagline sits between two short gilded rules. */
.wordmark__tagline::before,
.wordmark__tagline::after {
	content: "✦";
	margin: 0 0.9em;
	color: var(--gold-deep);
	font-size: 0.7em;
	vertical-align: 0.15em;
}

.masthead__seal {
	position: absolute;
	top: clamp(0.6rem, 2vw, 1.4rem);
	right: 0;
}

@media (max-width: 47.99em) {
	.masthead__seal { display: none; }
}

.masthead__bar {
	background: rgba(5, 11, 28, 0.86);
	backdrop-filter: blur(8px);
	border-top: 1px solid var(--rule-soft);
	border-bottom: 1px solid var(--rule-soft);
	box-shadow: 0 12px 30px -26px #000;
}

.masthead__bar.is-stuck {
	background: rgba(5, 11, 28, 0.96);
	box-shadow: 0 10px 30px -18px #000;
}

/*
 * Drop the blur below 62em. `backdrop-filter` makes this bar the containing block for
 * its `position: fixed` descendants, so `.site-nav`'s `inset: 0` resolved against the
 * bar rather than the viewport and the full-screen menu rendered as a clipped strip.
 *
 * This has to sit after the rule above rather than with the rest of the small-screen
 * layout: a media query adds no specificity, so the unconditional `blur(8px)` further
 * down the file would otherwise win on source order alone.
 */
@media (max-width: 61.99em) {
	.masthead__bar {
		backdrop-filter: none;
	}
}

.site-nav li a {
	color: var(--cream);
	font-family: var(--font-body);
	font-size: 0.74rem;
	font-weight: 700;
	letter-spacing: 0.16em;
	text-transform: uppercase;
}

.site-nav li a:hover,
.site-nav .is-current a {
	color: var(--gold-bright);
}

.site-nav li a::after {
	background: var(--gold);
}

/* Hairline separators between the top-level items, as in the plate. */
@media (min-width: 62em) {
	.site-nav__list > li + li {
		border-left: 1px solid var(--rule-soft);
		padding-left: clamp(0.8rem, 1.6vw, 1.5rem);
		margin-left: clamp(0.1rem, 0.6vw, 0.6rem);
	}
}

/* --------------------------------------------------------- 15.8 Buttons */

/*
 * Red enamel with a gold bezel. The bezel is an inset ring rather than a border so it
 * survives the compact and block variants without recomputing padding.
 */
.button,
.wp-block-button__link,
.woocommerce a.button,
.woocommerce button.button,
.woocommerce input.button,
.woocommerce #respond input#submit {
	position: relative;
	background: linear-gradient(180deg, var(--ember) 0%, var(--postbox) 45%, var(--berry) 100%);
	border-color: var(--gold-deep);
	color: var(--gold-bright);
	box-shadow:
		inset 0 0 0 1px rgba(242, 214, 154, 0.35),
		0 2px 0 var(--berry),
		0 10px 26px -14px rgba(0, 0, 0, 0.9);
}

.button:hover,
.wp-block-button__link:hover,
.woocommerce a.button:hover,
.woocommerce button.button:hover {
	background: linear-gradient(180deg, #d84450 0%, var(--postbox) 50%, var(--berry) 100%);
	color: var(--snow);
	box-shadow:
		inset 0 0 0 1px rgba(242, 214, 154, 0.6),
		0 3px 0 var(--berry),
		0 0 30px -6px rgba(255, 207, 133, 0.4);
}

.button--outline,
.button--ghost {
	background: rgba(221, 229, 247, 0.03);
	color: var(--gold-bright);
	border-color: var(--gold);
	box-shadow: inset 0 0 0 1px rgba(216, 171, 92, 0.18);
}

.button--outline:hover,
.button--ghost:hover {
	background: rgba(216, 171, 92, 0.14);
	color: var(--gold-bright);
	box-shadow: inset 0 0 0 1px rgba(216, 171, 92, 0.45);
}

/* -------------------------------------------------- 15.9 Surfaces and cards */

/*
 * A panel in this theme is a pane of dark glass with a gilded hairline, not a sheet of
 * paper. Every inherited `.paper`, `.card`, `.stamp-card` and `.related__card` picks
 * this up through the token aliases; what is added here is the gilding.
 */
.paper,
.card,
.stamp-card,
.related__card,
.inline-reveal,
.faq__item,
.key-facts,
.verdict,
.glance,
.ticket {
	background-color: var(--panel);
	background-image: linear-gradient(180deg, rgba(221, 229, 247, 0.045), transparent 60%);
	border: 1px solid var(--rule-soft);
	color: var(--text);
	box-shadow: var(--shadow-paper);
}

.paper:hover,
.card:hover,
.stamp-card:hover,
.related__card:hover {
	border-color: var(--rule);
	box-shadow: var(--shadow-lift), var(--glow-gold);
}

.stamp-card--featured {
	border-color: var(--gold);
	box-shadow: var(--shadow-lift), var(--glow-gold);
}

.section--kraft,
.guide-section--kraft {
	background-color: rgba(18, 32, 74, 0.55);
	border-block: 1px solid var(--rule-soft);
}

.section--pine,
.section--night {
	background-color: rgba(5, 11, 28, 0.72);
	background-image: var(--fibre);
}

/* A gilded flourish opening every section title. */
.section__title,
.video-showcase__title {
	color: var(--parchment);
}

.eyebrow {
	color: var(--gold);
	letter-spacing: 0.3em;
}

.eyebrow::after,
.eyebrow--light::after {
	background: var(--gold-deep);
}

/* ------------------------------------------------- 15.10 The framed picture */

/*
 * The hero photograph and the in-content media frames are hung as tilted prints with a
 * deckled paper border — the plate's defining object. The tilt is applied to the frame
 * and removed on hover so the image can be read straight.
 */
.media-frame,
.video-showcase__frame {
	position: relative;
	padding: clamp(0.7rem, 1.6vw, 1.15rem) clamp(0.7rem, 1.6vw, 1.15rem) clamp(1.6rem, 3vw, 2.4rem);
	background-color: #e8eeff;
	background-image: var(--art-frame);
	background-size: 100% 100%;
	border: 0;
	border-radius: var(--radius-sm);
	box-shadow:
		0 2px 4px rgba(0, 0, 0, 0.5),
		0 30px 60px -24px rgba(0, 0, 0, 0.95),
		var(--glow-gold);
	transform: rotate(-1.4deg);
	transition: transform 400ms var(--ease);
}

.media-frame:hover,
.video-showcase__frame:hover {
	transform: rotate(0deg);
}

.media-frame img,
.video-showcase__poster {
	border-radius: var(--radius-sm);
	box-shadow: inset 0 0 0 1px rgba(0, 0, 0, 0.15);
}

/* The sprig of holly that rests on the lower right corner of the print. */
.media-frame::after,
.video-showcase__frame::after {
	content: "";
	position: absolute;
	right: -14px;
	bottom: -10px;
	width: clamp(48px, 7vw, 96px);
	aspect-ratio: 1.4;
	background-image: var(--art-holly);
	background-size: contain;
	background-position: bottom right;
	background-repeat: no-repeat;
	pointer-events: none;
}

/* ------------------------------------------------------------ 15.11 Hero */

.hero,
.article-hero {
	position: relative;
	background-color: transparent;
	color: var(--text);
	overflow: hidden;
}

.hero::before,
.article-hero::before {
	background-image: var(--lr5-hero-image, var(--hero-image, none));
	background-size: cover;
	background-position: center;
	opacity: 0.5;
	filter: saturate(1.05);
}

.hero h1,
.article-hero h1 {
	color: var(--parchment);
	font-weight: 500;
	line-height: 1.04;
	text-wrap: balance;
}

/*
 * The plate sets the second and third lines of the headline in gold. An editor cannot
 * be asked to wrap spans by hand across twelve pages, so the theme gilds any <em> or
 * <strong> the copy already carries in a hero heading.
 */
.hero h1 em,
.hero h1 strong,
.article-hero h1 em,
.article-hero h1 strong {
	background-image: linear-gradient(180deg, var(--gold-bright), var(--gold) 60%, var(--gold-deep));
	-webkit-background-clip: text;
	background-clip: text;
	color: transparent;
	font-style: normal;
	font-weight: inherit;
}

.hero .lede,
.article-hero .lede {
	color: var(--cream);
	opacity: 0.92;
}

/* --------------------------------------------------------- 15.12 Footer */

.site-footer {
	position: relative;
	background: linear-gradient(180deg, rgba(5, 11, 28, 0.6), var(--night-deep));
	border-top: 1px solid var(--rule-soft);
	color: var(--cream);
	padding-top: calc(var(--space-xl) + var(--snow-edge-height));
}

.site-footer__col h3 {
	color: var(--gold);
	letter-spacing: 0.22em;
}

.site-footer__mark {
	background-image: linear-gradient(180deg, var(--gold-bright), var(--gold-deep));
	-webkit-background-clip: text;
	background-clip: text;
	color: transparent;
}

/* -------------------------------------------------------- 15.13 Sparkle */

/*
 * The drifting gold specks in the plate. One element, three gradients, no JavaScript —
 * and switched off entirely under reduced motion, where a moving background is exactly
 * the thing being asked about.
 */
/*
 * Two layers, because one never looked like weather. `.sparkle` itself is the gold
 * motes — the warm dust that belongs to the lanterns and drifts diagonally. Its
 * ::after is snow: cold, white, larger, falling nearly straight down and slower. The
 * two speeds and two directions are the whole trick; matching them collapses the
 * effect back into a single moving texture.
 */
.sparkle {
	position: absolute;
	inset: 0;
	pointer-events: none;
	overflow: hidden;
	background-image:
		radial-gradient(1.5px 1.5px at 12% 22%, rgba(255, 231, 184, 0.9), transparent),
		radial-gradient(1.5px 1.5px at 68% 12%, rgba(255, 231, 184, 0.7), transparent),
		radial-gradient(2px 2px at 84% 58%, rgba(255, 231, 184, 0.75), transparent),
		radial-gradient(1.5px 1.5px at 34% 76%, rgba(255, 231, 184, 0.6), transparent),
		radial-gradient(1.5px 1.5px at 52% 42%, rgba(255, 231, 184, 0.55), transparent);
	background-size: 420px 420px;
	animation: lr5-drift 26s linear infinite, lr5-twinkle 7s ease-in-out infinite;
	opacity: 0.7;
}

.sparkle::after {
	content: "";
	position: absolute;
	inset: -20% 0 0;
	background-image:
		radial-gradient(2px 2px at 18% 10%, rgba(255, 255, 255, 0.85), transparent),
		radial-gradient(1.5px 1.5px at 47% 28%, rgba(221, 229, 247, 0.7), transparent),
		radial-gradient(2.5px 2.5px at 73% 6%, rgba(255, 255, 255, 0.6), transparent),
		radial-gradient(1.5px 1.5px at 91% 40%, rgba(221, 229, 247, 0.75), transparent),
		radial-gradient(2px 2px at 6% 62%, rgba(255, 255, 255, 0.5), transparent),
		radial-gradient(1.5px 1.5px at 61% 78%, rgba(221, 229, 247, 0.55), transparent);
	background-size: 560px 560px;
	animation: lr5-snowfall 34s linear infinite;
}

@keyframes lr5-drift {
	from { background-position: 0 0; }
	to { background-position: 420px 420px; }
}

/* Snow falls; it does not drift sideways as fast as the motes do. */
@keyframes lr5-snowfall {
	from { background-position: 0 -560px; }
	to { background-position: 90px 560px; }
}

/* The motes brighten and dim together, which reads as candlelight moving. */
@keyframes lr5-twinkle {
	0%, 100% { opacity: 0.7; }
	50%      { opacity: 0.95; }
}

@media (prefers-reduced-motion: reduce) {
	.sparkle,
	.sparkle::after,
	.lantern,
	body::before {
		animation: none;
	}
}

/* --------------------------------------------- 15.14 Contrast and fallback */

/*
 * Under forced high contrast the gilded hairlines and the clipped-gradient type are
 * the two things that fail first, so both revert to flat, fully opaque colour.
 */
@media (prefers-contrast: more) {
	:root {
		--rule: rgba(216, 171, 92, 0.8);
		--rule-soft: rgba(216, 171, 92, 0.55);
	}

	.wordmark__name,
	.hero h1 em,
	.hero h1 strong,
	.article-hero h1 em,
	.article-hero h1 strong,
	.site-footer__mark {
		background-image: none;
		-webkit-text-fill-color: currentColor;
		color: var(--gold-bright);
	}

	body::after {
		display: none;
	}
}

/*
 * GENERATED ART. Uncomment a line once the matching file exists in
 * assets/images/ornaments/. Each is safe to enable independently — the fallback for
 * that ornament simply stops being visible underneath it.
 */
/*
:root {
	--art-snow-edge: url("../images/ornaments/snow-edge.webp");
	--art-corner: url("../images/ornaments/corner-filigree.webp");
	--art-seal: url("../images/ornaments/wax-seal.webp");
	--art-flourish: url("../images/ornaments/flourish.webp");
	--art-frame: url("../images/ornaments/photo-frame.webp");
	--art-aurora-plate: url("../images/ornaments/aurora-plate.webp");
	--art-holly: url("../images/ornaments/holly-sprig.webp");
}

.snow-edge::before,
.gild-frame > .corner::before,
.seal::before,
.flourish::before {
	display: none;
}
*/

/*
 * The drawn lantern exists, so it is switched on for real here. Unlike the crown
 * plates it keeps its alpha channel and is composited normally: it is a solid brass
 * object rather than a glow, so `screen` would make the dark brass and the chain go
 * translucent and lose them against the spruce ground.
 */
:root {
	--art-lantern: url("../images/ornaments/lantern.webp");
	--art-snow-edge: url("../images/ornaments/snow-edge.webp");

	/*
	 * Both inert until the file exists — an unresolved url() leaves the layer
	 * transparent, so the CSS sky and the standard drift keep working underneath.
	 */
	--art-snow-drift: url("../images/ornaments/snow-drift-deep.webp");
	--art-treeline: url("../images/ornaments/treeline.webp");

	/*
	 * aurora-plate.webp is rendered and sits in assets/images/ornaments/, but it is
	 * deliberately NOT switched on. The sky band is masthead-only now, and the masthead
	 * sits directly above a hero whose plate is already a painted aurora — so enabling
	 * this would butt one photographic aurora against another with only the nav between
	 * them. The CSS gradient washes the masthead without competing, which is the job
	 * that actually needed doing.
	 *
	 * It is switched on for the FOOTER instead — see below.
	 */
	--art-aurora-plate: url("../images/ornaments/aurora-plate.webp");
}

/*
 * The sky, at the other end of the page.
 *
 * The aurora plate had nowhere to go at the top: the masthead sits directly above a
 * hero whose plate is already a painted aurora, so putting a second photographic sky
 * there just recreated the pile-up. The footer is the opposite case — it is as far from
 * the hero as the page gets, and the text it carries is navigation and legal lines
 * rather than anything that needs to win attention.
 *
 * So the page now opens and closes under the same sky, and the hero's aurora is
 * uncontested in between. That is a bookend rather than a repetition.
 *
 * Deliberately NOT on .postbox-cta, which butts directly against this: two auroras
 * touching would be the original problem moved to the bottom of the page. The CTA is
 * also the one place on the site that should be legible before it is atmospheric — its
 * existing radial glow already points at the button, and a photograph behind the
 * headline would only soften the moment that has to convert.
 */
.site-footer {
	/*
	 * Scrim first so it sits above the plate: the aurora shows across the top of the
	 * footer, then dissolves into solid --night-deep well before the columns of links.
	 * The plate's own lower third is featureless dark blue, which does half this work
	 * already — the gradient finishes it.
	 */
	background-image:
		linear-gradient(180deg, rgba(5, 11, 28, 0.42) 0%, rgba(5, 11, 28, 0.86) 46%, var(--night-deep) 82%),
		var(--art-aurora-plate);
	background-size: auto, cover;
	background-position: center top, center 28%;
	background-repeat: no-repeat, no-repeat;
	background-color: var(--night-deep);
}

/*
 * The horizon. A tiling silhouette of spruce tops along the foot of the dark section,
 * which gives a long page a distance to sit in front of instead of stacking flat
 * panels. Used on .section--night only — roughly once per page — because the moment it
 * appears at every seam it stops reading as a horizon and starts reading as wallpaper.
 */
.section--night {
	position: relative;
}

.section--night::after {
	content: "";
	position: absolute;
	left: 0;
	right: 0;
	bottom: 0;
	height: clamp(3.4rem, 7vw, 6rem);
	background-image: var(--art-treeline);
	background-repeat: repeat-x;
	background-position: center bottom;
	background-size: auto 100%;
	pointer-events: none;
	z-index: 0;
}

/* The section's own content must sit in front of the treeline, not behind it. */
.section--night > * {
	position: relative;
	z-index: 1;
}

/*
 * The drawn drift is opaque snow with shaded undersides, so it keeps its alpha channel
 * and composites normally. It is deliberately not stored on black and screened like the
 * gilded crown: the drift's underside sits at 0.36 luminance, and `screen` turns
 * anything that dark translucent — the overhanging edge and the icicles, which is
 * exactly where the form reads, would go see-through against the spruce.
 */
.snow-edge::before {
	display: none;
}

/*
 * The heroes clip their contents to keep the tilted photo print inside, which would also
 * shear off the icicles now that the drift hangs past the boundary. `clip` with a margin
 * lets the overhang through while still containing the print. Browsers without
 * `overflow-clip-margin` drop this rule and keep the plain `hidden` above, so the worst
 * case is the old clipped edge rather than a broken layout.
 */
.hero,
.article-hero {
	overflow: clip;
	/*
	 * A plain length, deliberately: `overflow-clip-margin` rejects `calc()` and `var()`
	 * (it resolves them to 0 and silently clips again). 22px covers the deepest overhang
	 * this can produce — the drift caps at 54px tall and hangs by 36% of that.
	 */
	overflow-clip-margin: 22px;
}

.lantern {
	/* The drawn lantern's own aspect, so `contain` fits it with nothing left over. */
	aspect-ratio: 238 / 470;
}

.lantern::before,
.lantern::after {
	display: none;
}

/*
 * The eyebrow becomes a centred, star-flanked label — the plate's
 * "✦ THE FIRST SCENE OF THEIR ADVENTURE ✦". The inherited rule set it as a label
 * followed by a dashed rule that filled the row, so that trailing rule is retired
 * here and a matching star put on each side instead.
 */
.eyebrow {
	justify-content: center;
	gap: 0.9em;
	text-align: center;
}

.eyebrow::before,
.eyebrow::after {
	content: "✦";
	flex: 0 0 auto;
	height: auto;
	background: none;
	color: var(--gold-deep);
	font-size: 0.8em;
}

/* Left-aligned contexts keep the label at the start of the line. */
.article-body .eyebrow,
.inline-reveal .eyebrow,
.postbox-cta__copy .eyebrow {
	justify-content: flex-start;
}

/* ------------------------------------- 15.15 Corrections to inherited rules */

/*
 * Four places where the light theme's geometry, not its colour, is wrong for v4.
 * They are gathered here rather than edited in place so section 15 stays the single
 * thing that has to be read to understand what v4 changed.
 */

/* 1. The hero wash. The inherited ::before was a 3px stamp-perforation stripe down
      the left edge; here it carries the hero photograph across the whole panel. */
.hero::before,
.article-hero::before {
	inset: 0;
	width: auto;
	/*
	 * Held well back. The same photograph is also hung as the pinned print to the
	 * right, so at full strength the hero showed it twice and ran the headline across
	 * Santa's face. Here it is atmosphere behind the type, and the print is the one
	 * place the picture is actually legible.
	 */
	opacity: 0.32;
}

/* A scrim under the copy, heaviest where the text starts. */
.hero::before,
.article-hero::before {
	box-shadow: inset 0 0 0 100vmax rgba(5, 11, 28, 0.15);
}

.hero,
.article-hero {
	background-image:
		linear-gradient(96deg, rgba(5, 11, 28, 0.92) 0%, rgba(5, 11, 28, 0.72) 38%, rgba(5, 11, 28, 0.3) 66%, transparent 100%),
		var(--fibre);
	background-size: auto, 160px 160px;
	background-repeat: no-repeat, repeat;
}

/*
 * The scrim is painted on the section, so the copy has to sit above it — but the
 * ornaments are absolutely positioned against the hero, and lifting them with
 * `position: relative` drops the snow drift back into the flow, where it has no height
 * and never appears. Everything except the ornaments.
 */
.hero > *:not(.sparkle):not(.snow-edge),
.article-hero > *:not(.sparkle):not(.snow-edge) {
	position: relative;
	z-index: 2;
}

.hero > .sparkle,
.hero > .snow-edge,
.article-hero > .sparkle,
.article-hero > .snow-edge {
	z-index: 3;
}

/*
 * 2. The pinned hero print. It only earns its place when there is a photograph to put
 *    in it — an empty bordered rectangle is worse than nothing. The theme prints
 *    --lr5-hero-print alongside the image URL, so the frame appears only on pages
 *    that actually have hero art, and the wide-screen media query below still gates
 *    it on there being room.
 */
@media (min-width: 62em) {
	.hero::after,
	.article-hero::after {
		display: var(--lr5-hero-print, none);
		border: clamp(0.6rem, 1.1vw, 0.9rem) solid #e8eeff;
		border-bottom-width: clamp(1.6rem, 2.6vw, 2.2rem);
		border-radius: var(--radius-sm);
		box-shadow:
			0 2px 4px rgba(0, 0, 0, 0.5),
			0 30px 60px -24px rgba(0, 0, 0, 0.95),
			var(--glow-gold);
	}
}

/*
 * 3. The showcase poster is absolutely positioned to fill its frame, so the paper
 *    margin the frame paints underneath was invisible. Inset it by the same amounts
 *    the frame is padded, and the print border appears.
 */
.video-showcase__frame {
	--frame-pad: clamp(0.7rem, 1.6vw, 1.15rem);
	--frame-pad-bottom: clamp(1.6rem, 3vw, 2.4rem);
	aspect-ratio: auto;
	overflow: visible;
}

.video-showcase__poster,
.video-showcase__frame iframe {
	position: relative;
	inset: auto;
	display: block;
	width: 100%;
	height: auto;
	aspect-ratio: 16 / 9;
	object-fit: cover;
}

/* The play control is positioned against the frame, so it has to skip the margin. */
.video-showcase__play {
	inset: var(--frame-pad) var(--frame-pad) var(--frame-pad-bottom);
}

/*
 * 4. Section headers are centred in this theme — the eyebrow, the title and the lede
 *    read as one plate. Article bodies and the two split layouts keep their left
 *    alignment, where centring would hurt the line length.
 */
.section > .wrap > .section__title,
.section > .wrap > .lede,
.ladder__note {
	text-align: center;
}

.section > .wrap > .lede {
	margin-inline: auto;
}

.article-body :where(h2, h3, p),
.postbox-cta__copy :where(h2, p),
.inline-reveal :where(h3, p) {
	text-align: left;
}

/* 5. Three marks, not one — the single glyph read as a stray asterisk. */
.flourish::before {
	content: "✦ ❋ ✦";
	letter-spacing: 0.5em;
	text-indent: 0.5em;
	font-size: 0.8rem;
}

/* ------------------------------ 15.16 The closing call to action */

/*
 * The inherited version was a solid postbox-red band — right when the page above it
 * was parchment, far too loud when the whole site is already dark and gilded. Here it
 * becomes the deepest panel on the page, with the red kept for the button alone.
 */
.postbox-cta {
	background-color: var(--night-deep);
	background-image:
		radial-gradient(80% 120% at 50% 0%, rgba(216, 171, 92, 0.12), transparent 60%),
		var(--fibre);
	border-top: 1px solid var(--rule-soft);
	color: var(--cream);
}

.postbox-cta h2 {
	color: var(--parchment);
}

.envelope {
	border-color: var(--rule);
}

/*
 * The closing CTA's button was inverted to candlelight-on-red because the band behind
 * it used to be solid postbox red. The band is now the darkest panel on the page, so
 * the button goes back to the site's red enamel and the secondary to a gold outline —
 * a pale block with pale type is unreadable either way round.
 */
.postbox-cta .button {
	background: linear-gradient(180deg, var(--ember) 0%, var(--postbox) 45%, var(--berry) 100%);
	color: var(--gold-bright);
	border-color: var(--gold-deep);
	box-shadow:
		inset 0 0 0 1px rgba(242, 214, 154, 0.35),
		0 2px 0 var(--berry),
		0 10px 26px -14px rgba(0, 0, 0, 0.9);
}

.postbox-cta .button:hover {
	background: linear-gradient(180deg, #d84450 0%, var(--postbox) 50%, var(--berry) 100%);
	color: var(--snow);
}

.postbox-cta .button--outline {
	background: rgba(221, 229, 247, 0.03);
	color: var(--gold-bright);
	border-color: var(--gold);
	box-shadow: inset 0 0 0 1px rgba(216, 171, 92, 0.18);
}

/* Ticks read as gold on this ground; red on spruce is close to invisible. */
.ticks li::before,
.tick-list li::before {
	border-left-color: var(--gold);
	border-bottom-color: var(--gold);
}

/* --------------------------- 15.17 Surfaces that were still pale */

/*
 * The last of the light theme's paper panels. Each was a parchment surface holding
 * text that inherited its colour — which was ink-on-paper then and cream-on-cream now.
 * These are the panels that do not appear in a static screenshot of the home page:
 * the mobile menu, the desktop dropdown, the breadcrumb bar, the selection highlight.
 */
.site-nav,
.site-nav .sub-menu,
.page-utility {
	background-color: rgba(5, 11, 28, 0.97);
	background-image: var(--fibre);
	border-color: var(--rule-soft);
	color: var(--cream);
}

@supports (backdrop-filter: blur(1px)) {
	.site-nav .sub-menu {
		background-color: rgba(5, 11, 28, 0.92);
		backdrop-filter: blur(10px);
	}
}

.page-utility {
	border-bottom: 1px solid var(--rule-soft);
}

/*
 * The two remaining gold plates carry dark type, not light — they are the only places
 * in the theme where the surface is brighter than the text.
 */
.product-price {
	background: linear-gradient(180deg, var(--gold-bright), var(--gold));
	color: var(--night-deep);
}

.demo__card.is-updating [data-lr5-demo-name] {
	color: var(--night-deep);
}

::selection {
	background: var(--candle);
	color: var(--night-deep);
}

/* --------------------------------- 16 Hero plates — one photograph per page */

/*
 * v4 drew every hero in CSS. v5 hangs a rendered night plate behind each one instead,
 * because the single strongest thing the brand icon does is *subject on a cold ground
 * with the aurora behind it* — and that is a composition, not a colour.
 *
 * Every published page already carries a `hero--*` modifier on either `.hero` (the two
 * landing pages) or `.article-hero` (the other ten), so the whole mechanism is: the
 * modifier names a file, and the two hero classes know how to render whatever it names.
 * No page markup changes. A page whose plate has not been rendered yet falls back to
 * the drawn gradient underneath, exactly like the ornament policy in section 15.
 *
 * Filenames and the prompt for each plate live in assets/images/heroes/PROMPTS.md.
 */

/*
 * Hero height is a function of WIDTH, not of content.
 *
 * Left to the content, a hero settles at ~435px and stays there however wide the window
 * gets — so the box ratio runs away from the plate's native 2.40:1 and `cover` throws
 * the difference away. Measured before this rule: 21% of the plate lost at 1345px, 45%
 * at 1920px. What goes is the top and the bottom, which is precisely where the aurora
 * and the snow are.
 *
 * Deliberately NOT 100vh. A 1920x1080 box is 1.78:1 — TALLER than the plate — so cover
 * would stop cropping top-and-bottom and start cropping the sides, ~13% off each edge.
 * Every plate is composed with its subject right of centre, so a full-viewport hero
 * would clip the subject. It also pushes the price and CTA below the fold on the
 * commercial pages and puts a screenful of picture in front of a 4,000-word guide.
 *
 * Two tiers, along the split the markup already has: .hero is the three commercial
 * pages, where the art is doing the selling and is allowed to run near native ratio;
 * .article-hero is the nine editorial pages, which should get to the words sooner.
 * Crop at 1920 goes from 45% to 4% and 28% respectively.
 *
 * Both cap out, so ultrawide still crops — an uncapped `aspect-ratio: 12/5` would crop
 * perfectly at every width but stand 1067px tall at 2560, which is too much page to ask
 * anyone to scroll past.
 *
 * 41vw, and never more, because 100/2.4 = 41.6 is the ratio of the plate: any taller and
 * the box becomes narrower than 2.40:1, at which point `cover` stops trimming top and
 * bottom and starts trimming the SIDES — clipping the subject every plate deliberately
 * places right of centre. A first attempt used 44vw and did exactly that at 1680px,
 * turning a harmless 6% top-and-bottom trim into a 6% bite out of the edges. 41 rather
 * than 41.6 leaves room for the scrollbar, which 100vw counts and the layout does not.
 *
 * `min()` and not `clamp()`: no floor is wanted. Where the copy is taller than this the
 * copy simply wins, which is what already happens on the home hero below ~1500px.
 */
.hero,
.article-hero {
	position: relative;
	isolation: isolate;
}

/*
 * Grid purely to centre the copy in the taller box. Until the min-heights above, a hero
 * was exactly as tall as its content and there was nothing to centre; now the extra
 * height would otherwise all pool beneath the buttons and leave the text riding high.
 *
 * `align-content` and not `align-items`, so the content block is centred as a unit
 * rather than each child being stretched. The decorations — .sparkle, .snow-edge, the
 * corners, both pseudo-elements — are absolutely positioned and therefore out of flow,
 * so the grid never sees them and their placement is untouched.
 */
.hero,
.article-hero {
	display: grid;
	align-content: center;
}

.hero {
	min-height: min(41vw, 48rem);
}

.article-hero {
	min-height: min(41vw, 36rem);
}

/*
 * Plate, scrim and sky are all layers of the SAME pseudo-element.
 *
 * They have to be. `::after` on these two selectors is already spoken for — section
 * 15.11 uses it for the tilted print pinned to the right of the hero — and `::before`
 * is the only backdrop layer a hero has. Putting the scrim on `::after` paints it
 * inside the deckled frame instead of over the photograph, which empties the frame.
 *
 * The scrim goes FIRST in the list, because background layers paint front-to-back:
 * first declared sits on top. So it darkens the plate beneath it rather than the other
 * way round.
 *
 * Every background-* property below is deliberately a SINGLE value. `--aurora` is five
 * gradients and `--hero-plate` is one, so a comma-separated list here would cycle its
 * values across seven layers and tile parts of the sky — the same trap that banded the
 * page background in section 15.1. A single value applies to every layer, whatever the
 * count, and stays correct if --aurora ever gains or loses a stop.
 */
.hero::before,
.article-hero::before {
	background-image: var(--hero-scrim), var(--hero-plate, none), var(--aurora);
	background-size: cover;
	background-position: center 38%;
	background-repeat: no-repeat;
	/*
	 * Section 15.11 half-fades .article-hero::before, because there it was a stray
	 * photograph pressed into service as a backdrop. A hero plate is authored for this
	 * job and carries its own scrim, so it is shown at full strength.
	 */
	opacity: 1;
}

/*
 * There is deliberately NO CSS aurora bloom over a hero.
 *
 * There was one, added with the plates: a teal-and-violet blur across the top 62% of
 * every hero. It had to go. Each plate is itself a painted aurora, so the bloom laid a
 * second, cruder aurora on top of a better one — and with the sky band behind them both,
 * the first screen carried three auroras in one 550px run. They fought.
 *
 * The plate is the aurora. Anything else here is competition, not lining.
 */

/*
 * The plates. Each line is inert until the file exists — an unresolved url() makes the
 * layer transparent and the drawn hero shows through, so these ship enabled.
 */
.hero--home     { --hero-plate: url("../images/heroes/hero-home.webp"); }
.hero--video    { --hero-plate: url("../images/heroes/hero-video.webp"); }
.hero--kit      { --hero-plate: url("../images/heroes/hero-kit.webp"); }
.hero--letter   { --hero-plate: url("../images/heroes/hero-letter.webp"); }
.hero--ideas    { --hero-plate: url("../images/heroes/hero-ideas.webp"); }
.hero--ticket   { --hero-plate: url("../images/heroes/hero-ticket.webp"); }
.hero--elf      { --hero-plate: url("../images/heroes/hero-elf.webp"); }
.hero--invitation { --hero-plate: url("../images/heroes/hero-invitation.webp"); }
.hero--december { --hero-plate: url("../images/heroes/hero-december.webp"); }
.hero--november { --hero-plate: url("../images/heroes/hero-november.webp"); }
.hero--packing  { --hero-plate: url("../images/heroes/hero-packing.webp"); }
.hero--age      { --hero-plate: url("../images/heroes/hero-age.webp"); }
.hero--worth    { --hero-plate: url("../images/heroes/hero-worth.webp"); }

/*
 * Pages with no modifier at all — privacy, 404, anything added later — get the sky
 * only, which is a deliberate non-answer rather than a borrowed photograph.
 */
